summaryrefslogtreecommitdiff
path: root/protocols
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2014-01-12 11:59:23 +0000
committerGeorge Hazan <george.hazan@gmail.com>2014-01-12 11:59:23 +0000
commite528a508b7e307bd35b142b269a0bbd1b6813e89 (patch)
treee7e0a45738745420c563b141398e60d51558b46c /protocols
parent484267e90233bcef4ed9bda249053f5657b3974d (diff)
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
Diffstat (limited to 'protocols')
-rw-r--r--protocols/VKontakte/src/misc.cpp34
-rw-r--r--protocols/VKontakte/src/vk.h11
-rw-r--r--protocols/VKontakte/src/vk_avatars.cpp4
-rw-r--r--protocols/VKontakte/src/vk_captcha.cpp7
-rw-r--r--protocols/VKontakte/src/vk_chats.cpp89
-rw-r--r--protocols/VKontakte/src/vk_proto.cpp13
-rw-r--r--protocols/VKontakte/src/vk_proto.h49
-rw-r--r--protocols/VKontakte/src/vk_queue.cpp69
-rw-r--r--protocols/VKontakte/src/vk_thread.cpp107
9 files changed, 168 insertions, 215 deletions
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 <http://www.gnu.org/licenses/>.
*/
-#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 <http://www.gnu.org/licenses/>.
#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<CVkProto>
__forceinline void setGroup(LPCTSTR grp) { m_defaultGroup = mir_tstrdup(grp); }
private:
+ friend struct AsyncHttpRequest;
+
LIST<AsyncHttpRequest> 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<void> m_sendIds;
- bool CheckMid(int msgid);
+ bool CheckMid(int guid);
static INT_PTR CALLBACK OptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
OBJLIST<CVkChatInfo> 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 &param)
+{
+ 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 &param)
+{
+ 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 &param)
+{
+ 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, &param);
+ 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, &param);
+ 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, &param);
+ 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, &param);
+ 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;