diff options
Diffstat (limited to 'protocols/Icq10/src/http.cpp')
-rw-r--r-- | protocols/Icq10/src/http.cpp | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/protocols/Icq10/src/http.cpp b/protocols/Icq10/src/http.cpp new file mode 100644 index 0000000000..a65f0bc3c6 --- /dev/null +++ b/protocols/Icq10/src/http.cpp @@ -0,0 +1,164 @@ +// ----------------------------------------------------------------------------- +// ICQ plugin for Miranda NG +// ----------------------------------------------------------------------------- +// Copyright © 2018 Miranda NG team +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// ----------------------------------------------------------------------------- + +#include "stdafx.h" + +#pragma comment(lib, "Rpcrt4.lib") + +void __cdecl CIcqProto::ServerThread(void*) +{ + m_hAPIConnection = nullptr; + m_bTerminated = false; + + int uin = getDword("UIN"); + ptrA szPassword(getStringA("Password")); + if (uin == 0 || szPassword == nullptr) { + debugLogA("Thread ended, UIN/password are not configured"); + ConnectionFailed(LOGINERR_BADUSERID); + return; + } + + debugLogA("CIcqProto::WorkerThread: %s", "entering"); + { + char mirVer[100]; + Miranda_GetVersionText(mirVer, _countof(mirVer)); + + auto *pReq = new AsyncHttpRequest(REQUEST_POST, "https://api.login.icq.net/auth/clientLogin", &CIcqProto::OnCheckPassword); + pReq << CHAR_PARAM("clientName", "Miranda NG") << CHAR_PARAM("clientVersion", mirVer) << CHAR_PARAM("devId", "ic1nmMjqg7Yu-0hL") + << CHAR_PARAM("f", "json") << CHAR_PARAM("tokenType", "longTerm") << INT_PARAM("s", uin) << CHAR_PARAM("pwd", szPassword); + pReq->flags |= NLHRF_NODUMPSEND; + Push(pReq); + } + + while (true) { + WaitForSingleObject(m_evRequestsQueue, 1000); + if (m_bTerminated) + break; + + AsyncHttpRequest *pReq; + bool need_sleep = false; + while (true) { + { + mir_cslock lck(m_csHttpQueue); + if (m_arHttpQueue.getCount() == 0) + break; + + pReq = m_arHttpQueue[0]; + m_arHttpQueue.remove(0); + need_sleep = (m_arHttpQueue.getCount() > 1); + } + if (m_bTerminated) + break; + ExecuteRequest(pReq); + if (need_sleep) { + Sleep(330); + debugLogA("CIcqProto::WorkerThread: %s", "need to sleep"); + } + } + } + + m_hWorkerThread = nullptr; + if (m_hAPIConnection) { + Netlib_CloseHandle(m_hAPIConnection); + m_hAPIConnection = nullptr; + } + + debugLogA("CIcqProto::WorkerThread: %s", "leaving"); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +AsyncHttpRequest::AsyncHttpRequest(int iType, const char *szUrl, MTHttpRequestHandler pFunc) +{ + flags = NLHRF_HTTP11 | NLHRF_SSL; + requestType = iType; + m_szUrl = szUrl; + m_pFunc = pFunc; + UuidCreate(&m_reqId); + + if (iType == REQUEST_POST) { + AddHeader("Content-Type", "application/x-www-form-urlencoded"); + + dataLength = m_szParam.GetLength(); + pData = m_szParam.Detach(); + } +} + +void CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) +{ + CMStringA str; + + pReq->szUrl = pReq->m_szUrl.GetBuffer(); + if (!pReq->m_szParam.IsEmpty()) { + if (pReq->requestType == REQUEST_GET) { + str.Format("%s?%s", pReq->m_szUrl.c_str(), pReq->m_szParam.c_str()); + pReq->szUrl = str.GetBuffer(); + } + else { + pReq->pData = mir_strdup(pReq->m_szParam); + pReq->dataLength = pReq->m_szParam.GetLength(); + } + } + + if (pReq->m_bMainSite) { + pReq->flags |= NLHRF_PERSISTENT; + pReq->nlc = m_hAPIConnection; + } + + RPC_CSTR szId; + UuidToStringA(&pReq->m_reqId, &szId); + debugLogA("Executing request %s:\n%s", (char*)szId, pReq->szUrl); + + NETLIBHTTPREQUEST *reply = Netlib_HttpTransaction(m_hNetlibUser, pReq); + if (reply != nullptr) { + if (pReq->m_pFunc != nullptr) + (this->*(pReq->m_pFunc))(reply, pReq); + + if (pReq->m_bMainSite) + m_hAPIConnection = reply->nlc; + + Netlib_FreeHttpRequest(reply); + } + else { + debugLogA("Request %s failed", (char*)szId); + + if (pReq->m_bMainSite) { + if (IsStatusConnecting(m_iStatus)) + ConnectionFailed(LOGINERR_NONETWORK); + m_hAPIConnection = nullptr; + } + } + + RpcStringFreeA(&szId); + delete pReq; +} + +void CIcqProto::Push(MHttpRequest *p) +{ + AsyncHttpRequest *pReq = (AsyncHttpRequest*)p; + + pReq->timeout = 10000; + { + mir_cslock lck(m_csHttpQueue); + m_arHttpQueue.insert(pReq); + } + + SetEvent(m_evRequestsQueue); +} |