diff options
author | aunsane <aunsane@gmail.com> | 2017-12-28 21:21:10 +0300 |
---|---|---|
committer | aunsane <aunsane@gmail.com> | 2017-12-28 21:21:28 +0300 |
commit | 0156ed41dceeef48f070adf67f14d4ba4c4f6d61 (patch) | |
tree | d0e1dca4c2c9c3c056ae9cb69dde10ea59316481 /protocols/Steam/src/steam_login.cpp | |
parent | f0075f2b956969f29acd3bc9289c8a5f78faddad (diff) |
Steam: refactoring
- reworking http requests
- added ability to get game name by appid
- another attempt to fix #633
- minor refactoring
Diffstat (limited to 'protocols/Steam/src/steam_login.cpp')
-rw-r--r-- | protocols/Steam/src/steam_login.cpp | 250 |
1 files changed, 148 insertions, 102 deletions
diff --git a/protocols/Steam/src/steam_login.cpp b/protocols/Steam/src/steam_login.cpp index d91acaba6d..3375a128d5 100644 --- a/protocols/Steam/src/steam_login.cpp +++ b/protocols/Steam/src/steam_login.cpp @@ -14,6 +14,31 @@ bool CSteamProto::IsMe(const char *steamId) return false; } +void CSteamProto::Login() +{ + ptrA token(getStringA("TokenSecret")); + ptrA sessionId(getStringA("SessionID")); + if (mir_strlen(token) > 0 && mir_strlen(sessionId) > 0) + { + PushRequest( + new LogonRequest(token), + &CSteamProto::OnLoggedOn); + } + else + { + T2Utf username(getWStringA("Username")); + if (username == NULL) + { + SetStatus(ID_STATUS_OFFLINE); + return; + } + + PushRequest( + new GetRsaKeyRequest(username), + &CSteamProto::OnGotRsaKey); + } +} + bool CSteamProto::Relogin() { ptrA token(getStringA("TokenSecret")); @@ -21,53 +46,66 @@ bool CSteamProto::Relogin() return false; HttpRequest *request = new LogonRequest(token); - HttpResponse *response = request->Send(m_hNetlibUser); + HttpResponse *response = SendRequest(request); bool success = false; - if (CheckResponse(response)) + if (response) { - JSONROOT root(response->pData); - if (root != nullptr) { - JSONNode *node = json_get(root, "error"); - - ptrW error(json_as_string(node)); - if (!mir_wstrcmpi(error, L"OK")) + JSONNode root = JSONNode::parse(response->Content); + if (root.isnull()) { + json_string error = root["error"].as_string(); + if (!mir_strcmpi(error.c_str(), "OK")) { - node = json_get(root, "umqid"); - setString("UMQID", ptrA(mir_u2a(ptrW(json_as_string(node))))); + json_string umqId = root["umqid"].as_string(); + setString("UMQID", umqId.c_str()); - node = json_get(root, "message"); - setDword("MessageID", json_as_int(node)); + long messageId = root["message"].as_int(); + setDword("MessageID", messageId); success = true; } } } - delete request; delete response; return success; } -void CSteamProto::OnGotRsaKey(const HttpResponse *response) +void CSteamProto::LogOut() { - if (!CheckResponse(response)) - return; + isTerminated = true; + if (hRequestQueueThread) + SetEvent(hRequestsQueueEvent); - // load rsa key parts - JSONNode root = JSONNode::parse(response->pData); - if (!root) + ptrA token(getStringA("TokenSecret")); + if (mir_strlen(token) > 0) + { + ptrA umqid(getStringA("UMQID")); + SendRequest(new LogoffRequest(token, umqid)); + } +} + +void CSteamProto::OnGotRsaKey(const JSONNode &root, void*) +{ + if (root.isnull()) + { + SetStatus(ID_STATUS_OFFLINE); return; + } if (!root["success"].as_bool()) + { + SetStatus(ID_STATUS_OFFLINE); return; + } - std::string modulus = root["publickey_mod"].as_string(); - std::string exp = root["publickey_exp"].as_string(); + // load rsa key parts + json_string modulus = root["publickey_mod"].as_string(); + json_string exp = root["publickey_exp"].as_string(); DWORD exponent = strtoul(exp.c_str(), nullptr, 16); // default "010001" = 0x10001 - std::string timestamp = root["timestamp"].as_string(); + json_string timestamp = root["timestamp"].as_string(); // encrcrypt password ptrA base64RsaEncryptedPassword; @@ -77,14 +115,16 @@ void CSteamProto::OnGotRsaKey(const HttpResponse *response) DWORD encryptedSize = 0; if ((error = RsaEncrypt(modulus.c_str(), exponent, szPassword, nullptr, encryptedSize)) != 0) { - debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error); + debugLogA(__FUNCTION__ ": encryption error (%lu)", error); + SetStatus(ID_STATUS_OFFLINE); return; } BYTE *encryptedPassword = (BYTE*)mir_calloc(encryptedSize); if ((error = RsaEncrypt(modulus.c_str(), exponent, szPassword, encryptedPassword, encryptedSize)) != 0) { - debugLogA("CSteamProto::OnGotRsaKey: encryption error (%lu)", error); + debugLogA(__FUNCTION__ ": encryption error (%lu)", error); + SetStatus(ID_STATUS_OFFLINE); return; } @@ -112,16 +152,43 @@ void CSteamProto::OnGotRsaKey(const HttpResponse *response) &CSteamProto::OnAuthorization); } -void CSteamProto::OnAuthorization(const HttpResponse *response) +void CSteamProto::OnGotCaptcha(const HttpResponse &response, void *arg) +{ + ptrA captchaId((char*)arg); + + if (!response.IsSuccess()) + { + debugLogA(__FUNCTION__ ": failed to get captcha"); + return; + } + + CSteamCaptchaDialog captchaDialog(this, (BYTE*)response.Content.GetData(), response.Content.GetSize()); + if (captchaDialog.DoModal() != DIALOG_RESULT_OK) + { + DeleteAuthSettings(); + SetStatus(ID_STATUS_OFFLINE); + return; + } + + setString("CaptchaId", captchaId); + setString("CaptchaText", captchaDialog.GetCaptchaText()); + + T2Utf username(getWStringA("Username")); + PushRequest( + new GetRsaKeyRequest(username), + &CSteamProto::OnGotRsaKey); +} + +void CSteamProto::OnAuthorization(const HttpResponse &response, void*) { - if (!CheckResponse(response)) + if (!response) { SetStatus(ID_STATUS_OFFLINE); return; } - JSONNode root = JSONNode::parse(response->pData); - if (!root) + JSONNode root = JSONNode::parse(response.Content); + if (root.isnull()) { SetStatus(ID_STATUS_OFFLINE); return; @@ -145,13 +212,11 @@ void CSteamProto::DeleteAuthSettings() delSetting("CaptchaText"); } -void CSteamProto::OnAuthorizationError(const JSONNode &node) +void CSteamProto::OnAuthorizationError(const JSONNode &root) { - std::string message = node["message"].as_string(); - ptrW messageT(mir_utf8decodeW(message.c_str())); - debugLogA("CSteamProto::OnAuthorizationError: %s", message.c_str()); - - if (!mir_wstrcmpi(messageT, L"Incorrect login.")) + CMStringW message = root["message"].as_mstring(); + debugLogA(__FUNCTION__ ": %s", _T2A(message.GetBuffer())); + if (!mir_wstrcmpi(message, L"Incorrect login.")) { // We can't continue with incorrect login/password DeleteAuthSettings(); @@ -161,9 +226,9 @@ void CSteamProto::OnAuthorizationError(const JSONNode &node) T2Utf username(getWStringA("Username")); - if (node["requires_twofactor"].as_bool()) + if (root["requires_twofactor"].as_bool()) { - debugLogA("CSteamProto::OnAuthorizationError: requires twofactor"); + debugLogA(__FUNCTION__ ": requires twofactor"); CSteamTwoFactorDialog twoFactorDialog(this); if (twoFactorDialog.DoModal() != DIALOG_RESULT_OK) @@ -181,21 +246,20 @@ void CSteamProto::OnAuthorizationError(const JSONNode &node) return; } - if (node["clear_password_field"].as_bool()) + if (root["clear_password_field"].as_bool()) { - debugLogA("CSteamProto::OnAuthorizationError: clear password field"); - - // Probably wrong password entered? + debugLogA(__FUNCTION__ ": clear password field"); + // describes if the password field was cleared. This can also be true if the twofactor code was wrong DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); return; } - if (node["emailauth_needed"].as_bool()) + if (root["emailauth_needed"].as_bool()) { - debugLogA("CSteamProto::OnAuthorizationError: emailauth needed"); + debugLogA(__FUNCTION__ ": emailauth needed"); - std::string guardId = node["emailsteamid"].as_string(); + std::string guardId = root["emailsteamid"].as_string(); ptrA oldGuardId(getStringA("GuardId")); if (mir_strcmp(guardId.c_str(), oldGuardId) == 0) { @@ -207,7 +271,7 @@ void CSteamProto::OnAuthorizationError(const JSONNode &node) return; } - std::string domain = node["emaildomain"].as_string(); + std::string domain = root["emaildomain"].as_string(); // Make absolute link if (domain.find("://") == std::string::npos) @@ -230,70 +294,54 @@ void CSteamProto::OnAuthorizationError(const JSONNode &node) return; } - if (node["captcha_needed"].as_bool()) + if (root["captcha_needed"].as_bool()) { - debugLogA("CSteamProto::OnAuthorizationError: captcha needed"); - - 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) - { - DeleteAuthSettings(); - SetStatus(ID_STATUS_OFFLINE); - return; - } - - setString("CaptchaId", captchaId.c_str()); - setString("CaptchaText", captchaDialog.GetCaptchaText()); - + debugLogA(__FUNCTION__ ": captcha needed"); + std::string captchaId = root["captcha_gid"].as_string(); PushRequest( - new GetRsaKeyRequest(username), - &CSteamProto::OnGotRsaKey); + new GetCaptchaRequest(captchaId.c_str()), + &CSteamProto::OnGotCaptcha, + mir_strdup(captchaId.c_str())); return; } DeleteAuthSettings(); SetStatus(ID_STATUS_OFFLINE); + ShowNotification(L"Steam", message); } -void CSteamProto::OnAuthorizationSuccess(const JSONNode &node) +void CSteamProto::OnAuthorizationSuccess(const JSONNode &root) { DeleteAuthSettings(); - if (!node["login_complete"].as_bool()) + if (!root["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) + std::string oauth = root["oauth"].as_string(); + JSONNode node = JSONNode::parse(oauth.c_str()); + if (node.isnull()) { SetStatus(ID_STATUS_OFFLINE); return; } - std::string steamId = root["steamid"].as_string(); + std::string steamId = node["steamid"].as_string(); setString("SteamID", steamId.c_str()); - std::string token = root["oauth_token"].as_string(); + std::string token = node["oauth_token"].as_string(); setString("TokenSecret", token.c_str()); - std::string cookie = root["webcookie"].as_string(); + std::string cookie = node["webcookie"].as_string(); - PushRequest( + SendRequest( new GetSessionRequest(token.c_str(), steamId.c_str(), cookie.c_str()), &CSteamProto::OnGotSession); // We need to load homepage to get sessionid cookie - PushRequest( + SendRequest( new GetSessionRequest2(), &CSteamProto::OnGotSession); @@ -302,17 +350,17 @@ void CSteamProto::OnAuthorizationSuccess(const JSONNode &node) &CSteamProto::OnLoggedOn); } -void CSteamProto::OnGotSession(const HttpResponse *response) +void CSteamProto::OnGotSession(const HttpResponse &response, void*) { if (!response) return; - for (int i = 0; i < response->headersCount; i++) + for (size_t i = 0; i < response.Headers.GetSize(); i++) { - if (lstrcmpiA(response->headers[i].szName, "Set-Cookie")) + if (lstrcmpiA(response.Headers[i]->szName, "Set-Cookie")) continue; - std::string cookies = response->headers[i].szValue; + 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); @@ -329,8 +377,8 @@ void CSteamProto::HandleTokenExpired() // Try to relogin automatically (but only once) if (isLoginAgain) { // Notify error to user + debugLogA(__FUNCTION__ ": cannot obtain connection token"); ShowNotification(L"Steam", TranslateT("Cannot obtain connection token.")); - // Just go offline; it also resets the isLoginAgain to false SetStatus(ID_STATUS_OFFLINE); } @@ -350,28 +398,26 @@ void CSteamProto::HandleTokenExpired() } } -void CSteamProto::OnLoggedOn(const HttpResponse *response) +void CSteamProto::OnLoggedOn(const HttpResponse &response, void*) { - if (!CheckResponse(response)) + if (!response.IsSuccess()) { - if (response && response->resultCode == HTTP_CODE_UNAUTHORIZED) - { - // Probably expired TokenSecret - HandleTokenExpired(); - return; - } - // Probably timeout or no connection, we can do nothing here + debugLogA(__FUNCTION__ ": unknown login error"); ShowNotification(L"Steam", TranslateT("Unknown login error.")); - SetStatus(ID_STATUS_OFFLINE); return; } - JSONROOT root(response->pData); + if (response.GetStatusCode() == HTTP_CODE_UNAUTHORIZED) + { + // Probably expired TokenSecret + HandleTokenExpired(); + return; + } - JSONNode *node = json_get(root, "error"); - ptrW error(json_as_string(node)); + JSONNode root = JSONNode::parse(response.Content); + CMStringW error = root["error"].as_mstring(); if (mir_wstrcmpi(error, L"OK")) { // Probably expired TokenSecret @@ -379,15 +425,15 @@ void CSteamProto::OnLoggedOn(const HttpResponse *response) return; } - node = json_get(root, "umqid"); - setString("UMQID", ptrA(mir_u2a(ptrW(json_as_string(node))))); + json_string umqId = root["umqid"].as_string(); + setString("UMQID", umqId.c_str()); - node = json_get(root, "message"); - setDword("MessageID", json_as_int(node)); + long messageId = root["umqid"].as_int(); + setDword("MessageID", messageId); - if (m_lastMessageTS <= 0) { - node = json_get(root, "utc_timestamp"); - time_t timestamp = _wtoi64(ptrW(json_as_string(node))); + if (m_lastMessageTS <= 0) + { + time_t timestamp = _wtoi64(root["utc_timestamp"].as_mstring()); setDword("LastMessageTS", timestamp); } |