summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/m_json.h5
-rw-r--r--protocols/VKontakte/src/misc.cpp152
-rw-r--r--protocols/VKontakte/src/version.h2
-rw-r--r--protocols/VKontakte/src/vk.h1
-rw-r--r--protocols/VKontakte/src/vk_avatars.cpp2
-rw-r--r--protocols/VKontakte/src/vk_captcha.cpp160
-rw-r--r--protocols/VKontakte/src/vk_proto.cpp9
-rw-r--r--protocols/VKontakte/src/vk_proto.h60
-rw-r--r--protocols/VKontakte/src/vk_queue.cpp6
-rw-r--r--protocols/VKontakte/src/vk_thread.cpp71
-rw-r--r--protocols/VKontakte/vk_10.vcxproj1
-rw-r--r--protocols/VKontakte/vk_10.vcxproj.filters3
-rw-r--r--protocols/VKontakte/vk_11.vcxproj1
-rw-r--r--protocols/VKontakte/vk_11.vcxproj.filters3
14 files changed, 281 insertions, 195 deletions
diff --git a/include/m_json.h b/include/m_json.h
index 9556becc00..99266e27d7 100644
--- a/include/m_json.h
+++ b/include/m_json.h
@@ -124,10 +124,13 @@ class JSONROOT
JSONNODE *m_node;
public:
- __forceinline JSONROOT(LPCSTR text) { m_node = json_parse(text); }
+ __forceinline JSONROOT() { m_node = NULL; }
+ __forceinline JSONROOT(LPCSTR text) { Parse(text); }
__forceinline ~JSONROOT() { json_delete(m_node); }
__forceinline operator JSONNODE*() const { return m_node; }
+
+ __forceinline JSONNODE* Parse(LPCSTR text) { return (m_node = json_parse(text)); }
};
#ifdef _XSTRING_
diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp
index 2f063e414c..f4c2a86439 100644
--- a/protocols/VKontakte/src/misc.cpp
+++ b/protocols/VKontakte/src/misc.cpp
@@ -79,7 +79,19 @@ LPCSTR findHeader(NETLIBHTTPREQUEST *pReq, LPCSTR szField)
return NULL;
}
-bool CVkProto::CheckJsonResult(JSONNODE *pNode)
+JSONNODE* CVkProto::CheckJsonResponse(AsyncHttpRequest *pReq, NETLIBHTTPREQUEST *reply, JSONROOT &pRoot)
+{
+ pRoot.Parse(reply->pData);
+ if (pRoot == NULL)
+ return NULL;
+
+ if ( !CheckJsonResult(pReq, reply, pRoot))
+ return NULL;
+
+ return json_get(pRoot, "response");
+}
+
+bool CVkProto::CheckJsonResult(AsyncHttpRequest *pReq, NETLIBHTTPREQUEST *reply, JSONNODE *pNode)
{
if (pNode == NULL)
return false;
@@ -91,9 +103,17 @@ bool CVkProto::CheckJsonResult(JSONNODE *pNode)
int iErrorCode = json_as_int(pErrorCode);
if (iErrorCode == ERROR_ACCESS_DENIED)
ConnectionFailed(LOGINERR_WRONGPASSWORD);
+ else if (iErrorCode == 14) // captcha
+ ApplyCaptcha(pReq, pError);
return iErrorCode == 0;
}
+void CVkProto::OnReceiveSmth(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
+{
+ JSONROOT pRoot;
+ CheckJsonResponse(pReq, reply, pRoot);
+}
+
/////////////////////////////////////////////////////////////////////////////////////////
static IconItem iconList[] =
@@ -106,123 +126,13 @@ void InitIcons()
Icon_Register(hInst, LPGEN("Protocols")"/"LPGEN("VKontakte"), iconList, SIZEOF(iconList), "VKontakte");
}
-/////////////////////////////////////////////////////////////////////////////////////////
-// Captcha form
-
-struct CAPTCHA_FORM_PARAMS
-{
- HBITMAP bmp;
- int w,h;
- char Result[100];
-};
-
-static INT_PTR CALLBACK CaptchaFormDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+HANDLE GetIconHandle(int iCommand)
{
- CAPTCHA_FORM_PARAMS *params = (CAPTCHA_FORM_PARAMS*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
- switch (msg) {
- case WM_INITDIALOG: {
- TranslateDialogDefault(hwndDlg);
- SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_GetIconByHandle(iconList[0].hIcolib, TRUE));
- SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)Skin_GetIconByHandle(iconList[0].hIcolib));
- params = (CAPTCHA_FORM_PARAMS*)lParam;
-
- SetDlgItemText(hwndDlg, IDC_INSTRUCTION, TranslateT("Enter the text you see"));
- SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG)params);
-
- return TRUE;
- }
- case WM_CTLCOLORSTATIC:
- switch(GetWindowLongPtr((HWND)lParam, GWL_ID)) {
- case IDC_WHITERECT:
- case IDC_INSTRUCTION:
- case IDC_TITLE:
- return (BOOL)GetStockObject(WHITE_BRUSH);
- }
- return NULL;
-
- case WM_PAINT:
- if (params) {
- PAINTSTRUCT ps;
- HDC hdc, hdcMem;
- RECT rc;
+ for (int i=0; i < SIZEOF(iconList); i++)
+ if (iconList[i].defIconID == iCommand)
+ return iconList[i].hIcolib;
- GetClientRect(hwndDlg, &rc);
- hdc = BeginPaint(hwndDlg, &ps);
- hdcMem = CreateCompatibleDC(hdc);
- HGDIOBJ hOld = SelectObject(hdcMem, params->bmp);
-
- int y = (rc.bottom + rc.top - params->h) / 2;
- int x = (rc.right + rc.left - params->w) / 2;
- BitBlt(hdc, x, y, params->w, params->h, hdcMem, 0,0, SRCCOPY);
- SelectObject(hdcMem, hOld);
- DeleteDC(hdcMem);
-
- EndPaint(hwndDlg, &ps);
- }
- break;
-
- case WM_COMMAND:
- switch (LOWORD(wParam)) {
- case IDCANCEL:
- EndDialog(hwndDlg, 0);
- return TRUE;
-
- case IDOK:
- GetDlgItemTextA(hwndDlg, IDC_VALUE, params->Result, SIZEOF(params->Result));
- EndDialog(hwndDlg, 1);
- return TRUE;
- }
- break;
-
- case WM_CLOSE:
- EndDialog(hwndDlg, 0);
- break;
-
- case WM_DESTROY:
- Skin_ReleaseIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
- Skin_ReleaseIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0));
- break;
- }
- return FALSE;
-}
-
-CMStringA CVkProto::RunCaptchaForm(LPCSTR szUrl)
-{
- debugLogA("CVkProto::RunCaptchaForm: reading picture from %s", szUrl);
-
- NETLIBHTTPREQUEST req = { sizeof(req) };
- req.requestType = REQUEST_GET;
- req.szUrl = (LPSTR)szUrl;
- req.flags = NLHRF_HTTP11 | NLHRF_NODUMPHEADERS;
- req.timeout = 60;
-
- NETLIBHTTPREQUEST *reply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)&req);
- if (reply == NULL)
- return "";
-
- if (reply->resultCode != 200) {
- debugLogA("CVkProto::RunCaptchaForm: failed with code %d", reply->resultCode);
- return "";
- }
-
- CAPTCHA_FORM_PARAMS param = { 0 };
-
- IMGSRVC_MEMIO memio = { 0 };
- memio.iLen = reply->dataLength;
- memio.pBuf = reply->pData;
- memio.fif = FIF_UNKNOWN; /* detect */
- param.bmp = (HBITMAP)CallService(MS_IMG_LOADFROMMEM, (WPARAM)&memio, 0);
-
- BITMAP bmp = {0};
- GetObject(param.bmp, sizeof(bmp), &bmp);
- param.w = bmp.bmWidth;
- param.h = bmp.bmHeight;
- int res = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CAPTCHAFORM), NULL, CaptchaFormDlgProc, (LPARAM)&param);
- if (res == 0)
- return "";
-
- debugLogA("CVkProto::RunCaptchaForm: user entered text %s", param.Result);
- return param.Result;
+ return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -283,7 +193,7 @@ CMStringA CVkProto::AutoFillForm(char *pBody, CMStringA &szAction)
else if (name == "captcha_key") {
char *pCaptchaBeg = strstr(pFormBeg, "<img id=\"captcha\"");
if (pCaptchaBeg != NULL)
- value = RunCaptchaForm( getAttr(pCaptchaBeg, "src"));
+ RunCaptchaForm( getAttr(pCaptchaBeg, "src"), value);
}
if ( !result.IsEmpty())
@@ -298,7 +208,7 @@ CMStringA CVkProto::AutoFillForm(char *pBody, CMStringA &szAction)
/////////////////////////////////////////////////////////////////////////////////////////
-CVkProto::AsyncHttpRequest::AsyncHttpRequest()
+AsyncHttpRequest::AsyncHttpRequest()
{
cbSize = sizeof(NETLIBHTTPREQUEST);
@@ -306,7 +216,7 @@ CVkProto::AsyncHttpRequest::AsyncHttpRequest()
AddHeader("Accept-Encoding", "booo");
}
-CVkProto::AsyncHttpRequest::~AsyncHttpRequest()
+AsyncHttpRequest::~AsyncHttpRequest()
{
for (int i=0; i < headersCount; i++) {
mir_free(headers[i].szName);
@@ -317,7 +227,7 @@ CVkProto::AsyncHttpRequest::~AsyncHttpRequest()
mir_free(pData);
}
-void CVkProto::AsyncHttpRequest::AddHeader(LPCSTR szName, LPCSTR szValue)
+void AsyncHttpRequest::AddHeader(LPCSTR szName, LPCSTR szValue)
{
headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount+1));
headers[headersCount].szName = mir_strdup(szName);
@@ -325,7 +235,7 @@ void CVkProto::AsyncHttpRequest::AddHeader(LPCSTR szName, LPCSTR szValue)
headersCount++;
}
-void CVkProto::AsyncHttpRequest::Redirect(NETLIBHTTPREQUEST *nhr)
+void AsyncHttpRequest::Redirect(NETLIBHTTPREQUEST *nhr)
{
for (int i=0; i < nhr->headersCount; i++) {
LPCSTR szValue = nhr->headers[i].szValue;
diff --git a/protocols/VKontakte/src/version.h b/protocols/VKontakte/src/version.h
index 4cf96d5613..6cdcc75c3a 100644
--- a/protocols/VKontakte/src/version.h
+++ b/protocols/VKontakte/src/version.h
@@ -1,7 +1,7 @@
#define __MAJOR_VERSION 0
#define __MINOR_VERSION 1
#define __RELEASE_NUM 0
-#define __BUILD_NUM 1
+#define __BUILD_NUM 2
#define __FILEVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
#define __FILEVERSION_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM
diff --git a/protocols/VKontakte/src/vk.h b/protocols/VKontakte/src/vk.h
index 4a9833ea7f..2e77dfe03e 100644
--- a/protocols/VKontakte/src/vk.h
+++ b/protocols/VKontakte/src/vk.h
@@ -53,3 +53,4 @@ extern HINSTANCE hInst;
LPCSTR findHeader(NETLIBHTTPREQUEST *hdr, LPCSTR szField);
void InitIcons(void);
+HANDLE GetIconHandle(int iCommand);
diff --git a/protocols/VKontakte/src/vk_avatars.cpp b/protocols/VKontakte/src/vk_avatars.cpp
index a939cd2820..fa833dedda 100644
--- a/protocols/VKontakte/src/vk_avatars.cpp
+++ b/protocols/VKontakte/src/vk_avatars.cpp
@@ -17,7 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdafx.h"
-void CVkProto::OnReceiveAvatar(NETLIBHTTPREQUEST *reply, void* hContact)
+void CVkProto::OnReceiveAvatar(NETLIBHTTPREQUEST *reply, AsyncHttpRequest* hContact)
{
if (reply->resultCode != 200)
return;
diff --git a/protocols/VKontakte/src/vk_captcha.cpp b/protocols/VKontakte/src/vk_captcha.cpp
new file mode 100644
index 0000000000..930b804e29
--- /dev/null
+++ b/protocols/VKontakte/src/vk_captcha.cpp
@@ -0,0 +1,160 @@
+/*
+Copyright (C) 2013 Miranda NG Project (http://miranda-ng.org)
+
+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 version 2
+of the License.
+
+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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "stdafx.h"
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// Captcha form
+
+struct CAPTCHA_FORM_PARAMS
+{
+ HBITMAP bmp;
+ int w,h;
+ char Result[100];
+};
+
+static INT_PTR CALLBACK CaptchaFormDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ CAPTCHA_FORM_PARAMS *params = (CAPTCHA_FORM_PARAMS*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
+ switch (msg) {
+ case WM_INITDIALOG: {
+ TranslateDialogDefault(hwndDlg);
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)Skin_GetIconByHandle( GetIconHandle(IDI_KEYS), TRUE));
+ SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)Skin_GetIconByHandle( GetIconHandle(IDI_KEYS)));
+ params = (CAPTCHA_FORM_PARAMS*)lParam;
+
+ SetDlgItemText(hwndDlg, IDC_INSTRUCTION, TranslateT("Enter the text you see"));
+ SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG)params);
+
+ return TRUE;
+ }
+ case WM_CTLCOLORSTATIC:
+ switch(GetWindowLongPtr((HWND)lParam, GWL_ID)) {
+ case IDC_WHITERECT:
+ case IDC_INSTRUCTION:
+ case IDC_TITLE:
+ return (BOOL)GetStockObject(WHITE_BRUSH);
+ }
+ return NULL;
+
+ case WM_PAINT:
+ if (params) {
+ PAINTSTRUCT ps;
+ HDC hdc, hdcMem;
+ RECT rc;
+
+ GetClientRect(hwndDlg, &rc);
+ hdc = BeginPaint(hwndDlg, &ps);
+ hdcMem = CreateCompatibleDC(hdc);
+ HGDIOBJ hOld = SelectObject(hdcMem, params->bmp);
+
+ int y = (rc.bottom + rc.top - params->h) / 2;
+ int x = (rc.right + rc.left - params->w) / 2;
+ BitBlt(hdc, x, y, params->w, params->h, hdcMem, 0,0, SRCCOPY);
+ SelectObject(hdcMem, hOld);
+ DeleteDC(hdcMem);
+
+ EndPaint(hwndDlg, &ps);
+ }
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wParam)) {
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+
+ case IDOK:
+ GetDlgItemTextA(hwndDlg, IDC_VALUE, params->Result, SIZEOF(params->Result));
+ EndDialog(hwndDlg, 1);
+ return TRUE;
+ }
+ break;
+
+ case WM_CLOSE:
+ EndDialog(hwndDlg, 0);
+ break;
+
+ case WM_DESTROY:
+ Skin_ReleaseIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_BIG, 0));
+ Skin_ReleaseIcon((HICON)SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, 0));
+ break;
+ }
+ return FALSE;
+}
+
+bool CVkProto::RunCaptchaForm(LPCSTR szUrl, CMStringA &result)
+{
+ debugLogA("CVkProto::RunCaptchaForm: reading picture from %s", szUrl);
+ result.Empty();
+
+ NETLIBHTTPREQUEST req = { sizeof(req) };
+ req.requestType = REQUEST_GET;
+ req.szUrl = (LPSTR)szUrl;
+ req.flags = NLHRF_HTTP11 | NLHRF_NODUMPHEADERS;
+
+ NETLIBHTTPREQUEST *reply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)&req);
+ if (reply == NULL)
+ return false;
+
+ if (reply->resultCode != 200) {
+ debugLogA("CVkProto::RunCaptchaForm: failed with code %d", reply->resultCode);
+ return false;
+ }
+
+ CAPTCHA_FORM_PARAMS param = { 0 };
+
+ IMGSRVC_MEMIO memio = { 0 };
+ memio.iLen = reply->dataLength;
+ memio.pBuf = reply->pData;
+ memio.fif = FIF_UNKNOWN; /* detect */
+ param.bmp = (HBITMAP)CallService(MS_IMG_LOADFROMMEM, (WPARAM)&memio, 0);
+
+ BITMAP bmp = {0};
+ GetObject(param.bmp, sizeof(bmp), &bmp);
+ param.w = bmp.bmWidth;
+ param.h = bmp.bmHeight;
+ int res = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_CAPTCHAFORM), NULL, CaptchaFormDlgProc, (LPARAM)&param);
+ if (res == 0)
+ return false;
+
+ debugLogA("CVkProto::RunCaptchaForm: user entered text %s", param.Result);
+ result = param.Result;
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// fill a request from JSON
+
+bool CVkProto::ApplyCaptcha(AsyncHttpRequest *pReq, JSONNODE *pErrorNode)
+{
+ char *szUrl = NEWSTR_ALLOCA( _T2A( json_as_string( json_get(pErrorNode, "captcha_img"))));
+ char *szSid = NEWSTR_ALLOCA( _T2A( json_as_string( json_get(pErrorNode, "captcha_sid"))));
+ if (szUrl == NULL || szSid == NULL)
+ return false;
+
+ CMStringA userReply;
+ if ( !RunCaptchaForm(szUrl, userReply))
+ return false;
+
+ CMStringA szNewUrl = pReq->szUrl;
+ szNewUrl.AppendFormat("&captcha_sid=%s&captcha_key=%s", szSid, userReply.GetString());
+ replaceStr(pReq->szUrl, mir_strndup(szNewUrl, szNewUrl.GetLength()));
+ pReq->bNeedsRestart = true;
+ return true;
+}
diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp
index ab4a4dbedc..8ed039cb76 100644
--- a/protocols/VKontakte/src/vk_proto.cpp
+++ b/protocols/VKontakte/src/vk_proto.cpp
@@ -157,17 +157,14 @@ int CVkProto::SendMsg(HANDLE hContact, int flags, const char *msg)
return msgId;
}
-void CVkProto::OnSendMessage(NETLIBHTTPREQUEST *reply, void*)
+void CVkProto::OnSendMessage(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
{
debugLogA("CVkProto::OnSendMessage %d", reply->resultCode);
if (reply->resultCode != 200)
return;
- JSONROOT pRoot(reply->pData);
- if ( !CheckJsonResult(pRoot))
- return;
-
- JSONNODE *pResponse = json_get(pRoot, "response");
+ JSONROOT pRoot;
+ JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot);
if (pResponse != NULL)
m_sendIds.insert((HANDLE)json_as_int(pResponse));
}
diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h
index e6d309424b..8e0860f479 100644
--- a/protocols/VKontakte/src/vk_proto.h
+++ b/protocols/VKontakte/src/vk_proto.h
@@ -16,7 +16,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
struct CVkProto;
-typedef void (CVkProto::*VK_REQUEST_HANDLER)(NETLIBHTTPREQUEST*, void*);
+typedef void (CVkProto::*VK_REQUEST_HANDLER)(NETLIBHTTPREQUEST*, struct AsyncHttpRequest *pReq);
+
+struct AsyncHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
+{
+ AsyncHttpRequest();
+ ~AsyncHttpRequest();
+
+ void AddHeader(LPCSTR, LPCSTR);
+ void Redirect(NETLIBHTTPREQUEST*);
+
+ BOOL bNeedsRestart;
+ VK_REQUEST_HANDLER m_pFunc;
+ void *pUserInfo;
+};
struct CVkProto : public PROTO<CVkProto>
{
@@ -78,9 +91,10 @@ struct CVkProto : public PROTO<CVkProto>
int __cdecl OnOptionsInit(WPARAM, LPARAM);
int __cdecl OnPreShutdown(WPARAM, LPARAM);
- void OnOAuthAuthorize(NETLIBHTTPREQUEST*, void*);
- void OnReceiveMyInfo(NETLIBHTTPREQUEST*, void*);
- void OnReceiveAvatar(NETLIBHTTPREQUEST*, void*);
+ void OnOAuthAuthorize(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq);
+ void OnReceiveMyInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq);
+ void OnReceiveAvatar(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq);
+ void OnReceiveSmth(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq);
//==== Services ======================================================================
@@ -93,39 +107,28 @@ struct CVkProto : public PROTO<CVkProto>
TCHAR* GetUserStoredPassword(void);
void RetrieveUserInfo(LONG userId);
- void OnReceiveUserInfo(NETLIBHTTPREQUEST*, void*);
+ void OnReceiveUserInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq);
void RetrieveFriends();
- void OnReceiveFriends(NETLIBHTTPREQUEST*, void*);
+ void OnReceiveFriends(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq);
void RetrieveUnreadMessages();
- void OnReceiveMessages(NETLIBHTTPREQUEST*, void*);
- void OnSendMessage(NETLIBHTTPREQUEST*, void*);
+ void OnReceiveMessages(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq);
+ void OnSendMessage(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq);
void RetrievePollingInfo();
- void OnReceivePollingInfo(NETLIBHTTPREQUEST*, void*);
+ void OnReceivePollingInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq);
void __cdecl PollingThread(void*);
int PollServer();
void PollUpdates(JSONNODE*);
- void OnReceivePolling(NETLIBHTTPREQUEST*, void*);
+ void OnReceivePolling(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq);
int SetServerStatus(int);
__forceinline bool IsOnline() const { return m_bOnline; }
private:
- struct AsyncHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
- {
- AsyncHttpRequest();
- ~AsyncHttpRequest();
-
- void AddHeader(LPCSTR, LPCSTR);
- void Redirect(NETLIBHTTPREQUEST*);
-
- VK_REQUEST_HANDLER m_pFunc;
- void *pUserInfo;
- };
LIST<AsyncHttpRequest> m_arRequestsQueue;
CRITICAL_SECTION m_csRequestsQueue;
CMStringA m_prevUrl;
@@ -145,20 +148,23 @@ private:
};
OBJLIST<Cookie> m_cookies;
void GrabCookies(NETLIBHTTPREQUEST *nhr);
- void ApplyCookies(AsyncHttpRequest*);
+ void ApplyCookies(AsyncHttpRequest *pReq);
void InitQueue();
void UninitQueue();
- void ExecuteRequest(AsyncHttpRequest*);
+ void ExecuteRequest(AsyncHttpRequest *pReq);
bool PushAsyncHttpRequest(int iRequestType, LPCSTR szUrl, bool bSecure, VK_REQUEST_HANDLER pFunc, int nParams = 0, HttpParam *pParams = 0, int iTimeout = 10000);
bool PushAsyncHttpRequest(AsyncHttpRequest*, int iTimeout = 10000);
void __cdecl WorkerThread(void*);
- CMStringA RunCaptchaForm(LPCSTR szUrl);
+ bool RunCaptchaForm(LPCSTR szUrl, CMStringA&);
CMStringA AutoFillForm(char*, CMStringA&);
-
- void ConnectionFailed(int iReason);
- bool CheckJsonResult(JSONNODE*);
+
+ bool CheckJsonResult(AsyncHttpRequest *pReq, NETLIBHTTPREQUEST *reply, JSONNODE*);
+ JSONNODE* CheckJsonResponse(AsyncHttpRequest *pReq, NETLIBHTTPREQUEST *reply, JSONROOT&);
+ bool ApplyCaptcha(AsyncHttpRequest *pReq, JSONNODE*);
+
+ void ConnectionFailed(int iReason);
void OnLoggedIn();
void OnLoggedOut();
void ShutdownSession();
diff --git a/protocols/VKontakte/src/vk_queue.cpp b/protocols/VKontakte/src/vk_queue.cpp
index 6979a5ac46..d25a585527 100644
--- a/protocols/VKontakte/src/vk_queue.cpp
+++ b/protocols/VKontakte/src/vk_queue.cpp
@@ -34,11 +34,15 @@ void CVkProto::UninitQueue()
void CVkProto::ExecuteRequest(AsyncHttpRequest *pReq)
{
+LBL_Restart:
NETLIBHTTPREQUEST *reply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)pReq);
if (reply != NULL) {
if (pReq->m_pFunc != NULL)
- (this->*(pReq->m_pFunc))(reply, pReq->pUserInfo);
+ (this->*(pReq->m_pFunc))(reply, pReq);
+
CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)reply);
+ if (pReq->bNeedsRestart)
+ goto LBL_Restart;
}
delete pReq;
}
diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp
index 876454439a..b0fb61f257 100644
--- a/protocols/VKontakte/src/vk_thread.cpp
+++ b/protocols/VKontakte/src/vk_thread.cpp
@@ -75,7 +75,7 @@ int CVkProto::SetServerStatus(int iStatus)
{
if (iStatus != ID_STATUS_OFFLINE && iStatus != ID_STATUS_INVISIBLE) {
HttpParam param = { "access_token", m_szAccessToken };
- PushAsyncHttpRequest(REQUEST_GET, "/method/account.setOnline.json", true, NULL, 1, &param);
+ PushAsyncHttpRequest(REQUEST_GET, "/method/account.setOnline.json", true, &CVkProto::OnReceiveSmth, 1, &param);
}
return 0;
}
@@ -84,7 +84,7 @@ int CVkProto::SetServerStatus(int iStatus)
static char VK_TOKEN_BEG[] = "access_token=";
-void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, void*)
+void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
{
GrabCookies(reply);
@@ -154,7 +154,7 @@ LBL_NoForm:
m_prevError = true;
}
- AsyncHttpRequest *pReq = new AsyncHttpRequest();
+ pReq = new AsyncHttpRequest();
pReq->requestType = REQUEST_POST;
pReq->flags = NLHRF_DUMPASTEXT | NLHRF_PERSISTENT | NLHRF_HTTP11;
pReq->pData = mir_strdup(szBody);
@@ -169,7 +169,7 @@ LBL_NoForm:
/////////////////////////////////////////////////////////////////////////////////////////
-void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply, void*)
+void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
{
debugLogA("CVkProto::OnReceiveMyInfo %d", reply->resultCode);
if (reply->resultCode != 200) {
@@ -177,11 +177,8 @@ void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply, void*)
return;
}
- JSONROOT pRoot(reply->pData);
- if ( !CheckJsonResult(pRoot))
- return;
-
- JSONNODE *pResponse = json_get(pRoot, "response");
+ JSONROOT pRoot;
+ JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot);
if (pResponse == NULL)
return;
@@ -229,17 +226,14 @@ void CVkProto::RetrieveUserInfo(LONG userID)
PushAsyncHttpRequest(REQUEST_GET, "/method/getProfiles.json", true, &CVkProto::OnReceiveUserInfo, SIZEOF(params), params);
}
-void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply, void*)
+void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
{
debugLogA("CVkProto::OnReceiveUserInfo %d", reply->resultCode);
if (reply->resultCode != 200)
return;
- JSONROOT pRoot(reply->pData);
- if ( !CheckJsonResult(pRoot))
- return;
-
- JSONNODE *pResponse = json_get(pRoot, "response");
+ JSONROOT pRoot;
+ JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot);
if (pResponse == NULL)
return;
@@ -286,17 +280,14 @@ void CVkProto::RetrieveFriends()
PushAsyncHttpRequest(REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends, SIZEOF(params), params);
}
-void CVkProto::OnReceiveFriends(NETLIBHTTPREQUEST *reply, void*)
+void CVkProto::OnReceiveFriends(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
{
debugLogA("CVkProto::OnReceiveFriends %d", reply->resultCode);
if (reply->resultCode != 200)
return;
- JSONROOT pRoot(reply->pData);
- if ( !CheckJsonResult(pRoot))
- return;
-
- JSONNODE *pResponse = json_get(pRoot, "response"), *pInfo;
+ JSONROOT pRoot;
+ JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot), *pInfo;
if (pResponse == NULL)
return;
@@ -305,12 +296,24 @@ void CVkProto::OnReceiveFriends(NETLIBHTTPREQUEST *reply, void*)
if (szValue == NULL)
continue;
+ CMString tszNick;
HANDLE hContact = FindUser( _ttoi(szValue), true);
szValue = json_as_string( json_get(pInfo, "first_name"));
- if (szValue) setTString(hContact, "FirstName", szValue);
+ if (szValue) {
+ setTString(hContact, "FirstName", szValue);
+
+ tszNick.Append(szValue);
+ tszNick.AppendChar(' ');
+ }
szValue = json_as_string( json_get(pInfo, "last_name"));
- if (szValue) setTString(hContact, "LastName", szValue);
+ if (szValue) {
+ setTString(hContact, "LastName", szValue);
+ tszNick.Append(szValue);
+ }
+
+ if ( !tszNick.IsEmpty())
+ setTString(hContact, "Nick", tszNick);
szValue = json_as_string( json_get(pInfo, "photo"));
if (szValue) setTString(hContact, "AvatarUrl", szValue);
@@ -337,17 +340,14 @@ void CVkProto::RetrieveUnreadMessages()
PushAsyncHttpRequest(REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveMessages, SIZEOF(params), params);
}
-void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, void*)
+void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
{
debugLogA("CVkProto::OnReceiveMessages %d", reply->resultCode);
if (reply->resultCode != 200)
return;
- JSONROOT pRoot(reply->pData);
- if ( !CheckJsonResult(pRoot))
- return;
-
- JSONNODE *pResponse = json_get(pRoot, "response");
+ JSONROOT pRoot;
+ JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot);
if (pResponse == NULL)
return;
@@ -395,7 +395,7 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, void*)
{ "mids", mids },
{ "access_token", m_szAccessToken }
};
- PushAsyncHttpRequest(REQUEST_GET, "/method/messages.markAsRead.json", true, NULL, SIZEOF(params), params);
+ PushAsyncHttpRequest(REQUEST_GET, "/method/messages.markAsRead.json", true, &CVkProto::OnReceiveSmth, SIZEOF(params), params);
}
}
@@ -409,17 +409,14 @@ void CVkProto::RetrievePollingInfo()
PushAsyncHttpRequest(REQUEST_GET, "/method/messages.getLongPollServer.json", true, &CVkProto::OnReceivePollingInfo, 1, &param);
}
-void CVkProto::OnReceivePollingInfo(NETLIBHTTPREQUEST *reply, void*)
+void CVkProto::OnReceivePollingInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
{
debugLogA("CVkProto::OnReceivePollingInfo %d", reply->resultCode);
if (reply->resultCode != 200)
return;
- JSONROOT pRoot(reply->pData);
- if ( !CheckJsonResult(pRoot))
- return;
-
- JSONNODE *pResponse = json_get(pRoot, "response");
+ JSONROOT pRoot;
+ JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot);
if (pResponse == NULL)
return;
@@ -504,7 +501,7 @@ int CVkProto::PollServer()
int retVal = 0;
if (reply->resultCode = 200) {
JSONROOT pRoot(reply->pData);
- if ( CheckJsonResult(pRoot)) {
+ if ( CheckJsonResult(NULL, reply, pRoot)) {
m_pollingTs = mir_t2a( ptrT( json_as_string( json_get(pRoot, "ts"))));
JSONNODE *pUpdates = json_get(pRoot, "updates");
if (pUpdates != NULL)
diff --git a/protocols/VKontakte/vk_10.vcxproj b/protocols/VKontakte/vk_10.vcxproj
index 140b1141f1..ab6deb58e8 100644
--- a/protocols/VKontakte/vk_10.vcxproj
+++ b/protocols/VKontakte/vk_10.vcxproj
@@ -181,6 +181,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\vk_avatars.cpp" />
+ <ClCompile Include="src\vk_captcha.cpp" />
<ClCompile Include="src\vk_options.cpp" />
<ClCompile Include="src\vk_proto.cpp" />
<ClCompile Include="src\vk_queue.cpp" />
diff --git a/protocols/VKontakte/vk_10.vcxproj.filters b/protocols/VKontakte/vk_10.vcxproj.filters
index e7ac9a423b..fa0daf6a28 100644
--- a/protocols/VKontakte/vk_10.vcxproj.filters
+++ b/protocols/VKontakte/vk_10.vcxproj.filters
@@ -39,6 +39,9 @@
<ClCompile Include="src\vk_avatars.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\vk_captcha.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\resource.h">
diff --git a/protocols/VKontakte/vk_11.vcxproj b/protocols/VKontakte/vk_11.vcxproj
index 3e30504c57..3929e1d9bd 100644
--- a/protocols/VKontakte/vk_11.vcxproj
+++ b/protocols/VKontakte/vk_11.vcxproj
@@ -184,6 +184,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="src\vk_avatars.cpp" />
+ <ClCompile Include="src\vk_captcha.cpp" />
<ClCompile Include="src\vk_options.cpp" />
<ClCompile Include="src\vk_proto.cpp" />
<ClCompile Include="src\vk_queue.cpp" />
diff --git a/protocols/VKontakte/vk_11.vcxproj.filters b/protocols/VKontakte/vk_11.vcxproj.filters
index 6a23ec20c2..9f8217c6ef 100644
--- a/protocols/VKontakte/vk_11.vcxproj.filters
+++ b/protocols/VKontakte/vk_11.vcxproj.filters
@@ -39,6 +39,9 @@
<ClCompile Include="src\vk_avatars.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="src\vk_captcha.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\version.h">