diff options
author | George Hazan <ghazan@miranda.im> | 2019-03-11 20:14:39 +0300 |
---|---|---|
committer | George Hazan <ghazan@miranda.im> | 2019-03-11 20:14:39 +0300 |
commit | 35b203ece84f45a3ebc51f164e3710e0504df648 (patch) | |
tree | 32008e21776e712dcfe273b1f7107fbf61ecfa21 /protocols/ICQ-WIM/src | |
parent | 657afe8e174e6f0e9a2de1848546db8caa19dad4 (diff) |
fixes #1741 (ICQ10: Invalid Request. statusDetailCode 1015)
Diffstat (limited to 'protocols/ICQ-WIM/src')
-rw-r--r-- | protocols/ICQ-WIM/src/options.cpp | 3 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/proto.cpp | 4 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/proto.h | 6 | ||||
-rw-r--r-- | protocols/ICQ-WIM/src/server.cpp | 30 |
4 files changed, 34 insertions, 9 deletions
diff --git a/protocols/ICQ-WIM/src/options.cpp b/protocols/ICQ-WIM/src/options.cpp index b93772543f..03ecb37ad9 100644 --- a/protocols/ICQ-WIM/src/options.cpp +++ b/protocols/ICQ-WIM/src/options.cpp @@ -143,6 +143,9 @@ void CIcqProto::OnLoginViaPhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pRe mir_urlDecode(m_szAToken.GetBuffer()); setString(DB_KEY_ATOKEN, m_szAToken); + int srvTS = data["hostTime"].as_int(); + m_iTimeShift = (srvTS) ? time(0) - srvTS : 0; + m_szSessionKey = data["sessionKey"].as_mstring(); setString(DB_KEY_SESSIONKEY, m_szSessionKey); diff --git a/protocols/ICQ-WIM/src/proto.cpp b/protocols/ICQ-WIM/src/proto.cpp index 1e6057af82..e48d7b5c89 100644 --- a/protocols/ICQ-WIM/src/proto.cpp +++ b/protocols/ICQ-WIM/src/proto.cpp @@ -403,7 +403,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") << CHAR_PARAM("filename", mir_urlEncode(T2Utf(pTransfer->m_wszShortName))) - << CHAR_PARAM("k", ICQ_APP_ID) << INT_PARAM("size", statbuf.st_size) << INT_PARAM("ts", time(0)); + << CHAR_PARAM("k", ICQ_APP_ID) << INT_PARAM("size", statbuf.st_size) << INT_PARAM("ts", TS()); CalcHash(pReq); pReq->pUserInfo = pTransfer; Push(pReq); @@ -431,7 +431,7 @@ int CIcqProto::SendMsg(MCONTACT hContact, int, const char *pszSrc) } pReq << AIMSID(this) << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("k", ICQ_APP_ID) << CHAR_PARAM("mentions", "") - << CHAR_PARAM("message", pszSrc) << CHAR_PARAM("offlineIM", "true") << CHAR_PARAM("t", szUserid) << INT_PARAM("ts", time(0)); + << 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 96374acfee..40f0475fbf 100644 --- a/protocols/ICQ-WIM/src/proto.h +++ b/protocols/ICQ-WIM/src/proto.h @@ -160,6 +160,8 @@ class CIcqProto : public PROTO<CIcqProto> friend AsyncHttpRequest* operator <<(AsyncHttpRequest*, const AIMSID&); bool m_bOnline, m_bTerminated, m_bFirstBos; + int m_iTimeShift; + MCONTACT CheckOwnMessage(const CMStringA &reqId, const CMStringA &msgId, bool bRemove); void CheckPassword(void); void ConnectionFailed(int iReason, int iErrorCode = 0); @@ -357,6 +359,10 @@ public: void CheckStatus(void); CMStringW GetUserId(MCONTACT); + __forceinline int TS() const + { return time(0) - m_iTimeShift; + } + int __cdecl OnContactMenu(WPARAM, LPARAM); void SetPermitDeny(const CMStringW &userId, bool bAllow); }; diff --git a/protocols/ICQ-WIM/src/server.cpp b/protocols/ICQ-WIM/src/server.cpp index 217760f12c..27e813e940 100644 --- a/protocols/ICQ-WIM/src/server.cpp +++ b/protocols/ICQ-WIM/src/server.cpp @@ -387,9 +387,9 @@ bool CIcqProto::RefreshRobustToken() bool bRet = false; auto *tmp = new AsyncHttpRequest(CONN_RAPI, REQUEST_POST, ICQ_ROBUST_SERVER "/genToken"); - time_t ts = time(0); + time_t ts = TS(); tmp << 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); + << CHAR_PARAM("nonce", CMStringA(FORMAT, "%d-%d", ts, rand() % 10)) << INT_PARAM("ts", TS()); CalcHash(tmp); tmp->flags |= NLHRF_PERSISTENT; tmp->nlc = m_ConnPool[CONN_RAPI].s; @@ -547,7 +547,7 @@ void CIcqProto::StartSession() RpcStringFreeA(&szId); } - int ts = time(0); + int ts = TS(); CMStringA nonce(FORMAT, "%d-2", ts); CMStringA caps(WIM_CAP_UNIQ_REQ_ID "," WIM_CAP_EMOJI "," WIM_CAP_MAIL_NOTIFICATIONS "," WIM_CAP_INTRO_DLG_STATE); if (g_bSecureIM) { @@ -635,6 +635,9 @@ void CIcqProto::OnCheckPassword(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) if (szUin) m_szOwnId = szUin; + int srvTS = data["hostTime"].as_int(); + m_iTimeShift = (srvTS) ? time(0) - srvTS : 0; + StartSession(); } @@ -681,7 +684,7 @@ void CIcqProto::OnFileContinue(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pOld } pReq << AIMSID(this) << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("k", ICQ_APP_ID) << 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", time(0)); + << CHAR_PARAM("offlineIM", "true") << WCHAR_PARAM("parts", wszParts) << WCHAR_PARAM("t", GetUserId(pTransfer->pfts.hContact)) << INT_PARAM("ts", TS()); Push(pReq); } else ProtoBroadcastAck(pTransfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, pTransfer); @@ -691,7 +694,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", time(0)); + pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("client", "icq") << CHAR_PARAM("k", ICQ_APP_ID) << INT_PARAM("ts", TS()); CalcHash(pReq); pReq->m_szUrl.AppendChar('?'); pReq->m_szUrl += pReq->m_szParam; pReq->m_szParam.Empty(); @@ -722,7 +725,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", time(0)); + pReq << CHAR_PARAM("a", m_szAToken) << CHAR_PARAM("client", "icq") << CHAR_PARAM("k", ICQ_APP_ID) << INT_PARAM("ts", TS()); CalcHash(pReq); pReq->m_szUrl.AppendChar('?'); pReq->m_szUrl += pReq->m_szParam; pReq->m_szParam.Empty(); @@ -764,7 +767,7 @@ void CIcqProto::OnGetUserInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) ProtoBroadcastAck(pReq->hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, nullptr); } -void CIcqProto::OnStartSession(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CIcqProto::OnStartSession(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) { JsonReply root(pReply); switch (root.error()) { @@ -780,6 +783,16 @@ void CIcqProto::OnStartSession(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) else ConnectionFailed(LOGINERR_WRONGPASSWORD, root.error()); return; + case 400: + if (root.detail() == 1015 && m_iTimeShift == 0) { // wrong timestamp + JSONNode &data = root.data(); + int srvTS = data["ts"].as_int(); + m_iTimeShift = (srvTS) ? time(0) - srvTS : 0; + StartSession(); + return; + } + __fallthrough; + default: ConnectionFailed(LOGINERR_WRONGPROTOCOL, root.error()); return; @@ -789,6 +802,9 @@ void CIcqProto::OnStartSession(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) m_fetchBaseURL = data["fetchBaseURL"].as_mstring(); m_aimsid = data["aimsid"].as_mstring(); + int srvTS = data["ts"].as_int(); + m_iTimeShift = (srvTS) ? time(0) - srvTS : 0; + OnLoggedIn(); for (auto &it : data["events"]) |