From e528a508b7e307bd35b142b269a0bbd1b6813e89 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 12 Jan 2014 11:59:23 +0000 Subject: VKontakte: - completely rewritten schema of pushing requests; - typed http parameters insted of old strings git-svn-id: http://svn.miranda-ng.org/main/trunk@7613 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/VKontakte/src/misc.cpp | 34 +++++++++-- protocols/VKontakte/src/vk.h | 11 ++-- protocols/VKontakte/src/vk_avatars.cpp | 4 +- protocols/VKontakte/src/vk_captcha.cpp | 7 +-- protocols/VKontakte/src/vk_chats.cpp | 89 +++++++-------------------- protocols/VKontakte/src/vk_proto.cpp | 13 +--- protocols/VKontakte/src/vk_proto.h | 49 +++++++++++++-- protocols/VKontakte/src/vk_queue.cpp | 69 ++++++++++----------- protocols/VKontakte/src/vk_thread.cpp | 107 +++++++++------------------------ 9 files changed, 168 insertions(+), 215 deletions(-) (limited to 'protocols/VKontakte/src') diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp index b687f7fd16..1a3195812b 100644 --- a/protocols/VKontakte/src/misc.cpp +++ b/protocols/VKontakte/src/misc.cpp @@ -55,10 +55,10 @@ HANDLE CVkProto::FindUser(LONG dwUserid, bool bCreate) return hNewContact; } -bool CVkProto::CheckMid(int msgid) +bool CVkProto::CheckMid(int guid) { for (int i=m_sendIds.getCount()-1; i >= 0; i--) - if (m_sendIds[i] == (HANDLE)msgid) { + if ((int)m_sendIds[i] == guid) { m_sendIds.remove(i); return true; } @@ -216,6 +216,31 @@ AsyncHttpRequest::AsyncHttpRequest() AddHeader("Accept-Encoding", "booo"); } +AsyncHttpRequest::AsyncHttpRequest(CVkProto *ppro, int iRequestType, LPCSTR _url, bool bSecure, VK_REQUEST_HANDLER pFunc) +{ + cbSize = sizeof(NETLIBHTTPREQUEST); + + AddHeader("Connection", "keep-alive"); + AddHeader("Accept-Encoding", "booo"); + + flags = VK_NODUMPHEADERS | NLHRF_DUMPASTEXT | NLHRF_HTTP11 | NLHRF_REDIRECT; + if (bSecure) + flags |= NLHRF_SSL; + + if (*_url == '/') { // relative url leads to a site + m_szUrl = ((bSecure) ? "https://" : "http://") + CMStringA("api.vk.com"); + m_szUrl += _url; + bIsMainConn = true; + } + else m_szUrl = _url; + + if (bSecure) + this << CHAR_PARAM("access_token", ppro->m_szAccessToken); + + requestType = iRequestType; + m_pFunc = pFunc; +} + AsyncHttpRequest::~AsyncHttpRequest() { for (int i=0; i < headersCount; i++) { @@ -223,7 +248,6 @@ AsyncHttpRequest::~AsyncHttpRequest() mir_free(headers[i].szValue); } mir_free(headers); - mir_free(szUrl); mir_free(pData); } @@ -240,7 +264,7 @@ void AsyncHttpRequest::Redirect(NETLIBHTTPREQUEST *nhr) for (int i=0; i < nhr->headersCount; i++) { LPCSTR szValue = nhr->headers[i].szValue; if (!_stricmp(nhr->headers[i].szName, "Location")) - replaceStr(szUrl, szValue); + m_szUrl = szValue; } } @@ -286,7 +310,7 @@ 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)) + if (!strstr(pReq->m_szUrl, m_cookies[i].m_domain)) continue; if (!szCookie.IsEmpty()) diff --git a/protocols/VKontakte/src/vk.h b/protocols/VKontakte/src/vk.h index ee882de9d9..0a2058b874 100644 --- a/protocols/VKontakte/src/vk.h +++ b/protocols/VKontakte/src/vk.h @@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#define VK_APP_ID "3917910" +#define VK_APP_ID 3917910 #define VKPOLL_MSG_REMOVED 0 #define VKPOLL_MSG_NEWFLAGS 1 @@ -40,10 +40,11 @@ along with this program. If not, see . #define VKFLAG_MSGFIXED 256 // сообщение проверено пользователем на спам #define VKFLAG_MSGMEDIA 512 // сообщение содержит медиаконтент -struct HttpParam -{ - LPCSTR szName, szValue; -}; +#if defined(_DEBUG) + #define VK_NODUMPHEADERS 0 +#else + #define VK_NODUMPHEADERS NLHRF_NODUMPHEADERS +#endif extern HINSTANCE hInst; diff --git a/protocols/VKontakte/src/vk_avatars.cpp b/protocols/VKontakte/src/vk_avatars.cpp index f97fb430e5..f953e85eb0 100644 --- a/protocols/VKontakte/src/vk_avatars.cpp +++ b/protocols/VKontakte/src/vk_avatars.cpp @@ -78,11 +78,11 @@ INT_PTR CVkProto::SvcGetAvatarInfo(WPARAM wParam, LPARAM lParam) if ( IsOnline()) { AsyncHttpRequest *pReq = new AsyncHttpRequest(); pReq->flags = NLHRF_NODUMP | NLHRF_REDIRECT; - pReq->szUrl = mir_strdup(szUrl); + pReq->m_szUrl = szUrl; pReq->pUserInfo = (char*)AI->hContact; pReq->m_pFunc = &CVkProto::OnReceiveAvatar; pReq->requestType = REQUEST_GET; - PushAsyncHttpRequest(pReq); + Push(pReq); debugLogA("Requested to read an avatar from '%s'", szUrl); return GAIR_WAITFOR; diff --git a/protocols/VKontakte/src/vk_captcha.cpp b/protocols/VKontakte/src/vk_captcha.cpp index 3196082882..527c5d6e49 100644 --- a/protocols/VKontakte/src/vk_captcha.cpp +++ b/protocols/VKontakte/src/vk_captcha.cpp @@ -106,7 +106,7 @@ bool CVkProto::RunCaptchaForm(LPCSTR szUrl, CMStringA &result) NETLIBHTTPREQUEST req = { sizeof(req) }; req.requestType = REQUEST_GET; req.szUrl = (LPSTR)szUrl; - req.flags = NLHRF_NODUMPHEADERS; + req.flags = VK_NODUMPHEADERS; NETLIBHTTPREQUEST *reply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)&req); if (reply == NULL) @@ -152,9 +152,8 @@ bool CVkProto::ApplyCaptcha(AsyncHttpRequest *pReq, JSONNODE *pErrorNode) 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->m_szUrl = pReq->szUrl; + pReq->m_szUrl.AppendFormat("&captcha_sid=%s&captcha_key=%s", szSid, userReply.GetString()); pReq->bNeedsRestart = true; return true; } diff --git a/protocols/VKontakte/src/vk_chats.cpp b/protocols/VKontakte/src/vk_chats.cpp index 0df57d6856..0d4ad2e267 100644 --- a/protocols/VKontakte/src/vk_chats.cpp +++ b/protocols/VKontakte/src/vk_chats.cpp @@ -97,12 +97,8 @@ void CVkProto::RetrieveChatInfo(CVkChatInfo *cc) debugLogA("CVkProto::RetrieveChantInfo(%d)", cc->m_chatid); - HttpParam params[] = { - { "code", szQuery }, - { "access_token", m_szAccessToken } - }; - AsyncHttpRequest *pReq = PushAsyncHttpRequest(REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveChatInfo, SIZEOF(params), params); - pReq->pUserInfo = cc; + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveChatInfo) + << CHAR_PARAM("code", szQuery))->pUserInfo = cc; } void CVkProto::OnReceiveChatInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) @@ -210,7 +206,7 @@ void CVkProto::OnReceiveChatInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe for (int j = 0; j < cc->m_msgs.getCount(); j++) { CVkChatMessage &p = cc->m_msgs[j]; - AppendChatMessage(cc, p.m_uid, p.m_date, p.m_tszBody, false); + AppendChatMessage(cc, p.m_mid, p.m_uid, p.m_date, p.m_tszBody, false); } cc->m_msgs.destroy(); } @@ -225,9 +221,6 @@ void CVkProto::AppendChatMessage(int id, JSONNODE *pMsg, bool bIsHistory) int mid = json_as_int(json_get(pMsg, "mid")); int isOut = json_as_int(json_get(pMsg, "out")); - if (mid && isOut) - m_sendIds.insert((void*)mid); - int uid = json_as_int(json_get(pMsg, "uid")); int msgTime = json_as_int(json_get(pMsg, "date")); @@ -241,7 +234,7 @@ void CVkProto::AppendChatMessage(int id, JSONNODE *pMsg, bool bIsHistory) tszBody = mir_tstrdup(CMString(tszBody) + GetAttachmentDescr(pAttachments)); if (cc->m_bHistoryRead) - AppendChatMessage(cc, uid, msgTime, tszBody, bIsHistory); + AppendChatMessage(cc, mid, uid, msgTime, tszBody, bIsHistory); else { CVkChatMessage *cm = cc->m_msgs.find((CVkChatMessage *)&mid); if (cm == NULL) @@ -253,11 +246,8 @@ void CVkProto::AppendChatMessage(int id, JSONNODE *pMsg, bool bIsHistory) } } -void CVkProto::AppendChatMessage(CVkChatInfo *cc, int uid, int msgTime, LPCTSTR ptszBody, bool bIsHistory) +void CVkProto::AppendChatMessage(CVkChatInfo *cc, int mid, int uid, int msgTime, LPCTSTR ptszBody, bool bIsHistory) { - TCHAR tszId[20]; - _itot(uid, tszId, 10); - CVkChatUser *cu = cc->m_users.find((CVkChatUser*)&uid); if (cu == NULL) { cc->m_users.insert(cu = new CVkChatUser(uid)); @@ -265,6 +255,9 @@ void CVkProto::AppendChatMessage(CVkChatInfo *cc, int uid, int msgTime, LPCTSTR cu->m_bUnknown = true; } + TCHAR tszId[20]; + _itot(uid, tszId, 10); + GCDEST gcd = { m_szModuleName, cc->m_tszId, GC_EVENT_MESSAGE }; GCEVENT gce = { sizeof(GCEVENT), &gcd }; gce.bIsMe = uid == m_myUserId; @@ -326,18 +319,9 @@ int CVkProto::OnChatEvent(WPARAM, LPARAM lParam) TCHAR *buf = NEWTSTR_ALLOCA(gch->ptszText); rtrimt(buf); UnEscapeChatTags(buf); - ptrA szMsg(mir_utf8encodeT(buf)); - char szId[20]; - _itoa(cc->m_chatid, szId, 10); - - HttpParam params[] = { - { "type", "1" }, - { "chat_id", szId }, - { "message", szMsg }, - { "access_token", m_szAccessToken } - }; - PushAsyncHttpRequest(REQUEST_GET, "/method/messages.send.json", true, &CVkProto::OnSendChatMsg, SIZEOF(params), params); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.send.json", true, &CVkProto::OnSendChatMsg) + << INT_PARAM("type", 1) << INT_PARAM("chat_id", cc->m_chatid) << TCHAR_PARAM("message", buf)); } case GC_USER_LOGMENU: @@ -358,7 +342,7 @@ void CVkProto::OnSendChatMsg(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) JSONROOT pRoot; JSONNODE *pResponse = CheckJsonResponse(pReq, reply, pRoot); if (pResponse != NULL) - m_sendIds.insert((HANDLE)json_as_int(pResponse)); + m_sendIds.insert((void*)json_as_int(pResponse)); } } @@ -414,19 +398,12 @@ LPTSTR CVkProto::ChangeChatTopic(CVkChatInfo *cc) void CVkProto::LogMenuHook(CVkChatInfo *cc, GCHOOK *gch) { HANDLE hContact; - char szChatId[20]; - _itoa(cc->m_chatid, szChatId, 10); switch (gch->dwData) { case IDM_TOPIC: if (LPTSTR ptszNew = ChangeChatTopic(cc)) { - ptrA szTitle(mir_utf8encodeT(ptszNew)); - HttpParam params[] = { - { "title", szTitle }, - { "chat_id", szChatId }, - { "access_token", m_szAccessToken } - }; - PushAsyncHttpRequest(REQUEST_GET, "/method/messages.editChat.json", true, NULL, SIZEOF(params), params); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.editChat.json", true, &CVkProto::OnReceiveSmth) + << TCHAR_PARAM("title", ptszNew) << INT_PARAM("chat_id", cc->m_chatid)); mir_free(ptszNew); } break; @@ -435,17 +412,9 @@ void CVkProto::LogMenuHook(CVkChatInfo *cc, GCHOOK *gch) hContact = (HANDLE)DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_INVITE), NULL, InviteDlgProc, (LPARAM)this); if (hContact != NULL) { int uid = getDword(hContact, "ID", -1); - if (uid == -1) break; - - char szUid[20]; - _itoa(uid, szUid, 10); - - HttpParam params[] = { - { "uid", szUid }, - { "chat_id", szChatId }, - { "access_token", m_szAccessToken } - }; - PushAsyncHttpRequest(REQUEST_GET, "/method/messages.addChatUser.json", true, NULL, SIZEOF(params), params); + if (uid != -1) + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.addChatUser.json", true, &CVkProto::OnReceiveSmth) + << INT_PARAM("uid", uid) << INT_PARAM("chat_id", cc->m_chatid)); } break; @@ -454,12 +423,8 @@ void CVkProto::LogMenuHook(CVkChatInfo *cc, GCHOOK *gch) TranslateT("This chat is going to be destroyed forever with all its contents. This action cannot be undone. Are you sure?"), TranslateT("Warning"), MB_YESNOCANCEL | MB_ICONQUESTION)) { - HttpParam params[] = { - { "chat_id", szChatId }, - { "access_token", m_szAccessToken } - }; - AsyncHttpRequest *pReq = PushAsyncHttpRequest(REQUEST_GET, "/method/messages.deleteDialog.json", true, &CVkProto::OnChatDestroy, SIZEOF(params), params); - pReq->pUserInfo = cc; + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.deleteDialog.json", true, &CVkProto::OnChatDestroy) + << INT_PARAM("chat_id", cc->m_chatid))->pUserInfo = cc; } break; } @@ -498,12 +463,8 @@ void CVkProto::NickMenuHook(CVkChatInfo *cc, GCHOOK *gch) break; case IDM_KICK: - HttpParam params[] = { - { "chat_id", szChatId }, - { "uid", szUid }, - { "access_token", m_szAccessToken } - }; - PushAsyncHttpRequest(REQUEST_GET, "/method/messages.removeChatUser.json", true, NULL, SIZEOF(params), params); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.removeChatUser.json", true, &CVkProto::OnReceiveSmth) + << INT_PARAM("chat_id", cc->m_chatid) << INT_PARAM("uid", cu->m_uid)); cu->m_bUnknown = true; break; } @@ -642,14 +603,8 @@ INT_PTR CVkProto::SvcCreateChat(WPARAM, LPARAM) void CVkProto::CreateNewChat(LPCSTR uids, LPCTSTR ptszTitle) { - ptrA szTitle(mir_utf8encodeT(ptszTitle)); - - HttpParam params[] = { - { "title", szTitle }, - { "uids", uids }, - { "access_token", m_szAccessToken } - }; - PushAsyncHttpRequest(REQUEST_GET, "/method/messages.createChat.json", true, &CVkProto::OnCreateNewChat, SIZEOF(params), params); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.createChat.json", true, &CVkProto::OnCreateNewChat) + << TCHAR_PARAM("title", ptszTitle) << CHAR_PARAM("uids", uids)); } void CVkProto::OnCreateNewChat(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp index b94497d54b..ec69b2a3ee 100644 --- a/protocols/VKontakte/src/vk_proto.cpp +++ b/protocols/VKontakte/src/vk_proto.cpp @@ -175,19 +175,12 @@ int CVkProto::SendMsg(HANDLE hContact, int flags, const char *msg) else msg = mir_utf8encode(msg); - char szID[40]; - _itoa(userID, szID, 10); - HttpParam params[] = { - { "type", "0" }, - { "uid", szID }, - { "message", szMsg }, - { "access_token", m_szAccessToken } - }; - ULONG msgId = ::InterlockedIncrement(&m_msgId); - AsyncHttpRequest *pReq = PushAsyncHttpRequest(REQUEST_GET, "/method/messages.send.json", true, &CVkProto::OnSendMessage, SIZEOF(params), params); + AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.send.json", true, &CVkProto::OnSendMessage) + << INT_PARAM("type", 0) << INT_PARAM("uid", m_myUserId) << CHAR_PARAM("message", msg); pReq->pData = (char*)hContact; pReq->pUserInfo = (void*)msgId; + Push(pReq); if (!m_bServerDelivery) ForkThread(&CVkProto::SendMsgAck, new TFakeAckParams(hContact, msgId)); diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index 50fb47cef6..f17e6419c9 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -23,16 +23,54 @@ typedef void (CVkProto::*VK_REQUEST_HANDLER)(NETLIBHTTPREQUEST*, struct AsyncHtt struct AsyncHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject { AsyncHttpRequest(); + AsyncHttpRequest(CVkProto*, int iRequestType, LPCSTR szUrl, bool bSecure, VK_REQUEST_HANDLER pFunc); ~AsyncHttpRequest(); void AddHeader(LPCSTR, LPCSTR); void Redirect(NETLIBHTTPREQUEST*); - bool bNeedsRestart, bIsMainConn; + CMStringA m_szUrl; + bool bNeedsRestart, bIsMainConn, m_bHasParams; VK_REQUEST_HANDLER m_pFunc; void *pUserInfo; }; +struct PARAM +{ + LPCSTR szName; + __forceinline PARAM(LPCSTR _name) : szName(_name) {} +}; + +struct INT_PARAM : public PARAM +{ + int iValue; + __forceinline INT_PARAM(LPCSTR _name, int _value) : + PARAM(_name), iValue(_value) + { + } +}; +AsyncHttpRequest* operator<<(AsyncHttpRequest*, const INT_PARAM&); + +struct CHAR_PARAM : public PARAM +{ + LPCSTR szValue; + __forceinline CHAR_PARAM(LPCSTR _name, LPCSTR _value) : + PARAM(_name), szValue(_value) + { + } +}; +AsyncHttpRequest* operator<<(AsyncHttpRequest*, const CHAR_PARAM&); + +struct TCHAR_PARAM : public PARAM +{ + LPCTSTR tszValue; + __forceinline TCHAR_PARAM(LPCSTR _name, LPCTSTR _value) : + PARAM(_name), tszValue(_value) + { + } +}; +AsyncHttpRequest* operator<<(AsyncHttpRequest*, const TCHAR_PARAM&); + struct CVkChatMessage : public MZeroedObject { CVkChatMessage(int _id) : m_mid(_id) {} @@ -176,6 +214,8 @@ struct CVkProto : public PROTO __forceinline void setGroup(LPCTSTR grp) { m_defaultGroup = mir_tstrdup(grp); } private: + friend struct AsyncHttpRequest; + LIST m_arRequestsQueue; CRITICAL_SECTION m_csRequestsQueue; CMStringA m_prevUrl; @@ -202,8 +242,7 @@ private: void ExecuteRequest(AsyncHttpRequest*); void __cdecl WorkerThread(void*); - AsyncHttpRequest* PushAsyncHttpRequest(int iRequestType, LPCSTR szUrl, bool bSecure, VK_REQUEST_HANDLER pFunc, int nParams = 0, HttpParam *pParams = 0, int iTimeout = 10000); - AsyncHttpRequest* PushAsyncHttpRequest(AsyncHttpRequest*, int iTimeout = 10000); + AsyncHttpRequest* Push(AsyncHttpRequest*, int iTimeout = 10000); bool RunCaptchaForm(LPCSTR szUrl, CMStringA&); bool AutoFillForm(char*, CMStringA&, CMStringA&); @@ -239,14 +278,14 @@ private: bool m_prevError; LIST m_sendIds; - bool CheckMid(int msgid); + bool CheckMid(int guid); static INT_PTR CALLBACK OptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); OBJLIST m_chats; CVkChatInfo* AppendChat(int id, JSONNODE *pNode); void AppendChatMessage(int id, JSONNODE *pMsg, bool bIsHistory); - void AppendChatMessage(CVkChatInfo *cc, int uid, int msgTime, LPCTSTR ptszBody, bool bIsHistory); + void AppendChatMessage(CVkChatInfo *cc, int mid, int uid, int msgTime, LPCTSTR ptszBody, bool bIsHistory); void RetrieveChatInfo(CVkChatInfo*); void OnReceiveChatInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*); void OnSendChatMsg(NETLIBHTTPREQUEST*, AsyncHttpRequest*); diff --git a/protocols/VKontakte/src/vk_queue.cpp b/protocols/VKontakte/src/vk_queue.cpp index 46a344c753..f02dcde11a 100644 --- a/protocols/VKontakte/src/vk_queue.cpp +++ b/protocols/VKontakte/src/vk_queue.cpp @@ -35,6 +35,7 @@ void CVkProto::UninitQueue() void CVkProto::ExecuteRequest(AsyncHttpRequest *pReq) { LBL_Restart: + pReq->szUrl = pReq->m_szUrl.GetBuffer(); NETLIBHTTPREQUEST *reply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)pReq); if (reply != NULL) { if (pReq->m_pFunc != NULL) @@ -55,35 +56,7 @@ LBL_Restart: ///////////////////////////////////////////////////////////////////////////////////////// -AsyncHttpRequest* CVkProto::PushAsyncHttpRequest(int iRequestType, LPCSTR szUrl, bool bSecure, VK_REQUEST_HANDLER pFunc, int nParams, HttpParam *pParams, int iTimeout) -{ - AsyncHttpRequest *pReq = new AsyncHttpRequest(); - pReq->flags = NLHRF_NODUMPHEADERS | NLHRF_DUMPASTEXT | NLHRF_HTTP11 | NLHRF_REDIRECT; - if (bSecure) - pReq->flags |= NLHRF_SSL; - - CMStringA url; - if (*szUrl == '/') { // relative url leads to a site - url = ((bSecure) ? "https://" : "http://") + CMStringA("api.vk.com"); - url += szUrl; - pReq->bIsMainConn = true; - } - else url = szUrl; - - for (int i=0; i < nParams; i++) { - url.AppendChar((i == 0) ? '?' : '&'); - url += pParams[i].szName; - url.AppendChar('='); - url += ptrA( mir_urlEncode(pParams[i].szValue)); - } - - pReq->requestType = iRequestType; - pReq->szUrl = mir_strdup(url); - pReq->m_pFunc = pFunc; - return PushAsyncHttpRequest(pReq, iTimeout); -} - -AsyncHttpRequest* CVkProto::PushAsyncHttpRequest(AsyncHttpRequest *pReq, int iTimeout) +AsyncHttpRequest* CVkProto::Push(AsyncHttpRequest *pReq, int iTimeout) { pReq->timeout = iTimeout; { @@ -107,14 +80,9 @@ void CVkProto::WorkerThread(void*) else { // Initialize new OAuth session extern char szBlankUrl[]; - HttpParam params[] = { - { "client_id", VK_APP_ID }, - { "scope", "friends,photos,audio,video,wall,messages,offline" }, - { "redirect_uri", szBlankUrl }, - { "display", "wap" }, - { "response_type", "token" } - }; - PushAsyncHttpRequest(REQUEST_GET, "/oauth/authorize", false, &CVkProto::OnOAuthAuthorize, SIZEOF(params), params); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/oauth/authorize", false, &CVkProto::OnOAuthAuthorize) + << INT_PARAM("client_id", VK_APP_ID) << CHAR_PARAM("scope", "friends,photos,audio,video,wall,messages,offline") + << CHAR_PARAM("redirect_uri", szBlankUrl) << CHAR_PARAM("display", "wap") << CHAR_PARAM("response_type", "token")); } while(true) { @@ -139,3 +107,30 @@ void CVkProto::WorkerThread(void*) m_hWorkerThread = 0; debugLogA("CVkProto::WorkerThread: leaving"); } + +///////////////////////////////////////////////////////////////////////////////////////// + +AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const INT_PARAM ¶m) +{ + CMStringA &s = pReq->m_szUrl; + s.AppendFormat("%c%s=%i", pReq->m_bHasParams ? '&' : '?', param.szName, param.iValue); + pReq->m_bHasParams = true; + return pReq; +} + +AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const CHAR_PARAM ¶m) +{ + CMStringA &s = pReq->m_szUrl; + s.AppendFormat("%c%s=%s", pReq->m_bHasParams ? '&' : '?', param.szName, ptrA(mir_urlEncode(param.szValue))); + pReq->m_bHasParams = true; + return pReq; +} + +AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const TCHAR_PARAM ¶m) +{ + ptrA szValue(mir_utf8encodeT(param.tszValue)); + CMStringA &s = pReq->m_szUrl; + s.AppendFormat("%c%s=%s", pReq->m_bHasParams ? '&' : '?', param.szName, ptrA(mir_urlEncode(szValue))); + pReq->m_bHasParams = true; + return pReq; +} diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp index eb24d1b226..e1b47166f4 100644 --- a/protocols/VKontakte/src/vk_thread.cpp +++ b/protocols/VKontakte/src/vk_thread.cpp @@ -76,13 +76,11 @@ void CVkProto::SetServerStatus(int iNewStatus) if (iNewStatus == ID_STATUS_OFFLINE) { m_iStatus = ID_STATUS_OFFLINE; - HttpParam param = { "access_token", m_szAccessToken }; - PushAsyncHttpRequest(REQUEST_GET, "/method/account.setOffline.json", true, &CVkProto::OnReceiveSmth, 1, ¶m); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/account.setOffline.json", true, &CVkProto::OnReceiveSmth)); } else if (iNewStatus != ID_STATUS_INVISIBLE) { m_iStatus = ID_STATUS_ONLINE; - HttpParam param = { "access_token", m_szAccessToken }; - PushAsyncHttpRequest(REQUEST_GET, "/method/account.setOnline.json", true, &CVkProto::OnReceiveSmth, 1, ¶m); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/account.setOnline.json", true, &CVkProto::OnReceiveSmth)); } else m_iStatus = ID_STATUS_INVISIBLE; @@ -128,12 +126,11 @@ void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq pReq->m_pFunc = &CVkProto::OnOAuthAuthorize; pReq->AddHeader("Referer", m_prevUrl); pReq->Redirect(reply); - if (pReq->szUrl) { + if (pReq->m_szUrl) { ApplyCookies(pReq); - m_prevUrl = pReq->szUrl; + m_prevUrl = pReq->m_szUrl; } - - PushAsyncHttpRequest(pReq); + Push(pReq); } } else ConnectionFailed(LOGINERR_NOSERVER); @@ -170,20 +167,19 @@ LBL_NoForm: pReq->flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11; pReq->pData = mir_strdup(szBody); pReq->dataLength = szBody.GetLength(); - pReq->szUrl = mir_strdup(szAction); m_prevUrl = pReq->szUrl; + pReq->m_szUrl = szAction; m_prevUrl = pReq->m_szUrl; pReq->m_pFunc = &CVkProto::OnOAuthAuthorize; pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); pReq->Redirect(reply); ApplyCookies(pReq); - PushAsyncHttpRequest(pReq); + Push(pReq); } ///////////////////////////////////////////////////////////////////////////////////////// void CVkProto::RetrieveMyInfo() { - HttpParam param = { "access_token", m_szAccessToken }; - PushAsyncHttpRequest(REQUEST_GET, "/method/getUserInfoEx.json", true, &CVkProto::OnReceiveMyInfo, 1, ¶m); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/getUserInfoEx.json", true, &CVkProto::OnReceiveMyInfo)); } void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) @@ -219,15 +215,8 @@ void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) void CVkProto::RetrieveUserInfo(LONG userID) { - char szUserId[40]; - _itoa(userID, szUserId, 10); - - HttpParam params[] = { - { "fields", "uid,first_name,last_name,photo_medium,sex,bdate,city,relation" }, - { "uids", szUserId }, - { "access_token", m_szAccessToken } - }; - PushAsyncHttpRequest(REQUEST_GET, "/method/getProfiles.json", true, &CVkProto::OnReceiveUserInfo, SIZEOF(params), params); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/getProfiles.json", true, &CVkProto::OnReceiveUserInfo) + << INT_PARAM("uids", userID) << CHAR_PARAM("fields", "uid,first_name,last_name,photo_medium,sex,bdate,city,relation")); } void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) @@ -292,13 +281,9 @@ void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe void CVkProto::RetrieveFriends() { debugLogA("CVkProto::RetrieveFriends"); - - HttpParam params[] = { - { "fields", "uid,first_name,last_name,photo_medium,sex,country,timezone,contacts" }, - { "count", "1000" }, - { "access_token", m_szAccessToken } - }; - PushAsyncHttpRequest(REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends, SIZEOF(params), params); + + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/friends.get.json", true, &CVkProto::OnReceiveFriends) + << INT_PARAM("count", 1000) << CHAR_PARAM("fields", "uid,first_name,last_name,photo_medium,sex,country,timezone,contacts")); } void CVkProto::OnReceiveFriends(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) @@ -361,11 +346,8 @@ void CVkProto::MarkMessagesRead(const CMStringA &mids) if (mids.IsEmpty()) return; - HttpParam params[] = { - { "mids", mids }, - { "access_token", m_szAccessToken } - }; - PushAsyncHttpRequest(REQUEST_GET, "/method/messages.markAsRead.json", true, &CVkProto::OnReceiveSmth, SIZEOF(params), params); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.markAsRead.json", true, &CVkProto::OnReceiveSmth) + << CHAR_PARAM("mids", mids)); } void CVkProto::RetrieveMessagesByIds(const CMStringA &mids) @@ -373,22 +355,16 @@ void CVkProto::RetrieveMessagesByIds(const CMStringA &mids) if (mids.IsEmpty()) return; - HttpParam params[] = { - { "mids", mids }, - { "access_token", m_szAccessToken } - }; - PushAsyncHttpRequest(REQUEST_GET, "/method/messages.getById.json", true, &CVkProto::OnReceiveMessages, SIZEOF(params), params); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.getById.json", true, &CVkProto::OnReceiveMessages) + << CHAR_PARAM("mids", mids)); } void CVkProto::RetrieveUnreadMessages() { debugLogA("CVkProto::RetrieveMessages"); - HttpParam params[] = { - { "code", "return { \"msgs\":API.messages.get({\"filters\":1}), \"dlgs\":API.messages.getDialogs() };" }, - { "access_token", m_szAccessToken } - }; - PushAsyncHttpRequest(REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveMessages, SIZEOF(params), params); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.json", true, &CVkProto::OnReceiveMessages) + << CHAR_PARAM("code", "return { \"msgs\":API.messages.get({\"filters\":1}), \"dlgs\":API.messages.getDialogs() };")); } static char* szImageTypes[] = { "src_xxxbig", "src_xxbig", "src_xbig", "src_big", "src", "src_small" }; @@ -490,8 +466,7 @@ void CVkProto::RetrievePollingInfo() { debugLogA("CVkProto::RetrievePollingInfo"); - HttpParam param = { "access_token", m_szAccessToken }; - PushAsyncHttpRequest(REQUEST_GET, "/method/messages.getLongPollServer.json", true, &CVkProto::OnReceivePollingInfo, 1, ¶m); + Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/messages.getLongPollServer.json", true, &CVkProto::OnReceivePollingInfo)); } void CVkProto::OnReceivePollingInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) @@ -527,44 +502,16 @@ void CVkProto::PollUpdates(JSONNODE *pUpdates) switch (json_as_int( json_at(pChild, 0))) { case VKPOLL_MSG_ADDED: // new message msgid = json_as_int(json_at(pChild, 1)); - flags = json_as_int(json_at(pChild, 2)); // skip outgoing messages sent from a client - if (flags & VKFLAG_MSGOUTBOX) { - if (!(flags & VKFLAG_MSGCHAT)) + flags = json_as_int(json_at(pChild, 2)); + if ((flags & VKFLAG_MSGOUTBOX) && !(flags & VKFLAG_MSGCHAT)) + if (CheckMid(msgid)) break; - // my chat message - int from_id = json_as_int(json_at(pChild, 3)); - if (from_id > 2000000000) { - from_id -= 2000000000; - CVkChatInfo *cc = m_chats.find((CVkChatInfo*)&from_id); - if (cc != NULL) { - TCHAR tszId[20]; - _itot(m_myUserId, tszId, 10); - ptrT tszBody(json_as_string(json_at(pChild, 6))); - - CVkChatUser *cu = cc->m_users.find((CVkChatUser*)&m_myUserId); - LPCTSTR ptszNick = (cu) ? cu->m_tszTitle : TranslateT("me"); - - GCDEST gcd = { m_szModuleName, cc->m_tszId, GC_EVENT_MESSAGE }; - GCEVENT gce = { sizeof(GCEVENT), &gcd }; - gce.bIsMe = true; - gce.ptszUID = tszId; - gce.time = time(0); - gce.dwFlags = GCEF_ADDTOLOG; - gce.ptszNick = ptszNick; - gce.ptszText = tszBody; - CallServiceSync(MS_GC_EVENT, 0, (LPARAM)&gce); - } - } - } - - if ( !CheckMid(msgid)) { - if ( !mids.IsEmpty()) - mids.AppendChar(','); - mids.AppendFormat("%d", msgid); - } + if (!mids.IsEmpty()) + mids.AppendChar(','); + mids.AppendFormat("%d", msgid); break; case VKPOLL_USR_ONLINE: @@ -604,7 +551,7 @@ int CVkProto::PollServer() NETLIBHTTPREQUEST req = { sizeof(req) }; req.requestType = REQUEST_GET; req.szUrl = NEWSTR_ALLOCA(CMStringA().Format("http://%s?act=a_check&key=%s&ts=%s&wait=25&access_token=%s", m_pollingServer, m_pollingKey, m_pollingTs, m_szAccessToken)); - req.flags = NLHRF_NODUMPHEADERS | NLHRF_PERSISTENT; + req.flags = VK_NODUMPHEADERS | NLHRF_PERSISTENT; req.timeout = 30000; req.nlc = m_pollingConn; -- cgit v1.2.3