From d04a944cedf1e405ffa8879ea6ae139f675b8616 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 13 Oct 2013 11:54:13 +0000 Subject: VK: quick-n-dirty cookie parser git-svn-id: http://svn.miranda-ng.org/main/trunk@6488 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/VKontakte/src/misc.cpp | 70 +++++++++++++++++++++++++++-------- protocols/VKontakte/src/vk_proto.cpp | 1 + protocols/VKontakte/src/vk_proto.h | 21 +++++++++-- protocols/VKontakte/src/vk_queue.cpp | 2 +- protocols/VKontakte/src/vk_thread.cpp | 16 +++++--- 5 files changed, 84 insertions(+), 26 deletions(-) (limited to 'protocols/VKontakte') diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp index 64dc4d006a..2f063e414c 100644 --- a/protocols/VKontakte/src/misc.cpp +++ b/protocols/VKontakte/src/misc.cpp @@ -298,13 +298,12 @@ CMStringA CVkProto::AutoFillForm(char *pBody, CMStringA &szAction) ///////////////////////////////////////////////////////////////////////////////////////// -CMStringA loginCookie; - CVkProto::AsyncHttpRequest::AsyncHttpRequest() { cbSize = sizeof(NETLIBHTTPREQUEST); AddHeader("Connection", "keep-alive"); + AddHeader("Accept-Encoding", "booo"); } CVkProto::AsyncHttpRequest::~AsyncHttpRequest() @@ -328,26 +327,65 @@ void CVkProto::AsyncHttpRequest::AddHeader(LPCSTR szName, LPCSTR szValue) void CVkProto::AsyncHttpRequest::Redirect(NETLIBHTTPREQUEST *nhr) { - CMStringA szCookie; - for (int i=0; i < nhr->headersCount; i++) { LPCSTR szValue = nhr->headers[i].szValue; if (!_stricmp(nhr->headers[i].szName, "Location")) replaceStr(szUrl, szValue); - else if (!_stricmp(nhr->headers[i].szName, "Set-cookie")) { - if ( strstr(szValue, "login.vk.com")) { - if (!szCookie.IsEmpty()) - szCookie.Append("; "); - - LPCSTR p = strchr(szValue, ';'); - if (p == NULL) - szCookie += szValue; - else - szCookie.Append(szValue, p-szValue); + } +} + +void CVkProto::GrabCookies(NETLIBHTTPREQUEST *nhr) +{ + for (int i=0; i < nhr->headersCount; i++) { + if ( _stricmp(nhr->headers[i].szName, "Set-cookie")) + continue; + + CMStringA szValue = nhr->headers[i].szValue, szCookieName, szCookieVal, szDomain; + int iStart = 0; + while (true) { + bool bFirstToken = iStart == 0; + CMStringA szToken = szValue.Tokenize(";", iStart).Trim(); + if (iStart == -1) + break; + + if (bFirstToken) { + int iStart2 = 0; + szCookieName = szToken.Tokenize("=", iStart2); + szCookieVal = szToken.Tokenize("=", iStart2); } + else if ( !strncmp(szToken, "domain=", 7)) + szDomain = szToken.Mid(7); } + + if ( !szCookieName.IsEmpty() && !szDomain.IsEmpty()) { + int k; + for (k=0; k < m_cookies.getCount(); k++) { + if (m_cookies[k].m_name == szCookieName) { + m_cookies[k].m_value = szCookieVal; + break; + } + } + if (k == m_cookies.getCount()) + m_cookies.insert( new Cookie(szCookieName, szCookieVal, szDomain)); + } + } +} + +void CVkProto::ApplyCookies(AsyncHttpRequest *pReq) +{ + CMStringA szCookie; + + for (int i=0; i < m_cookies.getCount(); i++) { + if ( !strstr(pReq->szUrl, m_cookies[i].m_domain)) + continue; + + if (!szCookie.IsEmpty()) + szCookie.Append("; "); + szCookie.Append(m_cookies[i].m_name); + szCookie.AppendChar('='); + szCookie.Append(m_cookies[i].m_value); } - if (!szCookie.IsEmpty()) - loginCookie = szCookie; + if ( !szCookie.IsEmpty()) + pReq->AddHeader("Cookie", szCookie); } diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp index ebc02964c3..c566a72504 100644 --- a/protocols/VKontakte/src/vk_proto.cpp +++ b/protocols/VKontakte/src/vk_proto.cpp @@ -21,6 +21,7 @@ CVkProto::CVkProto(const char *szModuleName, const TCHAR *ptszUserName) : PROTO(szModuleName, ptszUserName), m_arRequestsQueue(10), m_sendIds(3, PtrKeySortT), + m_cookies(5), m_msgId(1) { InitQueue(); diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index fe499ee558..e6d309424b 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -128,11 +128,25 @@ private: }; LIST m_arRequestsQueue; CRITICAL_SECTION m_csRequestsQueue; - CMStringA m_prevUrl, m_savedCookie; + CMStringA m_prevUrl; HANDLE m_evRequestsQueue; HANDLE m_hWorkerThread; bool m_bTerminated; + struct Cookie + { + Cookie(const CMStringA& name, const CMStringA& value, const CMStringA& domain) : + m_name(name), + m_value(value), + m_domain(domain) + {} + + CMStringA m_name, m_value, m_domain; + }; + OBJLIST m_cookies; + void GrabCookies(NETLIBHTTPREQUEST *nhr); + void ApplyCookies(AsyncHttpRequest*); + void InitQueue(); void UninitQueue(); void ExecuteRequest(AsyncHttpRequest*); @@ -142,8 +156,8 @@ private: CMStringA RunCaptchaForm(LPCSTR szUrl); CMStringA AutoFillForm(char*, CMStringA&); - - void ConnectionFailed(int iReason); + + void ConnectionFailed(int iReason); bool CheckJsonResult(JSONNODE*); void OnLoggedIn(); void OnLoggedOut(); @@ -167,6 +181,7 @@ private: ptrA m_pollingServer, m_pollingKey, m_pollingTs; HANDLE m_pollingConn, m_hPollingThread; ULONG m_msgId; + bool m_prevError; LIST m_sendIds; bool CheckMid(int msgid); diff --git a/protocols/VKontakte/src/vk_queue.cpp b/protocols/VKontakte/src/vk_queue.cpp index e1574141c4..6979a5ac46 100644 --- a/protocols/VKontakte/src/vk_queue.cpp +++ b/protocols/VKontakte/src/vk_queue.cpp @@ -88,7 +88,7 @@ bool CVkProto::PushAsyncHttpRequest(AsyncHttpRequest *pReq, int iTimeout) void CVkProto::WorkerThread(void*) { debugLogA("CVkProto::WorkerThread: entering"); - m_bTerminated = false; + m_bTerminated = m_prevError = false; m_szAccessToken = getStringA("AccessToken"); if (m_szAccessToken != NULL) OnLoggedIn(); diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp index caaa8d8e91..876454439a 100644 --- a/protocols/VKontakte/src/vk_thread.cpp +++ b/protocols/VKontakte/src/vk_thread.cpp @@ -82,12 +82,12 @@ int CVkProto::SetServerStatus(int iStatus) ///////////////////////////////////////////////////////////////////////////////////////// -extern CMStringA loginCookie; - static char VK_TOKEN_BEG[] = "access_token="; void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, void*) { + GrabCookies(reply); + if (reply->resultCode == 302) { // manual redirect LPCSTR pszLocation = findHeader(reply, "Location"); if (pszLocation) { @@ -118,10 +118,10 @@ void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, void*) pReq->AddHeader("Referer", m_prevUrl); pReq->Redirect(reply); if (pReq->szUrl) { - if ( strstr(pReq->szUrl, "login.vk.com")) - pReq->AddHeader("Cookie", loginCookie); + ApplyCookies(pReq); m_prevUrl = pReq->szUrl; } + PushAsyncHttpRequest(pReq); } } @@ -148,8 +148,11 @@ LBL_NoForm: CMStringA szAction; CMStringA szBody = AutoFillForm(reply->pData, szAction); - if (szAction.IsEmpty() || szBody.IsEmpty()) - goto LBL_NoForm; + if (szAction.IsEmpty() || szBody.IsEmpty()) { + if (m_prevError) + goto LBL_NoForm; + m_prevError = true; + } AsyncHttpRequest *pReq = new AsyncHttpRequest(); pReq->requestType = REQUEST_POST; @@ -160,6 +163,7 @@ LBL_NoForm: pReq->m_pFunc = &CVkProto::OnOAuthAuthorize; pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); pReq->Redirect(reply); + ApplyCookies(pReq); PushAsyncHttpRequest(pReq); } -- cgit v1.2.3