summaryrefslogtreecommitdiff
path: root/protocols/Steam
diff options
context:
space:
mode:
authorRobert Pösel <robyer@seznam.cz>2015-12-19 17:05:44 +0000
committerRobert Pösel <robyer@seznam.cz>2015-12-19 17:05:44 +0000
commitb621abd5fa5c6e452d6627b362b62e415246684d (patch)
tree3a1813381c7b9989e85d072d23cdcd0ef4f7d34b /protocols/Steam
parentf75582e0394eddac7a9f2cc9ceafb157865d7dbf (diff)
Steam: Try to login again on PollThread's "Not Logged On" error
git-svn-id: http://svn.miranda-ng.org/main/trunk@15897 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'protocols/Steam')
-rw-r--r--protocols/Steam/src/steam_login.cpp656
-rw-r--r--protocols/Steam/src/steam_polling.cpp24
-rw-r--r--protocols/Steam/src/steam_proto.h2
3 files changed, 362 insertions, 320 deletions
diff --git a/protocols/Steam/src/steam_login.cpp b/protocols/Steam/src/steam_login.cpp
index 112bad8592..612af3496c 100644
--- a/protocols/Steam/src/steam_login.cpp
+++ b/protocols/Steam/src/steam_login.cpp
@@ -1,311 +1,347 @@
-#include "stdafx.h"
-
-bool CSteamProto::IsOnline()
-{
- return m_iStatus > ID_STATUS_OFFLINE && m_hPollingThread;
-}
-
-bool CSteamProto::IsMe(const char *steamId)
-{
- ptrA mySteamId(getStringA("SteamID"));
- if (!lstrcmpA(steamId, mySteamId))
- return true;
-
- return false;
-}
-
-void CSteamProto::OnGotRsaKey(const HttpResponse *response)
-{
- if (!CheckResponse(response))
- return;
-
- // load rsa key parts
- JSONNode root = JSONNode::parse(response->pData);
- if (!root)
- return;
-
- if (!root["success"].as_bool())
- return;
-
- std::string modulus = root["publickey_mod"].as_string();
- // exponent "010001" is used as constant in CSteamProto::RsaEncrypt
- //std::string exponent = root["publickey_exp"].as_string();
-
- std::string timestamp = root["timestamp"].as_string();
-
- // encrcrypt password
- ptrA base64RsaEncryptedPassword;
- ptrA szPassword(getStringA("Password"));
-
- DWORD error = 0;
- DWORD encryptedSize = 0;
- if ((error = RsaEncrypt(modulus.c_str(), szPassword, NULL, encryptedSize)) != 0)
- {
- debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error);
- return;
- }
-
- BYTE *encryptedPassword = (BYTE*)mir_calloc(encryptedSize);
- if ((error = RsaEncrypt(modulus.c_str(), szPassword, encryptedPassword, encryptedSize)) != 0)
- {
- debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error);
- return;
- }
-
- base64RsaEncryptedPassword = mir_base64_encode(encryptedPassword, encryptedSize);
- mir_free(encryptedPassword);
-
- // run authorization request
- T2Utf username(getTStringA("Username"));
-
- ptrA guardId(getStringA("GuardId"));
- if (!guardId) guardId = mir_strdup("");
- ptrA guardCode(getStringA("GuardCode"));
- if (!guardCode) guardCode = mir_strdup("");
-
- ptrA captchaId(getStringA("CaptchaId"));
- if (!captchaId) captchaId = mir_strdup("-1");
- ptrA captchaText(getStringA("CaptchaText"));
- if (!captchaText) captchaText = mir_strdup("");
-
- PushRequest(
- new AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp.c_str(), "", guardCode, guardId, captchaId, captchaText),
- &CSteamProto::OnAuthorization);
-}
-
-void CSteamProto::OnAuthorization(const HttpResponse *response)
-{
- if (!CheckResponse(response))
- {
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- JSONNode root = JSONNode::parse(response->pData);
- if (!root)
- {
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- if (!root["success"].as_bool())
- {
- OnAuthorizationError(root);
- return;
- }
-
- OnAuthorizationSuccess(root);
-}
-
-void CSteamProto::OnAuthorizationError(const JSONNode &node)
-{
- std::string message = node["message"].as_string();
- ptrT messageT(mir_utf8decodeT(message.c_str()));
- if (!mir_tstrcmpi(messageT, _T("Incorrect login.")))
- {
- // We can't continue with incorrect login/password
- delSetting("GuardId");
- delSetting("GuardCode");
- delSetting("CaptchaId");
- delSetting("CaptchaText");
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- T2Utf username(getTStringA("Username"));
-
- if (node["requires_twofactor"].as_bool())
- {
- return;
- }
-
- if (node["emailauth_needed"].as_bool())
- {
- std::string guardId = node["emailsteamid"].as_string();
- ptrA oldGuardId(getStringA("GuardId"));
- if (mir_strcmp(guardId.c_str(), oldGuardId) == 0)
- {
- delSetting("GuardId");
- delSetting("GuardCode");
- PushRequest(
- new GetRsaKeyRequest(username),
- &CSteamProto::OnGotRsaKey);
- return;
- }
-
- std::string domain = node["emaildomain"].as_string();
-
- CSteamGuardDialog guardDialog(this, domain.c_str());
- if (guardDialog.DoModal() != DIALOG_RESULT_OK)
- {
- delSetting("GuardId");
- delSetting("GuardCode");
- delSetting("CaptchaId");
- delSetting("CaptchaText");
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- setString("GuardId", guardId.c_str());
- setString("GuardCode", guardDialog.GetGuardCode());
-
- PushRequest(
- new GetRsaKeyRequest(username),
- &CSteamProto::OnGotRsaKey);
- return;
- }
-
- if (node["captcha_needed"].as_bool())
- {
- std::string captchaId = node["captcha_gid"].as_string();
-
- GetCaptchaRequest *request = new GetCaptchaRequest(captchaId.c_str());
- HttpResponse *response = request->Send(m_hNetlibUser);
- delete request;
-
- CSteamCaptchaDialog captchaDialog(this, (BYTE*)response->pData, response->dataLength);
- delete response;
- if (captchaDialog.DoModal() != DIALOG_RESULT_OK)
- {
- delSetting("CaptchaId");
- delSetting("CaptchaText");
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- setString("CaptchaId", captchaId.c_str());
- setString("CaptchaText", captchaDialog.GetCaptchaText());
-
- PushRequest(
- new GetRsaKeyRequest(username),
- &CSteamProto::OnGotRsaKey);
- return;
- }
-
- delSetting("GuardId");
- delSetting("GuardCode");
- delSetting("CaptchaId");
- delSetting("CaptchaText");
- SetStatus(ID_STATUS_OFFLINE);
-}
-
-void CSteamProto::OnAuthorizationSuccess(const JSONNode &node)
-{
- delSetting("GuardId");
- delSetting("GuardCode");
- delSetting("CaptchaId");
- delSetting("CaptchaText");
-
- if (!node["login_complete"].as_bool())
- {
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- std::string oauth = node["oauth"].as_string();
- JSONNode root = JSONNode::parse(oauth.c_str());
- if (!root)
- {
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- std::string steamId = root["steamid"].as_string();
- setString("SteamID", steamId.c_str());
-
- std::string token = root["oauth_token"].as_string();
- setString("TokenSecret", token.c_str());
-
- std::string cookie = root["webcookie"].as_string();
-
- PushRequest(
- new GetSessionRequest(token.c_str(), steamId.c_str(), cookie.c_str()),
- &CSteamProto::OnGotSession);
-
- PushRequest(
- new LogonRequest(token.c_str()),
- &CSteamProto::OnLoggedOn);
-}
-
-void CSteamProto::OnGotSession(const HttpResponse *response)
-{
- if(!response)
- return;
-
- for (int i = 0; i < response->headersCount; i++)
- {
- if (lstrcmpiA(response->headers[i].szName, "Set-Cookie"))
- continue;
-
- std::string cookies = response->headers[i].szValue;
- size_t start = cookies.find("sessionid=") + 10;
- size_t end = cookies.substr(start).find(';');
- std::string sessionId = cookies.substr(start, end - start + 10);
- setString("SessionID", sessionId.c_str());
- break;
- }
-}
-
-void CSteamProto::HandleTokenExpired()
-{
- // Notify error to user
- ShowNotification(_T("Steam"), TranslateT("Connection token expired. Please login again."));
-
- // Delete expired token
- delSetting("TokenSecret");
-
- // Set status to offline
- SetStatus(ID_STATUS_OFFLINE);
-
- // TODO: Try to login again acutomatically (at least once)
-}
-
-void CSteamProto::OnLoggedOn(const HttpResponse *response)
-{
- if (!CheckResponse(response))
- {
- if (response->resultCode == HTTP_CODE_UNAUTHORIZED)
- {
- // Probably expired TokenSecret
- HandleTokenExpired();
- return;
- }
-
- // Probably timeout or no connection, we can do nothing here
- ShowNotification(_T("Steam"), TranslateT("Unknown login error."));
-
- SetStatus(ID_STATUS_OFFLINE);
- return;
- }
-
- JSONROOT root(response->pData);
-
- JSONNode *node = json_get(root, "error");
- ptrT error(json_as_string(node));
- if (mir_tstrcmpi(error, _T("OK")))
- {
- // Probably expired TokenSecret
- HandleTokenExpired();
- return;
- }
-
- node = json_get(root, "umqid");
- setString("UMQID", ptrA(mir_u2a(ptrT(json_as_string(node)))));
-
- node = json_get(root, "message");
- setDword("MessageID", json_as_int(node));
-
- // load contact list
- ptrA token(getStringA("TokenSecret"));
- ptrA steamId(getStringA("SteamID"));
-
- PushRequest(
- new GetFriendListRequest(token, steamId),
- &CSteamProto::OnGotFriendList);
-
- // start polling thread
- m_hPollingThread = ForkThreadEx(&CSteamProto::PollingThread, 0, NULL);
-
- // go to online now
- ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus = m_iDesiredStatus);
+#include "stdafx.h"
+
+bool CSteamProto::IsOnline()
+{
+ return m_iStatus > ID_STATUS_OFFLINE && m_hPollingThread;
+}
+
+bool CSteamProto::IsMe(const char *steamId)
+{
+ ptrA mySteamId(getStringA("SteamID"));
+ if (!lstrcmpA(steamId, mySteamId))
+ return true;
+
+ return false;
+}
+
+bool CSteamProto::Relogin()
+{
+ ptrA token(getStringA("TokenSecret"));
+ if (mir_strlen(token) <= 0)
+ return false;
+
+ HttpRequest *request = new LogonRequest(token);
+ HttpResponse *response = request->Send(m_hNetlibUser);
+
+ bool success = false;
+ if (CheckResponse(response))
+ {
+ JSONROOT root(response->pData);
+ if (root != NULL) {
+ JSONNode *node = json_get(root, "error");
+
+ ptrT error(json_as_string(node));
+ if (!mir_tstrcmpi(error, _T("OK")))
+ {
+ node = json_get(root, "umqid");
+ setString("UMQID", ptrA(mir_u2a(ptrT(json_as_string(node)))));
+
+ node = json_get(root, "message");
+ setDword("MessageID", json_as_int(node));
+
+ success = true;
+ }
+ }
+ }
+
+ delete request;
+ delete response;
+
+ return success;
+}
+
+void CSteamProto::OnGotRsaKey(const HttpResponse *response)
+{
+ if (!CheckResponse(response))
+ return;
+
+ // load rsa key parts
+ JSONNode root = JSONNode::parse(response->pData);
+ if (!root)
+ return;
+
+ if (!root["success"].as_bool())
+ return;
+
+ std::string modulus = root["publickey_mod"].as_string();
+ // exponent "010001" is used as constant in CSteamProto::RsaEncrypt
+ //std::string exponent = root["publickey_exp"].as_string();
+
+ std::string timestamp = root["timestamp"].as_string();
+
+ // encrcrypt password
+ ptrA base64RsaEncryptedPassword;
+ ptrA szPassword(getStringA("Password"));
+
+ DWORD error = 0;
+ DWORD encryptedSize = 0;
+ if ((error = RsaEncrypt(modulus.c_str(), szPassword, NULL, encryptedSize)) != 0)
+ {
+ debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error);
+ return;
+ }
+
+ BYTE *encryptedPassword = (BYTE*)mir_calloc(encryptedSize);
+ if ((error = RsaEncrypt(modulus.c_str(), szPassword, encryptedPassword, encryptedSize)) != 0)
+ {
+ debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error);
+ return;
+ }
+
+ base64RsaEncryptedPassword = mir_base64_encode(encryptedPassword, encryptedSize);
+ mir_free(encryptedPassword);
+
+ // run authorization request
+ T2Utf username(getTStringA("Username"));
+
+ ptrA guardId(getStringA("GuardId"));
+ if (!guardId) guardId = mir_strdup("");
+ ptrA guardCode(getStringA("GuardCode"));
+ if (!guardCode) guardCode = mir_strdup("");
+
+ ptrA captchaId(getStringA("CaptchaId"));
+ if (!captchaId) captchaId = mir_strdup("-1");
+ ptrA captchaText(getStringA("CaptchaText"));
+ if (!captchaText) captchaText = mir_strdup("");
+
+ PushRequest(
+ new AuthorizationRequest(username, base64RsaEncryptedPassword, timestamp.c_str(), "", guardCode, guardId, captchaId, captchaText),
+ &CSteamProto::OnAuthorization);
+}
+
+void CSteamProto::OnAuthorization(const HttpResponse *response)
+{
+ if (!CheckResponse(response))
+ {
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ JSONNode root = JSONNode::parse(response->pData);
+ if (!root)
+ {
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ if (!root["success"].as_bool())
+ {
+ OnAuthorizationError(root);
+ return;
+ }
+
+ OnAuthorizationSuccess(root);
+}
+
+void CSteamProto::OnAuthorizationError(const JSONNode &node)
+{
+ std::string message = node["message"].as_string();
+ ptrT messageT(mir_utf8decodeT(message.c_str()));
+ if (!mir_tstrcmpi(messageT, _T("Incorrect login.")))
+ {
+ // We can't continue with incorrect login/password
+ delSetting("GuardId");
+ delSetting("GuardCode");
+ delSetting("CaptchaId");
+ delSetting("CaptchaText");
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ T2Utf username(getTStringA("Username"));
+
+ if (node["requires_twofactor"].as_bool())
+ {
+ return;
+ }
+
+ if (node["emailauth_needed"].as_bool())
+ {
+ std::string guardId = node["emailsteamid"].as_string();
+ ptrA oldGuardId(getStringA("GuardId"));
+ if (mir_strcmp(guardId.c_str(), oldGuardId) == 0)
+ {
+ delSetting("GuardId");
+ delSetting("GuardCode");
+ PushRequest(
+ new GetRsaKeyRequest(username),
+ &CSteamProto::OnGotRsaKey);
+ return;
+ }
+
+ std::string domain = node["emaildomain"].as_string();
+
+ CSteamGuardDialog guardDialog(this, domain.c_str());
+ if (guardDialog.DoModal() != DIALOG_RESULT_OK)
+ {
+ delSetting("GuardId");
+ delSetting("GuardCode");
+ delSetting("CaptchaId");
+ delSetting("CaptchaText");
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ setString("GuardId", guardId.c_str());
+ setString("GuardCode", guardDialog.GetGuardCode());
+
+ PushRequest(
+ new GetRsaKeyRequest(username),
+ &CSteamProto::OnGotRsaKey);
+ return;
+ }
+
+ if (node["captcha_needed"].as_bool())
+ {
+ std::string captchaId = node["captcha_gid"].as_string();
+
+ GetCaptchaRequest *request = new GetCaptchaRequest(captchaId.c_str());
+ HttpResponse *response = request->Send(m_hNetlibUser);
+ delete request;
+
+ CSteamCaptchaDialog captchaDialog(this, (BYTE*)response->pData, response->dataLength);
+ delete response;
+ if (captchaDialog.DoModal() != DIALOG_RESULT_OK)
+ {
+ delSetting("CaptchaId");
+ delSetting("CaptchaText");
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ setString("CaptchaId", captchaId.c_str());
+ setString("CaptchaText", captchaDialog.GetCaptchaText());
+
+ PushRequest(
+ new GetRsaKeyRequest(username),
+ &CSteamProto::OnGotRsaKey);
+ return;
+ }
+
+ delSetting("GuardId");
+ delSetting("GuardCode");
+ delSetting("CaptchaId");
+ delSetting("CaptchaText");
+ SetStatus(ID_STATUS_OFFLINE);
+}
+
+void CSteamProto::OnAuthorizationSuccess(const JSONNode &node)
+{
+ delSetting("GuardId");
+ delSetting("GuardCode");
+ delSetting("CaptchaId");
+ delSetting("CaptchaText");
+
+ if (!node["login_complete"].as_bool())
+ {
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ std::string oauth = node["oauth"].as_string();
+ JSONNode root = JSONNode::parse(oauth.c_str());
+ if (!root)
+ {
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ std::string steamId = root["steamid"].as_string();
+ setString("SteamID", steamId.c_str());
+
+ std::string token = root["oauth_token"].as_string();
+ setString("TokenSecret", token.c_str());
+
+ std::string cookie = root["webcookie"].as_string();
+
+ PushRequest(
+ new GetSessionRequest(token.c_str(), steamId.c_str(), cookie.c_str()),
+ &CSteamProto::OnGotSession);
+
+ PushRequest(
+ new LogonRequest(token.c_str()),
+ &CSteamProto::OnLoggedOn);
+}
+
+void CSteamProto::OnGotSession(const HttpResponse *response)
+{
+ if(!response)
+ return;
+
+ for (int i = 0; i < response->headersCount; i++)
+ {
+ if (lstrcmpiA(response->headers[i].szName, "Set-Cookie"))
+ continue;
+
+ std::string cookies = response->headers[i].szValue;
+ size_t start = cookies.find("sessionid=") + 10;
+ size_t end = cookies.substr(start).find(';');
+ std::string sessionId = cookies.substr(start, end - start + 10);
+ setString("SessionID", sessionId.c_str());
+ break;
+ }
+}
+
+void CSteamProto::HandleTokenExpired()
+{
+ // Notify error to user
+ ShowNotification(_T("Steam"), TranslateT("Connection token expired. Please login again."));
+
+ // Delete expired token
+ delSetting("TokenSecret");
+
+ // Set status to offline
+ SetStatus(ID_STATUS_OFFLINE);
+
+ // TODO: Try to login again acutomatically (at least once)
+}
+
+void CSteamProto::OnLoggedOn(const HttpResponse *response)
+{
+ if (!CheckResponse(response))
+ {
+ if (response->resultCode == HTTP_CODE_UNAUTHORIZED)
+ {
+ // Probably expired TokenSecret
+ HandleTokenExpired();
+ return;
+ }
+
+ // Probably timeout or no connection, we can do nothing here
+ ShowNotification(_T("Steam"), TranslateT("Unknown login error."));
+
+ SetStatus(ID_STATUS_OFFLINE);
+ return;
+ }
+
+ JSONROOT root(response->pData);
+
+ JSONNode *node = json_get(root, "error");
+ ptrT error(json_as_string(node));
+ if (mir_tstrcmpi(error, _T("OK")))
+ {
+ // Probably expired TokenSecret
+ HandleTokenExpired();
+ return;
+ }
+
+ node = json_get(root, "umqid");
+ setString("UMQID", ptrA(mir_u2a(ptrT(json_as_string(node)))));
+
+ node = json_get(root, "message");
+ setDword("MessageID", json_as_int(node));
+
+ // load contact list
+ ptrA token(getStringA("TokenSecret"));
+ ptrA steamId(getStringA("SteamID"));
+
+ PushRequest(
+ new GetFriendListRequest(token, steamId),
+ &CSteamProto::OnGotFriendList);
+
+ // start polling thread
+ m_hPollingThread = ForkThreadEx(&CSteamProto::PollingThread, 0, NULL);
+
+ // go to online now
+ ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus = m_iDesiredStatus);
} \ No newline at end of file
diff --git a/protocols/Steam/src/steam_polling.cpp b/protocols/Steam/src/steam_polling.cpp
index 0078009e15..0d278ee946 100644
--- a/protocols/Steam/src/steam_polling.cpp
+++ b/protocols/Steam/src/steam_polling.cpp
@@ -222,19 +222,23 @@ void CSteamProto::PollingThread(void*)
{
// Do nothing as this is not necessarily an error
}
- /*else if (!lstrcmpi(error, _T("Not Logged On"))) // 'else' below will handle this error, we don't need this particular check right now
+ else if (!lstrcmpi(error, _T("Not Logged On"))) // 'else' below will handle this error, we don't need this particular check right now
{
- if (!IsOnline())
- {
- // need to relogin
- debugLog(_T("CSteamProto::PollingThread: not logged on"));
+ // need to relogin
+ debugLog(_T("CSteamProto::PollingThread: Not Logged On"));
- SetStatus(ID_STATUS_OFFLINE);
+ if (Relogin())
+ {
+ // load umqId and messageId again
+ umqId = getStringA("UMQID"); // it's ptrA so we can assign it without fearing a memory leak
+ messageId = getDword("MessageID", 0);
}
-
- // let it jump out of further processing
- errors = errorsLimit;
- }*/
+ else
+ {
+ // let it jump out of further processing
+ errors = errorsLimit;
+ }
+ }
else
{
// something wrong
diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h
index e7a6844153..650675edfd 100644
--- a/protocols/Steam/src/steam_proto.h
+++ b/protocols/Steam/src/steam_proto.h
@@ -106,6 +106,8 @@ protected:
// account
bool IsOnline();
bool IsMe(const char *steamId);
+
+ bool Relogin();
void OnGotRsaKey(const HttpResponse *response);