summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-12-21 15:59:56 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-12-21 15:59:56 +0300
commitd30afe819abb03b139190c020db271888fab5eb1 (patch)
treeded6ed9860a4ea622a08450113400f9cbf9f47e9
parentd78ec3edaa1f6c3d6cb80aa2767a38afda76bc25 (diff)
attempt to unify AsyncHttpRequest in various protocols
-rw-r--r--include/m_netlib.h29
-rw-r--r--libs/win32/mir_app.libbin186428 -> 189168 bytes
-rw-r--r--libs/win64/mir_app.libbin181650 -> 184494 bytes
-rw-r--r--protocols/Discord/src/connection.cpp4
-rw-r--r--protocols/Discord/src/http.cpp68
-rw-r--r--protocols/Discord/src/proto.h17
-rw-r--r--protocols/VKontakte/src/vk_chats.cpp5
-rw-r--r--protocols/VKontakte/src/vk_files.cpp25
-rw-r--r--protocols/VKontakte/src/vk_messages.cpp5
-rw-r--r--protocols/VKontakte/src/vk_proto.h2
-rw-r--r--protocols/VKontakte/src/vk_queue.cpp37
-rw-r--r--protocols/VKontakte/src/vk_search.cpp21
-rw-r--r--protocols/VKontakte/src/vk_struct.cpp23
-rw-r--r--protocols/VKontakte/src/vk_struct.h18
-rw-r--r--protocols/VKontakte/src/vk_wallpost.cpp5
-rw-r--r--src/mir_app/src/MHttpRequest.cpp93
-rw-r--r--src/mir_app/src/mir_app.def9
-rw-r--r--src/mir_app/src/mir_app64.def9
-rwxr-xr-xsrc/mir_core/src/http.cpp25
19 files changed, 196 insertions, 199 deletions
diff --git a/include/m_netlib.h b/include/m_netlib.h
index c23d0fddc1..6c504e2702 100644
--- a/include/m_netlib.h
+++ b/include/m_netlib.h
@@ -550,6 +550,35 @@ public:
Netlib_FreeHttpRequest(_p);
}
};
+
+struct MIR_APP_EXPORT MHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
+{
+ MHttpRequest();
+ ~MHttpRequest();
+
+ CMStringA m_szUrl;
+ CMStringA m_szParam;
+ void *pUserInfo;
+
+ void AddHeader(const char *szName, const char *szValue);
+};
+
+template <class T>
+class MTHttpRequest : public MHttpRequest
+{
+public:
+ __inline MTHttpRequest()
+ {}
+
+ typedef void (T::*MTHttpRequestHandler)(NETLIBHTTPREQUEST*, struct AsyncHttpRequest*);
+ MTHttpRequestHandler m_pFunc = nullptr;
+};
+
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const INT_PARAM&);
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const INT64_PARAM&);
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const CHAR_PARAM&);
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const WCHAR_PARAM&);
+
#endif
/////////////////////////////////////////////////////////////////////////////////////////
diff --git a/libs/win32/mir_app.lib b/libs/win32/mir_app.lib
index 0b3694c692..7d1f32b898 100644
--- a/libs/win32/mir_app.lib
+++ b/libs/win32/mir_app.lib
Binary files differ
diff --git a/libs/win64/mir_app.lib b/libs/win64/mir_app.lib
index c03d0b753b..50cddcd753 100644
--- a/libs/win64/mir_app.lib
+++ b/libs/win64/mir_app.lib
Binary files differ
diff --git a/protocols/Discord/src/connection.cpp b/protocols/Discord/src/connection.cpp
index 80ec0c172a..b986921046 100644
--- a/protocols/Discord/src/connection.cpp
+++ b/protocols/Discord/src/connection.cpp
@@ -43,8 +43,8 @@ void CDiscordProto::ExecuteRequest(AsyncHttpRequest *pReq)
debugLogA("Executing request #%d:\n%s", pReq->m_iReqNum, pReq->szUrl);
NETLIBHTTPREQUEST *reply = Netlib_HttpTransaction(m_hNetlibUser, pReq);
if (reply != nullptr) {
- if (pReq->m_pCallback != nullptr)
- (this->*(pReq->m_pCallback))(reply, pReq);
+ if (pReq->m_pFunc != nullptr)
+ (this->*(pReq->m_pFunc))(reply, pReq);
if (pReq->m_bMainSite)
m_hAPIConnection = reply->nlc;
diff --git a/protocols/Discord/src/http.cpp b/protocols/Discord/src/http.cpp
index 743c615605..cf368a5270 100644
--- a/protocols/Discord/src/http.cpp
+++ b/protocols/Discord/src/http.cpp
@@ -38,7 +38,7 @@ AsyncHttpRequest::AsyncHttpRequest()
m_iReqNum = ::InterlockedIncrement(&g_reqNum);
}
-AsyncHttpRequest::AsyncHttpRequest(CDiscordProto *ppro, int iRequestType, LPCSTR _url, HttpCallback pFunc, JSONNode *pRoot)
+AsyncHttpRequest::AsyncHttpRequest(CDiscordProto *ppro, int iRequestType, LPCSTR _url, MTHttpRequestHandler pFunc, JSONNode *pRoot)
{
cbSize = sizeof(NETLIBHTTPREQUEST);
@@ -66,72 +66,8 @@ AsyncHttpRequest::AsyncHttpRequest(CDiscordProto *ppro, int iRequestType, LPCSTR
}
AddHeader("Content-Type", "application/json");
+ m_pFunc = pFunc;
requestType = iRequestType;
- m_pCallback = pFunc;
- pUserInfo = nullptr;
m_iErrorCode = 0;
m_iReqNum = ::InterlockedIncrement(&g_reqNum);
}
-
-AsyncHttpRequest::~AsyncHttpRequest()
-{
- for (int i = 0; i < headersCount; i++) {
- mir_free(headers[i].szName);
- mir_free(headers[i].szValue);
- }
- mir_free(headers);
- mir_free(pData);
-}
-
-void AsyncHttpRequest::AddHeader(LPCSTR szName, LPCSTR szValue)
-{
- for (int i = 0; i < headersCount; i++)
- if (!mir_strcmp(headers[i].szName, szName)) {
- replaceStr(headers[i].szValue, szValue);
- return;
- }
-
- headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount + 1));
- headers[headersCount].szName = mir_strdup(szName);
- headers[headersCount].szValue = mir_strdup(szValue);
- headersCount++;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const INT_PARAM &param)
-{
- CMStringA &s = pReq->m_szParam;
- if (!s.IsEmpty())
- s.AppendChar('&');
- s.AppendFormat("%s=%i", param.szName, param.iValue);
- return pReq;
-}
-
-AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const INT64_PARAM &param)
-{
- CMStringA &s = pReq->m_szParam;
- if (!s.IsEmpty())
- s.AppendChar('&');
- s.AppendFormat("%s=%lld", param.szName, param.iValue);
- return pReq;
-}
-
-AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const CHAR_PARAM &param)
-{
- CMStringA &s = pReq->m_szParam;
- if (!s.IsEmpty())
- s.AppendChar('&');
- s.AppendFormat("%s=%s", param.szName, ptrA(mir_urlEncode(param.szValue)));
- return pReq;
-}
-
-AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const WCHAR_PARAM &param)
-{
- T2Utf szValue(param.wszValue);
- CMStringA &s = pReq->m_szParam;
- if (!s.IsEmpty())
- s.AppendChar('&');
- s.AppendFormat("%s=%s", param.szName, ptrA(mir_urlEncode(szValue)));
- return pReq;
-}
diff --git a/protocols/Discord/src/proto.h b/protocols/Discord/src/proto.h
index fd9bc8d632..7321e9efa2 100644
--- a/protocols/Discord/src/proto.h
+++ b/protocols/Discord/src/proto.h
@@ -8,30 +8,17 @@ __forceinline int compareInt64(const SnowFlake i1, const SnowFlake i2)
}
class CDiscordProto;
-typedef void (CDiscordProto::*HttpCallback)(NETLIBHTTPREQUEST*, struct AsyncHttpRequest*);
typedef void (CDiscordProto::*GatewayHandlerFunc)(const JSONNode&);
-struct AsyncHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
+struct AsyncHttpRequest : public MTHttpRequest<CDiscordProto>
{
AsyncHttpRequest();
- AsyncHttpRequest(CDiscordProto*, int iRequestType, LPCSTR szUrl, HttpCallback pFunc, JSONNode *pNode = nullptr);
- ~AsyncHttpRequest();
+ AsyncHttpRequest(CDiscordProto*, int iRequestType, LPCSTR szUrl, MTHttpRequestHandler pFunc, JSONNode *pNode = nullptr);
- void AddHeader(LPCSTR, LPCSTR);
-
- CMStringA m_szUrl;
- CMStringA m_szParam;
- HttpCallback m_pCallback;
int m_iErrorCode, m_iReqNum;
bool m_bMainSite;
- void *pUserInfo;
};
-AsyncHttpRequest* operator<<(AsyncHttpRequest*, const INT_PARAM&);
-AsyncHttpRequest* operator<<(AsyncHttpRequest*, const INT64_PARAM&);
-AsyncHttpRequest* operator<<(AsyncHttpRequest*, const CHAR_PARAM&);
-AsyncHttpRequest* operator<<(AsyncHttpRequest*, const WCHAR_PARAM&);
-
/////////////////////////////////////////////////////////////////////////////////////////
struct CDiscordRole : public MZeroedObject
diff --git a/protocols/VKontakte/src/vk_chats.cpp b/protocols/VKontakte/src/vk_chats.cpp
index 46c990b205..a6f6d4cfd6 100644
--- a/protocols/VKontakte/src/vk_chats.cpp
+++ b/protocols/VKontakte/src/vk_chats.cpp
@@ -565,9 +565,8 @@ INT_PTR __cdecl CVkProto::OnJoinChat(WPARAM hContact, LPARAM)
if (chat_id == VK_INVALID_USER)
return 1;
- AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, &CVkProto::OnSendChatMsg, AsyncHttpRequest::rpHigh)
- << INT_PARAM("chat_id", chat_id)
- << WCHAR_PARAM("message", m_vkOptions.pwszReturnChatMessage);
+ AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, &CVkProto::OnSendChatMsg, AsyncHttpRequest::rpHigh);
+ pReq << INT_PARAM("chat_id", chat_id) << WCHAR_PARAM("message", m_vkOptions.pwszReturnChatMessage);
pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded");
Push(pReq);
db_unset(hContact, m_szModuleName, "off");
diff --git a/protocols/VKontakte/src/vk_files.cpp b/protocols/VKontakte/src/vk_files.cpp
index 68fbe7da09..717ba18dcf 100644
--- a/protocols/VKontakte/src/vk_files.cpp
+++ b/protocols/VKontakte/src/vk_files.cpp
@@ -263,10 +263,8 @@ void CVkProto::OnReciveUpload(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
SendFileFiled(fup, VKERR_INVALID_PARAMETERS);
return;
}
- pUploadReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/photos.saveMessagesPhoto.json", true, &CVkProto::OnReciveUploadFile)
- << WCHAR_PARAM("server", server)
- << WCHAR_PARAM("photo", upload)
- << WCHAR_PARAM("hash", hash);
+ pUploadReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/photos.saveMessagesPhoto.json", true, &CVkProto::OnReciveUploadFile);
+ pUploadReq << WCHAR_PARAM("server", server) << WCHAR_PARAM("photo", upload) << WCHAR_PARAM("hash", hash);
break;
case CVkFileUploadParam::typeAudio:
upload = jnRoot["audio"].as_mstring();
@@ -274,10 +272,8 @@ void CVkProto::OnReciveUpload(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
SendFileFiled(fup, VKERR_INVALID_PARAMETERS);
return;
}
- pUploadReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/audio.save.json", true, &CVkProto::OnReciveUploadFile)
- << WCHAR_PARAM("server", server)
- << WCHAR_PARAM("audio", upload)
- << WCHAR_PARAM("hash", hash);
+ pUploadReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/audio.save.json", true, &CVkProto::OnReciveUploadFile);
+ pUploadReq << WCHAR_PARAM("server", server) << WCHAR_PARAM("audio", upload) << WCHAR_PARAM("hash", hash);
break;
case CVkFileUploadParam::typeDoc:
upload = jnRoot["file"].as_mstring();
@@ -285,9 +281,8 @@ void CVkProto::OnReciveUpload(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq)
SendFileFiled(fup, VKERR_INVALID_PARAMETERS);
return;
}
- pUploadReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/docs.save.json", true, &CVkProto::OnReciveUploadFile)
- << CHAR_PARAM("title", fup->fileName())
- << WCHAR_PARAM("file", upload);
+ pUploadReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/docs.save.json", true, &CVkProto::OnReciveUploadFile);
+ pUploadReq << CHAR_PARAM("title", fup->fileName()) << WCHAR_PARAM("file", upload);
break;
default:
SendFileFiled(fup, VKERR_FTYPE_NOT_SUPPORTED);
@@ -359,8 +354,8 @@ void CVkProto::OnReciveUploadFile(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pR
return;
}
- pMsgReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, &CVkProto::OnSendChatMsg, AsyncHttpRequest::rpHigh)
- << INT_PARAM("chat_id", cc->m_chatid);
+ pMsgReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, &CVkProto::OnSendChatMsg, AsyncHttpRequest::rpHigh);
+ pMsgReq << INT_PARAM("chat_id", cc->m_chatid);
pMsgReq->pUserInfo = pReq->pUserInfo;
}
@@ -371,8 +366,8 @@ void CVkProto::OnReciveUploadFile(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pR
return;
}
- pMsgReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, &CVkProto::OnSendMessage, AsyncHttpRequest::rpHigh)
- << INT_PARAM("user_id", userID);
+ pMsgReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true, &CVkProto::OnSendMessage, AsyncHttpRequest::rpHigh);
+ pMsgReq << INT_PARAM("user_id", userID);
pMsgReq->pUserInfo = new CVkSendMsgParam(fup->hContact, fup);
}
diff --git a/protocols/VKontakte/src/vk_messages.cpp b/protocols/VKontakte/src/vk_messages.cpp
index f6cdbf0fc1..63d5ce317b 100644
--- a/protocols/VKontakte/src/vk_messages.cpp
+++ b/protocols/VKontakte/src/vk_messages.cpp
@@ -47,9 +47,8 @@ int CVkProto::SendMsg(MCONTACT hContact, int, const char *szMsg)
ULONG uMsgId = ::InterlockedIncrement(&m_msgId);
AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/messages.send.json", true,
- bIsChat ? &CVkProto::OnSendChatMsg : &CVkProto::OnSendMessage, AsyncHttpRequest::rpHigh)
- << INT_PARAM(bIsChat ? "chat_id" : "peer_id", iUserID)
- << INT_PARAM("random_id", ((LONG)time(0)) * 100 + uMsgId % 100);
+ bIsChat ? &CVkProto::OnSendChatMsg : &CVkProto::OnSendMessage, AsyncHttpRequest::rpHigh);
+ pReq << INT_PARAM(bIsChat ? "chat_id" : "peer_id", iUserID) << INT_PARAM("random_id", ((LONG)time(0)) * 100 + uMsgId % 100);
pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded");
if (StickerId)
diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h
index 6c3d632715..e77bea8472 100644
--- a/protocols/VKontakte/src/vk_proto.h
+++ b/protocols/VKontakte/src/vk_proto.h
@@ -361,7 +361,7 @@ private:
void UninitQueue();
void ExecuteRequest(AsyncHttpRequest*);
void __cdecl WorkerThread(void*);
- AsyncHttpRequest* Push(AsyncHttpRequest *pReq, int iTimeout = 10000);
+ AsyncHttpRequest* Push(MHttpRequest *pReq, int iTimeout = 10000);
bool RunCaptchaForm(LPCSTR szUrl, CMStringA&);
bool ApplyCaptcha(AsyncHttpRequest *pReq, const JSONNode&);
void ConnectionFailed(int iReason);
diff --git a/protocols/VKontakte/src/vk_queue.cpp b/protocols/VKontakte/src/vk_queue.cpp
index ff6b62b9ab..c4ef960cc0 100644
--- a/protocols/VKontakte/src/vk_queue.cpp
+++ b/protocols/VKontakte/src/vk_queue.cpp
@@ -90,8 +90,10 @@ void CVkProto::ExecuteRequest(AsyncHttpRequest *pReq)
/////////////////////////////////////////////////////////////////////////////////////////
-AsyncHttpRequest* CVkProto::Push(AsyncHttpRequest *pReq, int iTimeout)
+AsyncHttpRequest* CVkProto::Push(MHttpRequest *p, int iTimeout)
{
+ AsyncHttpRequest *pReq = (AsyncHttpRequest*)p;
+
debugLogA("CVkProto::Push");
pReq->timeout = iTimeout;
if (pReq->m_bApiReq) {
@@ -131,7 +133,8 @@ void CVkProto::WorkerThread(void*)
else {
// Initialize new OAuth session
extern char szBlankUrl[];
- AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "https://oauth.vk.com/authorize", false, &CVkProto::OnOAuthAuthorize)
+ AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "https://oauth.vk.com/authorize", false, &CVkProto::OnOAuthAuthorize);
+ pReq
<< INT_PARAM("client_id", VK_APP_ID)
<< CHAR_PARAM("scope", Score)
<< CHAR_PARAM("redirect_uri", szBlankUrl)
@@ -203,33 +206,3 @@ void CVkProto::WorkerThread(void*)
m_hWorkerThread = nullptr;
}
}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const INT_PARAM &param)
-{
- CMStringA &s = pReq->m_szParam;
- if (!s.IsEmpty())
- s.AppendChar('&');
- s.AppendFormat("%s=%ld", param.szName, param.iValue);
- return pReq;
-}
-
-AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const CHAR_PARAM &param)
-{
- CMStringA &s = pReq->m_szParam;
- if (!s.IsEmpty())
- s.AppendChar('&');
- s.AppendFormat("%s=%s", param.szName, ptrA(pReq->bExpUrlEncode ? ExpUrlEncode(param.szValue) : mir_urlEncode(param.szValue)));
- return pReq;
-}
-
-AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const WCHAR_PARAM &param)
-{
- T2Utf szValue(param.wszValue);
- CMStringA &s = pReq->m_szParam;
- if (!s.IsEmpty())
- s.AppendChar('&');
- s.AppendFormat("%s=%s", param.szName, ptrA(pReq->bExpUrlEncode ? ExpUrlEncode(szValue) : mir_urlEncode(szValue)));
- return pReq;
-} \ No newline at end of file
diff --git a/protocols/VKontakte/src/vk_search.cpp b/protocols/VKontakte/src/vk_search.cpp
index 3796fbb530..9cba181b6f 100644
--- a/protocols/VKontakte/src/vk_search.cpp
+++ b/protocols/VKontakte/src/vk_search.cpp
@@ -46,11 +46,9 @@ void CVkProto::SearchBasicThread(void *id)
debugLogA("CVkProto::OnSearchBasicThread");
if (!IsOnline())
return;
- AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/users.get.json", true, &CVkProto::OnSearch)
- << WCHAR_PARAM("user_ids", (wchar_t *)id)
- << CHAR_PARAM("fields", "nickname, domain");
- pReq->pUserInfo = nullptr;
- Push(pReq);
+
+ Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/users.get.json", true, &CVkProto::OnSearch)
+ << WCHAR_PARAM("user_ids", (wchar_t *)id) << CHAR_PARAM("fields", "nickname, domain"));
}
void CVkProto::SearchByMailThread(void *email)
@@ -58,10 +56,9 @@ void CVkProto::SearchByMailThread(void *email)
debugLogA("CVkProto::OnSearchBasicThread");
if (!IsOnline())
return;
- AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/account.lookupContacts.json", true, &CVkProto::OnSearchByMail)
- << WCHAR_PARAM("contacts", (wchar_t *)email)
- << CHAR_PARAM("service", "email");
- Push(pReq);
+
+ Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/account.lookupContacts.json", true, &CVkProto::OnSearchByMail)
+ << WCHAR_PARAM("contacts", (wchar_t *)email) << CHAR_PARAM("service", "email"));
}
void __cdecl CVkProto::SearchThread(void *p)
@@ -74,12 +71,10 @@ void __cdecl CVkProto::SearchThread(void *p)
if (!IsOnline())
return;
- AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_GET, "/method/users.search.json", true, &CVkProto::OnSearch)
+ Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/users.search.json", true, &CVkProto::OnSearch)
<< WCHAR_PARAM("q", (wchar_t *)arg)
<< CHAR_PARAM("fields", "nickname, domain")
- << INT_PARAM("count", 200);
- pReq->pUserInfo = p;
- Push(pReq);
+ << INT_PARAM("count", 200))->pUserInfo = p;
}
void CVkProto::FreeProtoShearchStruct(PROTOSEARCHBYNAME *pParam)
diff --git a/protocols/VKontakte/src/vk_struct.cpp b/protocols/VKontakte/src/vk_struct.cpp
index 4f7a58001a..e02430914b 100644
--- a/protocols/VKontakte/src/vk_struct.cpp
+++ b/protocols/VKontakte/src/vk_struct.cpp
@@ -32,17 +32,15 @@ AsyncHttpRequest::AsyncHttpRequest()
bNeedsRestart = false;
bIsMainConn = false;
m_pFunc = nullptr;
- bExpUrlEncode = true;
m_reqNum = ::InterlockedIncrement(&m_reqCount);
m_priority = rpLow;
}
-AsyncHttpRequest::AsyncHttpRequest(CVkProto *ppro, int iRequestType, LPCSTR _url, bool bSecure, VK_REQUEST_HANDLER pFunc, RequestPriority rpPriority)
+AsyncHttpRequest::AsyncHttpRequest(CVkProto *ppro, int iRequestType, LPCSTR _url, bool bSecure, MTHttpRequestHandler pFunc, RequestPriority rpPriority)
{
cbSize = sizeof(NETLIBHTTPREQUEST);
m_bApiReq = true;
bIsMainConn = false;
- bExpUrlEncode = (BYTE)ppro->m_vkOptions.bUseStandardUrlEncode == 0;
AddHeader("Connection", "keep-alive");
if (*_url == '/') { // relative url leads to a site
@@ -69,24 +67,6 @@ AsyncHttpRequest::AsyncHttpRequest(CVkProto *ppro, int iRequestType, LPCSTR _url
m_priority = rpPriority;
}
-AsyncHttpRequest::~AsyncHttpRequest()
-{
- for (int i = 0; i < headersCount; i++) {
- mir_free(headers[i].szName);
- mir_free(headers[i].szValue);
- }
- mir_free(headers);
- mir_free(pData);
-}
-
-void AsyncHttpRequest::AddHeader(LPCSTR szName, LPCSTR szValue)
-{
- headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount + 1));
- headers[headersCount].szName = mir_strdup(szName);
- headers[headersCount].szValue = mir_strdup(szValue);
- headersCount++;
-}
-
void AsyncHttpRequest::Redirect(NETLIBHTTPREQUEST *nhr)
{
for (int i = 0; i < nhr->headersCount; i++) {
@@ -208,7 +188,6 @@ CVKOptions::CVKOptions(PROTO_INTERFACE *proto) :
bSendVKLinksAsAttachments(proto, "SendVKLinksAsAttachments", true),
bLoadSentAttachments(proto, "LoadSentAttachments", bSendVKLinksAsAttachments),
bUseNonStandardNotifications(proto, "UseNonStandardNotifications", false),
- bUseStandardUrlEncode(proto, "UseStandardUrlEncode", false),
bShortenLinksForAudio(proto, "ShortenLinksForAudio", true),
bAddMessageLinkToMesWAtt(proto, "AddMessageLinkToMesWAtt", true),
bSplitFormatFwdMsg(proto, "SplitFormatFwdMsg", true),
diff --git a/protocols/VKontakte/src/vk_struct.h b/protocols/VKontakte/src/vk_struct.h
index 00e24f5b90..96916c6fd3 100644
--- a/protocols/VKontakte/src/vk_struct.h
+++ b/protocols/VKontakte/src/vk_struct.h
@@ -18,37 +18,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "stdafx.h"
#pragma once
-typedef void (CVkProto::*VK_REQUEST_HANDLER)(NETLIBHTTPREQUEST*, struct AsyncHttpRequest*);
-
-struct AsyncHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject
+struct AsyncHttpRequest : public MTHttpRequest<CVkProto>
{
enum RequestPriority { rpLow, rpMedium, rpHigh };
AsyncHttpRequest();
- AsyncHttpRequest(CVkProto*, int iRequestType, LPCSTR szUrl, bool bSecure, VK_REQUEST_HANDLER pFunc, RequestPriority rpPriority = rpMedium);
- ~AsyncHttpRequest();
+ AsyncHttpRequest(CVkProto*, int iRequestType, LPCSTR szUrl, bool bSecure, MTHttpRequestHandler pFunc, RequestPriority rpPriority = rpMedium);
- void AddHeader(LPCSTR, LPCSTR);
void Redirect(NETLIBHTTPREQUEST*);
- CMStringA m_szUrl;
- CMStringA m_szParam;
- VK_REQUEST_HANDLER m_pFunc;
- void *pUserInfo;
int m_iRetry;
int m_iErrorCode;
RequestPriority m_priority;
static ULONG m_reqCount;
ULONG m_reqNum;
bool m_bApiReq;
- bool bExpUrlEncode;
bool bNeedsRestart, bIsMainConn;
};
-AsyncHttpRequest* operator<<(AsyncHttpRequest*, const INT_PARAM&);
-AsyncHttpRequest* operator<<(AsyncHttpRequest*, const CHAR_PARAM&);
-AsyncHttpRequest* operator<<(AsyncHttpRequest*, const WCHAR_PARAM&);
-
struct CVkFileUploadParam : public MZeroedObject {
enum VKFileType { typeInvalid, typeImg, typeAudio, typeDoc, typeNotSupported };
wchar_t *FileName;
@@ -301,7 +288,6 @@ struct CVKOptions {
CMOption<BYTE> bNotificationFilterInvites;
CMOption<BYTE> bNotificationFilterAcceptedFriends;
CMOption<BYTE> bUseNonStandardNotifications;
- CMOption<BYTE> bUseStandardUrlEncode;
CMOption<BYTE> bShortenLinksForAudio;
CMOption<BYTE> bAddMessageLinkToMesWAtt;
CMOption<BYTE> bSplitFormatFwdMsg;
diff --git a/protocols/VKontakte/src/vk_wallpost.cpp b/protocols/VKontakte/src/vk_wallpost.cpp
index e90296b151..aa41fcec2a 100644
--- a/protocols/VKontakte/src/vk_wallpost.cpp
+++ b/protocols/VKontakte/src/vk_wallpost.cpp
@@ -40,9 +40,8 @@ void CVkProto::WallPost(MCONTACT hContact, wchar_t *pwszMsg, wchar_t *pwszUrl, b
if (userID == VK_INVALID_USER || userID == VK_FEED_USER)
return;
- AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/wall.post.json", true, &CVkProto::OnReceiveSmth)
- << INT_PARAM("owner_id", userID)
- << INT_PARAM("friends_only", bFriendsOnly ? 1 : 0);
+ AsyncHttpRequest *pReq = new AsyncHttpRequest(this, REQUEST_POST, "/method/wall.post.json", true, &CVkProto::OnReceiveSmth);
+ pReq << INT_PARAM("owner_id", userID) << INT_PARAM("friends_only", bFriendsOnly ? 1 : 0);
if (!IsEmpty(pwszMsg))
pReq << WCHAR_PARAM("message", pwszMsg);
diff --git a/src/mir_app/src/MHttpRequest.cpp b/src/mir_app/src/MHttpRequest.cpp
new file mode 100644
index 0000000000..ce511f8e4b
--- /dev/null
+++ b/src/mir_app/src/MHttpRequest.cpp
@@ -0,0 +1,93 @@
+/*
+
+Miranda NG: the free IM client for Microsoft* Windows*
+
+Copyright (C) 2012-18 Miranda NG team,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "stdafx.h"
+
+MHttpRequest::MHttpRequest()
+{
+ cbSize = sizeof(NETLIBHTTPREQUEST);
+ requestType = REQUEST_GET;
+}
+
+MHttpRequest::~MHttpRequest()
+{
+ for (int i = 0; i < headersCount; i++) {
+ mir_free(headers[i].szName);
+ mir_free(headers[i].szValue);
+ }
+ mir_free(headers);
+ mir_free(pData);
+}
+
+void MHttpRequest::AddHeader(LPCSTR szName, LPCSTR szValue)
+{
+ for (int i = 0; i < headersCount; i++)
+ if (!mir_strcmp(headers[i].szName, szName)) {
+ replaceStr(headers[i].szValue, szValue);
+ return;
+ }
+
+ headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount + 1));
+ headers[headersCount].szName = mir_strdup(szName);
+ headers[headersCount].szValue = mir_strdup(szValue);
+ headersCount++;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest *pReq, const INT_PARAM &param)
+{
+ CMStringA &s = pReq->m_szParam;
+ if (!s.IsEmpty())
+ s.AppendChar('&');
+ s.AppendFormat("%s=%ld", param.szName, param.iValue);
+ return pReq;
+}
+
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest *pReq, const INT64_PARAM &param)
+{
+ CMStringA &s = pReq->m_szParam;
+ if (!s.IsEmpty())
+ s.AppendChar('&');
+ s.AppendFormat("%s=%lld", param.szName, param.iValue);
+ return pReq;
+}
+
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest *pReq, const CHAR_PARAM &param)
+{
+ CMStringA &s = pReq->m_szParam;
+ if (!s.IsEmpty())
+ s.AppendChar('&');
+ s.AppendFormat("%s=%s", param.szName, ptrA(mir_urlEncode(param.szValue)));
+ return pReq;
+}
+
+MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest *pReq, const WCHAR_PARAM &param)
+{
+ T2Utf szValue(param.wszValue);
+ CMStringA &s = pReq->m_szParam;
+ if (!s.IsEmpty())
+ s.AppendChar('&');
+ s.AppendFormat("%s=%s", param.szName, ptrA(mir_urlEncode(szValue)));
+ return pReq;
+}
diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def
index e3be5f3916..673016746d 100644
--- a/src/mir_app/src/mir_app.def
+++ b/src/mir_app/src/mir_app.def
@@ -671,3 +671,12 @@ g_hevSettingChanged @696 NONAME
?MetaRemoveSubHistory@MDatabaseReadonly@@UAGHPAUDBCachedContact@@@Z @704 NONAME
Chat_GetGroup @705
Chat_SetGroup @706
+??0MHttpRequest@@QAE@ABU0@@Z @707 NONAME
+??0MHttpRequest@@QAE@XZ @708 NONAME
+??1MHttpRequest@@QAE@XZ @709 NONAME
+??4MHttpRequest@@QAEAAU0@ABU0@@Z @710 NONAME
+??6@YGPAUMHttpRequest@@PAU0@ABUCHAR_PARAM@@@Z @711 NONAME
+??6@YGPAUMHttpRequest@@PAU0@ABUINT_PARAM@@@Z @712 NONAME
+??6@YGPAUMHttpRequest@@PAU0@ABUWCHAR_PARAM@@@Z @713 NONAME
+??6@YGPAUMHttpRequest@@PAU0@ABUINT64_PARAM@@@Z @714 NONAME
+?AddHeader@MHttpRequest@@QAEXPBD0@Z @715 NONAME
diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def
index bb0746bc4e..513a79e71c 100644
--- a/src/mir_app/src/mir_app64.def
+++ b/src/mir_app/src/mir_app64.def
@@ -671,3 +671,12 @@ g_hevSettingChanged @696 NONAME
?MetaRemoveSubHistory@MDatabaseReadonly@@UEAAHPEAUDBCachedContact@@@Z @704 NONAME
Chat_GetGroup @705
Chat_SetGroup @706
+??0MHttpRequest@@QEAA@AEBU0@@Z @707 NONAME
+??0MHttpRequest@@QEAA@XZ @708 NONAME
+??1MHttpRequest@@QEAA@XZ @709 NONAME
+??4MHttpRequest@@QEAAAEAU0@AEBU0@@Z @710 NONAME
+??6@YAPEAUMHttpRequest@@PEAU0@AEBUCHAR_PARAM@@@Z @711 NONAME
+??6@YAPEAUMHttpRequest@@PEAU0@AEBUINT_PARAM@@@Z @712 NONAME
+??6@YAPEAUMHttpRequest@@PEAU0@AEBUWCHAR_PARAM@@@Z @713 NONAME
+??6@YAPEAUMHttpRequest@@PEAU0@AEBUINT64_PARAM@@@Z @714 NONAME
+?AddHeader@MHttpRequest@@QEAAXPEBD0@Z @715 NONAME
diff --git a/src/mir_core/src/http.cpp b/src/mir_core/src/http.cpp
index ae5a9f3ff4..fad969c680 100755
--- a/src/mir_core/src/http.cpp
+++ b/src/mir_core/src/http.cpp
@@ -29,11 +29,14 @@ MIR_CORE_DLL(char*) mir_urlEncode(const char *szUrl)
const BYTE *s;
int outputLen;
for (outputLen = 0, s = (const BYTE*)szUrl; *s; s++) {
- if (('0' <= *s && *s <= '9') || //0-9
+ if ((*s & 0x80) ||
+ ('0' <= *s && *s <= '9') || //0-9
('A' <= *s && *s <= 'Z') || //ABC...XYZ
('a' <= *s && *s <= 'z') || //abc...xyz
- *s == '-' || *s == '_' || *s == '.' || *s == ' ' || *s == '~') outputLen++;
- else outputLen += 3;
+ *s == '-' || *s == '_' || *s == '.' || *s == ' ' || *s == '~')
+ outputLen++;
+ else
+ outputLen += 3;
}
char *szOutput = (char*)mir_alloc(outputLen+1);
@@ -42,11 +45,17 @@ MIR_CORE_DLL(char*) mir_urlEncode(const char *szUrl)
char *d = szOutput;
for (s = (const BYTE*)szUrl; *s; s++) {
- if (('0' <= *s && *s <= '9') || //0-9
- ('A' <= *s && *s <= 'Z') || //ABC...XYZ
- ('a' <= *s && *s <= 'z') || //abc...xyz
- *s == '-' || *s == '_' || *s == '.' || *s == '~') *d++ = *s;
- else if (*s == ' ') *d++='+';
+ if ((*s & 0x80) ||
+ ('0' <= *s && *s <= '9') || //0-9
+ ('A' <= *s && *s <= 'Z') || //ABC...XYZ
+ ('a' <= *s && *s <= 'z') || //abc...xyz
+ *s == '-' || *s == '_' || *s == '.' || *s == '~')
+ {
+ *d++ = *s;
+ }
+ else if (*s == ' ') {
+ *d++ = '+';
+ }
else {
*d++ = '%';
*d++ = szHexDigits[*s >> 4];