diff options
author | George Hazan <ghazan@miranda.im> | 2021-08-10 11:09:20 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2021-08-10 11:09:20 +0300 |
commit | 5bd2d22ff78409953ee036df93f3eb09b36ef002 (patch) | |
tree | 15b6a1a94bc14439d18bb617ef600898f2d6686b /protocols | |
parent | 8cef81c096966af5775861220e67432648a29a7e (diff) |
ICQ:
- fixes wrong online status detection when lastSeen == 0;
- fixes correct APP_ID sending;
- fixes error handling inside RAPI token generation
Diffstat (limited to 'protocols')
-rw-r--r-- | protocols/ICQ-WIM/src/http.cpp | 4 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/options.cpp | 6 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/poll.cpp | 6 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/proto.cpp | 8 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/proto.h | 7 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/server.cpp | 39 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/utils.cpp | 13 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/version.h | 2 |
8 files changed, 48 insertions, 37 deletions
diff --git a/protocols/ICQ-WIM/src/http.cpp b/protocols/ICQ-WIM/src/http.cpp index 66509d6d2b..e3fc4cd62c 100644 --- a/protocols/ICQ-WIM/src/http.cpp +++ b/protocols/ICQ-WIM/src/http.cpp @@ -162,7 +162,7 @@ bool CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) pReq->AddHeader("Content-Type", "application/json"); if (m_szRToken.IsEmpty()) { - if (!RefreshRobustToken()) { + if (!RefreshRobustToken(pReq)) { delete pReq; return false; } @@ -203,7 +203,7 @@ bool CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) m_szRToken.Empty(); // if token refresh succeeded, replace it in the query and push request back - if (!RefreshRobustToken()) { + if (!RefreshRobustToken(pReq)) { delete pReq; return false; } diff --git a/protocols/ICQ-WIM/src/options.cpp b/protocols/ICQ-WIM/src/options.cpp index 4775fed3f3..fae31b9ea3 100644 --- a/protocols/ICQ-WIM/src/options.cpp +++ b/protocols/ICQ-WIM/src/options.cpp @@ -99,7 +99,7 @@ struct CIcqRegistrationDlg : public CIcqDlgBase bool OnApply() override { auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, "https://www.icq.com/smsreg/loginWithPhoneNumber.php", &CIcqProto::OnLoginViaPhone); - pReq << CHAR_PARAM("locale", "en") << CHAR_PARAM("msisdn", szMsisdn) << CHAR_PARAM("trans_id", szTrans) << CHAR_PARAM("k", ICQ_APP_ID) + pReq << CHAR_PARAM("locale", "en") << CHAR_PARAM("msisdn", szMsisdn) << CHAR_PARAM("trans_id", szTrans) << CHAR_PARAM("k", m_proto->appId()) << CHAR_PARAM("r", pReq->m_reqId) << CHAR_PARAM("f", "json") << WCHAR_PARAM("sms_code", ptrW(edtCode.GetText())) << INT_PARAM("create_account", 1); pReq->pUserInfo = this; @@ -127,7 +127,7 @@ struct CIcqRegistrationDlg : public CIcqDlgBase { auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, "https://www.icq.com/smsreg/requestPhoneValidation.php", &CIcqProto::OnValidateSms); pReq << CHAR_PARAM("locale", "en") << CHAR_PARAM("msisdn", szMsisdn) << CHAR_PARAM("r", pReq->m_reqId) - << CHAR_PARAM("smsFormatType", "human") << CHAR_PARAM("k", ICQ_APP_ID); + << CHAR_PARAM("smsFormatType", "human") << CHAR_PARAM("k", m_proto->appId()); pReq->pUserInfo = this; m_proto->Push(pReq); } @@ -154,7 +154,7 @@ void CIcqProto::OnCheckPhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) auto *pNew = new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, "https://www.icq.com/smsreg/normalizePhoneNumber.php", &CIcqProto::OnNormalizePhone); pNew << CHAR_PARAM("countryCode", szPrefix) << CHAR_PARAM("phoneNumber", szPhoneNumber.c_str() + szPrefix.GetLength()) - << CHAR_PARAM("k", ICQ_APP_ID) << CHAR_PARAM("r", pReq->m_reqId); + << CHAR_PARAM("k", appId()) << CHAR_PARAM("r", pReq->m_reqId); pNew->pUserInfo = pDlg; Push(pNew); } diff --git a/protocols/ICQ-WIM/src/poll.cpp b/protocols/ICQ-WIM/src/poll.cpp index 918782e5cc..a7e59c3744 100644 --- a/protocols/ICQ-WIM/src/poll.cpp +++ b/protocols/ICQ-WIM/src/poll.cpp @@ -324,11 +324,7 @@ void CIcqProto::ProcessPresence(const JSONNode &ev) if (pCache == nullptr) return; - int iNewStatus = StatusFromString(ev["state"].as_mstring()); - - int iLastSeen = ev["lastseen"].as_int(); - if (iLastSeen == 0) - iNewStatus = ID_STATUS_ONLINE; + int iNewStatus = StatusFromPresence(ev, pCache->m_hContact); // major crutch dedicated to the official client behaviour to go offline // when its window gets closed. we change the status of a contact to the diff --git a/protocols/ICQ-WIM/src/proto.cpp b/protocols/ICQ-WIM/src/proto.cpp index 6504dba8cb..a228835cf3 100644 --- a/protocols/ICQ-WIM/src/proto.cpp +++ b/protocols/ICQ-WIM/src/proto.cpp @@ -57,8 +57,8 @@ CIcqProto::CIcqProto(const char *aProtoName, const wchar_t *aUserName) : m_bErrorPopups(this, "ShowErrorPopups", true), m_bLaunchMailbox(this, "LaunchMailbox", true) { - db_set_resident(m_szModuleName, "IdleTS"); - db_set_resident(m_szModuleName, "OnlineTS"); + db_set_resident(m_szModuleName, DB_KEY_IDLE); + db_set_resident(m_szModuleName, DB_KEY_ONLINETS); m_isMra = !stricmp(Proto_GetAccount(m_szModuleName)->szProtoName, "MRA"); @@ -562,7 +562,7 @@ HANDLE CIcqProto::SendFile(MCONTACT hContact, const wchar_t *szDescription, wcha auto *pReq = new AsyncHttpRequest(CONN_NONE, REQUEST_GET, "https://files.icq.com/files/init", &CIcqProto::OnFileInit); pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("client", "icq") << CHAR_PARAM("f", "json") << WCHAR_PARAM("filename", pTransfer->m_wszShortName) - << CHAR_PARAM("k", ICQ_APP_ID) << INT_PARAM("size", statbuf.st_size) << INT_PARAM("ts", TS()); + << CHAR_PARAM("k", appId()) << INT_PARAM("size", statbuf.st_size) << INT_PARAM("ts", TS()); CalcHash(pReq); pReq->pUserInfo = pTransfer; Push(pReq); @@ -589,7 +589,7 @@ int CIcqProto::SendMsg(MCONTACT hContact, int, const char *pszSrc) m_arOwnIds.insert(pOwn); } - pReq << AIMSID(this) << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("k", ICQ_APP_ID) << CHAR_PARAM("mentions", "") + pReq << AIMSID(this) << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("k", appId()) << CHAR_PARAM("mentions", "") << CHAR_PARAM("message", pszSrc) << CHAR_PARAM("offlineIM", "true") << CHAR_PARAM("t", szUserid) << INT_PARAM("ts", TS()); Push(pReq); return id; diff --git a/protocols/ICQ-WIM/src/proto.h b/protocols/ICQ-WIM/src/proto.h index c6f0ff9502..1326120f80 100644 --- a/protocols/ICQ-WIM/src/proto.h +++ b/protocols/ICQ-WIM/src/proto.h @@ -274,6 +274,7 @@ class CIcqProto : public PROTO<CIcqProto> void Json2string(MCONTACT, const JSONNode&, const char *szJson, const char *szSetting); MCONTACT ParseBuddyInfo(const JSONNode &buddy, MCONTACT hContact = INVALID_CONTACT_ID); void ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNode &msg, bool bCreateRead, bool bLocalTime); + int StatusFromPresence(const JSONNode &presence, MCONTACT hContact); void OnLoggedIn(void); void OnLoggedOut(void); @@ -376,7 +377,7 @@ class CIcqProto : public PROTO<CIcqProto> bool ExecuteRequest(AsyncHttpRequest*); bool IsQueueEmpty(); void Push(MHttpRequest*); - bool RefreshRobustToken(); + bool RefreshRobustToken(AsyncHttpRequest *pReq); //////////////////////////////////////////////////////////////////////////////////////// // cache @@ -474,6 +475,10 @@ public: { return time(0) - m_iTimeShift; } + __forceinline const char *appId() const + { return (m_isMra) ? MRA_APP_ID : ICQ_APP_ID; + } + void SetPermitDeny(const CMStringW &userId, bool bAllow); }; diff --git a/protocols/ICQ-WIM/src/server.cpp b/protocols/ICQ-WIM/src/server.cpp index 5e08e895e7..cb0ed62849 100644 --- a/protocols/ICQ-WIM/src/server.cpp +++ b/protocols/ICQ-WIM/src/server.cpp @@ -100,7 +100,7 @@ void CIcqProto::CheckPassword() } else { auto *pReq = new AsyncHttpRequest(CONN_MAIN, REQUEST_POST, "https://api.login.icq.net/auth/clientLogin", &CIcqProto::OnCheckPassword); - pReq << CHAR_PARAM("clientName", "Miranda NG") << CHAR_PARAM("clientVersion", mirVer) << CHAR_PARAM("devId", ICQ_APP_ID) + pReq << CHAR_PARAM("clientName", "Miranda NG") << CHAR_PARAM("clientVersion", mirVer) << CHAR_PARAM("devId", appId()) << CHAR_PARAM("f", "json") << CHAR_PARAM("tokenType", "longTerm") << WCHAR_PARAM("s", m_szOwnId) << CHAR_PARAM("pwd", m_szPassword); #ifndef _DEBUG pReq->flags |= NLHRF_NODUMPSEND; @@ -348,9 +348,6 @@ MCONTACT CIcqProto::ParseBuddyInfo(const JSONNode &buddy, MCONTACT hContact) } else delSetting(hContact, "MirVer"); - CMStringW str(buddy["state"].as_mstring()); - WORD wStatus = StatusFromString(str); - const JSONNode &var = buddy["friendly"]; if (var) setWString(hContact, "Nick", var.as_mstring()); @@ -365,12 +362,7 @@ MCONTACT CIcqProto::ParseBuddyInfo(const JSONNode &buddy, MCONTACT hContact) Json2string(hContact, buddy, "phoneNumber", "Phone"); Json2string(hContact, buddy, "workNumber", "CompanyPhone"); - // zero here means that a contact is currently online - int lastSeen = buddy["lastseen"].as_int(); - setDword(hContact, DB_KEY_LASTSEEN, lastSeen ? lastSeen : time(0)); - if (lastSeen == 0) - wStatus = ID_STATUS_ONLINE; - setDword(hContact, "Status", wStatus); + setDword(hContact, "Status", StatusFromPresence(buddy, hContact)); Json2int(hContact, buddy, "official", "Official"); Json2int(hContact, buddy, "onlineTime", DB_KEY_ONLINETS); @@ -401,7 +393,7 @@ MCONTACT CIcqProto::ParseBuddyInfo(const JSONNode &buddy, MCONTACT hContact) } } - str = profile["gender"].as_mstring(); + CMStringW str = profile["gender"].as_mstring(); if (!str.IsEmpty()) { if (str == "male") setByte(hContact, "Gender", 'M'); @@ -416,7 +408,7 @@ MCONTACT CIcqProto::ParseBuddyInfo(const JSONNode &buddy, MCONTACT hContact) } } - str = buddy["statusMsg"].as_mstring(); + CMStringW str = buddy["statusMsg"].as_mstring(); if (str.IsEmpty()) db_unset(hContact, "CList", "StatusMsg"); else @@ -558,7 +550,7 @@ void CIcqProto::ParseMessage(MCONTACT hContact, __int64 &lastMsgId, const JSONNo ProtoChainRecvMsg(hContact, &pre); } -bool CIcqProto::RefreshRobustToken() +bool CIcqProto::RefreshRobustToken(AsyncHttpRequest *pOrigReq) { if (!m_szRToken.IsEmpty()) return true; @@ -569,13 +561,18 @@ bool CIcqProto::RefreshRobustToken() #endif int ts = TS(); - pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("k", ICQ_APP_ID) << CHAR_PARAM("nonce", CMStringA(FORMAT, "%d-%d", ts, rand() % 10)) << INT_PARAM("ts", ts); + pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("k", appId()) << CHAR_PARAM("nonce", CMStringA(FORMAT, "%d-%d", ts, rand() % 10)) << INT_PARAM("ts", ts); CalcHash(pReq); CMStringA szAgent(FORMAT, "%S Mail.ru Windows ICQ (version 10.0.1999)", (wchar_t*)m_szOwnId); pReq->AddHeader("User-Agent", szAgent); - if (!ExecuteRequest(pReq)) + if (!ExecuteRequest(pReq)) { +LBL_Error: + (this->*(pOrigReq->m_pFunc))(nullptr, pOrigReq); return false; + } + if (m_szRToken.IsEmpty()) + goto LBL_Error; // now add this token bool bRet = false; @@ -583,11 +580,11 @@ bool CIcqProto::RefreshRobustToken() #ifndef _DEBUG pReq->flags |= NLHRF_NODUMPSEND; #endif - pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("f", "json") << CHAR_PARAM("k", ICQ_APP_ID) << INT_PARAM("ts", ts) + pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("f", "json") << CHAR_PARAM("k", appId()) << INT_PARAM("ts", ts) << CHAR_PARAM("client", "icq") << CHAR_PARAM("reqId", pReq->m_reqId) << CHAR_PARAM("authToken", m_szRToken); pReq->pUserInfo = &bRet; if (!ExecuteRequest(pReq)) - return false; + goto LBL_Error; return bRet; } @@ -735,7 +732,7 @@ void CIcqProto::StartSession() << INT_PARAM("buildNumber", __BUILD_NUM) << CHAR_PARAM("deviceId", szDeviceId) << CHAR_PARAM("events", EVENTS) << CHAR_PARAM("f", "json") << CHAR_PARAM("imf", "plain") << CHAR_PARAM("inactiveView", "offline") << CHAR_PARAM("includePresenceFields", FIELDS) << CHAR_PARAM("invisible", "false") - << CHAR_PARAM("k", ICQ_APP_ID) << INT_PARAM("mobile", 0) << CHAR_PARAM("nonce", nonce) << CHAR_PARAM("r", pReq->m_reqId) + << CHAR_PARAM("k", appId()) << INT_PARAM("mobile", 0) << CHAR_PARAM("nonce", nonce) << CHAR_PARAM("r", pReq->m_reqId) << INT_PARAM("rawMsg", 0) << INT_PARAM("sessionTimeout", 7776000) << INT_PARAM("ts", ts) << CHAR_PARAM("view", "online"); CalcHash(pReq); @@ -877,7 +874,7 @@ void CIcqProto::OnFileContinue(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pOld m_arOwnIds.insert(pOwn); } - pReq << AIMSID(this) << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("k", ICQ_APP_ID) << CHAR_PARAM("mentions", "") << WCHAR_PARAM("message", wszUrl) + pReq << AIMSID(this) << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("k", appId()) << CHAR_PARAM("mentions", "") << WCHAR_PARAM("message", wszUrl) << CHAR_PARAM("offlineIM", "true") << WCHAR_PARAM("parts", wszParts) << WCHAR_PARAM("t", GetUserId(pTransfer->pfts.hContact)) << INT_PARAM("ts", TS()); Push(pReq); @@ -889,7 +886,7 @@ void CIcqProto::OnFileContinue(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pOld // else send the next portion auto *pReq = new AsyncHttpRequest(CONN_NONE, REQUEST_POST, pTransfer->m_szHost, &CIcqProto::OnFileContinue); - pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("client", "icq") << CHAR_PARAM("k", ICQ_APP_ID) << INT_PARAM("ts", TS()); + pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("client", "icq") << CHAR_PARAM("k", appId()) << INT_PARAM("ts", TS()); CalcHash(pReq); pReq->m_szUrl.AppendChar('?'); pReq->m_szUrl += pReq->m_szParam; pReq->m_szParam.Empty(); @@ -920,7 +917,7 @@ void CIcqProto::OnFileInit(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pOld) pTransfer->m_szHost = L"https://" + wszHost + wszUrl; auto *pReq = new AsyncHttpRequest(CONN_NONE, REQUEST_POST, pTransfer->m_szHost, &CIcqProto::OnFileContinue); - pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("client", "icq") << CHAR_PARAM("k", ICQ_APP_ID) << INT_PARAM("ts", TS()); + pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("client", "icq") << CHAR_PARAM("k", appId()) << INT_PARAM("ts", TS()); CalcHash(pReq); pReq->m_szUrl.AppendChar('?'); pReq->m_szUrl += pReq->m_szParam; pReq->m_szParam.Empty(); diff --git a/protocols/ICQ-WIM/src/utils.cpp b/protocols/ICQ-WIM/src/utils.cpp index b8d380f05d..1204cbfb53 100644 --- a/protocols/ICQ-WIM/src/utils.cpp +++ b/protocols/ICQ-WIM/src/utils.cpp @@ -286,6 +286,19 @@ int StatusFromString(const CMStringW &wszStatus) return ID_STATUS_OFFLINE; } +int CIcqProto::StatusFromPresence(const JSONNode &presence, MCONTACT hContact) +{ + int iStatus = StatusFromString(presence["state"].as_mstring()); + + int iLastSeen = presence["lastseen"].as_int(); + if (iLastSeen != 0) + setDword(hContact, DB_KEY_LASTSEEN, iLastSeen); + else if (getDword(hContact, DB_KEY_ONLINETS)) + iStatus = ID_STATUS_ONLINE; + + return iStatus; +} + ///////////////////////////////////////////////////////////////////////////////////////// __int64 CIcqProto::getId(MCONTACT hContact, const char *szSetting) diff --git a/protocols/ICQ-WIM/src/version.h b/protocols/ICQ-WIM/src/version.h index 77882b494a..35a2dc3d6d 100644 --- a/protocols/ICQ-WIM/src/version.h +++ b/protocols/ICQ-WIM/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 96 #define __RELEASE_NUM 1 -#define __BUILD_NUM 3 +#define __BUILD_NUM 4 #include <stdver.h> |