From 14c4e44a0a91e1ad701d4ae3c58185d25118e64e Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 5 Jan 2024 15:54:03 +0300 Subject: Netlib: - NETLIBHTTPHEADER & NETLIBHTTPREQUEST obsoleted; - NETLIBHTTPREQUEST divided into MHttpRequest & MHttpResponse; - MHttpHeaders now manager headers both for MHttpRequest & MHttpResponse; --- include/m_netlib.h | 133 +++++---- libs/win32/mir_app.lib | Bin 278210 -> 290906 bytes libs/win64/mir_app.lib | Bin 277538 -> 290624 bytes plugins/HTTPServer/src/GuiElements.cpp | 13 +- plugins/MirLua/src/Modules/m_http.cpp | 272 ++++------------- plugins/PackUpdater/Src/Utils.cpp | 26 +- plugins/PasteIt/src/PasteToWeb.cpp | 44 +-- plugins/PluginUpdater/src/Utils.cpp | 25 +- plugins/SendScreenshotPlus/src/CSend.cpp | 175 ++++------- plugins/SendScreenshotPlus/src/CSend.h | 3 +- .../src/CSendHost_ImageShack.cpp | 12 +- .../SendScreenshotPlus/src/CSendHost_ImageShack.h | 2 +- plugins/SendScreenshotPlus/src/CSendHost_imgur.cpp | 11 +- plugins/SendScreenshotPlus/src/CSendHost_imgur.h | 2 +- .../SendScreenshotPlus/src/CSendHost_uploadpie.cpp | 12 +- .../SendScreenshotPlus/src/CSendHost_uploadpie.h | 2 +- plugins/SmileyAdd/src/download.cpp | 39 +-- .../CloudFile/src/Services/dropbox_service.cpp | 4 +- .../CloudFile/src/Services/google_service.cpp | 8 +- .../CloudFile/src/Services/microsoft_service.cpp | 6 +- .../CloudFile/src/Services/yandex_service.cpp | 6 +- protocols/CloudFile/src/cloud_file.cpp | 12 +- protocols/CloudFile/src/cloud_file.h | 6 +- protocols/CloudFile/src/http_request.h | 82 +----- protocols/CurrencyRates/src/HTTPSession.cpp | 38 +-- protocols/Discord/src/avatars.cpp | 6 +- protocols/Discord/src/connection.cpp | 9 +- protocols/Discord/src/gateway.cpp | 18 +- protocols/Discord/src/http.cpp | 7 +- protocols/Discord/src/proto.cpp | 18 +- protocols/Discord/src/proto.h | 26 +- protocols/Discord/src/server.cpp | 16 +- protocols/Facebook/src/avatars.cpp | 16 +- protocols/Facebook/src/http.cpp | 29 +- protocols/Facebook/src/proto.h | 4 +- protocols/Facebook/src/server.cpp | 10 +- protocols/Gadu-Gadu/src/avatar.cpp | 104 +++---- protocols/Gadu-Gadu/src/oauth.cpp | 155 +++++----- protocols/GmailNotifier/src/check.cpp | 41 +-- protocols/ICQ-WIM/src/avatars.cpp | 16 +- protocols/ICQ-WIM/src/file.cpp | 5 +- protocols/ICQ-WIM/src/groupchats.cpp | 4 +- protocols/ICQ-WIM/src/http.cpp | 46 +-- protocols/ICQ-WIM/src/http.h | 6 +- protocols/ICQ-WIM/src/ignore.cpp | 2 +- protocols/ICQ-WIM/src/mra.cpp | 8 +- protocols/ICQ-WIM/src/options.cpp | 10 +- protocols/ICQ-WIM/src/poll.cpp | 2 +- protocols/ICQ-WIM/src/proto.cpp | 8 +- protocols/ICQ-WIM/src/proto.h | 62 ++-- protocols/ICQ-WIM/src/server.cpp | 44 +-- protocols/JabberG/src/jabber_file.cpp | 26 +- protocols/JabberG/src/jabber_ft.cpp | 26 +- protocols/JabberG/src/jabber_util.cpp | 12 +- protocols/MinecraftDynmap/src/communication.cpp | 130 +++----- protocols/MinecraftDynmap/src/proto.h | 5 +- protocols/MinecraftDynmap/src/utils.h | 11 - protocols/NewsAggregator/Src/Utils.cpp | 118 ++------ protocols/Non-IM Contact/src/http.cpp | 15 +- protocols/SkypeWeb/src/request_queue.cpp | 13 +- protocols/SkypeWeb/src/requests/avatars.h | 12 +- protocols/SkypeWeb/src/requests/files.h | 12 +- protocols/SkypeWeb/src/skype_avatars.cpp | 12 +- protocols/SkypeWeb/src/skype_chatrooms.cpp | 4 +- protocols/SkypeWeb/src/skype_contacts.cpp | 8 +- protocols/SkypeWeb/src/skype_files.cpp | 8 +- protocols/SkypeWeb/src/skype_history_sync.cpp | 4 +- protocols/SkypeWeb/src/skype_login.cpp | 30 +- protocols/SkypeWeb/src/skype_messages.cpp | 6 +- protocols/SkypeWeb/src/skype_oauth.cpp | 38 +-- protocols/SkypeWeb/src/skype_polling.cpp | 8 +- protocols/SkypeWeb/src/skype_profile.cpp | 2 +- protocols/SkypeWeb/src/skype_proto.cpp | 2 +- protocols/SkypeWeb/src/skype_proto.h | 56 ++-- protocols/SkypeWeb/src/skype_search.cpp | 2 +- protocols/SkypeWeb/src/skype_trouter.cpp | 2 +- protocols/SkypeWeb/src/skype_utils.cpp | 4 +- protocols/SkypeWeb/src/skype_utils.h | 2 +- protocols/Steam/src/http_request.h | 14 +- protocols/Steam/src/steam_proto.h | 2 +- protocols/Steam/src/steam_request.cpp | 23 +- protocols/Tox/src/http_request.h | 41 +-- protocols/Tox/src/tox_bootstrap.cpp | 6 +- protocols/Twitter/src/http.cpp | 4 - protocols/Twitter/src/oauth.cpp | 4 +- protocols/Twitter/src/proto.h | 4 +- protocols/Twitter/src/utility.cpp | 6 +- protocols/VKontakte/src/misc.cpp | 27 +- protocols/VKontakte/src/vk_avatars.cpp | 6 +- protocols/VKontakte/src/vk_captcha.cpp | 8 +- protocols/VKontakte/src/vk_chats.cpp | 10 +- protocols/VKontakte/src/vk_feed.cpp | 4 +- protocols/VKontakte/src/vk_files.cpp | 12 +- protocols/VKontakte/src/vk_history.cpp | 2 +- protocols/VKontakte/src/vk_messages.cpp | 6 +- protocols/VKontakte/src/vk_pollserver.cpp | 8 +- protocols/VKontakte/src/vk_proto.cpp | 2 +- protocols/VKontakte/src/vk_proto.h | 60 ++-- protocols/VKontakte/src/vk_queue.cpp | 10 +- protocols/VKontakte/src/vk_search.cpp | 4 +- protocols/VKontakte/src/vk_status.cpp | 4 +- protocols/VKontakte/src/vk_struct.cpp | 4 +- protocols/VKontakte/src/vk_struct.h | 2 +- protocols/VKontakte/src/vk_thread.cpp | 26 +- protocols/Weather/src/weather_http.cpp | 37 +-- protocols/WebView/src/webview_getdata.cpp | 22 +- protocols/WhatsApp/src/avatars.cpp | 10 +- protocols/WhatsApp/src/server.cpp | 9 +- protocols/WhatsApp/src/utils.cpp | 15 +- src/mir_app/mir_app.vcxproj | 2 + src/mir_app/mir_app.vcxproj.filters | 6 + src/mir_app/src/MHttpHeaders.cpp | 82 ++++++ src/mir_app/src/MHttpRequest.cpp | 22 +- src/mir_app/src/MHttpResponse.cpp | 60 ++++ src/mir_app/src/mir_app.def | 58 +++- src/mir_app/src/mir_app64.def | 58 +++- src/mir_app/src/netlib.h | 55 +++- src/mir_app/src/netlib_autoproxy.cpp | 12 +- src/mir_app/src/netlib_http.cpp | 328 +++++++-------------- src/mir_app/src/netlib_openconn.cpp | 9 +- src/mir_app/src/netlib_websocket.cpp | 13 +- 121 files changed, 1335 insertions(+), 1935 deletions(-) create mode 100644 src/mir_app/src/MHttpHeaders.cpp create mode 100644 src/mir_app/src/MHttpResponse.cpp diff --git a/include/m_netlib.h b/include/m_netlib.h index 0f8cdc2015..3ccf546860 100644 --- a/include/m_netlib.h +++ b/include/m_netlib.h @@ -39,7 +39,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // a pointer, I have decided to diverge from the rest of Miranda and go with // the convention that functions return false on failure and nonzero on success. -struct NETLIBHTTPREQUEST; +struct MHttpRequest; struct NETLIBOPENCONNECTION; #define NETLIB_USER_AGENT "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.112 Safari/537.36" @@ -402,16 +402,6 @@ EXTERN_C MIR_APP_DLL(NETLIBIPLIST*) Netlib_GetMyIp(bool bGlobalOnly); ///////////////////////////////////////////////////////////////////////////////////////// -struct NETLIBHTTPHEADER -{ - char *szName; - char *szValue; -}; - -EXTERN_C MIR_APP_DLL(char*) Netlib_GetHeader(const NETLIBHTTPREQUEST *pRec, const char *pszName); - -///////////////////////////////////////////////////////////////////////////////////////// - #define REQUEST_RESPONSE 0 // used by structure returned by MS_NETLIB_RECVHTTPHEADERS #define REQUEST_GET 1 #define REQUEST_POST 2 @@ -434,80 +424,93 @@ EXTERN_C MIR_APP_DLL(char*) Netlib_GetHeader(const NETLIBHTTPREQUEST *pRec, cons #define NLHRF_DUMPASTEXT 0x00080000 // dump posted and reply data as text. Headers are always dumped as text. #define NLHRF_NODUMPSEND 0x00100000 // do not dump sent message. -struct MIR_APP_EXPORT NETLIBHTTPREQUEST +struct MHttpHeader { - int requestType; // a REQUEST_ - uint32_t flags; - char *szUrl; - NETLIBHTTPHEADER *headers; // If this is a POST request and headers doesn't contain a Content-Length it'll be added automatically - int headersCount; - char *pData; // data to be sent in POST request. - int dataLength; // must be 0 for REQUEST_GET/REQUEST_CONNECT - int resultCode; - char *szResultDescr; - HNETLIBCONN nlc; - int timeout; + MHttpHeader(const char *_1, const char *_2) : + szName(mir_strdup(_1)), + szValue(mir_strdup(_2)) + {} - CMStringA GetCookies() const; + ptrA szName, szValue; +}; + +struct MIR_APP_EXPORT MHttpHeaders : public OBJLIST +{ + MHttpHeaders(); + ~MHttpHeaders(); __forceinline const char *operator[](const char *pszName) { - return Netlib_GetHeader(this, pszName); + return FindHeader(pszName); } + + void AddHeader(const char *pszName, const char *pszValue); + void DeleteHeader(const char *pszName); + char* FindHeader(const char *pszName) const; + CMStringA GetCookies() const; }; -///////////////////////////////////////////////////////////////////////////////////////// -// Free the memory used by a NETLIBHTTPREQUEST structure -// -// Returns true on success, false on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) -// This should only be called on structures returned by -// MS_NETLIB_RECVHTTPHEADERS or MS_NETLIB_HTTPTRANSACTION. Calling it on an -// arbitrary structure will have disastrous results. -// Errors: ERROR_INVALID_PARAMETER +struct MIR_APP_EXPORT MHttpRequest : public MHttpHeaders, public MNonCopyable, public MZeroedObject +{ + MHttpRequest(); + ~MHttpRequest(); -EXTERN_C MIR_APP_DLL(bool) Netlib_FreeHttpRequest(NETLIBHTTPREQUEST*); + int requestType = REQUEST_GET; // a REQUEST_ + uint32_t flags; + CMStringA m_szUrl, m_szParam; + HNETLIBCONN nlc; + int timeout; + void *pUserInfo; -///////////////////////////////////////////////////////////////////////////////////////// -// smart pointer for NETLIBHTTPREQUEST via a call of Netlib_FreeHttpRequest() + void SetData(const void *pData, size_t cbLen); +}; + +struct MIR_APP_EXPORT MHttpResponse : public MHttpHeaders, public MNonCopyable, public MZeroedObject +{ + MHttpResponse(); + ~MHttpResponse(); + + int resultCode; + char *szUrl, *szResultDescr; + HNETLIBCONN nlc; + CMStringA body; +}; -#ifdef __cplusplus class NLHR_PTR { -protected: - NETLIBHTTPREQUEST *_p; + MHttpResponse *_p; public: - __forceinline explicit NLHR_PTR(NETLIBHTTPREQUEST *p) : _p(p) {} + __forceinline explicit NLHR_PTR(MHttpResponse *p) : _p(p) {} - __forceinline NETLIBHTTPREQUEST* operator=(INT_PTR i_p) + __forceinline MHttpResponse *operator=(INT_PTR i_p) { - return operator=((NETLIBHTTPREQUEST*)i_p); + return operator=((MHttpResponse *)i_p); } - __forceinline NETLIBHTTPREQUEST* operator=(NETLIBHTTPREQUEST *p) + __forceinline MHttpResponse* operator=(MHttpResponse *p) { if (_p) - Netlib_FreeHttpRequest(_p); + delete _p; _p = p; return _p; } - __forceinline operator NETLIBHTTPREQUEST*() const { return _p; } - __forceinline NETLIBHTTPREQUEST* operator->() const { return _p; } + __forceinline operator MHttpResponse*() const { return _p; } + __forceinline MHttpResponse* operator->() const { return _p; } __forceinline ~NLHR_PTR() { - Netlib_FreeHttpRequest(_p); + delete _p; } }; -struct MIR_APP_EXPORT MHttpRequest : public NETLIBHTTPREQUEST, public MZeroedObject -{ - MHttpRequest(); - ~MHttpRequest(); +EXTERN_C MIR_APP_DLL(bool) Netlib_FreeHttpRequest(MHttpResponse *); - CMStringA m_szUrl; - CMStringA m_szParam; - void *pUserInfo = nullptr; - - void AddHeader(const char *szName, const char *szValue); -}; +///////////////////////////////////////////////////////////////////////////////////////// +// Free the memory used by a MHttpRequest structure +// +// Returns true on success, false on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +// This should only be called on structures returned by +// MS_NETLIB_RECVHTTPHEADERS or MS_NETLIB_HTTPTRANSACTION. Calling it on an +// arbitrary structure will have disastrous results. +// Errors: ERROR_INVALID_PARAMETER template class MTHttpRequest : public MHttpRequest @@ -516,21 +519,25 @@ public: __forceinline MTHttpRequest() {} - typedef void (T::*MTHttpRequestHandler)(NETLIBHTTPREQUEST*, struct AsyncHttpRequest*); + typedef void (T::*MTHttpRequestHandler)(MHttpResponse*, 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 INT64_PARAM&); MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const WCHAR_PARAM&); -#endif +__forceinline MHttpRequest* operator<<(MHttpRequest &req, const INT_PARAM ¶m) { return &req << param; } +__forceinline MHttpRequest* operator<<(MHttpRequest &req, const CHAR_PARAM ¶m) { return &req << param; } +__forceinline MHttpRequest* operator<<(MHttpRequest &req, const INT64_PARAM ¶m) { return &req << param; } +__forceinline MHttpRequest* operator<<(MHttpRequest &req, const WCHAR_PARAM ¶m) { return &req << param; } + ///////////////////////////////////////////////////////////////////////////////////////// // Do an entire HTTP transaction // -// Returns a pointer to another NETLIBHTTPREQUEST structure on success, NULL on failure. +// Returns a pointer to another MHttpRequest structure on success, NULL on failure. // Call Netlib_FreeHttpRequest() to free this. // hUser must have been returned by MS_NETLIB_REGISTERUSER // nlhr.szUrl should be a full HTTP URL. If it does not start with http:// , that @@ -555,7 +562,7 @@ MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest*, const WCHAR_PARAM&); // Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, anything from the above // list of functions -EXTERN_C MIR_APP_DLL(NETLIBHTTPREQUEST*) Netlib_HttpTransaction(HNETLIBUSER hNlu, NETLIBHTTPREQUEST *pRequest); +EXTERN_C MIR_APP_DLL(MHttpResponse *) Netlib_HttpTransaction(HNETLIBUSER hNlu, MHttpRequest *pRequest); ///////////////////////////////////////////////////////////////////////////////////////// // Send data over a connection @@ -753,7 +760,7 @@ struct WSHeader }; // connects to a WebSocket server -EXTERN_C MIR_APP_DLL(NETLIBHTTPREQUEST*) WebSocket_Connect(HNETLIBUSER, const char *szHost, NETLIBHTTPHEADER *pHeaders = nullptr); +EXTERN_C MIR_APP_DLL(MHttpResponse*) WebSocket_Connect(HNETLIBUSER, const char *szHost, const MHttpHeaders *pHeaders = nullptr); // validates that the provided buffer contains full WebSocket datagram EXTERN_C MIR_APP_DLL(bool) WebSocket_InitHeader(WSHeader &hdr, const void *pData, size_t bufSize); diff --git a/libs/win32/mir_app.lib b/libs/win32/mir_app.lib index 0adef99d45..6f707bba15 100644 Binary files a/libs/win32/mir_app.lib and b/libs/win32/mir_app.lib differ diff --git a/libs/win64/mir_app.lib b/libs/win64/mir_app.lib index 5ed62c15f7..87a691b6e8 100644 Binary files a/libs/win64/mir_app.lib and b/libs/win64/mir_app.lib differ diff --git a/plugins/HTTPServer/src/GuiElements.cpp b/plugins/HTTPServer/src/GuiElements.cpp index 329258e1b9..a3f02f86bb 100644 --- a/plugins/HTTPServer/src/GuiElements.cpp +++ b/plugins/HTTPServer/src/GuiElements.cpp @@ -141,11 +141,9 @@ unsigned long GetExternIP(const char *szURL, const char *szPattern) { HCURSOR hPrevCursor = ::SetCursor(::LoadCursor(nullptr, IDC_WAIT)); - NETLIBHTTPREQUEST nlhr; - memset(&nlhr, 0, sizeof(nlhr)); - nlhr.requestType = REQUEST_GET; + MHttpRequest nlhr; nlhr.flags = NLHRF_DUMPASTEXT; - nlhr.szUrl = (char*)szURL; + nlhr.m_szUrl = szURL; IN_ADDR externIP; externIP.s_addr = 0; @@ -153,16 +151,15 @@ unsigned long GetExternIP(const char *szURL, const char *szPattern) NLHR_PTR nlreply(Netlib_HttpTransaction(hNetlibUser, &nlhr)); if (nlreply) { if (nlreply->resultCode >= 200 && nlreply->resultCode < 300) { - nlreply->pData[nlreply->dataLength] = 0;// make sure its null terminated - char * pszIp = strstr(nlreply->pData, szPattern); + char *pszIp = strstr(nlreply->body.GetBuffer(), szPattern); if (pszIp == nullptr) - pszIp = nlreply->pData; + pszIp = nlreply->body.GetBuffer(); else pszIp += mir_strlen(szPattern); while ((*pszIp < '0' || *pszIp > '9') && *pszIp) pszIp++; - char * pszEnd = pszIp; + char *pszEnd = pszIp; while ((*pszEnd >= '0' && *pszEnd <= '9') || *pszEnd == '.') pszEnd++; *pszEnd = NULL; diff --git a/plugins/MirLua/src/Modules/m_http.cpp b/plugins/MirLua/src/Modules/m_http.cpp index 7526b29612..fcc0365078 100644 --- a/plugins/MirLua/src/Modules/m_http.cpp +++ b/plugins/MirLua/src/Modules/m_http.cpp @@ -2,154 +2,22 @@ #define MT_NETLIBHTTPHEADERS "NETLIBHTTPHEADERS" -static NETLIBHTTPREQUEST* CreateRequest() +static MHttpRequest* CreateRequest() { - NETLIBHTTPREQUEST *request = (NETLIBHTTPREQUEST*)mir_calloc(sizeof(NETLIBHTTPREQUEST)); + MHttpRequest *request = new MHttpRequest(); request->flags = NLHRF_HTTP11 | NLHRF_NODUMP; return request; } -static void SetUrl(NETLIBHTTPREQUEST *request, const char *url) +static void SetUrl(MHttpRequest *request, const char *url) { - request->szUrl = mir_strdup(url); - if (mir_strncmpi(request->szUrl, "https", 5) == 0) + request->m_szUrl = url; + if (mir_strncmpi(request->m_szUrl, "https", 5) == 0) request->flags |= NLHRF_SSL; else request->flags &= ~(NLHRF_SSL); } -static void SetHeader(NETLIBHTTPREQUEST *request, const char *name, const char *value) -{ - for (int i = 0; i < request->headersCount; i++) { - if (mir_strcmp(request->headers[i].szName, name) == 0) { - mir_free(request->headers[i].szValue); - request->headers[i].szValue = mir_strdup(value); - return; - } - } - - request->headers = (NETLIBHTTPHEADER*)mir_realloc(request->headers, - sizeof(NETLIBHTTPHEADER)*(request->headersCount + 1)); - NETLIBHTTPHEADER &header = request->headers[request->headersCount]; - header.szName = mir_strdup(name); - header.szValue = mir_strdup(value); - request->headersCount++; -} - -static void DropHeader(NETLIBHTTPREQUEST *request, const char *name) -{ - for (int i = 0; i < request->headersCount - 1; i++) { - if (mir_strcmp(request->headers[i].szName, name) == 0) { - mir_free(request->headers[i].szName); - mir_free(request->headers[i].szValue); - request->headersCount--; - request->headers[i].szName = request->headers[request->headersCount].szName; - request->headers[i].szValue = request->headers[request->headersCount].szValue; - } - } - request->headers = (NETLIBHTTPHEADER*)mir_realloc(request->headers, - sizeof(NETLIBHTTPHEADER)*(request->headersCount + 1)); -} - -static void ClearHeaders(NETLIBHTTPREQUEST *request) -{ - for (int i = 0; i < request->headersCount; i++) { - mir_free(request->headers[i].szName); - mir_free(request->headers[i].szValue); - } - request->headersCount = 0; - request->headers = (NETLIBHTTPHEADER*)mir_realloc(request->headers, - sizeof(NETLIBHTTPHEADER)*(request->headersCount + 1)); -} - -static void SetContent(NETLIBHTTPREQUEST *request, const char *data, size_t length) -{ - if (request->pData != nullptr) - mir_free(request->pData); - request->pData = mir_strdup(data); - request->dataLength = (int)length; -} - -/***********************************************/ - -struct NETLIBHTTPHEADERS -{ - const NETLIBHTTPHEADER *headers; - int count; -}; - -static int headers_Iterator(lua_State *L) -{ - NETLIBHTTPHEADER *headers = (NETLIBHTTPHEADER*)lua_touserdata(L, lua_upvalueindex(1)); - int count = lua_tointeger(L, lua_upvalueindex(2)); - int idx = lua_tointeger(L, lua_upvalueindex(3)); - - if (idx < count) { - lua_pushstring(L, headers[idx].szName); - lua_pushstring(L, headers[idx].szValue); - lua_pushinteger(L, idx + 1); - lua_replace(L, lua_upvalueindex(3)); - return 2; - } - - lua_pushnil(L); - - return 1; -} - -static int headers__pairs(lua_State *L) -{ - NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); - - lua_pushlightuserdata(L, (void*)headers->headers); - lua_pushinteger(L, headers->count); - lua_pushinteger(L, 0); - lua_pushcclosure(L, headers_Iterator, 3); - - return 1; -} - -static int headers__index(lua_State *L) -{ - NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); - - if (lua_isinteger(L, 2)) { - int idx = lua_tointeger(L, 2); - if (idx > 0 && idx <= headers->count) { - lua_pushstring(L, headers->headers[idx - 1].szValue); - return 1; - } - } - - const char *key = lua_tostring(L, 2); - for (int i = 0; i < headers->count; i++) { - if (mir_strcmp(headers->headers[i].szName, key) == 0) { - lua_pushstring(L, headers->headers[i].szValue); - return 1; - } - } - - lua_pushnil(L); - - return 1; -} - -static int headers__len(lua_State *L) -{ - NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)luaL_checkudata(L, 1, MT_NETLIBHTTPHEADERS); - lua_pushinteger(L, headers->count); - return 1; -} - -static const luaL_Reg headersApi[] = -{ - { "__pairs", headers__pairs }, - { "__index", headers__index }, - { "__len", headers__len }, - - { nullptr, nullptr } -}; - /***********************************************/ #define MT_NETLIBHTTPCONTENT "NETLIBHTTPCONTENT" @@ -202,10 +70,10 @@ static const luaL_Reg contentApi[] = #define MT_NETLIBHTTPRESPONSE "NETLIBHTTPRESPONSE" -static NETLIBHTTPREQUEST* response_Create(lua_State *L, NETLIBHTTPREQUEST *request) +static MHttpResponse* response_Create(lua_State *L, MHttpRequest *request) { - NETLIBHTTPREQUEST *response = Netlib_HttpTransaction(g_plugin.hNetlib, request); - NETLIBHTTPREQUEST **udata = (NETLIBHTTPREQUEST**)lua_newuserdata(L, sizeof(NETLIBHTTPREQUEST*)); + auto *response = Netlib_HttpTransaction(g_plugin.hNetlib, request); + MHttpResponse **udata = (MHttpResponse **)lua_newuserdata(L, sizeof(MHttpResponse *)); *udata = response; luaL_setmetatable(L, MT_NETLIBHTTPRESPONSE); return response; @@ -213,7 +81,7 @@ static NETLIBHTTPREQUEST* response_Create(lua_State *L, NETLIBHTTPREQUEST *reque static int response__index(lua_State *L) { - NETLIBHTTPREQUEST *response = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPRESPONSE); + MHttpResponse *response = *(MHttpResponse **)luaL_checkudata(L, 1, MT_NETLIBHTTPRESPONSE); const char *key = lua_tostring(L, 2); if (mir_strcmpi(key, "IsSuccess") == 0) { @@ -226,16 +94,16 @@ static int response__index(lua_State *L) } if (mir_strcmpi(key, "StatusCode") == 0) lua_pushinteger(L, response->resultCode); - else if (mir_strcmpi(key, "Headers") == 0) { + /*else if (mir_strcmpi(key, "Headers") == 0) { NETLIBHTTPHEADERS *headers = (NETLIBHTTPHEADERS*)lua_newuserdata(L, sizeof(NETLIBHTTPHEADERS)); headers->headers = response->headers; headers->count = response->headersCount; luaL_setmetatable(L, MT_NETLIBHTTPHEADERS); - } + }*/ else if (mir_strcmpi(key, "Content") == 0) { NETLIBHTTPCONTENT *content = (NETLIBHTTPCONTENT*)lua_newuserdata(L, sizeof(NETLIBHTTPCONTENT)); - content->data = response->pData; - content->length = response->dataLength; + content->data = response->body.GetBuffer(); + content->length = response->body.GetLength(); luaL_setmetatable(L, MT_NETLIBHTTPCONTENT); } else @@ -246,7 +114,7 @@ static int response__index(lua_State *L) static int response__gc(lua_State *L) { - NETLIBHTTPREQUEST **response = (NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPRESPONSE); + MHttpResponse **response = (MHttpResponse **)luaL_checkudata(L, 1, MT_NETLIBHTTPRESPONSE); Netlib_FreeHttpRequest(*response); return 0; } @@ -267,7 +135,7 @@ struct HttpRequestParam int threadRef; int callbackRef; - NETLIBHTTPREQUEST *request; + MHttpRequest *request; }; static void __cdecl SendHttpRequestThread(HttpRequestParam *param) @@ -280,11 +148,11 @@ static void __cdecl SendHttpRequestThread(HttpRequestParam *param) luaL_unref(param->L, LUA_REGISTRYINDEX, param->callbackRef); luaL_unref(param->L, LUA_REGISTRYINDEX, param->threadRef); - Netlib_FreeHttpRequest(param->request); + delete param->request; delete param; } -static void SendRequestAsync(lua_State *L, int idx, NETLIBHTTPREQUEST *request) +static void SendRequestAsync(lua_State *L, int idx, MHttpRequest *request) { HttpRequestParam *param = new HttpRequestParam(); param->request = request; @@ -297,13 +165,13 @@ static void SendRequestAsync(lua_State *L, int idx, NETLIBHTTPREQUEST *request) /***********************************************/ -#define MT_NETLIBHTTPREQUEST "NETLIBHTTPREQUEST" +#define MT_NETLIBHTTPREQUEST "MHttpRequest" static const char *httpMethods[] = { "GET", "POST", "PUT", "DELETE", nullptr }; static int request_SetMethod(lua_State *L) { - NETLIBHTTPREQUEST *request = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + MHttpRequest *request = *(MHttpRequest**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); request->requestType = (1 << (luaL_checkoption(L, 2, nullptr, httpMethods))); lua_pushvalue(L, 1); return 1; @@ -311,7 +179,7 @@ static int request_SetMethod(lua_State *L) static int request_SetUrl(lua_State *L) { - NETLIBHTTPREQUEST *request = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + MHttpRequest *request = *(MHttpRequest**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); const char *url = luaL_checkstring(L, 2); SetUrl(request, url); @@ -322,14 +190,14 @@ static int request_SetUrl(lua_State *L) static int request_SetHeaders(lua_State *L) { - NETLIBHTTPREQUEST *request = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + MHttpRequest *request = *(MHttpRequest**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); luaL_checktype(L, 2, LUA_TTABLE); - ClearHeaders(request); + request->destroy(); for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) { const char *name = lua_tostring(L, -2); const char *value = lua_tostring(L, -1); - SetHeader(request, name, value); + request->AddHeader(name, value); } lua_pushvalue(L, 1); @@ -338,34 +206,34 @@ static int request_SetHeaders(lua_State *L) static int request_SetContent(lua_State *L) { - NETLIBHTTPREQUEST *request = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + MHttpRequest *request = *(MHttpRequest**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); switch (lua_type(L, 2)) { case LUA_TNONE: case LUA_TNIL: - SetContent(request, nullptr, 0); - DropHeader(request, "Content-Type"); + request->SetData(nullptr, 0); + request->DeleteHeader("Content-Type"); break; case LUA_TSTRING: - { - const char *data = lua_tostring(L, 2); - SetContent(request, data, mir_strlen(data)); - SetHeader(request, "Content-Type", "text/plain"); + { + const char *data = lua_tostring(L, 2); + request->SetData(data, mir_strlen(data)); + request->AddHeader("Content-Type", "text/plain"); + } break; - } case LUA_TTABLE: - { - CMStringA formData; - for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) { - const char *name = lua_tostring(L, -2); - const char *value = lua_tostring(L, -1); - formData.AppendFormat("&%s=%s", name, value); + { + CMStringA formData; + for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) { + const char *name = lua_tostring(L, -2); + const char *value = lua_tostring(L, -1); + formData.AppendFormat("&%s=%s", name, value); + } + formData.Delete(0); + request->SetData(formData.GetString(), formData.GetLength()); + request->AddHeader("Content-Type", "application/x-www-form-urlencoded"); } - formData.Delete(0); - SetContent(request, formData.GetString(), formData.GetLength()); - SetHeader(request, "Content-Type", "application/x-www-form-urlencoded"); break; - } default: luaL_argerror(L, 2, luaL_typename(L, 2)); } @@ -376,14 +244,14 @@ static int request_SetContent(lua_State *L) static int request_SetContentType(lua_State *L) { - NETLIBHTTPREQUEST *request = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + MHttpRequest *request = *(MHttpRequest**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); if (!lua_isstring(L, 2)) { lua_pushvalue(L, 1); return 1; } const char *type = lua_tostring(L, 2); - SetHeader(request, "Content-Type", type); + request->AddHeader("Content-Type", type); lua_pushvalue(L, 1); return 1; @@ -391,7 +259,7 @@ static int request_SetContentType(lua_State *L) static int request_SetTimeout(lua_State *L) { - NETLIBHTTPREQUEST *request = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + MHttpRequest *request = *(MHttpRequest**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); request->timeout = luaL_optinteger(L, -1, 0); lua_pushvalue(L, 1); return 1; @@ -399,22 +267,16 @@ static int request_SetTimeout(lua_State *L) static int request_Send(lua_State *L) { - NETLIBHTTPREQUEST *request = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + MHttpRequest *request = *(MHttpRequest**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); - NETLIBHTTPREQUEST *newRequest = (NETLIBHTTPREQUEST*)mir_calloc(sizeof(NETLIBHTTPREQUEST)); + MHttpRequest *newRequest = new MHttpRequest(); newRequest->flags = request->flags; newRequest->requestType = request->requestType; - newRequest->szUrl = mir_strdup(request->szUrl); - newRequest->headersCount = request->headersCount; - newRequest->headers = (NETLIBHTTPHEADER*)mir_calloc(sizeof(NETLIBHTTPHEADER)*(request->headersCount + 1)); - for (int i = 0; i < request->headersCount; i++) { - newRequest->headers[i].szName = mir_strdup(request->headers[i].szName); - newRequest->headers[i].szValue = mir_strdup(request->headers[i].szValue); - } - newRequest->dataLength = request->dataLength; - newRequest->pData = (char*)mir_calloc(request->dataLength + 1); - memcpy(newRequest->pData, request->pData, request->dataLength); + newRequest->m_szUrl = request->m_szUrl; + newRequest->m_szParam = request->m_szParam; newRequest->timeout = request->timeout; + for (auto &it : *request) + newRequest->AddHeader(it->szName, it->szValue); if (lua_isfunction(L, 2)) { SendRequestAsync(L, 2, newRequest); @@ -422,8 +284,7 @@ static int request_Send(lua_State *L) } response_Create(L, newRequest); - Netlib_FreeHttpRequest(newRequest); - + delete newRequest; return 1; } @@ -454,8 +315,8 @@ static int request__index(lua_State *L) static int request__gc(lua_State *L) { - NETLIBHTTPREQUEST *request = *(NETLIBHTTPREQUEST**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); - Netlib_FreeHttpRequest(request); + MHttpRequest *request = *(MHttpRequest**)luaL_checkudata(L, 1, MT_NETLIBHTTPREQUEST); + delete request; return 0; } @@ -471,8 +332,8 @@ static const luaL_Reg requestApi[] = static int http_Request(lua_State *L) { - NETLIBHTTPREQUEST *request = CreateRequest(); - NETLIBHTTPREQUEST **udata = (NETLIBHTTPREQUEST**)lua_newuserdata(L, sizeof(NETLIBHTTPREQUEST*)); + MHttpRequest *request = CreateRequest(); + MHttpRequest **udata = (MHttpRequest**)lua_newuserdata(L, sizeof(MHttpRequest*)); *udata = request; request->requestType = (1 << (luaL_checkoption(L, 1, nullptr, httpMethods))); SetUrl(request, luaL_checkstring(L, 2)); @@ -483,7 +344,7 @@ static int http_Request(lua_State *L) static int http_Get(lua_State *L) { - NETLIBHTTPREQUEST *request = CreateRequest(); + MHttpRequest *request = CreateRequest(); request->requestType = REQUEST_GET; const char *url = luaL_checkstring(L, 1); @@ -495,14 +356,13 @@ static int http_Get(lua_State *L) } response_Create(L, request); - Netlib_FreeHttpRequest(request); - + delete request; return 1; } static int http_Post(lua_State *L) { - NETLIBHTTPREQUEST *request = CreateRequest(); + MHttpRequest *request = CreateRequest(); request->requestType = REQUEST_POST; const char *url = luaL_checkstring(L, 1); @@ -524,14 +384,13 @@ static int http_Post(lua_State *L) } response_Create(L, request); - Netlib_FreeHttpRequest(request); - + delete request; return 1; } static int http_Put(lua_State *L) { - NETLIBHTTPREQUEST *request = CreateRequest(); + MHttpRequest *request = CreateRequest(); request->requestType = REQUEST_PUT; const char *url = luaL_checkstring(L, 1); @@ -553,14 +412,13 @@ static int http_Put(lua_State *L) } response_Create(L, request); - Netlib_FreeHttpRequest(request); - + delete request; return 1; } static int http_Delete(lua_State *L) { - NETLIBHTTPREQUEST *request = CreateRequest(); + MHttpRequest *request = CreateRequest(); request->requestType = REQUEST_DELETE; const char *url = luaL_checkstring(L, 1); @@ -609,9 +467,9 @@ LUAMOD_API int luaopen_m_http(lua_State *L) luaL_setfuncs(L, responseApi, 0); lua_pop(L, 1); - luaL_newmetatable(L, MT_NETLIBHTTPHEADERS); - luaL_setfuncs(L, headersApi, 0); - lua_pop(L, 1); + // luaL_newmetatable(L, MT_NETLIBHTTPHEADERS); + // luaL_setfuncs(L, headersApi, 0); + // lua_pop(L, 1); luaL_newmetatable(L, MT_NETLIBHTTPCONTENT); luaL_setfuncs(L, contentApi, 0); diff --git a/plugins/PackUpdater/Src/Utils.cpp b/plugins/PackUpdater/Src/Utils.cpp index 1c24905cac..9e6a563606 100644 --- a/plugins/PackUpdater/Src/Utils.cpp +++ b/plugins/PackUpdater/Src/Utils.cpp @@ -107,38 +107,28 @@ void LoadOptions() BOOL DownloadFile(LPCTSTR tszURL, LPCTSTR tszLocal) { - NETLIBHTTPREQUEST nlhr = { 0 }; + MHttpRequest nlhr; nlhr.requestType = REQUEST_GET; nlhr.flags = NLHRF_REDIRECT | NLHRF_DUMPASTEXT | NLHRF_HTTP11; - char* szUrl = mir_u2a(tszURL); - nlhr.szUrl = szUrl; - nlhr.headersCount = 4; - nlhr.headers = (NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER)*nlhr.headersCount); - nlhr.headers[0].szName = "User-Agent"; - nlhr.headers[0].szValue = NETLIB_USER_AGENT; - nlhr.headers[1].szName = "Connection"; - nlhr.headers[1].szValue = "close"; - nlhr.headers[2].szName = "Cache-Control"; - nlhr.headers[2].szValue = "no-cache"; - nlhr.headers[3].szName = "Pragma"; - nlhr.headers[3].szValue = "no-cache"; + nlhr.m_szUrl = _T2A(tszURL); + nlhr.AddHeader("User-Agent", NETLIB_USER_AGENT); + nlhr.AddHeader("Connection", "close"); + nlhr.AddHeader("Cache-Control", "no-cache"); + nlhr.AddHeader("Pragma", "no-cache"); bool ret = false; NLHR_PTR pReply(Netlib_HttpTransaction(hNetlibUser, &nlhr)); if (pReply) { - if (200 == pReply->resultCode && pReply->dataLength > 0) { + if (200 == pReply->resultCode && !pReply->body.IsEmpty()) { HANDLE hFile = CreateFile(tszLocal, GENERIC_READ | GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); DWORD dwBytes; - WriteFile(hFile, pReply->pData, (uint32_t)pReply->dataLength, &dwBytes, nullptr); + WriteFile(hFile, pReply->body, pReply->body.GetLength(), &dwBytes, nullptr); ret = true; if (hFile) CloseHandle(hFile); } } - mir_free(szUrl); - mir_free(nlhr.headers); - DlgDld = ret; return ret; } diff --git a/plugins/PasteIt/src/PasteToWeb.cpp b/plugins/PasteIt/src/PasteToWeb.cpp index 9d1ad7ac5f..5fdfc7afec 100644 --- a/plugins/PasteIt/src/PasteToWeb.cpp +++ b/plugins/PasteIt/src/PasteToWeb.cpp @@ -426,47 +426,19 @@ char *PasteToWeb::SendToWeb(char *url, std::map &heade WideCharToMultiByte(CP_UTF8, 0, content.c_str(), -1, contentBytes, cbLen, nullptr, nullptr); --cbLen; - int nHeaders = 0; - for (std::map::iterator it = headers.begin(); it != headers.end(); ++it) { - ++nHeaders; - } - - NETLIBHTTPHEADER *httpHeaders = new NETLIBHTTPHEADER[nHeaders]; - - NETLIBHTTPREQUEST nlhr = { 0 }; + MHttpRequest nlhr; nlhr.requestType = REQUEST_POST; nlhr.flags = NLHRF_NODUMPSEND | NLHRF_DUMPASTEXT | NLHPIF_HTTP11; - nlhr.szUrl = url; - nlhr.headers = httpHeaders; - nlhr.pData = contentBytes; - nlhr.dataLength = cbLen; - nHeaders = 0; - std::list mallBuf; - for (std::map::iterator it = headers.begin(); it != headers.end(); ++it) { - char *b1 = new char[it->first.length() + 1]; - char *b2 = new char[it->second.length() + 1]; - mir_strncpy(b1, it->first.c_str(), it->first.length() + 1); - mir_strncpy(b2, it->second.c_str(), it->second.length() + 1); - httpHeaders[nHeaders].szName = b1; - httpHeaders[nHeaders].szValue = b2; - mallBuf.push_back(b1); - mallBuf.push_back(b2); - ++nHeaders; - } + nlhr.m_szUrl = url; + nlhr.SetData(contentBytes, cbLen); + for (auto it : headers) + nlhr.AddHeader(it.first.c_str(), it.second.c_str()); char *resCont = nullptr; - nlhr.headersCount = nHeaders; NLHR_PTR nlhrReply(Netlib_HttpTransaction(g_hNetlibUser, &nlhr)); - if (nlhrReply != nullptr) { - if (nlhrReply->resultCode == 200) { - resCont = nlhrReply->pData; - nlhrReply->pData = 0; - } - } - - delete[] httpHeaders; - for (std::list::iterator it = mallBuf.begin(); it != mallBuf.end(); ++it) - delete *it; + if (nlhrReply != nullptr) + if (nlhrReply->resultCode == 200) + resCont = nlhrReply->body.Detach(); mir_free(contentBytes); return resCont; diff --git a/plugins/PluginUpdater/src/Utils.cpp b/plugins/PluginUpdater/src/Utils.cpp index 9a30007c66..4cc80eaec1 100644 --- a/plugins/PluginUpdater/src/Utils.cpp +++ b/plugins/PluginUpdater/src/Utils.cpp @@ -143,22 +143,17 @@ int DownloadFile(FILEURL *pFileURL, HNETLIBCONN &nlc) #endif szUserAgent.Append(")"); - NETLIBHTTPHEADER headers[4] = { - { "User-Agent", szUserAgent.GetBuffer() }, - { "Connection", "close" }, - { "Cache-Control", "no-cache" }, - { "Pragma", "no-cache" } - }; - ptrA szUrl(mir_u2a(pFileURL->wszDownloadURL)); - NETLIBHTTPREQUEST nlhr = {}; + MHttpRequest nlhr; nlhr.flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11 | NLHRF_PERSISTENT; nlhr.requestType = REQUEST_GET; nlhr.nlc = nlc; - nlhr.szUrl = szUrl; - nlhr.headersCount = _countof(headers); - nlhr.headers = headers; + nlhr.m_szUrl = szUrl; + nlhr.AddHeader("User-Agent", szUserAgent); + nlhr.AddHeader("Connection", "close"); + nlhr.AddHeader("Cache-Control", "no-cache"); + nlhr.AddHeader("Pragma", "no-cache"); for (int i = 0; i < MAX_RETRIES; i++) { Netlib_LogfW(g_hNetlibUser, L"Downloading file %s to %s (attempt %d)", pFileURL->wszDownloadURL, pFileURL->wszDiskPath, i + 1); @@ -170,14 +165,14 @@ int DownloadFile(FILEURL *pFileURL, HNETLIBCONN &nlc) } nlc = pReply->nlc; - if (pReply->resultCode != 200 || pReply->dataLength <= 0) { + if (pReply->resultCode != 200 || pReply->body.IsEmpty()) { Netlib_LogfW(g_hNetlibUser, L"Downloading file %s failed with error %d", pFileURL->wszDownloadURL, pReply->resultCode); return pReply->resultCode; } // Check CRC sum if (pFileURL->CRCsum) { - int crc = crc32(0, (unsigned char *)pReply->pData, pReply->dataLength); + int crc = crc32(0, (unsigned char *)pReply->body.c_str(), pReply->body.GetLength()); if (crc != pFileURL->CRCsum) { // crc check failed, try again Netlib_LogfW(g_hNetlibUser, L"crc check failed for file %s", pFileURL->wszDiskPath); @@ -190,7 +185,7 @@ int DownloadFile(FILEURL *pFileURL, HNETLIBCONN &nlc) HANDLE hFile = CreateFile(pFileURL->wszDiskPath, GENERIC_READ | GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (hFile != INVALID_HANDLE_VALUE) { // write the downloaded file directly - WriteFile(hFile, pReply->pData, (DWORD)pReply->dataLength, &dwBytes, nullptr); + WriteFile(hFile, pReply->body, pReply->body.GetLength(), &dwBytes, nullptr); CloseHandle(hFile); } else { @@ -199,7 +194,7 @@ int DownloadFile(FILEURL *pFileURL, HNETLIBCONN &nlc) mir_snwprintf(wszTempFile, L"%s\\pulocal.tmp", g_wszTempPath); hFile = CreateFile(wszTempFile, GENERIC_READ | GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); if (hFile != INVALID_HANDLE_VALUE) { - WriteFile(hFile, pReply->pData, (DWORD)pReply->dataLength, &dwBytes, nullptr); + WriteFile(hFile, pReply->body, pReply->body.GetLength(), &dwBytes, nullptr); CloseHandle(hFile); PU::SafeMoveFile(wszTempFile, pFileURL->wszDiskPath); } diff --git a/plugins/SendScreenshotPlus/src/CSend.cpp b/plugins/SendScreenshotPlus/src/CSend.cpp index 9290e8d923..23f2c19c5c 100644 --- a/plugins/SendScreenshotPlus/src/CSend.cpp +++ b/plugins/SendScreenshotPlus/src/CSend.cpp @@ -422,36 +422,10 @@ const char* CSend::GetHTMLContent(char* str, const char* startTag, const char* e return begin; } -static void HTTPFormAppendData(NETLIBHTTPREQUEST* nlhr, size_t* dataMax, char** dataPos, const char* data, size_t len) -{ - nlhr->dataLength = (*dataPos - nlhr->pData); - if (nlhr->dataLength + len >= *dataMax) { - *dataPos = nlhr->pData; - *dataMax += 0x1000 + 0x1000 * (len >> 12); - nlhr->pData = (char*)mir_realloc(nlhr->pData, *dataMax); - if (!nlhr->pData) mir_free(*dataPos); - *dataPos = nlhr->pData; - if (!*dataPos) - return; - *dataPos += nlhr->dataLength; - } - if (data) { - memcpy(*dataPos, data, sizeof(char)*len); *dataPos += len; - nlhr->dataLength += (int)len; // not necessary - } -} - -void CSend::HTTPFormDestroy(NETLIBHTTPREQUEST* nlhr) -{ - mir_free(nlhr->headers[0].szValue), nlhr->headers[0].szValue = nullptr; - mir_free(nlhr->headers), nlhr->headers = nullptr; - mir_free(nlhr->pData), nlhr->pData = nullptr; -} - -int CSend::HTTPFormCreate(NETLIBHTTPREQUEST* nlhr, int requestType, const char* url, HTTPFormData* frm, size_t frmNum) +int CSend::HTTPFormCreate(MHttpRequest* nlhr, int requestType, const char* url, HTTPFormData* frm, size_t frmNum) { char boundary[16]; - memcpy(boundary, "--M461C/", 8); + strcpy(boundary, "--M461C/"); { union { @@ -467,57 +441,40 @@ int CSend::HTTPFormCreate(NETLIBHTTPREQUEST* nlhr, int requestType, const char* } nlhr->requestType = requestType; nlhr->flags = NLHRF_HTTP11; - if (!strncmp(url, "https://", 8)) nlhr->flags |= NLHRF_SSL; - nlhr->szUrl = (char*)url; - nlhr->headersCount = 3; + if (!strncmp(url, "https://", 8)) + nlhr->flags |= NLHRF_SSL; + nlhr->m_szUrl = url; + nlhr->AddHeader("Content-Type", CMStringA("multipart/form-data; boundary=") + boundary); + nlhr->AddHeader("User-Agent", __USER_AGENT_STRING); + nlhr->AddHeader("Accept-Language", "en-us,en;q=0.8"); for (HTTPFormData* iter = frm, *end = frm + frmNum; iter != end; ++iter) { - if (!(iter->flags&HTTPFF_HEADER)) break; - ++nlhr->headersCount; - } - nlhr->headers = (NETLIBHTTPHEADER*)mir_alloc(sizeof(NETLIBHTTPHEADER)*nlhr->headersCount); - { - char* contenttype = (char*)mir_alloc(sizeof(char)*(30 + 1 + sizeof(boundary))); - memcpy(contenttype, "multipart/form-data; boundary=", 30); - memcpy(contenttype + 30, boundary, sizeof(boundary)); - contenttype[30 + sizeof(boundary)] = '\0'; - nlhr->headers[0].szName = "Content-Type"; - nlhr->headers[0].szValue = contenttype; - nlhr->headers[1].szName = "User-Agent"; - nlhr->headers[1].szValue = __USER_AGENT_STRING; - nlhr->headers[2].szName = "Accept-Language"; - nlhr->headers[2].szValue = "en-us,en;q=0.8"; - int i = 3; - for (HTTPFormData* iter = frm, *end = frm + frmNum; iter != end; ++iter) { - if (!(iter->flags&HTTPFF_HEADER)) break; - nlhr->headers[i].szName = (char*)iter->name; - nlhr->headers[i++].szValue = (char*)iter->value_str; - } + if (!(iter->flags & HTTPFF_HEADER)) + break; + nlhr->AddHeader(iter->name, iter->value_str); } - char* dataPos = nlhr->pData; - size_t dataMax = 0; - for (HTTPFormData* iter = frm, *end = frm + frmNum; iter != end; ++iter) { - if (iter->flags&HTTPFF_HEADER) continue; - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, 2 + sizeof(boundary) + 40); - memset(dataPos, '-', 2); dataPos += 2; - memcpy(dataPos, boundary, sizeof(boundary)); dataPos += sizeof(boundary); - memcpy(dataPos, "\r\nContent-Disposition: form-data; name=\"", 40); dataPos += 40; - size_t namelen = mir_strlen(iter->name), valuelen = 0; - if (!(iter->flags&HTTPFF_INT)) - valuelen = mir_strlen(iter->value_str); - if (iter->flags&HTTPFF_FILE) { - const char* filename = strrchr(iter->value_str, '\\'); + + auto &str = nlhr->m_szParam; + for (HTTPFormData *iter = frm, *end = frm + frmNum; iter != end; ++iter) { + if (iter->flags & HTTPFF_HEADER) + continue; + + str.AppendFormat("--%s", boundary); + str.Append("\r\nContent-Disposition: form-data; name=\""); + + if (iter->flags & HTTPFF_FILE) { + const char *filename = strrchr(iter->value_str, '\\'); if (!filename) filename = strrchr(iter->value_str, '/'); if (!filename) filename = iter->value_str; else ++filename; - valuelen = mir_strlen(filename); - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 13 + valuelen + 17); - memcpy(dataPos, iter->name, namelen); dataPos += namelen; - memcpy(dataPos, "\"; filename=\"", 13); dataPos += 13; - memcpy(dataPos, filename, valuelen); dataPos += valuelen; - memcpy(dataPos, "\"\r\nContent-Type: ", 17); dataPos += 17; + + str.Append(iter->name); + str.Append("\"; filename=\""); + str.Append(filename); + str.Append("\"\r\nContent-Type: "); + /// add mime type - const char* mime = "application/octet-stream"; - const char* fileext = strrchr(filename, '.'); + const char *mime = "application/octet-stream"; + const char *fileext = strrchr(filename, '.'); if (fileext) { if (!mir_strcmp(fileext, ".jpg") || !mir_strcmp(fileext, ".jpeg") || !mir_strcmp(fileext, ".jpe")) mime = "image/jpeg"; @@ -530,71 +487,49 @@ int CSend::HTTPFormCreate(NETLIBHTTPREQUEST* nlhr, int requestType, const char* else if (!mir_strcmp(fileext, ".tif") || !mir_strcmp(fileext, ".tiff")) mime = "image/tiff"; } - HTTPFormAppendData(nlhr, &dataMax, &dataPos, mime, mir_strlen(mime)); - HTTPFormAppendData(nlhr, &dataMax, &dataPos, "\r\n\r\n", 4); + str.Append(mime); + str.Append("\r\n\r\n"); + /// add file content size_t filesize = 0; - FILE* fp = fopen(iter->value_str, "rb"); + FILE *fp = fopen(iter->value_str, "rb"); if (fp) { fseek(fp, 0, SEEK_END); filesize = ftell(fp); fseek(fp, 0, SEEK_SET); - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, filesize + 2); - if (fread(dataPos, 1, filesize, fp) != filesize) { + ptrA buf((char *)mir_alloc(filesize)); + if (fread(buf, 1, filesize, fp) != filesize) { + str.Append(buf, filesize); fclose(fp), fp = nullptr; } } if (!fp) { - HTTPFormDestroy(nlhr); Error(L"Error occurred when opening local file.\nAborting file upload..."); Exit(ACKRESULT_FAILED); return 1; } - else - fclose(fp); - dataPos += filesize; - memcpy(dataPos, "\r\n", 2); dataPos += 2; + fclose(fp); + str.Append("\r\n"); } - else if (iter->flags&HTTPFF_8BIT) { - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 38 + valuelen + 2); - memcpy(dataPos, iter->name, namelen); dataPos += namelen; - memcpy(dataPos, "\"\r\nContent-Transfer-Encoding: 8bit\r\n\r\n", 38); dataPos += 38; - memcpy(dataPos, iter->value_str, valuelen); dataPos += valuelen; - memcpy(dataPos, "\r\n", 2); dataPos += 2; + else if (iter->flags & HTTPFF_8BIT) { + str.Append(iter->name); + str.Append("\"\r\nContent-Transfer-Encoding: 8bit\r\n\r\n"); + str.Append(iter->value_str); + str.Append("\r\n"); } - else if (iter->flags&HTTPFF_INT) { - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 5 + 17/*max numbers*/ + 2); - memcpy(dataPos, iter->name, namelen); dataPos += namelen; - memcpy(dataPos, "\"\r\n\r\n", 5); dataPos += 5; - int ret = snprintf(dataPos, 17, "%Id", iter->value_int); - if (ret < 17 && ret>0) dataPos += ret; - memcpy(dataPos, "\r\n", 2); dataPos += 2; + else if (iter->flags & HTTPFF_INT) { + str.Append(iter->name); + str.Append("\"\r\n\r\n"); + str.AppendFormat("%Id", iter->value_int); + str.Append("\r\n"); } else { - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, namelen + 5 + valuelen + 2); - memcpy(dataPos, iter->name, namelen); dataPos += namelen; - memcpy(dataPos, "\"\r\n\r\n", 5); dataPos += 5; - memcpy(dataPos, iter->value_str, valuelen); dataPos += valuelen; - memcpy(dataPos, "\r\n", 2); dataPos += 2; + str.Append(iter->name); + str.Append("\"\r\n\r\n"); + str.Append(iter->value_str); + str.Append("\r\n"); } } - HTTPFormAppendData(nlhr, &dataMax, &dataPos, nullptr, 2 + sizeof(boundary) + 4); - memset(dataPos, '-', 2); dataPos += 2; - memcpy(dataPos, boundary, sizeof(boundary)); dataPos += sizeof(boundary); - memcpy(dataPos, "--\r\n", 4); dataPos += 4; - nlhr->dataLength = dataPos - nlhr->pData; -#ifdef _DEBUG /// print request content to "_sendss_tmp" file for debugging - { - FILE* fp = fopen("_sendss_tmp", "wb"); - if (fp) { - fprintf(fp, "--Target-- %s\n", nlhr->szUrl); - for (int i = 0; i < nlhr->headersCount; ++i) { - fprintf(fp, "%s: %s\n", nlhr->headers[i].szName, nlhr->headers[i].szValue); - } - fprintf(fp, "\n\n"); - fwrite(nlhr->pData, 1, nlhr->dataLength, fp); - fclose(fp); - } - } -#endif // _DEBUG + + str.AppendFormat("--%s--\r\n", boundary); return 0; } diff --git a/plugins/SendScreenshotPlus/src/CSend.h b/plugins/SendScreenshotPlus/src/CSend.h index 9301811f17..c694167eae 100644 --- a/plugins/SendScreenshotPlus/src/CSend.h +++ b/plugins/SendScreenshotPlus/src/CSend.h @@ -130,8 +130,7 @@ protected: }; static const char* GetHTMLContent(char* str, const char* startTag, const char* endTag); // changes "str", can be successfully used only once - void HTTPFormDestroy(NETLIBHTTPREQUEST* nlhr); // use to free data inside "nlhr" created by HTTPFormCreate - int HTTPFormCreate(NETLIBHTTPREQUEST* nlhr, int requestType, const char* url, HTTPFormData* frm, size_t frmNum); // returns "0" on success, Exit() will be called on failure (stop processing) + int HTTPFormCreate(MHttpRequest* nlhr, int requestType, const char* url, HTTPFormData* frm, size_t frmNum); // returns "0" on success, Exit() will be called on failure (stop processing) }; #endif diff --git a/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.cpp b/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.cpp index 5a2a4d8a34..6b604c33ba 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.cpp +++ b/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.cpp @@ -76,12 +76,10 @@ void CSendHost_ImageShack::SendThread() { // send DATA and wait for m_nlreply NLHR_PTR reply(Netlib_HttpTransaction(g_hNetlibUser, &m_nlhr)); - HTTPFormDestroy(&m_nlhr); if (reply) { - if (reply->resultCode >= 200 && reply->resultCode < 300 && reply->dataLength) { - reply->pData[reply->dataLength - 1] = '\0'; // make sure its null terminated + if (reply->resultCode >= 200 && reply->resultCode < 300 && reply->body.GetLength()) { const char* url = nullptr; - url = GetHTMLContent(reply->pData, "", ""); + url = GetHTMLContent(reply->body.GetBuffer(), "", ""); if (url && *url) { m_URLthumb = m_URL = url; @@ -95,19 +93,19 @@ void CSendHost_ImageShack::SendThread() return; } - url = GetHTMLContent(reply->pData, ""); + url = GetHTMLContent(reply->body.GetBuffer(), ""); wchar_t* err = nullptr; if (url) err = mir_a2u(url); if (!err || !*err) { // fallback to server response mess mir_free(err); - err = mir_a2u(reply->pData); + err = mir_a2u(reply->body); } Error(L"%s", err); mir_free(err); } else Error(SS_ERR_RESPONSE, m_pszSendTyp, reply->resultCode); } - else Error(SS_ERR_NORESPONSE, m_pszSendTyp, m_nlhr.resultCode); + else Error(SS_ERR_NORESPONSE, m_pszSendTyp, 500); Exit(ACKRESULT_FAILED); } diff --git a/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.h b/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.h index 7c58094aac..5197e8718a 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.h +++ b/plugins/SendScreenshotPlus/src/CSendHost_ImageShack.h @@ -40,7 +40,7 @@ public: int Send() override; protected: - NETLIBHTTPREQUEST m_nlhr; + MHttpRequest m_nlhr; void SendThread(); static void SendThreadWrapper(void * Obj); diff --git a/plugins/SendScreenshotPlus/src/CSendHost_imgur.cpp b/plugins/SendScreenshotPlus/src/CSendHost_imgur.cpp index bde9f158bb..c4bb3897f7 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_imgur.cpp +++ b/plugins/SendScreenshotPlus/src/CSendHost_imgur.cpp @@ -15,8 +15,8 @@ */ #include "stdafx.h" -CSendHost_Imgur::CSendHost_Imgur(HWND Owner, MCONTACT hContact, bool bAsync) - : CSend(Owner, hContact, bAsync) +CSendHost_Imgur::CSendHost_Imgur(HWND Owner, MCONTACT hContact, bool bAsync) : + CSend(Owner, hContact, bAsync) { m_EnableItem = SS_DLG_DESCRIPTION | SS_DLG_AUTOSEND | SS_DLG_DELETEAFTERSSEND; m_pszSendTyp = LPGENW("Image upload"); @@ -60,10 +60,9 @@ void CSendHost_Imgur::SendThread(void* obj) CSendHost_Imgur *self = (CSendHost_Imgur*)obj; // send DATA and wait for m_nlreply NLHR_PTR reply(Netlib_HttpTransaction(g_hNetlibUser, &self->m_nlhr)); - self->HTTPFormDestroy(&self->m_nlhr); if (reply) { - if (reply->dataLength) { - JSONROOT root(reply->pData); + if (reply->body.GetLength()) { + JSONROOT root(reply->body); if (root) { if ((*root)["success"].as_bool()) { self->m_URL = (*root)["data"]["link"].as_mstring(); @@ -80,7 +79,7 @@ void CSendHost_Imgur::SendThread(void* obj) } else self->Error(SS_ERR_RESPONSE, self->m_pszSendTyp, reply->resultCode); } - else self->Error(SS_ERR_NORESPONSE, self->m_pszSendTyp, self->m_nlhr.resultCode); + else self->Error(SS_ERR_NORESPONSE, self->m_pszSendTyp, 500); self->Exit(ACKRESULT_FAILED); } diff --git a/plugins/SendScreenshotPlus/src/CSendHost_imgur.h b/plugins/SendScreenshotPlus/src/CSendHost_imgur.h index 544afecd53..fee457d00a 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_imgur.h +++ b/plugins/SendScreenshotPlus/src/CSendHost_imgur.h @@ -24,7 +24,7 @@ class CSendHost_Imgur : public CSend { int Send() override; protected: - NETLIBHTTPREQUEST m_nlhr; + MHttpRequest m_nlhr; static void SendThread(void* obj); }; #endif diff --git a/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.cpp b/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.cpp index 58651ae85d..4fcf8f7d8b 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.cpp +++ b/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.cpp @@ -65,11 +65,9 @@ void CSendHost_UploadPie::SendThread(void* obj) CSendHost_UploadPie* self = (CSendHost_UploadPie*)obj; // send DATA and wait for m_nlreply NLHR_PTR reply(Netlib_HttpTransaction(g_hNetlibUser, &self->m_nlhr)); - self->HTTPFormDestroy(&self->m_nlhr); if (reply) { - if (reply->resultCode >= 200 && reply->resultCode < 300 && reply->dataLength) { - reply->pData[reply->dataLength - 1] = '\0'; // make sure its null terminated - char* url = reply->pData; + if (reply->resultCode >= 200 && reply->resultCode < 300 && reply->body.GetLength()) { + char* url = reply->body.GetBuffer(); do { char* pos; if ((url = strstr(url, kHostURL))) { @@ -89,17 +87,17 @@ void CSendHost_UploadPie::SendThread(void* obj) self->svcSendMsgExit(url); return; } else { // check error mess from server - const char* err = GetHTMLContent(reply->pData, "

"); + const char* err = GetHTMLContent(reply->body.GetBuffer(), "

"); wchar_t* werr; if (err) werr = mir_a2u(err); - else werr = mir_a2u(reply->pData); + else werr = mir_a2u(reply->body); self->Error(L"%s", werr); mir_free(werr); } } else self->Error(SS_ERR_RESPONSE, self->m_pszSendTyp, reply->resultCode); } - else self->Error(SS_ERR_NORESPONSE, self->m_pszSendTyp, self->m_nlhr.resultCode); + else self->Error(SS_ERR_NORESPONSE, self->m_pszSendTyp, 500); self->Exit(ACKRESULT_FAILED); } diff --git a/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.h b/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.h index 94cfdf1fbc..8a4abd350f 100644 --- a/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.h +++ b/plugins/SendScreenshotPlus/src/CSendHost_uploadpie.h @@ -24,7 +24,7 @@ class CSendHost_UploadPie : public CSend { protected: int m_expire; - NETLIBHTTPREQUEST m_nlhr; + MHttpRequest m_nlhr; static void SendThread(void* obj); }; #endif diff --git a/plugins/SmileyAdd/src/download.cpp b/plugins/SmileyAdd/src/download.cpp index ef0e4a0682..1aa2ac1fd4 100644 --- a/plugins/SmileyAdd/src/download.cpp +++ b/plugins/SmileyAdd/src/download.cpp @@ -42,22 +42,17 @@ static bool threadRunning; bool InternetDownloadFile(const char *szUrl, char *szDest, HNETLIBCONN &hHttpDwnl) { int result = 0xBADBAD; - char *szRedirUrl = nullptr; - NETLIBHTTPREQUEST nlhr = {}; // initialize the netlib request + MHttpRequest nlhr; nlhr.requestType = REQUEST_GET; nlhr.flags = NLHRF_NODUMP | NLHRF_HTTP11 | NLHRF_PERSISTENT | NLHRF_REDIRECT; - nlhr.szUrl = (char*)szUrl; + nlhr.m_szUrl = szUrl; nlhr.nlc = hHttpDwnl; // change the header so the plugin is pretended to be IE 6 + WinXP - nlhr.headersCount = 2; - nlhr.headers = (NETLIBHTTPHEADER*)alloca(sizeof(NETLIBHTTPHEADER)*nlhr.headersCount); - nlhr.headers[0].szName = "User-Agent"; - nlhr.headers[0].szValue = NETLIB_USER_AGENT; - nlhr.headers[1].szName = "Connection"; - nlhr.headers[1].szValue = "close"; + nlhr.AddHeader("User-Agent", NETLIB_USER_AGENT); + nlhr.AddHeader("Connection", "close"); while (result == 0xBADBAD) { // download the page @@ -73,7 +68,7 @@ bool InternetDownloadFile(const char *szUrl, char *szDest, HNETLIBCONN &hHttpDwn int res = -1; int fh = _open(szDest, _O_BINARY | _O_WRONLY | _O_CREAT, _S_IREAD | _S_IWRITE); if (fh != -1) { - res = _write(fh, nlhrReply->pData, nlhrReply->dataLength); + res = _write(fh, nlhrReply->body, nlhrReply->body.GetLength()); _close(fh); } if (res < 0) @@ -81,28 +76,6 @@ bool InternetDownloadFile(const char *szUrl, char *szDest, HNETLIBCONN &hHttpDwn else result = 0; } - // if the recieved code is 302 Moved, Found, etc - // workaround for url forwarding - else if (nlhrReply->resultCode == 302 || nlhrReply->resultCode == 301 || nlhrReply->resultCode == 307) { // page moved - // get the url for the new location and save it to szInfo - // look for the reply header "Location" - if (auto *pszUrl = Netlib_GetHeader(nlhrReply, "Location")) { - size_t rlen = 0; - if (pszUrl[0] == '/') { - const char *szPref = strstr(szUrl, "://"); - szPref = szPref ? szPref + 3 : szUrl; - const char *szPath = strchr(szPref, '/'); - rlen = szPath != nullptr ? szPath - szUrl : mir_strlen(szUrl); - } - - szRedirUrl = (char *)mir_realloc(szRedirUrl, rlen + mir_strlen(pszUrl) * 3 + 1); - - strncpy(szRedirUrl, szUrl, rlen); - mir_strcpy(szRedirUrl + rlen, pszUrl); - - nlhr.szUrl = szRedirUrl; - } - } else result = 1; } else { @@ -111,8 +84,6 @@ bool InternetDownloadFile(const char *szUrl, char *szDest, HNETLIBCONN &hHttpDwn } } - mir_free(szRedirUrl); - return result == 0; } diff --git a/protocols/CloudFile/src/Services/dropbox_service.cpp b/protocols/CloudFile/src/Services/dropbox_service.cpp index 805a7f2800..92b00fc493 100644 --- a/protocols/CloudFile/src/Services/dropbox_service.cpp +++ b/protocols/CloudFile/src/Services/dropbox_service.cpp @@ -85,7 +85,7 @@ void CDropboxService::RequestAccessTokenThread(void *param) return; } - JSONNode root = JSONNode::parse(response->pData); + JSONNode root = JSONNode::parse(response->body); if (root.empty()) { Netlib_Logf(m_hConnection, "%s: %s", GetAccountName(), HttpStatusToError(response->resultCode)); ShowNotification(TranslateT("Server does not respond"), MB_ICONERROR); @@ -206,7 +206,7 @@ auto CDropboxService::CreateSharedLink(const std::string &path) if (!response || response->resultCode != HTTP_CODE_CONFLICT) HttpResponseToError(response); - JSONNode root = JSONNode::parse(response->pData); + JSONNode root = JSONNode::parse(response->body); if (root.isnull()) throw Exception(HttpStatusToError()); diff --git a/protocols/CloudFile/src/Services/google_service.cpp b/protocols/CloudFile/src/Services/google_service.cpp index 58b32eaa7f..fea2c3b2b4 100644 --- a/protocols/CloudFile/src/Services/google_service.cpp +++ b/protocols/CloudFile/src/Services/google_service.cpp @@ -100,8 +100,8 @@ void CGDriveService::RequestAccessTokenThread(void *param) NLHR_PTR response(request.Send(m_hConnection)); if (response == nullptr || response->resultCode != HTTP_CODE_OK) { - const char *error = response && response->dataLength - ? response->pData + const char *error = response && response->body.GetLength() + ? response->body : HttpStatusToError(response ? response->resultCode : 0); Netlib_Logf(m_hConnection, "%s: %s", GetAccountName(), error); @@ -110,7 +110,7 @@ void CGDriveService::RequestAccessTokenThread(void *param) return; } - JSONNode root = JSONNode::parse(response->pData); + JSONNode root = JSONNode::parse(response->body); if (root.empty()) { Netlib_Logf(m_hConnection, "%s: %s", GetAccountName(), HttpStatusToError(response->resultCode)); ShowNotification(TranslateT("Server does not respond"), MB_ICONERROR); @@ -180,7 +180,7 @@ auto CGDriveService::CreateUploadSession(const std::string &parentId, const std: HandleHttpError(response); if (HTTP_CODE_SUCCESS(response->resultCode)) - if (auto *pszHdr = Netlib_GetHeader(response, "Location")) + if (auto *pszHdr = response->FindHeader("Location")) return std::string(pszHdr); HttpResponseToError(response); diff --git a/protocols/CloudFile/src/Services/microsoft_service.cpp b/protocols/CloudFile/src/Services/microsoft_service.cpp index 8d63f4a23f..17115235cd 100644 --- a/protocols/CloudFile/src/Services/microsoft_service.cpp +++ b/protocols/CloudFile/src/Services/microsoft_service.cpp @@ -100,8 +100,8 @@ void COneDriveService::RequestAccessTokenThread(void *param) NLHR_PTR response(request.Send(m_hConnection)); if (response == nullptr || response->resultCode != HTTP_CODE_OK) { - const char *error = response->dataLength - ? response->pData + const char *error = response->body.GetLength() + ? response->body : HttpStatusToError(response->resultCode); Netlib_Logf(m_hConnection, "%s: %s", GetAccountName(), error); @@ -110,7 +110,7 @@ void COneDriveService::RequestAccessTokenThread(void *param) return; } - JSONNode root = JSONNode::parse(response->pData); + JSONNode root = JSONNode::parse(response->body); if (root.empty()) { Netlib_Logf(m_hConnection, "%s: %s", GetAccountName(), HttpStatusToError(response->resultCode)); ShowNotification(TranslateT("Server does not respond"), MB_ICONERROR); diff --git a/protocols/CloudFile/src/Services/yandex_service.cpp b/protocols/CloudFile/src/Services/yandex_service.cpp index f21e9ef2e0..892821e0c4 100644 --- a/protocols/CloudFile/src/Services/yandex_service.cpp +++ b/protocols/CloudFile/src/Services/yandex_service.cpp @@ -102,8 +102,8 @@ void CYandexService::RequestAccessTokenThread(void *param) NLHR_PTR response(request.Send(m_hConnection)); if (response == nullptr || response->resultCode != HTTP_CODE_OK) { - const char *error = response->dataLength - ? response->pData + const char *error = response->body.GetLength() + ? response->body : HttpStatusToError(response->resultCode); Netlib_Logf(m_hConnection, "%s: %s", GetAccountName(), error); @@ -112,7 +112,7 @@ void CYandexService::RequestAccessTokenThread(void *param) return; } - JSONNode root = JSONNode::parse(response->pData); + JSONNode root = JSONNode::parse(response->body); if (root.empty()) { Netlib_Logf(m_hConnection, "%s: %s", GetAccountName(), HttpStatusToError(response->resultCode)); ShowNotification(TranslateT("Server does not respond"), MB_ICONERROR); diff --git a/protocols/CloudFile/src/cloud_file.cpp b/protocols/CloudFile/src/cloud_file.cpp index 9f66caaf82..772b42ae36 100644 --- a/protocols/CloudFile/src/cloud_file.cpp +++ b/protocols/CloudFile/src/cloud_file.cpp @@ -129,16 +129,16 @@ char* CCloudService::HttpStatusToError(int status) return "Unknown error"; } -void CCloudService::HttpResponseToError(NETLIBHTTPREQUEST *response) +void CCloudService::HttpResponseToError(MHttpResponse *response) { if (response == nullptr) throw Exception(HttpStatusToError()); - if (response->dataLength) - throw Exception(response->pData); + if (response->body.GetLength()) + throw Exception(response->body.c_str()); throw Exception(HttpStatusToError(response->resultCode)); } -void CCloudService::HandleHttpError(NETLIBHTTPREQUEST *response) +void CCloudService::HandleHttpError(MHttpResponse *response) { if (response == nullptr) throw Exception(HttpStatusToError()); @@ -152,11 +152,11 @@ void CCloudService::HandleHttpError(NETLIBHTTPREQUEST *response) HttpResponseToError(response); } -JSONNode CCloudService::GetJsonResponse(NETLIBHTTPREQUEST *response) +JSONNode CCloudService::GetJsonResponse(MHttpResponse *response) { HandleHttpError(response); - JSONNode root = JSONNode::parse(response->pData); + JSONNode root = JSONNode::parse(response->body); if (root.isnull()) throw Exception(HttpStatusToError()); diff --git a/protocols/CloudFile/src/cloud_file.h b/protocols/CloudFile/src/cloud_file.h index de053af431..4a5b91da72 100644 --- a/protocols/CloudFile/src/cloud_file.h +++ b/protocols/CloudFile/src/cloud_file.h @@ -18,15 +18,15 @@ protected: std::string PreparePath(const std::string &path) const; virtual char* HttpStatusToError(int status = 0); - virtual void HttpResponseToError(NETLIBHTTPREQUEST *response); - virtual void HandleHttpError(NETLIBHTTPREQUEST *response); + virtual void HttpResponseToError(MHttpResponse *response); + virtual void HandleHttpError(MHttpResponse *response); virtual void HandleJsonError(JSONNode &node) = 0; // events void OnModulesLoaded() override; MWindow OnCreateAccMgrUI(MWindow) override; - JSONNode GetJsonResponse(NETLIBHTTPREQUEST *response); + JSONNode GetJsonResponse(MHttpResponse *response); virtual void Upload(FileTransferParam *ftp) = 0; diff --git a/protocols/CloudFile/src/http_request.h b/protocols/CloudFile/src/http_request.h index 68be404921..214ecea761 100644 --- a/protocols/CloudFile/src/http_request.h +++ b/protocols/CloudFile/src/http_request.h @@ -17,7 +17,7 @@ public: } }; -class HttpRequest : protected NETLIBHTTPREQUEST +class HttpRequest : public MHttpRequest { private: CMStringA m_szUrl; @@ -26,28 +26,11 @@ private: { requestType = type; flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMP; - szUrl = NULL; - headers = NULL; - headersCount = 0; - pData = NULL; - dataLength = 0; - resultCode = 0; - szResultDescr = NULL; nlc = NULL; timeout = 0; } protected: - enum HttpRequestUrlFormat { FORMAT }; - - void 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 AddBasicAuthHeader(LPCSTR szLogin, LPCSTR szPassword) { size_t length = mir_strlen(szLogin) + mir_strlen(szPassword) + 1; @@ -60,47 +43,17 @@ protected: szPassword); ptrA ePair(mir_base64_encode(cPair, length)); - - length = mir_strlen(ePair) + 7; - char *value = (char*)mir_calloc(length + 1); - mir_snprintf(value, length, "Basic %s", ePair.get()); - - headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount + 1)); - headers[headersCount].szName = mir_strdup("Authorization"); - headers[headersCount].szValue = value; - headersCount++; + AddHeader("Authorization", CMStringA(FORMAT, "Basic %s", ePair.get())); } void AddBearerAuthHeader(LPCSTR szValue) { - size_t length = mir_strlen(szValue) + 8; - char *value = (char*)mir_calloc(length + 1); - mir_snprintf( - value, - length, - "Bearer %s", - szValue); - - headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount + 1)); - headers[headersCount].szName = mir_strdup("Authorization"); - headers[headersCount].szValue = value; - headersCount++; + AddHeader("Authorization", CMStringA(FORMAT, "Bearer %s", szValue)); } void AddOAuthHeader(LPCSTR szValue) { - size_t length = mir_strlen(szValue) + 7; - char *value = (char*)mir_calloc(length + 1); - mir_snprintf( - value, - length, - "OAuth %s", - szValue); - - headers = (NETLIBHTTPHEADER*)mir_realloc(headers, sizeof(NETLIBHTTPHEADER)*(headersCount + 1)); - headers[headersCount].szName = mir_strdup("Authorization"); - headers[headersCount].szValue = value; - headersCount++; + AddHeader("Authorization", CMStringA(FORMAT, "OAuth %s", szValue)); } void AddUrlParameter(const char *urlFormat, ...) @@ -124,16 +77,6 @@ protected: va_end(valueArgs); } - void SetData(const char *data, size_t size) - { - if (pData != NULL) - mir_free(pData); - - dataLength = (int)size; - pData = (char*)mir_alloc(size); - memcpy(pData, data, size); - } - public: HttpRequest(int type, LPCSTR url) { @@ -142,7 +85,7 @@ public: m_szUrl = url; } - HttpRequest(int type, HttpRequestUrlFormat, LPCSTR urlFormat, ...) + HttpRequest(int type, CMStringDataFormat, LPCSTR urlFormat, ...) { Init(type); @@ -152,22 +95,9 @@ public: va_end(formatArgs); } - ~HttpRequest() - { - for (int i = 0; i < headersCount; i++) - { - mir_free(headers[i].szName); - mir_free(headers[i].szValue); - } - mir_free(headers); - if (pData) - mir_free(pData); - } - - NETLIBHTTPREQUEST* Send(HNETLIBUSER hConnection) + MHttpResponse* Send(HNETLIBUSER hConnection) { m_szUrl.Replace('\\', '/'); - szUrl = m_szUrl.GetBuffer(); return Netlib_HttpTransaction(hConnection, this); } }; diff --git a/protocols/CurrencyRates/src/HTTPSession.cpp b/protocols/CurrencyRates/src/HTTPSession.cpp index beee03b47c..a00a71d635 100644 --- a/protocols/CurrencyRates/src/HTTPSession.cpp +++ b/protocols/CurrencyRates/src/HTTPSession.cpp @@ -9,15 +9,6 @@ void CALLBACK waitStub() show_popup(g_pCurrentProvider, 0, -1, TranslateW(ERROR_MSG)); } -static int find_header(const NETLIBHTTPREQUEST* pRequest, const char* hdr) -{ - for (int i = 0; i < pRequest->headersCount; ++i) - if (0 == _stricmp(pRequest->headers[i].szName, hdr)) - return i; - - return -1; -} - bool CHTTPSession::OpenURL(const CMStringW &rsURL) { m_szUrl = rsURL; @@ -29,20 +20,14 @@ bool CHTTPSession::ReadResponce(CMStringW &rsResponce) if (m_szUrl.IsEmpty()) return false; - NETLIBHTTPHEADER headers[] = - { - { "User-Agent", NETLIB_USER_AGENT }, - { "Connection", "close" }, - { "Cache-Control", "no-cache" }, - { "Pragma", "no-cache" } - }; - - NETLIBHTTPREQUEST nlhr = {}; + MHttpRequest nlhr; nlhr.requestType = REQUEST_GET; nlhr.flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11 | NLHRF_REDIRECT; - nlhr.szUrl = m_szUrl.GetBuffer(); - nlhr.headersCount = _countof(headers); - nlhr.headers = headers; + nlhr.m_szUrl = m_szUrl; + nlhr.AddHeader("User-Agent", NETLIB_USER_AGENT); + nlhr.AddHeader("Connection", "close"); + nlhr.AddHeader("Cache-Control", "no-cache"); + nlhr.AddHeader("Pragma", "no-cache"); bool bResult = false; NLHR_PTR pReply(0); @@ -52,13 +37,12 @@ bool CHTTPSession::ReadResponce(CMStringW &rsResponce) } if (pReply) { - if ((200 == pReply->resultCode) && (pReply->dataLength > 0)) { - CMStringA buf(pReply->pData, pReply->dataLength); - int nIndex = find_header(pReply, "Content-Type"); - if ((-1 != nIndex) && (nullptr != strstr(_strlwr(pReply->headers[nIndex].szValue), "utf-8"))) - rsResponce = ptrW(mir_utf8decodeW(buf)); + if ((200 == pReply->resultCode) && !pReply->body.IsEmpty()) { + auto *pEncoding = pReply->FindHeader("Content-Type"); + if (pEncoding && strstr(pEncoding, "utf-8")) + rsResponce = ptrW(mir_utf8decodeW(pReply->body)); else - rsResponce = _A2T(buf); + rsResponce = _A2T(pReply->body); bResult = true; } diff --git a/protocols/Discord/src/avatars.cpp b/protocols/Discord/src/avatars.cpp index a131b23856..fd2d57181c 100644 --- a/protocols/Discord/src/avatars.cpp +++ b/protocols/Discord/src/avatars.cpp @@ -52,7 +52,7 @@ INT_PTR CDiscordProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam) ///////////////////////////////////////////////////////////////////////////////////////// -void CDiscordProto::OnReceiveAvatar(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CDiscordProto::OnReceiveAvatar(MHttpResponse *reply, AsyncHttpRequest *pReq) { PROTO_AVATAR_INFORMATION ai = { 0 }; ai.format = PA_FORMAT_UNKNOWN; @@ -64,7 +64,7 @@ LBL_Error: return; } - if (auto *pszHdr = Netlib_GetHeader(reply, "Content-Type")) + if (auto *pszHdr = reply->FindHeader("Content-Type")) ai.format = ProtoGetAvatarFormatByMimeType(pszHdr); if (ai.format == PA_FORMAT_UNKNOWN) { @@ -81,7 +81,7 @@ LBL_Error: goto LBL_Error; } - fwrite(reply->pData, 1, reply->dataLength, out); + fwrite(reply->body, 1, reply->body.GetLength(), out); fclose(out); if (ai.hContact) diff --git a/protocols/Discord/src/connection.cpp b/protocols/Discord/src/connection.cpp index d98d6e4ec8..00c9214b2c 100644 --- a/protocols/Discord/src/connection.cpp +++ b/protocols/Discord/src/connection.cpp @@ -21,15 +21,10 @@ void CDiscordProto::ExecuteRequest(AsyncHttpRequest *pReq) { CMStringA str; - pReq->szUrl = pReq->m_szUrl.GetBuffer(); if (!pReq->m_szParam.IsEmpty()) { if (pReq->requestType == REQUEST_GET) { str.Format("%s?%s", pReq->m_szUrl.c_str(), pReq->m_szParam.c_str()); - pReq->szUrl = str.GetBuffer(); - } - else { - pReq->pData = mir_strdup(pReq->m_szParam); - pReq->dataLength = pReq->m_szParam.GetLength(); + pReq->m_szUrl = str.GetBuffer(); } } @@ -40,7 +35,7 @@ void CDiscordProto::ExecuteRequest(AsyncHttpRequest *pReq) } bool bRetryable = pReq->nlc != nullptr; - debugLogA("Executing request #%d:\n%s", pReq->m_iReqNum, pReq->szUrl); + debugLogA("Executing request #%d:\n%s", pReq->m_iReqNum, pReq->m_szUrl.c_str()); LBL_Retry: NLHR_PTR reply(Netlib_HttpTransaction(m_hNetlibUser, pReq)); diff --git a/protocols/Discord/src/gateway.cpp b/protocols/Discord/src/gateway.cpp index e76de2848a..759afed573 100644 --- a/protocols/Discord/src/gateway.cpp +++ b/protocols/Discord/src/gateway.cpp @@ -43,19 +43,15 @@ void CDiscordProto::GatewayThread(void*) bool CDiscordProto::GatewayThreadWorker() { - NETLIBHTTPHEADER hdrs[] = - { - { "Origin", "https://discord.com" }, - { 0, 0 }, - { 0, 0 }, - }; - + bool bHasCookie = false; + MHttpHeaders hdrs; + hdrs.AddHeader("Origin", "https://discord.com"); if (!m_szWSCookie.IsEmpty()) { - hdrs[1].szName = "Cookie"; - hdrs[1].szValue = m_szWSCookie.GetBuffer(); + bHasCookie = true; + hdrs.AddHeader("Cookie", m_szWSCookie); } - NLHR_PTR pReply(WebSocket_Connect(m_hGatewayNetlibUser, m_szGateway + "/?encoding=json&v=8", hdrs)); + NLHR_PTR pReply(WebSocket_Connect(m_hGatewayNetlibUser, m_szGateway + "/?encoding=json&v=8", &hdrs)); if (pReply == nullptr) { debugLogA("Gateway connection failed, exiting"); return false; @@ -66,7 +62,7 @@ bool CDiscordProto::GatewayThreadWorker() if (pReply->resultCode != 101) { // if there's no cookie & Miranda is bounced with error 404, simply apply the cookie and try again if (pReply->resultCode == 404) { - if (hdrs[1].szName == nullptr) + if (!bHasCookie) return true; m_szWSCookie.Empty(); // don't use the same cookie twice diff --git a/protocols/Discord/src/http.cpp b/protocols/Discord/src/http.cpp index f65451f9ce..82e8d495d0 100644 --- a/protocols/Discord/src/http.cpp +++ b/protocols/Discord/src/http.cpp @@ -59,8 +59,7 @@ AsyncHttpRequest::AsyncHttpRequest(CDiscordProto *ppro, int iRequestType, LPCSTR if (pRoot != nullptr) { ptrW text(json_write(pRoot)); - pData = mir_utf8encodeW(text); - dataLength = (int)mir_strlen(pData); + m_szParam = ptrA(mir_utf8encodeW(text)); AddHeader("Content-Type", "application/json"); } @@ -71,7 +70,7 @@ AsyncHttpRequest::AsyncHttpRequest(CDiscordProto *ppro, int iRequestType, LPCSTR m_iReqNum = ::InterlockedIncrement(&g_reqNum); } -JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) +JsonReply::JsonReply(MHttpResponse *pReply) { if (pReply == nullptr) { m_errorCode = 500; @@ -80,7 +79,7 @@ JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) m_errorCode = pReply->resultCode; - m_root = json_parse(pReply->pData); + m_root = json_parse(pReply->body); if (m_root == nullptr) m_errorCode = 500; } diff --git a/protocols/Discord/src/proto.cpp b/protocols/Discord/src/proto.cpp index 1e76ead10d..210d649d00 100644 --- a/protocols/Discord/src/proto.cpp +++ b/protocols/Discord/src/proto.cpp @@ -329,7 +329,7 @@ HANDLE CDiscordProto::SearchAdvanced(HWND hwndDlg) ///////////////////////////////////////////////////////////////////////////////////////// // Basic search - by SnowFlake -void CDiscordProto::OnReceiveUserinfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CDiscordProto::OnReceiveUserinfo(MHttpResponse *pReply, AsyncHttpRequest*) { JsonReply root(pReply); if (!root) { @@ -459,7 +459,7 @@ MCONTACT CDiscordProto::AddToListByEvent(int flags, int, MEVENT hDbEvent) //////////////////////////////////////////////////////////////////////////////////////// // SendMsg -void CDiscordProto::OnSendMsg(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CDiscordProto::OnSendMsg(MHttpResponse *pReply, AsyncHttpRequest *pReq) { JsonReply root(pReply); if (!root) { @@ -574,7 +574,7 @@ int CDiscordProto::UserIsTyping(MCONTACT hContact, int type) ///////////////////////////////////////////////////////////////////////////////////////// -void CDiscordProto::OnReceiveMarkRead(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) +void CDiscordProto::OnReceiveMarkRead(MHttpResponse *pReply, AsyncHttpRequest *) { JsonReply root(pReply); if (root) @@ -712,10 +712,10 @@ void CDiscordProto::SendFileThread(void *param) szBoundary.Insert(0, "\r\n"); szBoundary.Append("--\r\n"); - pReq->dataLength = int(szBody.GetLength() + szBoundary.GetLength() + cbBytes); - pReq->pData = (char*)mir_alloc(pReq->dataLength+1); - memcpy(pReq->pData, szBody.c_str(), szBody.GetLength()); - size_t cbRead = fread(pReq->pData + szBody.GetLength(), 1, cbBytes, in); + pReq->m_szParam.Truncate(int(szBody.GetLength() + szBoundary.GetLength() + cbBytes)); + + memcpy(pReq->m_szParam.GetBuffer(), szBody.c_str(), szBody.GetLength()); + size_t cbRead = fread(pReq->m_szParam.GetBuffer() + szBody.GetLength(), 1, cbBytes, in); fclose(in); if (cbBytes != cbRead) { debugLogA("cannot read file %S: %d bytes read instead of %d", p->wszFileName.c_str(), cbRead, cbBytes); @@ -723,14 +723,14 @@ void CDiscordProto::SendFileThread(void *param) goto LBL_Error; } - memcpy(pReq->pData + szBody.GetLength() + cbBytes, szBoundary, szBoundary.GetLength()); + memcpy(pReq->m_szParam.GetBuffer() + szBody.GetLength() + cbBytes, szBoundary, szBoundary.GetLength()); pReq->pUserInfo = p; Push(pReq); ProtoBroadcastAck(p->hContact, ACKTYPE_FILE, ACKRESULT_CONNECTED, param); } -void CDiscordProto::OnReceiveFile(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CDiscordProto::OnReceiveFile(MHttpResponse *pReply, AsyncHttpRequest *pReq) { SendFileThreadParam *p = (SendFileThreadParam*)pReq->pUserInfo; if (pReply->resultCode != 200) { diff --git a/protocols/Discord/src/proto.h b/protocols/Discord/src/proto.h index e34f6cbfa9..fdb5e6a33b 100644 --- a/protocols/Discord/src/proto.h +++ b/protocols/Discord/src/proto.h @@ -80,7 +80,7 @@ class JsonReply int m_errorCode = 0; public: - JsonReply(NETLIBHTTPREQUEST *); + JsonReply(MHttpResponse *); ~JsonReply(); __forceinline int error() const { return m_errorCode; } @@ -495,25 +495,25 @@ public: void OnLoggedIn(); void OnLoggedOut(); - void OnReceiveCreateChannel(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveFile(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveGateway(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveLogout(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveMarkRead(NETLIBHTTPREQUEST*, AsyncHttpRequest *); - void OnReceiveMessageAck(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveToken(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveUserinfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveCreateChannel(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveFile(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveGateway(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveLogout(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveMarkRead(MHttpResponse*, AsyncHttpRequest *); + void OnReceiveMessageAck(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveToken(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveUserinfo(MHttpResponse*, AsyncHttpRequest*); void RetrieveMyInfo(); - void OnReceiveMyInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveMyInfo(MHttpResponse*, AsyncHttpRequest*); void RetrieveHistory(CDiscordUser *pUser, CDiscordHistoryOp iOp = MSG_NOFILTER, SnowFlake msgid = 0, int iLimit = 50); - void OnReceiveHistory(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveHistory(MHttpResponse*, AsyncHttpRequest*); bool RetrieveAvatar(MCONTACT hContact); - void OnReceiveAvatar(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveAvatar(MHttpResponse*, AsyncHttpRequest*); - void OnSendMsg(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnSendMsg(MHttpResponse*, AsyncHttpRequest*); ////////////////////////////////////////////////////////////////////////////////////// // Misc diff --git a/protocols/Discord/src/server.cpp b/protocols/Discord/src/server.cpp index 1ef3517822..104d45435d 100644 --- a/protocols/Discord/src/server.cpp +++ b/protocols/Discord/src/server.cpp @@ -54,7 +54,7 @@ static int compareMsgHistory(const JSONNode *p1, const JSONNode *p2) return wcscmp((*p1)["id"].as_mstring(), (*p2)["id"].as_mstring()); } -void CDiscordProto::OnReceiveHistory(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CDiscordProto::OnReceiveHistory(MHttpResponse *pReply, AsyncHttpRequest *pReq) { CDiscordUser *pUser = (CDiscordUser*)pReq->pUserInfo; @@ -147,7 +147,7 @@ void CDiscordProto::RetrieveMyInfo() Push(new AsyncHttpRequest(this, REQUEST_GET, "/users/@me", &CDiscordProto::OnReceiveMyInfo)); } -void CDiscordProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CDiscordProto::OnReceiveMyInfo(MHttpResponse *pReply, AsyncHttpRequest*) { JsonReply root(pReply); if (!root) { @@ -179,7 +179,7 @@ void CDiscordProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest* ///////////////////////////////////////////////////////////////////////////////////////// // finds a gateway address -void CDiscordProto::OnReceiveGateway(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CDiscordProto::OnReceiveGateway(MHttpResponse *pReply, AsyncHttpRequest*) { JsonReply root(pReply); if (!root) { @@ -195,7 +195,7 @@ void CDiscordProto::OnReceiveGateway(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest ///////////////////////////////////////////////////////////////////////////////////////// // logs a session out -void CDiscordProto::OnReceiveLogout(NETLIBHTTPREQUEST *, AsyncHttpRequest *) +void CDiscordProto::OnReceiveLogout(MHttpResponse *, AsyncHttpRequest *) { delSetting("AccessToken"); } @@ -213,7 +213,7 @@ void CDiscordProto::SetServerStatus(int iStatus) ///////////////////////////////////////////////////////////////////////////////////////// // channels -void CDiscordProto::OnReceiveCreateChannel(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CDiscordProto::OnReceiveCreateChannel(MHttpResponse *pReply, AsyncHttpRequest*) { JsonReply root(pReply); if (root) @@ -222,7 +222,7 @@ void CDiscordProto::OnReceiveCreateChannel(NETLIBHTTPREQUEST *pReply, AsyncHttpR ///////////////////////////////////////////////////////////////////////////////////////// -void CDiscordProto::OnReceiveMessageAck(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CDiscordProto::OnReceiveMessageAck(MHttpResponse *pReply, AsyncHttpRequest*) { JsonReply root(pReply); if (!root) @@ -243,10 +243,10 @@ void CDiscordProto::OnReceiveMessageAck(NETLIBHTTPREQUEST *pReply, AsyncHttpRequ #define RECAPTCHA_API_KEY "6Lef5iQTAAAAAKeIvIY-DeexoO3gj7ryl9rLMEnn" #define RECAPTCHA_SITE_URL "https://discord.com" -void CDiscordProto::OnReceiveToken(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CDiscordProto::OnReceiveToken(MHttpResponse *pReply, AsyncHttpRequest*) { if (pReply->resultCode != 200) { - JSONNode root = JSONNode::parse(pReply->pData); + JSONNode root = JSONNode::parse(pReply->body); if (root) { const JSONNode &captcha = root["captcha_key"].as_array(); if (captcha) { diff --git a/protocols/Facebook/src/avatars.cpp b/protocols/Facebook/src/avatars.cpp index 6759d20468..224bd707b0 100644 --- a/protocols/Facebook/src/avatars.cpp +++ b/protocols/Facebook/src/avatars.cpp @@ -33,7 +33,7 @@ void FacebookProto::GetAvatarFilename(MCONTACT hContact, wchar_t *pwszFileName) void __cdecl FacebookProto::AvatarsUpdate(void *) { - NETLIBHTTPREQUEST req = {}; + MHttpRequest req; req.flags = NLHRF_NODUMP | NLHRF_SSL | NLHRF_HTTP11 | NLHRF_REDIRECT; req.requestType = REQUEST_GET; @@ -48,13 +48,11 @@ void __cdecl FacebookProto::AvatarsUpdate(void *) continue; delSetting(cc, "UpdateNeeded"); - - CMStringA szUrl(FORMAT, "https://graph.facebook.com/%s/picture?%s", getMStringA(cc, DBKEY_ID).c_str(), szParams.c_str()); - req.szUrl = szUrl.GetBuffer(); + req.m_szUrl.Format("https://graph.facebook.com/%s/picture?%s", getMStringA(cc, DBKEY_ID).c_str(), szParams.c_str()); NLHR_PTR pReply(Netlib_HttpTransaction(m_hNetlibUser, &req)); if (pReply == nullptr) { - debugLogA("Failed to retrieve avatar from url: %s", szUrl.c_str()); + debugLogA("Failed to retrieve avatar from url: %s", req.m_szUrl.c_str()); continue; } @@ -64,14 +62,14 @@ void __cdecl FacebookProto::AvatarsUpdate(void *) GetAvatarFilename(cc, ai.filename); bool bSuccess = false; - if (pReply->resultCode == 200 && pReply->pData && pReply->dataLength) { - if (auto *pszHdr = Netlib_GetHeader(pReply, "Content-Type")) + if (pReply->resultCode == 200 && !pReply->body.IsEmpty()) { + if (auto *pszHdr = pReply->FindHeader("Content-Type")) ai.format = ProtoGetAvatarFormatByMimeType(pszHdr); if (ai.format != PA_FORMAT_UNKNOWN) { FILE *fout = _wfopen(ai.filename, L"wb"); if (fout) { - fwrite(pReply->pData, 1, pReply->dataLength, fout); + fwrite(pReply->body, 1, pReply->body.GetLength(), fout); fclose(fout); bSuccess = true; } @@ -79,7 +77,7 @@ void __cdecl FacebookProto::AvatarsUpdate(void *) } else debugLogA("unknown avatar mime type"); } - else debugLogA("Error %d reading avatar from url: %s", pReply->resultCode, szUrl.c_str()); + else debugLogA("Error %d reading avatar from url: %s", pReply->resultCode, req.m_szUrl.c_str()); ProtoBroadcastAck(cc, ACKTYPE_AVATAR, bSuccess ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, &ai); } diff --git a/protocols/Facebook/src/http.cpp b/protocols/Facebook/src/http.cpp index 55e8ce5a5c..caf8113ef7 100644 --- a/protocols/Facebook/src/http.cpp +++ b/protocols/Facebook/src/http.cpp @@ -69,7 +69,7 @@ AsyncHttpRequest* operator<<(AsyncHttpRequest *pReq, const INT_PARAM ¶m) ///////////////////////////////////////////////////////////////////////////////////////// -JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) +JsonReply::JsonReply(MHttpResponse *pReply) { if (pReply == nullptr) { m_errorCode = 500; @@ -80,7 +80,7 @@ JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) if (m_errorCode != 200) return; - m_root = json_parse(pReply->pData); + m_root = json_parse(pReply->body); if (m_root == nullptr) { m_errorCode = 500; return; @@ -96,10 +96,10 @@ JsonReply::~JsonReply() ///////////////////////////////////////////////////////////////////////////////////////// -AsyncHttpRequest* FacebookProto::CreateRequest(const char *szUrl, const char *szName, const char *szMethod) +AsyncHttpRequest* FacebookProto::CreateRequest(const char *url, const char *szName, const char *szMethod) { AsyncHttpRequest *pReq = new AsyncHttpRequest(); - pReq->m_szUrl = szUrl; + pReq->m_szUrl = url; pReq->requestType = REQUEST_POST; pReq << CHAR_PARAM("api_key", FB_API_KEY) << CHAR_PARAM("device_id", m_szDeviceID) @@ -160,26 +160,15 @@ AsyncHttpRequest* FacebookProto::CreateRequestGQL(int64_t query_id) { return pReq; } -NETLIBHTTPREQUEST* FacebookProto::ExecuteRequest(AsyncHttpRequest *pReq) +MHttpResponse* FacebookProto::ExecuteRequest(AsyncHttpRequest *pReq) { - CMStringA str; - pReq->flags |= NLHRF_HTTP11; - pReq->szUrl = pReq->m_szUrl.GetBuffer(); - if (!pReq->m_szParam.IsEmpty()) { - if (pReq->requestType == REQUEST_GET) { - str.Format("%s?%s", pReq->m_szUrl.c_str(), pReq->m_szParam.c_str()); - pReq->szUrl = str.GetBuffer(); - } - else { - pReq->dataLength = pReq->m_szParam.GetLength(); - pReq->pData = mir_strdup(pReq->m_szParam); - } - } + if (!pReq->m_szParam.IsEmpty() && pReq->requestType == REQUEST_GET) + pReq->m_szUrl.AppendFormat("?%s", pReq->m_szParam.c_str()); - debugLogA("Executing request:\n%s", pReq->szUrl); + debugLogA("Executing request:\n%s", pReq->m_szUrl.c_str()); - NETLIBHTTPREQUEST *reply = Netlib_HttpTransaction(m_hNetlibUser, pReq); + MHttpResponse *reply = Netlib_HttpTransaction(m_hNetlibUser, pReq); delete pReq; return reply; } diff --git a/protocols/Facebook/src/proto.h b/protocols/Facebook/src/proto.h index e8ea77d658..318ef336d6 100644 --- a/protocols/Facebook/src/proto.h +++ b/protocols/Facebook/src/proto.h @@ -332,7 +332,7 @@ class JsonReply int m_errorCode = 0; public: - JsonReply(NETLIBHTTPREQUEST *); + JsonReply(MHttpResponse *); ~JsonReply(); __forceinline JSONNode &data() const { return *m_root; } @@ -412,7 +412,7 @@ class FacebookProto : public PROTO AsyncHttpRequest *CreateRequest(const char *szUrl, const char *szName, const char *szMethod); AsyncHttpRequest *CreateRequestGQL(int64_t id); - NETLIBHTTPREQUEST *ExecuteRequest(AsyncHttpRequest *pReq); + MHttpResponse *ExecuteRequest(AsyncHttpRequest *pReq); CMStringA GetAgentString(); // Avatars diff --git a/protocols/Facebook/src/server.cpp b/protocols/Facebook/src/server.cpp index 72ff76ac1f..db725ba6a0 100644 --- a/protocols/Facebook/src/server.cpp +++ b/protocols/Facebook/src/server.cpp @@ -760,16 +760,16 @@ void FacebookProto::OnPublishPrivateMessage(const JSONNode &root) // wszFileName.Format(L"%s\\STK{%S}.webp", wszPath.c_str(), stickerId.c_str()); std::string szUrl = sticker["thread_image"]["uri"].as_string(); - NETLIBHTTPREQUEST req = {}; + MHttpRequest req; req.flags = NLHRF_NODUMP | NLHRF_SSL | NLHRF_HTTP11 | NLHRF_REDIRECT; req.requestType = REQUEST_GET; - req.szUrl = (char*)szUrl.c_str(); + req.m_szUrl = szUrl.c_str(); - NETLIBHTTPREQUEST *pReply = Netlib_HttpTransaction(m_hNetlibUser, &req); - if (pReply != nullptr && pReply->resultCode == 200 && pReply->pData && pReply->dataLength) { + MHttpResponse *pReply = Netlib_HttpTransaction(m_hNetlibUser, &req); + if (pReply != nullptr && pReply->resultCode == 200 && !pReply->body.IsEmpty()) { bSuccess = true; FILE *out = _wfopen(wszFileName, L"wb"); - fwrite(pReply->pData, 1, pReply->dataLength, out); + fwrite(pReply->body, 1, pReply->body.GetLength(), out); fclose(out); } } diff --git a/protocols/Gadu-Gadu/src/avatar.cpp b/protocols/Gadu-Gadu/src/avatar.cpp index 3ab82cd50f..c9887a1da4 100644 --- a/protocols/Gadu-Gadu/src/avatar.cpp +++ b/protocols/Gadu-Gadu/src/avatar.cpp @@ -51,9 +51,9 @@ bool GaduProto::getAvatarFileInfo(uin_t uin, char **avatarurl, char **avatarts) char szUrl[128]; mir_snprintf(szUrl, "http://api.gadu-gadu.pl/avatars/%d/0.xml", uin); - NETLIBHTTPREQUEST req = { sizeof(req) }; + MHttpRequest req; req.requestType = REQUEST_GET; - req.szUrl = szUrl; + req.m_szUrl = szUrl; req.flags = NLHRF_NODUMP | NLHRF_HTTP11 | NLHRF_REDIRECT; NLHR_PTR resp(Netlib_HttpTransaction(m_hNetlibUser, &req)); @@ -62,15 +62,15 @@ bool GaduProto::getAvatarFileInfo(uin_t uin, char **avatarurl, char **avatarts) return false; } - if (resp->resultCode != 200 || !resp->dataLength || !resp->pData) { + if (resp->resultCode != 200 || resp->body.IsEmpty()) { debugLogA("getAvatarFileInfo(): Invalid response code from HTTP request"); return false; } - if ((strncmp(resp->pData, "", 8) == 0) || (strncmp(resp->pData, "body, "", 8) == 0) || (strncmp(resp->body, "pData) == 0) { + if (doc.Parse(resp->body) == 0) { auto *node = TiXmlConst(doc.FirstChildElement("result"))["users"]["user"]["avatars"]["avatar"].ToElement(); const char *blank = (node != nullptr) ? node->Attribute("blank") : nullptr; if (mir_strcmp(blank, "1")) { @@ -84,9 +84,9 @@ bool GaduProto::getAvatarFileInfo(uin_t uin, char **avatarurl, char **avatarts) } } } - else if (strncmp(resp->pData, "{\"result\":", 10) == 0) { + else if (strncmp(resp->body, "{\"result\":", 10) == 0) { // if this url returns json data (11.2013 gg convention) - JSONNode root = JSONNode::parse(resp->pData); + JSONNode root = JSONNode::parse(resp->body); if (root) { const JSONNode &respJSONavatars = root["result"].at("users").at("user").at("avatars"); if (respJSONavatars) { @@ -225,26 +225,26 @@ void __cdecl GaduProto::avatarrequestthread(void*) ai.hContact = data->hContact; ai.format = getByte(ai.hContact, GG_KEY_AVATARTYPE, GG_KEYDEF_AVATARTYPE); - NETLIBHTTPREQUEST req = { sizeof(req) }; + MHttpRequest req; req.requestType = REQUEST_GET; - req.szUrl = data->szAvatarURL; + req.m_szUrl = data->szAvatarURL; req.flags = NLHRF_NODUMP | NLHRF_HTTP11 | NLHRF_REDIRECT; NLHR_PTR resp(Netlib_HttpTransaction(m_hNetlibUser, &req)); if (resp) { - if (resp->resultCode == 200 && resp->dataLength > 0 && resp->pData) { + if (resp->resultCode == 200 && !resp->body.IsEmpty()) { int file_fd; int avatarType = PA_FORMAT_UNKNOWN; - if (strncmp(resp->pData, "\xFF\xD8", 2) == 0) avatarType = PA_FORMAT_JPEG; - if (strncmp(resp->pData, "\x47\x49\x46\x38", 4) == 0) avatarType = PA_FORMAT_GIF; - if (strncmp(resp->pData, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) == 0) avatarType = PA_FORMAT_PNG; + if (strncmp(resp->body, "\xFF\xD8", 2) == 0) avatarType = PA_FORMAT_JPEG; + if (strncmp(resp->body, "\x47\x49\x46\x38", 4) == 0) avatarType = PA_FORMAT_GIF; + if (strncmp(resp->body, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) == 0) avatarType = PA_FORMAT_PNG; setByte(data->hContact, GG_KEY_AVATARTYPE, (uint8_t)avatarType); getAvatarFilename(ai.hContact, ai.filename, _countof(ai.filename)); file_fd = _wopen(ai.filename, _O_WRONLY | _O_TRUNC | _O_BINARY | _O_CREAT, _S_IREAD | _S_IWRITE); if (file_fd != -1) { - _write(file_fd, resp->pData, resp->dataLength); + _write(file_fd, resp->body, resp->body.GetLength()); _close(file_fd); result = 1; debugLogW(L"avatarrequestthread() new avatar_transfers item. Saved data to file=%s.", ai.filename); @@ -367,49 +367,26 @@ void __cdecl GaduProto::setavatarthread(void *param) CMStringA avatarFileB64Enc(mir_urlEncode(avatarFileB64)); - char dataPrefix[64]; - mir_snprintf(dataPrefix, "uin=%d&photo=", getDword(GG_KEY_UIN, 0)); - size_t dataPrefixLen = mir_strlen(dataPrefix); - - size_t dataLen = dataPrefixLen + avatarFileB64Enc.GetLength(); - char* data = (char*)mir_alloc(dataLen); - memcpy(data, dataPrefix, dataPrefixLen); - memcpy(data + dataPrefixLen, avatarFileB64Enc, avatarFileB64Enc.GetLength()); - - //check if we have token, if no - receive new one + // check if we have token, if no - receive new one oauth_checktoken(0); char* token = getStringA(GG_KEY_TOKEN); - //construct request - NETLIBHTTPREQUEST req = {}; + // construct request + MHttpRequest req = {}; req.requestType = REQUEST_POST; - req.szUrl = "http://avatars.nowe.gg/upload"; + req.m_szUrl = "http://avatars.nowe.gg/upload"; req.flags = NLHRF_NODUMP | NLHRF_HTTP11; - req.headersCount = 10; - NETLIBHTTPHEADER httpHeaders[10]; - httpHeaders[0].szName = "X-Request"; - httpHeaders[0].szValue = "JSON"; - httpHeaders[1].szName = "Authorization"; - httpHeaders[1].szValue = token; - httpHeaders[2].szName = "X-Requested-With"; - httpHeaders[2].szValue = "XMLHttpRequest"; - httpHeaders[3].szName = "From"; - httpHeaders[3].szValue = "avatars to avatars"; - httpHeaders[4].szName = "X-IM-Web-App-Version"; - httpHeaders[4].szValue = "10,5,2,13164"; - httpHeaders[5].szName = "User-Agent"; - httpHeaders[5].szValue = "avatars to avatars"; - httpHeaders[6].szName = "From"; - httpHeaders[6].szValue = NETLIB_USER_AGENT; - httpHeaders[7].szName = "Content-type"; - httpHeaders[7].szValue = "application/x-www-form-urlencoded; charset=utf-8"; - httpHeaders[8].szName = "Accept"; - httpHeaders[8].szValue = "application/json"; - httpHeaders[9].szName = "Referer"; - httpHeaders[9].szValue = "http://avatars.nowe.gg/.static/index_new_22.0.2_595nwh.html"; - req.headers = httpHeaders; - req.pData = data; - req.dataLength = int(dataLen); + req.AddHeader("X-Request", "JSON"); + req.AddHeader("Authorization", token); + req.AddHeader("X-Requested-With", "XMLHttpRequest"); + req.AddHeader("From", "avatars to avatars"); + req.AddHeader("X-IM-Web-App-Version", "10,5,2,13164"); + req.AddHeader("User-Agent", "avatars to avatars"); + req.AddHeader("From", NETLIB_USER_AGENT); + req.AddHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8"); + req.AddHeader("Accept", "application/json"); + req.AddHeader("Referer", "http://avatars.nowe.gg/.static/index_new_22.0.2_595nwh.html"); + req << INT_PARAM("uin", getDword(GG_KEY_UIN, 0)) << CHAR_PARAM("photo", avatarFileB64Enc); // send request int resultSuccess = 0; @@ -417,8 +394,8 @@ void __cdecl GaduProto::setavatarthread(void *param) { NLHR_PTR resp(Netlib_HttpTransaction(m_hNetlibUser, &req)); if (resp) { - if (resp->resultCode == 200 && resp->dataLength > 0 && resp->pData) { - debugLogA("setavatarthread(): 1 resp.data= %s", resp->pData); + if (resp->resultCode == 200 && !resp->body.IsEmpty()) { + debugLogA("setavatarthread(): 1 resp.data= %s", resp->body.c_str()); resultSuccess = 1; } else { @@ -439,22 +416,14 @@ void __cdecl GaduProto::setavatarthread(void *param) oauth_checktoken(1); mir_free(token); token = getStringA(GG_KEY_TOKEN); - httpHeaders[1].szValue = token; - - //construct 2nd request - memset(&req, 0, sizeof(req)); - req.requestType = REQUEST_POST; - req.szUrl = "http://avatars.nowe.gg/upload"; - req.flags = NLHRF_NODUMP | NLHRF_HTTP11; - req.headersCount = 10; - req.headers = httpHeaders; - req.pData = data; - req.dataLength = int(dataLen); + + // construct 2nd request + req.AddHeader("Authorization", token); NLHR_PTR resp(Netlib_HttpTransaction(m_hNetlibUser, &req)); if (resp) { - if (resp->resultCode == 200 && resp->dataLength > 0 && resp->pData) { - debugLogA("setavatarthread(): 2 resp.data= %s", resp->pData); + if (resp->resultCode == 200 && !resp->body.IsEmpty()) { + debugLogA("setavatarthread(): 2 resp.data= %s", resp->body.c_str()); resultSuccess = 1; } else debugLogA("setavatarthread(): Invalid response code from HTTP request [%d]", resp->resultCode); @@ -464,7 +433,6 @@ void __cdecl GaduProto::setavatarthread(void *param) //clean and end thread mir_free(token); - mir_free(data); if (resultSuccess) { debugLogA("setavatarthread(): User avatar set successfully."); diff --git a/protocols/Gadu-Gadu/src/oauth.cpp b/protocols/Gadu-Gadu/src/oauth.cpp index 932c9c1553..084b4df1bf 100644 --- a/protocols/Gadu-Gadu/src/oauth.cpp +++ b/protocols/Gadu-Gadu/src/oauth.cpp @@ -271,7 +271,7 @@ char *oauth_auth_header(const char *httpmethod, const char *url, OAUTHSIGNMETHOD int GaduProto::oauth_receivetoken() { - char szUrl[256], uin[32], *token = nullptr, *token_secret = nullptr; + char uin[32], *token = nullptr, *token_secret = nullptr; int res = 0; HNETLIBCONN nlc = nullptr; @@ -280,109 +280,90 @@ int GaduProto::oauth_receivetoken() // 1. Obtaining an Unauthorized Request Token debugLogA("oauth_receivetoken(): Obtaining an Unauthorized Request Token..."); - mir_strcpy(szUrl, "http://api.gadu-gadu.pl/request_token"); - char *str = oauth_auth_header("POST", szUrl, HMACSHA1, uin, password, nullptr, nullptr); - - NETLIBHTTPHEADER httpHeaders[3]; - httpHeaders[0].szName = "User-Agent"; - httpHeaders[0].szValue = GG8_VERSION; - httpHeaders[1].szName = "Authorization"; - httpHeaders[1].szValue = str; - httpHeaders[2].szName = "Accept"; - httpHeaders[2].szValue = "*/*"; - - NETLIBHTTPREQUEST req = { sizeof(req) }; - req.requestType = REQUEST_POST; - req.szUrl = szUrl; - req.flags = NLHRF_NODUMP | NLHRF_HTTP11 | NLHRF_PERSISTENT; - req.headersCount = 3; - req.headers = httpHeaders; - - NLHR_PTR resp(Netlib_HttpTransaction(m_hNetlibUser, &req)); - if (resp) { - nlc = resp->nlc; - if (resp->resultCode == 200 && resp->dataLength > 0 && resp->pData) { - TiXmlDocument doc; - if (0 == doc.Parse(resp->pData)) { - TiXmlConst hXml(doc.FirstChildElement("result")); - if (auto *p = hXml["oauth_token"].ToElement()) - token = mir_strdup(p->GetText()); - - if (auto *p = hXml["oauth_token_secret"].ToElement()) - token_secret = mir_strdup(p->GetText()); + + NLHR_PTR resp(0); + { + MHttpRequest req; + req.requestType = REQUEST_POST; + req.m_szUrl = "http://api.gadu-gadu.pl/request_token"; + req.flags = NLHRF_NODUMP | NLHRF_HTTP11 | NLHRF_PERSISTENT; + req.AddHeader("User-Agent", GG8_VERSION); + req.AddHeader("Authorization", ptrA(oauth_auth_header("POST", req.m_szUrl, HMACSHA1, uin, password, nullptr, nullptr))); + req.AddHeader("Accept", "*/*"); + + resp = Netlib_HttpTransaction(m_hNetlibUser, &req); + if (resp) { + nlc = resp->nlc; + if (resp->resultCode == 200 && !resp->body.IsEmpty()) { + TiXmlDocument doc; + if (0 == doc.Parse(resp->body)) { + TiXmlConst hXml(doc.FirstChildElement("result")); + if (auto *p = hXml["oauth_token"].ToElement()) + token = mir_strdup(p->GetText()); + + if (auto *p = hXml["oauth_token_secret"].ToElement()) + token_secret = mir_strdup(p->GetText()); + } } + else debugLogA("oauth_receivetoken(): Invalid response code from HTTP request"); } - else debugLogA("oauth_receivetoken(): Invalid response code from HTTP request"); + else debugLogA("oauth_receivetoken(): No response from HTTP request"); } - else debugLogA("oauth_receivetoken(): No response from HTTP request"); // 2. Obtaining User Authorization debugLogA("oauth_receivetoken(): Obtaining User Authorization..."); - mir_free(str); - str = oauth_uri_escape("http://www.mojageneracja.pl"); - - mir_snprintf(szUrl, "callback_url=%s&request_token=%s&uin=%s&password=%s", - str, token, uin, password); - mir_free(str); - str = mir_strdup(szUrl); - - memset(&req, 0, sizeof(req)); - req.requestType = REQUEST_POST; - req.szUrl = szUrl; - req.flags = NLHRF_NODUMP | NLHRF_HTTP11; - req.headersCount = 3; - req.headers = httpHeaders; - mir_strcpy(szUrl, "https://login.gadu-gadu.pl/authorize"); - httpHeaders[1].szName = "Content-Type"; - httpHeaders[1].szValue = "application/x-www-form-urlencoded"; - req.pData = str; - req.dataLength = (int)mir_strlen(str); - - resp = Netlib_HttpTransaction(m_hNetlibUser, &req); - if (!resp) - debugLogA("oauth_receivetoken(): No response from HTTP request"); + { + MHttpRequest req; + req.requestType = REQUEST_POST; + req.m_szUrl = "https://login.gadu-gadu.pl/authorize"; + req.flags = NLHRF_NODUMP | NLHRF_HTTP11; + req.m_szParam.Format("callback_url=%s&request_token=%s&uin=%s&password=%s", ptrA(oauth_uri_escape("http://www.mojageneracja.pl")), token, uin, password); + req.AddHeader("User-Agent", GG8_VERSION); + req.AddHeader("Content-Type", "application/x-www-form-urlencoded"); + req.AddHeader("Accept", "*/*"); + + resp = Netlib_HttpTransaction(m_hNetlibUser, &req); + if (!resp) + debugLogA("oauth_receivetoken(): No response from HTTP request"); + } // 3. Obtaining an Access Token debugLogA("oauth_receivetoken(): Obtaining an Access Token..."); - mir_strcpy(szUrl, "http://api.gadu-gadu.pl/access_token"); - mir_free(str); - str = oauth_auth_header("POST", szUrl, HMACSHA1, uin, password, token, token_secret); + mir_free(token); mir_free(token_secret); token = nullptr; token_secret = nullptr; - - memset(&req, 0, sizeof(req)); - req.requestType = REQUEST_POST; - req.szUrl = szUrl; - req.flags = NLHRF_NODUMP | NLHRF_HTTP11 | NLHRF_PERSISTENT; - req.nlc = nlc; - req.headersCount = 3; - req.headers = httpHeaders; - httpHeaders[1].szName = "Authorization"; - httpHeaders[1].szValue = str; - - resp = Netlib_HttpTransaction(m_hNetlibUser, &req); - if (resp) { - if (resp->resultCode == 200 && resp->dataLength > 0 && resp->pData) { - TiXmlDocument doc; - if (0 == doc.Parse(resp->pData)) { - TiXmlConst hXml(doc.FirstChildElement("result")); - if (auto *p = hXml["oauth_token"].ToElement()) - token = mir_strdup(p->GetText()); - - if (auto *p = hXml["oauth_token_secret"].ToElement()) - token_secret = mir_strdup(p->GetText()); + { + MHttpRequest req; + req.requestType = REQUEST_POST; + req.m_szUrl = "http://api.gadu-gadu.pl/access_token"; + req.flags = NLHRF_NODUMP | NLHRF_HTTP11 | NLHRF_PERSISTENT; + req.nlc = nlc; + req.AddHeader("User-Agent", GG8_VERSION); + req.AddHeader("Authorization", ptrA(oauth_auth_header("POST", req.m_szUrl, HMACSHA1, uin, password, token, token_secret))); + req.AddHeader("Accept", "*/*"); + + resp = Netlib_HttpTransaction(m_hNetlibUser, &req); + if (resp) { + if (resp->resultCode == 200 && !resp->body.IsEmpty()) { + TiXmlDocument doc; + if (0 == doc.Parse(resp->body)) { + TiXmlConst hXml(doc.FirstChildElement("result")); + if (auto *p = hXml["oauth_token"].ToElement()) + token = mir_strdup(p->GetText()); + + if (auto *p = hXml["oauth_token_secret"].ToElement()) + token_secret = mir_strdup(p->GetText()); + } } - } - else debugLogA("oauth_receivetoken(): Invalid response code from HTTP request"); + else debugLogA("oauth_receivetoken(): Invalid response code from HTTP request"); - Netlib_CloseHandle(resp->nlc); + Netlib_CloseHandle(resp->nlc); + } + else debugLogA("oauth_receivetoken(): No response from HTTP request"); } - else debugLogA("oauth_receivetoken(): No response from HTTP request"); - mir_free(password); - mir_free(str); if (token != nullptr && token_secret != nullptr) { setString(GG_KEY_TOKEN, token); diff --git a/protocols/GmailNotifier/src/check.cpp b/protocols/GmailNotifier/src/check.cpp index b5fa2d2dee..df86f3fa0d 100644 --- a/protocols/GmailNotifier/src/check.cpp +++ b/protocols/GmailNotifier/src/check.cpp @@ -67,19 +67,13 @@ void CheckMailInbox(Account *curAcc) szBody.Append("&password="); szBody.Append(curAcc->pass); - NETLIBHTTPHEADER headers[1] = { - { "Content-Type", "application/x-www-form-urlencoded" } - }; - - NETLIBHTTPREQUEST nlr = {}; - nlr.szUrl = szUrl.GetBuffer(); - nlr.requestType = REQUEST_POST; - nlr.headersCount = _countof(headers); - nlr.headers = headers; - nlr.dataLength = szBody.GetLength(); - nlr.pData = szBody.GetBuffer(); - - NLHR_PTR nlu(Netlib_HttpTransaction(hNetlibUser, &nlr)); + MHttpRequest nlhr; + nlhr.m_szUrl = szUrl.GetBuffer(); + nlhr.m_szParam = szBody; + nlhr.requestType = REQUEST_POST; + nlhr.AddHeader("Content-Type", "application/x-www-form-urlencoded"); + + NLHR_PTR nlu(Netlib_HttpTransaction(hNetlibUser, &nlhr)); if (nlu == nullptr || nlu->resultCode != 200) { mir_strcpy(curAcc->results.content, Translate("Can't send account data!")); @@ -99,25 +93,18 @@ void CheckMailInbox(Account *curAcc) else szUrl.Append("/mail/feed/atom"); - NETLIBHTTPHEADER headers[1] = { - { "Authorization", szAuth.GetBuffer() } - }; - - NETLIBHTTPREQUEST nlr = {}; - nlr.szUrl = szUrl.GetBuffer(); - nlr.requestType = REQUEST_GET; - nlr.headers = headers; - nlr.headersCount = _countof(headers); + MHttpRequest nlhr; + nlhr.m_szUrl = szUrl.GetBuffer(); + nlhr.requestType = REQUEST_GET; + nlhr.AddHeader("Authorization", szAuth.GetBuffer()); - NLHR_PTR nlu(Netlib_HttpTransaction(hNetlibUser, &nlr)); + NLHR_PTR nlu(Netlib_HttpTransaction(hNetlibUser, &nlhr)); if (nlu == nullptr) { - mir_snprintf(curAcc->results.content, "%s [%s]", szNick.get(), - (nlr.resultCode == 401) ? Translate("Wrong name or password!") : Translate("Can't get RSS feed!")); - + mir_snprintf(curAcc->results.content, "%s [%s]", szNick.get(), Translate("Wrong name or password!")); curAcc->results_num = -1; } else { - curAcc->results_num = ParsePage(nlu->pData, &curAcc->results); + curAcc->results_num = ParsePage(nlu->body.GetBuffer(), &curAcc->results); mir_snprintf(curAcc->results.content, "%s [%d]", szNick.get(), curAcc->results_num); } diff --git a/protocols/ICQ-WIM/src/avatars.cpp b/protocols/ICQ-WIM/src/avatars.cpp index 452a9da444..73766e7ec8 100644 --- a/protocols/ICQ-WIM/src/avatars.cpp +++ b/protocols/ICQ-WIM/src/avatars.cpp @@ -106,23 +106,13 @@ INT_PTR __cdecl CIcqProto::SetAvatar(WPARAM, LPARAM lParam) } unsigned dwSize = (unsigned)_filelengthi64(fileId); - char *pData = (char *)mir_alloc(dwSize); - if (pData == nullptr) { - _close(fileId); - delete pReq; - return 2; - } - - _read(fileId, pData, dwSize); + pReq->m_szParam.Truncate(dwSize); + _read(fileId, pReq->m_szParam.GetBuffer(), dwSize); _close(fileId); - pReq->pData = pData; - pReq->dataLength = dwSize; - - int iAvatarType = ProtoGetBufferFormat(pData); + int iAvatarType = ProtoGetBufferFormat(pReq->m_szParam); if (iAvatarType == PA_FORMAT_UNKNOWN) { delete pReq; - delete pData; return 3; } diff --git a/protocols/ICQ-WIM/src/file.cpp b/protocols/ICQ-WIM/src/file.cpp index 1dc58ba06b..eb20c4c18b 100644 --- a/protocols/ICQ-WIM/src/file.cpp +++ b/protocols/ICQ-WIM/src/file.cpp @@ -51,10 +51,9 @@ void IcqFileTransfer::FillHeaders(AsyncHttpRequest *pReq) pReq->AddHeader("Content-Range", CMStringA(FORMAT, "bytes %lld-%lld/%lld", pfts.currentFileProgress, pfts.currentFileProgress + dwPortion - 1, pfts.currentFileSize)); pReq->AddHeader("Content-Length", CMStringA(FORMAT, "%d", dwPortion)); - pReq->dataLength = dwPortion; - pReq->pData = (char *)mir_alloc(dwPortion); + pReq->m_szParam.Truncate(dwPortion); _lseek(m_fileId, pfts.currentFileProgress, SEEK_SET); - _read(m_fileId, pReq->pData, dwPortion); + _read(m_fileId, pReq->m_szParam.GetBuffer(), dwPortion); pfts.currentFileProgress += dwPortion; pfts.totalProgress += dwPortion; diff --git a/protocols/ICQ-WIM/src/groupchats.cpp b/protocols/ICQ-WIM/src/groupchats.cpp index 968182e63b..a765426045 100644 --- a/protocols/ICQ-WIM/src/groupchats.cpp +++ b/protocols/ICQ-WIM/src/groupchats.cpp @@ -60,7 +60,7 @@ INT_PTR CIcqProto::SvcLeaveChat(WPARAM hContact, LPARAM) ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnGetChatInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnGetChatInfo(MHttpResponse *pReply, AsyncHttpRequest *pReq) { RobustReply root(pReply); if (root.error() != 20000) @@ -191,7 +191,7 @@ void CIcqProto::InviteUserToChat(SESSION_INFO *si) dlg.DoModal(); } -void CIcqProto::OnLeaveChat(NETLIBHTTPREQUEST*, AsyncHttpRequest *pReq) +void CIcqProto::OnLeaveChat(MHttpResponse*, AsyncHttpRequest *pReq) { db_delete_contact(INT_PTR(pReq->pUserInfo)); } diff --git a/protocols/ICQ-WIM/src/http.cpp b/protocols/ICQ-WIM/src/http.cpp index b422c0d57b..97fc58875d 100644 --- a/protocols/ICQ-WIM/src/http.cpp +++ b/protocols/ICQ-WIM/src/http.cpp @@ -147,12 +147,8 @@ AsyncHttpRequest::AsyncHttpRequest(IcqConnection conn, int iType, const char *sz strncpy_s(m_reqId, (char*)szId, _TRUNCATE); RpcStringFreeA(&szId); - if (iType == REQUEST_POST) { + if (iType == REQUEST_POST) AddHeader("Content-Type", "application/x-www-form-urlencoded"); - - dataLength = m_szParam.GetLength(); - pData = m_szParam.Detach(); - } } void AsyncHttpRequest::ReplaceJsonParam(const JSONNode &n) @@ -166,29 +162,15 @@ void AsyncHttpRequest::ReplaceJsonParam(const JSONNode &n) else root.push_back(n); m_szParam = root.write().c_str(); - - replaceStr(pData, nullptr); - dataLength = 0; } bool CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) { - CMStringA str; - - pReq->szUrl = pReq->m_szUrl.GetBuffer(); - if (!pReq->m_szParam.IsEmpty()) { - if (pReq->requestType == REQUEST_GET) { - str.Format("%s?%s", pReq->m_szUrl.c_str(), pReq->m_szParam.c_str()); - pReq->szUrl = str.GetBuffer(); - } - else { - pReq->dataLength = pReq->m_szParam.GetLength(); - pReq->pData = mir_strdup(pReq->m_szParam); - } - } + if (!pReq->m_szParam.IsEmpty() && pReq->requestType == REQUEST_GET) + pReq->m_szUrl.AppendFormat("?%s", pReq->m_szParam.c_str()); // replace credentials inside JSON body for pure RAPI requests - if (pReq->m_conn == CONN_RAPI && !mir_strcmp(pReq->szUrl, ICQ_ROBUST_SERVER) && !getByte(DB_KEY_PHONEREG)) { + if (pReq->m_conn == CONN_RAPI && !mir_strcmp(pReq->m_szUrl, ICQ_ROBUST_SERVER) && !getByte(DB_KEY_PHONEREG)) { CMStringA szAgent(FORMAT, "%S Mail.ru Windows ICQ (version 10.0.1999)", (wchar_t*)m_szOwnId); pReq->AddHeader("User-Agent", szAgent); pReq->AddHeader("Content-Type", "application/json"); @@ -203,11 +185,9 @@ bool CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) if (m_iRClientId) pReq->ReplaceJsonParam(JSONNode("clientId", m_iRClientId)); pReq->ReplaceJsonParam(JSONNode("authToken", m_szRToken)); - pReq->dataLength = pReq->m_szParam.GetLength(); - pReq->pData = mir_strdup(pReq->m_szParam); } - debugLogA("Executing request %s:\n%s", pReq->m_reqId, pReq->szUrl); + debugLogA("Executing request %s:\n%s", pReq->m_reqId, pReq->m_szUrl.c_str()); if (pReq->m_conn != CONN_NONE) { pReq->flags |= NLHRF_PERSISTENT; @@ -222,14 +202,14 @@ bool CIcqProto::ExecuteRequest(AsyncHttpRequest *pReq) auto &conn = m_ConnPool[pReq->m_conn]; conn.s = reply->nlc; conn.timeout = 0; - if (auto *pszHdr = Netlib_GetHeader(reply, "Keep-Alive")) { + if (auto *pszHdr = reply->FindHeader("Keep-Alive")) { int timeout; if (1 == sscanf(pszHdr, "timeout=%d", &timeout)) conn.timeout = timeout; } } - if (pReq->m_conn == CONN_RAPI && reply->pData && strstr(reply->pData, "\"code\": 40201")) { + if (pReq->m_conn == CONN_RAPI && reply->body.Find("\"code\": 40201") != -1) { RobustReply r(reply); if (r.error() == 40201) { // robust token expired m_szRToken.Empty(); @@ -305,7 +285,7 @@ MHttpRequest* operator<<(MHttpRequest *pReq, const GROUP_PARAM ¶m) ///////////////////////////////////////////////////////////////////////////////////////// -JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) +JsonReply::JsonReply(MHttpResponse *pReply) { if (pReply == nullptr) { m_errorCode = 500; @@ -316,7 +296,7 @@ JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) if (m_errorCode != 200) return; - m_root = json_parse(pReply->pData); + m_root = json_parse(pReply->body); if (m_root == nullptr) { m_errorCode = 500; return; @@ -336,7 +316,7 @@ JsonReply::~JsonReply() ///////////////////////////////////////////////////////////////////////////////////////// -FileReply::FileReply(NETLIBHTTPREQUEST *pReply) +FileReply::FileReply(MHttpResponse *pReply) { if (pReply == nullptr) { m_errorCode = 500; @@ -347,7 +327,7 @@ FileReply::FileReply(NETLIBHTTPREQUEST *pReply) if (m_errorCode != 200) return; - m_root = json_parse(pReply->pData); + m_root = json_parse(pReply->body); if (m_root == nullptr) { m_errorCode = 500; return; @@ -364,7 +344,7 @@ FileReply::~FileReply() ///////////////////////////////////////////////////////////////////////////////////////// -RobustReply::RobustReply(NETLIBHTTPREQUEST *pReply) +RobustReply::RobustReply(MHttpResponse *pReply) { if (pReply == nullptr) { m_errorCode = 500; @@ -375,7 +355,7 @@ RobustReply::RobustReply(NETLIBHTTPREQUEST *pReply) if (m_errorCode != 200) return; - m_root = json_parse(pReply->pData); + m_root = json_parse(pReply->body); if (m_root == nullptr) { m_errorCode = 500; return; diff --git a/protocols/ICQ-WIM/src/http.h b/protocols/ICQ-WIM/src/http.h index 5bbccd0be7..1b201d097a 100644 --- a/protocols/ICQ-WIM/src/http.h +++ b/protocols/ICQ-WIM/src/http.h @@ -49,7 +49,7 @@ class JsonReply CMStringA m_requestId; public: - JsonReply(NETLIBHTTPREQUEST*); + JsonReply(MHttpResponse*); ~JsonReply(); __forceinline const CMStringA& requestId() const { return m_requestId; } @@ -65,7 +65,7 @@ class FileReply JSONNode* m_data = nullptr; public: - FileReply(NETLIBHTTPREQUEST*); + FileReply(MHttpResponse*); ~FileReply(); __forceinline JSONNode& data() const { return *m_data; } @@ -80,7 +80,7 @@ class RobustReply JSONNode *m_results = nullptr; public: - RobustReply(NETLIBHTTPREQUEST*); + RobustReply(MHttpResponse*); ~RobustReply(); __forceinline JSONNode &result() const { return *m_result; } diff --git a/protocols/ICQ-WIM/src/ignore.cpp b/protocols/ICQ-WIM/src/ignore.cpp index 6dd86c51fb..a07b5271c7 100644 --- a/protocols/ICQ-WIM/src/ignore.cpp +++ b/protocols/ICQ-WIM/src/ignore.cpp @@ -26,7 +26,7 @@ void CIcqProto::GetPermitDeny() Push(new AsyncHttpRequest(CONN_MAIN, REQUEST_GET, "/preference/getPermitDeny", &CIcqProto::OnGetPermitDeny) << AIMSID(this)); } -void CIcqProto::OnGetPermitDeny(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CIcqProto::OnGetPermitDeny(MHttpResponse *pReply, AsyncHttpRequest*) { JsonReply root(pReply); if (root.error() == 200) diff --git a/protocols/ICQ-WIM/src/mra.cpp b/protocols/ICQ-WIM/src/mra.cpp index b65ae238dc..751734e43b 100644 --- a/protocols/ICQ-WIM/src/mra.cpp +++ b/protocols/ICQ-WIM/src/mra.cpp @@ -17,7 +17,7 @@ along with this program. If not, see . #include "stdafx.h" -void CIcqProto::SendMrimLogin(NETLIBHTTPREQUEST *pReply) +void CIcqProto::SendMrimLogin(MHttpResponse *pReply) { m_szMraCookie = pReply->GetCookies(); @@ -33,7 +33,7 @@ void CIcqProto::SendMrimLogin(NETLIBHTTPREQUEST *pReply) Push(pReq); } -void CIcqProto::OnCheckMrimLogin(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) +void CIcqProto::OnCheckMrimLogin(MHttpResponse *pReply, AsyncHttpRequest *) { JsonReply root(pReply); switch (root.error()) { @@ -98,7 +98,7 @@ void CIcqProto::OnCheckMrimLogin(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) StartSession(); } -void CIcqProto::OnCheckMraAuth(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) +void CIcqProto::OnCheckMraAuth(MHttpResponse *pReply, AsyncHttpRequest *) { JsonReply root(pReply); switch (root.error()) { @@ -113,7 +113,7 @@ void CIcqProto::OnCheckMraAuth(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) } } -void CIcqProto::OnCheckMraAuthFinal(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) +void CIcqProto::OnCheckMraAuthFinal(MHttpResponse *pReply, AsyncHttpRequest *) { switch (pReply->resultCode) { case 200: diff --git a/protocols/ICQ-WIM/src/options.cpp b/protocols/ICQ-WIM/src/options.cpp index b06ee210a1..9036ed95c9 100644 --- a/protocols/ICQ-WIM/src/options.cpp +++ b/protocols/ICQ-WIM/src/options.cpp @@ -133,7 +133,7 @@ struct CIcqRegistrationDlg : public CIcqDlgBase } }; -void CIcqProto::OnCheckPhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnCheckPhone(MHttpResponse *pReply, AsyncHttpRequest *pReq) { if (pReply == nullptr || pReply->resultCode != 200) return; @@ -142,7 +142,7 @@ void CIcqProto::OnCheckPhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) pDlg->btnSendSms.Disable(); pDlg->edtCode.Disable(); - JSONROOT root(pReply->pData); + JSONROOT root(pReply->body); CMStringW wszStatus((*root)["status"].as_mstring()); if (wszStatus != L"OK") { pDlg->edtCode.SetText((*root)["printable"].as_mstring()); @@ -159,7 +159,7 @@ void CIcqProto::OnCheckPhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) Push(pNew); } -void CIcqProto::OnNormalizePhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnNormalizePhone(MHttpResponse *pReply, AsyncHttpRequest *pReq) { CIcqRegistrationDlg *pDlg = (CIcqRegistrationDlg*)pReq->pUserInfo; @@ -173,7 +173,7 @@ void CIcqProto::OnNormalizePhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pR pDlg->btnSendSms.Enable(); } -void CIcqProto::OnValidateSms(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnValidateSms(MHttpResponse *pReply, AsyncHttpRequest *pReq) { JsonReply root(pReply); if (root.error() != 200) @@ -187,7 +187,7 @@ void CIcqProto::OnValidateSms(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) pDlg->edtCode.SetText(L""); } -void CIcqProto::OnLoginViaPhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnLoginViaPhone(MHttpResponse *pReply, AsyncHttpRequest *pReq) { CIcqRegistrationDlg *pDlg = (CIcqRegistrationDlg*)pReq->pUserInfo; diff --git a/protocols/ICQ-WIM/src/poll.cpp b/protocols/ICQ-WIM/src/poll.cpp index 2f2d8fdf32..1be03cc30d 100644 --- a/protocols/ICQ-WIM/src/poll.cpp +++ b/protocols/ICQ-WIM/src/poll.cpp @@ -362,7 +362,7 @@ void CIcqProto::ProcessTyping(const JSONNode &ev) } } -void CIcqProto::OnFetchEvents(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CIcqProto::OnFetchEvents(MHttpResponse *pReply, AsyncHttpRequest*) { JsonReply root(pReply); if (root.error() != 200) { diff --git a/protocols/ICQ-WIM/src/proto.cpp b/protocols/ICQ-WIM/src/proto.cpp index 68567975b1..ac913a8afe 100644 --- a/protocols/ICQ-WIM/src/proto.cpp +++ b/protocols/ICQ-WIM/src/proto.cpp @@ -242,7 +242,7 @@ void CIcqProto::OnEventDeleted(MCONTACT hContact, MEVENT hEvent) ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnFileRecv(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnFileRecv(MHttpResponse *pReply, AsyncHttpRequest *pReq) { if (pReply->resultCode != 200) return; @@ -255,10 +255,10 @@ void CIcqProto::OnFileRecv(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) return; } - int cbWritten = _write(fileId, pReply->pData, pReply->dataLength); + int cbWritten = _write(fileId, pReply->body, pReply->body.GetLength()); _close(fileId); - if (cbWritten != pReply->dataLength) { - debugLogW(L"Error writing data into [%s]: %d instead of %d", ofd->wszPath.c_str(), cbWritten, pReply->dataLength); + if (cbWritten != pReply->body.GetLength()) { + debugLogW(L"Error writing data into [%s]: %d instead of %d", ofd->wszPath.c_str(), cbWritten, pReply->body.GetLength()); return; } diff --git a/protocols/ICQ-WIM/src/proto.h b/protocols/ICQ-WIM/src/proto.h index 44def39b16..3ca731e905 100644 --- a/protocols/ICQ-WIM/src/proto.h +++ b/protocols/ICQ-WIM/src/proto.h @@ -229,7 +229,7 @@ class CIcqProto : public PROTO void RetrieveUserCaps(IcqUser *pUser); void RetrieveUserHistory(MCONTACT, __int64 startMsgId, bool bCreateRead); void RetrieveUserInfo(MCONTACT hContact); - void SendMrimLogin(NETLIBHTTPREQUEST *pReply); + void SendMrimLogin(MHttpResponse *pReply); void SendMessageParts(MCONTACT hContact, const JSONNode &parts, IcqOwnMessage *pOwn = nullptr); void SetOwnId(const CMStringW &wszId); void SetServerStatus(int iNewStatus); @@ -263,36 +263,36 @@ class CIcqProto : public PROTO __int64 getId(MCONTACT hContact, const char *szSetting); void setId(MCONTACT hContact, const char *szSetting, __int64 iValue); - void OnAddBuddy(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnAddClient(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnCheckMraAuth(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnCheckMraAuthFinal(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnCheckMrimLogin(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnCheckPassword(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnCheckPhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnFetchEvents(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnFileContinue(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnFileInit(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnFileInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnFileRecv(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnGenToken(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnGetChatInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnGetPatches(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnGetPermitDeny(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnGePresence(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnGetSticker(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnGetUserCaps(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnGetUserHistory(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnGetUserInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnLeaveChat(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnLoginViaPhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnNormalizePhone(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnReceiveAvatar(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnSearchResults(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnSendMessage(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnSessionEnd(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnStartSession(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); - void OnValidateSms(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq); + void OnAddBuddy(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnAddClient(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnCheckMraAuth(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnCheckMraAuthFinal(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnCheckMrimLogin(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnCheckPassword(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnCheckPhone(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnFetchEvents(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnFileContinue(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnFileInit(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnFileInfo(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnFileRecv(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnGenToken(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnGetChatInfo(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnGetPatches(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnGetPermitDeny(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnGePresence(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnGetSticker(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnGetUserCaps(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnGetUserHistory(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnGetUserInfo(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnLeaveChat(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnLoginViaPhone(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnNormalizePhone(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnReceiveAvatar(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnSearchResults(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnSendMessage(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnSessionEnd(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnStartSession(MHttpResponse *pReply, AsyncHttpRequest *pReq); + void OnValidateSms(MHttpResponse *pReply, AsyncHttpRequest *pReq); void ProcessBuddyList(const JSONNode &pRoot); void ProcessDiff(const JSONNode &pRoot); diff --git a/protocols/ICQ-WIM/src/server.cpp b/protocols/ICQ-WIM/src/server.cpp index 36887220fa..e62a609cc4 100644 --- a/protocols/ICQ-WIM/src/server.cpp +++ b/protocols/ICQ-WIM/src/server.cpp @@ -133,7 +133,7 @@ void CIcqProto::CheckPassword() ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnFileInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnFileInfo(MHttpResponse *pReply, AsyncHttpRequest *pReq) { IcqFileInfo **res = (IcqFileInfo **)pReq->pUserInfo; *res = nullptr; @@ -691,7 +691,7 @@ LBL_Error: ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnGetUserCaps(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnGetUserCaps(MHttpResponse *pReply, AsyncHttpRequest *pReq) { JsonReply root(pReply); if (root.error() != 200) @@ -718,7 +718,7 @@ void CIcqProto::RetrieveUserCaps(IcqUser *pUser) ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnGePresence(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnGePresence(MHttpResponse *pReply, AsyncHttpRequest *pReq) { JsonReply root(pReply); if (root.error() != 200) @@ -744,7 +744,7 @@ void CIcqProto::RetrievePresence(MCONTACT hContact) ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnGetUserInfo(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnGetUserInfo(MHttpResponse *pReply, AsyncHttpRequest *pReq) { RobustReply root(pReply); if (root.error() != 20000) { @@ -774,7 +774,7 @@ void CIcqProto::RetrieveUserInfo(MCONTACT hContact) ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnGetPatches(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnGetPatches(MHttpResponse *pReply, AsyncHttpRequest *pReq) { RobustReply root(pReply); if (root.error() != 20000) @@ -828,7 +828,7 @@ void CIcqProto::ProcessPatchVersion(MCONTACT hContact, __int64 currPatch) ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnGetUserHistory(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnGetUserHistory(MHttpResponse *pReply, AsyncHttpRequest *pReq) { RobustReply root(pReply); if (root.error() != 20000) @@ -998,7 +998,7 @@ void CIcqProto::StartSession() ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnAddBuddy(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnAddBuddy(MHttpResponse *pReply, AsyncHttpRequest *pReq) { JsonReply root(pReply); if (root.error() != 200) @@ -1032,7 +1032,7 @@ void CIcqProto::OnAddBuddy(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) } } -void CIcqProto::OnAddClient(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnAddClient(MHttpResponse *pReply, AsyncHttpRequest *pReq) { bool *pRet = (bool*)pReq->pUserInfo; @@ -1048,7 +1048,7 @@ void CIcqProto::OnAddClient(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) *pRet = true; } -void CIcqProto::OnCheckPassword(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CIcqProto::OnCheckPassword(MHttpResponse *pReply, AsyncHttpRequest*) { JsonReply root(pReply); switch (root.error()) { @@ -1087,7 +1087,7 @@ void CIcqProto::OnCheckPassword(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) StartSession(); } -void CIcqProto::OnFileContinue(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pOld) +void CIcqProto::OnFileContinue(MHttpResponse *pReply, AsyncHttpRequest *pOld) { IcqFileTransfer *pTransfer = (IcqFileTransfer*)pOld->pUserInfo; if (pTransfer->m_bCanceled) { @@ -1155,7 +1155,7 @@ LBL_Error: ProtoBroadcastAck(pTransfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, pTransfer, (LPARAM)&pTransfer->pfts); } -void CIcqProto::OnFileInit(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pOld) +void CIcqProto::OnFileInit(MHttpResponse *pReply, AsyncHttpRequest *pOld) { IcqFileTransfer *pTransfer = (IcqFileTransfer*)pOld->pUserInfo; if (pTransfer->m_bCanceled) { @@ -1192,7 +1192,7 @@ LBL_Error: ///////////////////////////////////////////////////////////////////////////////////////// // Support for stickers -void CIcqProto::OnGetSticker(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnGetSticker(MHttpResponse *pReply, AsyncHttpRequest *pReq) { if (pReply->resultCode != 200) { debugLogA("Error getting sticker: %d", pReply->resultCode); @@ -1204,7 +1204,7 @@ void CIcqProto::OnGetSticker(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) CMStringW wszFileName(FORMAT, L"%s\\STK{%s}.png", wszPath.c_str(), (wchar_t*)pReq->pUserInfo); FILE *out = _wfopen(wszFileName, L"wb"); - fwrite(pReply->pData, 1, pReply->dataLength, out); + fwrite(pReply->body, 1, pReply->body.GetLength(), out); fclose(out); SmileyAdd_LoadContactSmileys(SMADD_FILE, m_szModuleName, wszFileName); @@ -1212,7 +1212,7 @@ void CIcqProto::OnGetSticker(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnGenToken(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) +void CIcqProto::OnGenToken(MHttpResponse *pReply, AsyncHttpRequest*) { RobustReply root(pReply); if (root.error() != 20000) @@ -1222,7 +1222,7 @@ void CIcqProto::OnGenToken(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest*) m_szRToken = results["authToken"].as_mstring(); } -void CIcqProto::OnStartSession(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) +void CIcqProto::OnStartSession(MHttpResponse *pReply, AsyncHttpRequest *) { JsonReply root(pReply); switch (root.error()) { @@ -1279,18 +1279,18 @@ void CIcqProto::OnStartSession(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) ForkThread(&CIcqProto::PollThread); } -void CIcqProto::OnReceiveAvatar(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnReceiveAvatar(MHttpResponse *pReply, AsyncHttpRequest *pReq) { PROTO_AVATAR_INFORMATION ai = {}; ai.hContact = pReq->hContact; - if (pReply->resultCode != 200 || pReply->pData == nullptr) { + if (pReply->resultCode != 200 || pReply->body.IsEmpty()) { LBL_Error: ProtoBroadcastAck(pReq->hContact, ACKTYPE_AVATAR, ACKRESULT_FAILED, &ai); return; } - const char *szContentType = Netlib_GetHeader(pReply, "Content-Type"); + const char *szContentType = pReply->FindHeader("Content-Type"); if (szContentType == nullptr) szContentType = "image/jpeg"; @@ -1302,7 +1302,7 @@ LBL_Error: if (out == nullptr) goto LBL_Error; - fwrite(pReply->pData, pReply->dataLength, 1, out); + fwrite(pReply->body, pReply->body.GetLength(), 1, out); fclose(out); if (pReq->hContact != 0) { @@ -1312,7 +1312,7 @@ LBL_Error: else ReportSelfAvatarChanged(); } -void CIcqProto::OnSearchResults(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnSearchResults(MHttpResponse *pReply, AsyncHttpRequest *pReq) { RobustReply root(pReply); if (root.error() != 20000) { @@ -1347,7 +1347,7 @@ void CIcqProto::OnSearchResults(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pRe ///////////////////////////////////////////////////////////////////////////////////////// // Send message -void CIcqProto::OnSendMessage(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *pReq) +void CIcqProto::OnSendMessage(MHttpResponse *pReply, AsyncHttpRequest *pReq) { IcqOwnMessage *ownMsg = (IcqOwnMessage *)pReq->pUserInfo; @@ -1394,7 +1394,7 @@ void CIcqProto::SendMessageParts(MCONTACT hContact, const JSONNode &parts, IcqOw ///////////////////////////////////////////////////////////////////////////////////////// -void CIcqProto::OnSessionEnd(NETLIBHTTPREQUEST *pReply, AsyncHttpRequest *) +void CIcqProto::OnSessionEnd(MHttpResponse *pReply, AsyncHttpRequest *) { JsonReply root(pReply); if (root.error() == 200) { diff --git a/protocols/JabberG/src/jabber_file.cpp b/protocols/JabberG/src/jabber_file.cpp index ebd33b3d93..c35069a294 100644 --- a/protocols/JabberG/src/jabber_file.cpp +++ b/protocols/JabberG/src/jabber_file.cpp @@ -49,10 +49,10 @@ void __cdecl CJabberProto::OfflineFileThread(OFDTHREAD *ofd) } // initialize the netlib request - NETLIBHTTPREQUEST nlhr = {}; + MHttpRequest nlhr; nlhr.requestType = REQUEST_GET; nlhr.flags = NLHRF_HTTP11 | NLHRF_DUMPASTEXT | NLHRF_REDIRECT; - nlhr.szUrl = (char *)url; + nlhr.m_szUrl = url; // download the page NLHR_PTR nlhrReply(Netlib_HttpTransaction(m_hNetlibUser, &nlhr)); @@ -61,18 +61,18 @@ void __cdecl CJabberProto::OfflineFileThread(OFDTHREAD *ofd) size_t written = 0; if (f) { if (encrypted) { - int payload_len = nlhrReply->dataLength - 16; + int payload_len = nlhrReply->body.GetLength() - 16; if (payload_len > 0) { uint8_t ivkey[44]; hex2bin(hexkey, ivkey, 44); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL); EVP_DecryptInit(ctx, EVP_aes_256_gcm(), ivkey + 12, ivkey); - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, nlhrReply->pData + payload_len); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, (uint8_t *)nlhrReply->body.c_str() + payload_len); int outl = 0, round_len = 0; uint8_t *out = (uint8_t *)mir_alloc(payload_len); - EVP_DecryptUpdate(ctx, out, &outl, (uint8_t *)nlhrReply->pData, (int)payload_len); + EVP_DecryptUpdate(ctx, out, &outl, (uint8_t *)nlhrReply->body.c_str(), (int)payload_len); int dec_success = EVP_DecryptFinal(ctx, out + outl, &round_len); outl += round_len; EVP_CIPHER_CTX_free(ctx); @@ -82,8 +82,8 @@ void __cdecl CJabberProto::OfflineFileThread(OFDTHREAD *ofd) mir_free(out); } } - else if (fwrite(nlhrReply->pData, 1, nlhrReply->dataLength, f) == size_t(nlhrReply->dataLength)) - written = nlhrReply->dataLength; + else if (fwrite(nlhrReply->body, 1, nlhrReply->body.GetLength(), f) == size_t(nlhrReply->body.GetLength())) + written = nlhrReply->body.GetLength(); fclose(f); } @@ -127,16 +127,16 @@ void CJabberProto::OnReceiveOfflineFile(DB::FILE_BLOB &blob, void *pHandle) void __cdecl CJabberProto::FileReceiveHttpThread(filetransfer *ft) { - NETLIBHTTPREQUEST req = {}; + MHttpRequest req; req.requestType = REQUEST_GET; - req.szUrl = ft->httpPath; + req.m_szUrl = ft->httpPath; NLHR_PTR pResp(Netlib_HttpTransaction(m_hNetlibUser, &req)); if (pResp && pResp->resultCode == 200) { - ft->std.currentFileSize = pResp->dataLength; + ft->std.currentFileSize = pResp->body.GetLength(); ProtoBroadcastAck(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft); - FtReceive(ft, pResp->pData, pResp->dataLength); + FtReceive(ft, pResp->body.GetBuffer(), pResp->body.GetLength()); ft->complete(); } @@ -154,9 +154,9 @@ void CJabberProto::FileProcessHttpDownload(MCONTACT hContact, const char *jid, c szName.AppendChar(*b++); auto *pszName = szName.c_str(); - NETLIBHTTPREQUEST req = {}; + MHttpRequest req; req.requestType = REQUEST_HEAD; - req.szUrl = (char*)pszUrl; + req.m_szUrl = pszUrl; filetransfer *ft = new filetransfer(this, 0); ft->jid = mir_strdup(jid); diff --git a/protocols/JabberG/src/jabber_ft.cpp b/protocols/JabberG/src/jabber_ft.cpp index 9ca292ca71..a489aa696c 100644 --- a/protocols/JabberG/src/jabber_ft.cpp +++ b/protocols/JabberG/src/jabber_ft.cpp @@ -691,22 +691,16 @@ LBL_Fail: if (!szUrl) goto LBL_Fail; - NETLIBHTTPHEADER hdr[10]; - - NETLIBHTTPREQUEST nlhr = {}; + MHttpRequest nlhr; nlhr.requestType = REQUEST_PUT; nlhr.flags = NLHRF_NODUMPSEND | NLHRF_SSL | NLHRF_REDIRECT; - nlhr.szUrl = (char *)szUrl; + nlhr.m_szUrl = szUrl; for (auto *it : TiXmlFilter(putNode, "header")) { auto *szName = it->Attribute("name"); auto *szValue = it->GetText(); - if (szName && szValue && nlhr.headersCount < _countof(hdr)) { - nlhr.headers = hdr; - hdr[nlhr.headersCount].szName = (char *)szName; - hdr[nlhr.headersCount].szValue = (char *)szValue; - nlhr.headersCount++; - } + if (szName && szValue) + nlhr.AddHeader(szName, szValue); } const wchar_t *pwszFileName = ft->std.pszFiles.w[ft->std.currentFileNumber]; @@ -728,8 +722,8 @@ LBL_Fail: EVP_EncryptInit(ctx, EVP_aes_256_gcm(), key, iv); int tmp_len = 0, outl; - //EVP_EncryptUpdate(ctx, nullptr, &outl, aad, _countof(aad)); - unsigned char *out = (unsigned char *)mir_alloc(_filelength(fileId) + _countof(key) - 1 + _countof(tag)); + nlhr.m_szParam.Truncate(_filelength(fileId) + _countof(key) - 1 + _countof(tag)); + unsigned char *out = (unsigned char *)nlhr.m_szParam.GetBuffer(); unsigned char *in = (unsigned char *)mir_alloc(128 * 1024); for (;;) { int inl = _read(fileId, in, 128 * 1024); @@ -746,13 +740,11 @@ LBL_Fail: EVP_CIPHER_CTX_free(ctx); memcpy(out + tmp_len, tag, _countof(tag)); - nlhr.dataLength = tmp_len + _countof(tag); - nlhr.pData = (char *)out; } else { - nlhr.dataLength = _filelength(fileId); - nlhr.pData = new char[nlhr.dataLength]; - _read(fileId, nlhr.pData, nlhr.dataLength); + int iLength = _filelength(fileId); + nlhr.m_szParam.Truncate(iLength); + _read(fileId, nlhr.m_szParam.GetBuffer(), iLength); } _close(fileId); diff --git a/protocols/JabberG/src/jabber_util.cpp b/protocols/JabberG/src/jabber_util.cpp index e018c39b40..441b5de49c 100644 --- a/protocols/JabberG/src/jabber_util.cpp +++ b/protocols/JabberG/src/jabber_util.cpp @@ -881,17 +881,17 @@ void __cdecl CJabberProto::LoadHttpAvatars(void* param) OBJLIST &avs = *(OBJLIST*)param; HNETLIBCONN hHttpCon = nullptr; for (auto &it : avs) { - NETLIBHTTPREQUEST nlhr = { 0 }; + MHttpRequest nlhr; nlhr.requestType = REQUEST_GET; nlhr.flags = NLHRF_HTTP11 | NLHRF_REDIRECT | NLHRF_PERSISTENT; - nlhr.szUrl = it->Url; + nlhr.m_szUrl = it->Url; nlhr.nlc = hHttpCon; NLHR_PTR res(Netlib_HttpTransaction(m_hNetlibUser, &nlhr)); if (res) { hHttpCon = res->nlc; - if (res->resultCode == 200 && res->dataLength) { - int pictureType = ProtoGetBufferFormat(res->pData); + if (res->resultCode == 200 && !res->body.IsEmpty()) { + int pictureType = ProtoGetBufferFormat(res->body); if (pictureType != PA_FORMAT_UNKNOWN) { PROTO_AVATAR_INFORMATION ai; ai.format = pictureType; @@ -909,7 +909,7 @@ void __cdecl CJabberProto::LoadHttpAvatars(void* param) uint8_t digest[MIR_SHA1_HASH_SIZE]; mir_sha1_ctx sha; mir_sha1_init(&sha); - mir_sha1_append(&sha, (uint8_t*)res->pData, res->dataLength); + mir_sha1_append(&sha, (uint8_t*)res->body.c_str(), res->body.GetLength()); mir_sha1_finish(&sha, digest); bin2hex(digest, sizeof(digest), buffer); @@ -920,7 +920,7 @@ void __cdecl CJabberProto::LoadHttpAvatars(void* param) wcsncpy_s(ai.filename, tszFileName, _TRUNCATE); FILE* out = _wfopen(tszFileName, L"wb"); if (out != nullptr) { - fwrite(res->pData, res->dataLength, 1, out); + fwrite(res->body, res->body.GetLength(), 1, out); fclose(out); setString(ai.hContact, "AvatarHash", buffer); ProtoBroadcastAck(ai.hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &ai); diff --git a/protocols/MinecraftDynmap/src/communication.cpp b/protocols/MinecraftDynmap/src/communication.cpp index 47e6ec4480..e9e035404d 100644 --- a/protocols/MinecraftDynmap/src/communication.cpp +++ b/protocols/MinecraftDynmap/src/communication.cpp @@ -21,18 +21,16 @@ along with this program. If not, see . #include "stdafx.h" -http::response MinecraftDynmapProto::sendRequest(const int request_type, std::string *post_data, std::string *get_data) +MHttpResponse* MinecraftDynmapProto::sendRequest(const int request_type, std::string *post_data, std::string *get_data) { - http::response resp; - // Prepare the request - NETLIBHTTPREQUEST nlhr = { sizeof(NETLIBHTTPREQUEST) }; + MHttpRequest nlhr; // FIXME: get server // Set request URL std::string url = m_server + chooseAction(request_type, get_data); - nlhr.szUrl = (char*)url.c_str(); + nlhr.m_szUrl = url.c_str(); // Set timeout (bigger for channel request) nlhr.timeout = 1000 * ((request_type == MINECRAFTDYNMAP_REQUEST_EVENTS) ? 65 : 20); @@ -40,15 +38,18 @@ http::response MinecraftDynmapProto::sendRequest(const int request_type, std::st // Set request type (GET/POST) and eventually also POST data if (post_data != nullptr) { nlhr.requestType = REQUEST_POST; - nlhr.pData = (char*)(*post_data).c_str(); - nlhr.dataLength = (int)post_data->length(); - } - else { - nlhr.requestType = REQUEST_GET; + nlhr.SetData(post_data->c_str(), post_data->length()); } + else nlhr.requestType = REQUEST_GET; // Set headers - it depends on requestType so it must be after setting that - nlhr.headers = get_request_headers(nlhr.requestType, &nlhr.headersCount); + if (request_type == REQUEST_POST) + nlhr.AddHeader("Content-Type", "application/json; charset=utf-8"); + + nlhr.AddHeader("Cookie", m_cookie.c_str()); + nlhr.AddHeader("User-Agent", g_strUserAgent.c_str()); + nlhr.AddHeader("Accept", "*/*"); + nlhr.AddHeader("Accept-Language", "en,en-US;q=0.9"); // Set flags nlhr.flags = NLHRF_HTTP11; @@ -78,12 +79,10 @@ http::response MinecraftDynmapProto::sendRequest(const int request_type, std::st break; } - debugLogA("@@@@@ Sending request to '%s'", nlhr.szUrl); + debugLogA("@@@@@ Sending request to '%s'", nlhr.m_szUrl.c_str()); // Send the request - NLHR_PTR pnlhr(Netlib_HttpTransaction(m_hNetlibUser, &nlhr)); - - mir_free(nlhr.headers); + auto *pnlhr = Netlib_HttpTransaction(m_hNetlibUser, &nlhr); // Remember the persistent connection handle (or not) switch (request_type) { @@ -100,22 +99,7 @@ http::response MinecraftDynmapProto::sendRequest(const int request_type, std::st break; } - // Check and copy response data - if (pnlhr != nullptr) - { - debugLogA("@@@@@ Got response with code %d", pnlhr->resultCode); - store_headers(&resp, pnlhr->headers, pnlhr->headersCount); - resp.code = pnlhr->resultCode; - resp.data = pnlhr->pData ? pnlhr->pData : ""; - - // debugLogA("&&&&& Got response: %s", resp.data.c_str()); - } else { - debugLogA("!!!!! No response from server (time-out)"); - resp.code = HTTP_CODE_FAKE_DISCONNECTED; - // Better to have something set explicitely as this value is compaired in all communication requests - } - - return resp; + return pnlhr; } ////////////////////////////////////////////////////////////////////////////// @@ -138,56 +122,17 @@ std::string MinecraftDynmapProto::chooseAction(int request_type, std::string *ge } } - -NETLIBHTTPHEADER* MinecraftDynmapProto::get_request_headers(int request_type, int* headers_count) -{ - if (request_type == REQUEST_POST) - *headers_count = 5; - else - *headers_count = 4; - - NETLIBHTTPHEADER *headers = (NETLIBHTTPHEADER*)mir_calloc(sizeof(NETLIBHTTPHEADER)*(*headers_count)); - - if (request_type == REQUEST_POST) { - headers[4].szName = "Content-Type"; - headers[4].szValue = "application/json; charset=utf-8"; - } - - headers[3].szName = "Cookie"; - headers[3].szValue = (char *)m_cookie.c_str(); - headers[2].szName = "User-Agent"; - headers[2].szValue = (char *)g_strUserAgent.c_str(); - headers[1].szName = "Accept"; - headers[1].szValue = "*/*"; - headers[0].szName = "Accept-Language"; - headers[0].szValue = "en,en-US;q=0.9"; - - return headers; -} - -void MinecraftDynmapProto::store_headers(http::response* resp, NETLIBHTTPHEADER* headers, int headersCount) -{ - for (size_t i = 0; i < (size_t)headersCount; i++) { - std::string header_name = headers[i].szName; - std::string header_value = headers[i].szValue; - - resp->headers[header_name] = header_value; - } -} - ////////////////////////////////////////////////////////////////////////////// bool MinecraftDynmapProto::doSignOn() { handleEntry(__FUNCTION__); - http::response resp = sendRequest(MINECRAFTDYNMAP_REQUEST_CONFIGURATION); - - if (resp.code != HTTP_CODE_OK) { + NLHR_PTR resp(sendRequest(MINECRAFTDYNMAP_REQUEST_CONFIGURATION)); + if (!resp || resp->resultCode != HTTP_CODE_OK) return handleError(__FUNCTION__, "Can't load configuration", true); - } - JSONNode root = JSONNode::parse(resp.data.c_str()); + JSONNode root = JSONNode::parse(resp->body); if (!root) return false; @@ -212,16 +157,14 @@ bool MinecraftDynmapProto::doSignOn() m_updateRate = rate_.as_int(); m_cookie.clear(); - if (resp.headers.find("Set-Cookie") != resp.headers.end()) { - // Load Session identifier - std::string cookies = resp.headers["Set-Cookie"]; + if (auto *pszCookie = resp->FindHeader("Set-Cookie")) { + m_cookie = pszCookie; + // Load Session identifier const char *findStr = "JSESSIONID="; - std::string::size_type start = cookies.find(findStr); - - if (start != std::string::npos) { - m_cookie = cookies.substr(start, cookies.find(";") - start); - } + std::string::size_type start = m_cookie.find(findStr); + if (start != std::string::npos) + m_cookie = m_cookie.substr(start, m_cookie.find(";") - start); } if (m_cookie.empty()) { @@ -236,12 +179,11 @@ bool MinecraftDynmapProto::doEvents() handleEntry(__FUNCTION__); // Get update - http::response resp = sendRequest(MINECRAFTDYNMAP_REQUEST_EVENTS); - - if (resp.code != HTTP_CODE_OK) + NLHR_PTR resp(sendRequest(MINECRAFTDYNMAP_REQUEST_EVENTS)); + if (!resp || resp->resultCode != HTTP_CODE_OK) return handleError(__FUNCTION__, "Response is not code 200"); - JSONNode root = JSONNode::parse(resp.data.c_str()); + JSONNode root = JSONNode::parse(resp->body); if (!root) return handleError(__FUNCTION__, "Invalid JSON response"); @@ -290,10 +232,9 @@ bool MinecraftDynmapProto::doSendMessage(const std::string &message_text) json.push_back(JSONNode("message", message_text.c_str())); std::string data = json.write(); - http::response resp = sendRequest(MINECRAFTDYNMAP_REQUEST_MESSAGE, &data); - - if (resp.code == HTTP_CODE_OK) { - JSONNode root = JSONNode::parse(resp.data.c_str()); + NLHR_PTR resp(sendRequest(MINECRAFTDYNMAP_REQUEST_MESSAGE, &data)); + if (resp && resp->resultCode == HTTP_CODE_OK) { + JSONNode root = JSONNode::parse(resp->body); if (root) { const JSONNode &error_ = root["error"]; if (error_) { @@ -315,15 +256,14 @@ std::string MinecraftDynmapProto::doGetPage(const int request_type) { handleEntry(__FUNCTION__); - http::response resp = sendRequest(request_type); - - if (resp.code == HTTP_CODE_OK) { + NLHR_PTR resp(sendRequest(request_type)); + if (resp && resp->resultCode == HTTP_CODE_OK) { handleSuccess(__FUNCTION__); - } else { - handleError(__FUNCTION__); + return resp->body.c_str(); } - return resp.data; + handleError(__FUNCTION__); + return ""; } void MinecraftDynmapProto::SignOnWorker(void*) diff --git a/protocols/MinecraftDynmap/src/proto.h b/protocols/MinecraftDynmap/src/proto.h index fb8046d79b..9cebc8c128 100644 --- a/protocols/MinecraftDynmap/src/proto.h +++ b/protocols/MinecraftDynmap/src/proto.h @@ -86,8 +86,6 @@ public: HANDLE chatHandle_; // Data storage - void store_headers(http::response *resp, NETLIBHTTPHEADER *headers, int headers_count); - std::string get_server(bool not_last = false); std::string get_language(); @@ -104,9 +102,8 @@ public: void __inline reset_error() { error_count_ = 0; } // HTTP communication - http::response sendRequest(const int request_type, std::string *post_data = nullptr, std::string *get_data = nullptr); + MHttpResponse* sendRequest(const int request_type, std::string *post_data = nullptr, std::string *get_data = nullptr); std::string chooseAction(int, std::string *get_data = nullptr); - NETLIBHTTPHEADER *get_request_headers(int request_type, int *headers_count); // Requests and processing bool doSignOn(); diff --git a/protocols/MinecraftDynmap/src/utils.h b/protocols/MinecraftDynmap/src/utils.h index c42fb86d9e..135faf0d11 100644 --- a/protocols/MinecraftDynmap/src/utils.h +++ b/protocols/MinecraftDynmap/src/utils.h @@ -30,17 +30,6 @@ along with this program. If not, see . #define HTTP_CODE_FAKE_DISCONNECTED 0 #define HTTP_CODE_FAKE_ERROR 1 -namespace http -{ - struct response - { - response() : code(0) {} - int code; - std::map< std::string, std::string > headers; - std::string data; - }; -} - class ScopedLock { public: diff --git a/protocols/NewsAggregator/Src/Utils.cpp b/protocols/NewsAggregator/Src/Utils.cpp index 328c63bc8e..c5f1df5b95 100644 --- a/protocols/NewsAggregator/Src/Utils.cpp +++ b/protocols/NewsAggregator/Src/Utils.cpp @@ -47,48 +47,35 @@ void NetlibUnInit() void GetNewsData(wchar_t *tszUrl, char **szData, MCONTACT hContact, CFeedEditor *pEditDlg) { Netlib_LogfW(hNetlibUser, L"Getting feed data %s.", tszUrl); - NETLIBHTTPREQUEST nlhr = { 0 }; + MHttpRequest nlhr; // initialize the netlib request nlhr.requestType = REQUEST_GET; nlhr.flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11 | NLHRF_REDIRECT; if (wcsstr(tszUrl, L"https://") != nullptr) nlhr.flags |= NLHRF_SSL; - char *szUrl = mir_u2a(tszUrl); - nlhr.szUrl = szUrl; + nlhr.m_szUrl = _T2A(tszUrl); nlhr.nlc = hNetlibHttp; // change the header so the plugin is pretended to be IE 6 + WinXP - NETLIBHTTPHEADER headers[5]; - nlhr.headersCount = 4; - nlhr.headers = headers; - nlhr.headers[0].szName = "User-Agent"; - nlhr.headers[0].szValue = NETLIB_USER_AGENT; - nlhr.headers[1].szName = "Cache-Control"; - nlhr.headers[1].szValue = "no-cache"; - nlhr.headers[2].szName = "Pragma"; - nlhr.headers[2].szValue = "no-cache"; - nlhr.headers[3].szName = "Connection"; - nlhr.headers[3].szValue = "close"; - char auth[256]; - if (g_plugin.getByte(hContact, "UseAuth", 0) || (pEditDlg && pEditDlg->m_useauth.IsChecked()) /*IsDlgButtonChecked(hwndDlg, IDC_USEAUTH)*/) { - nlhr.headersCount++; - nlhr.headers[4].szName = "Authorization"; + nlhr.AddHeader("User-Agent", NETLIB_USER_AGENT); + nlhr.AddHeader("Cache-Control", "no-cache"); + nlhr.AddHeader("Pragma", "no-cache"); + nlhr.AddHeader("Connection", "close"); + if (g_plugin.getByte(hContact, "UseAuth", 0) || (pEditDlg && pEditDlg->m_useauth.IsChecked())) { + char auth[256]; CreateAuthString(auth, hContact, pEditDlg); - nlhr.headers[4].szValue = auth; + nlhr.AddHeader("Authorization", auth); } // download the page NLHR_PTR nlhrReply(Netlib_HttpTransaction(hNetlibUser, &nlhr)); if (nlhrReply) { // if the recieved code is 200 OK - if (nlhrReply->resultCode == 200 && nlhrReply->dataLength > 0) { + if (nlhrReply->resultCode == 200 && !nlhrReply->body.IsEmpty()) { Netlib_LogfW(hNetlibUser, L"Code 200: Succeeded getting feed data %s.", tszUrl); - // allocate memory and save the retrieved data - *szData = (char *)mir_alloc((size_t)nlhrReply->dataLength + 2); - memcpy(*szData, nlhrReply->pData, (size_t)nlhrReply->dataLength); - (*szData)[nlhrReply->dataLength] = 0; + *szData = nlhrReply->body.Detach(); } else if (nlhrReply->resultCode == 401) { Netlib_LogfW(hNetlibUser, L"Code 401: feed %s needs auth data.", tszUrl); @@ -99,8 +86,6 @@ void GetNewsData(wchar_t *tszUrl, char **szData, MCONTACT hContact, CFeedEditor else Netlib_LogfW(hNetlibUser, L"Code %d: Failed getting feed data %s.", nlhrReply->resultCode, tszUrl); } else Netlib_LogfW(hNetlibUser, L"Failed getting feed data %s, no response.", tszUrl); - - mir_free(szUrl); } time_t DateToUnixTime(const char *stamp, bool FeedType) @@ -220,81 +205,42 @@ time_t DateToUnixTime(const char *stamp, bool FeedType) bool DownloadFile(LPCTSTR tszURL, LPCTSTR tszLocal) { - NETLIBHTTPREQUEST nlhr = { 0 }; + MHttpRequest nlhr; nlhr.requestType = REQUEST_GET; nlhr.flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11; - char *szUrl = mir_u2a(tszURL); - nlhr.szUrl = szUrl; - NETLIBHTTPHEADER headers[4]; - nlhr.headersCount = 4; - nlhr.headers = headers; - nlhr.headers[0].szName = "User-Agent"; - nlhr.headers[0].szValue = NETLIB_USER_AGENT; - nlhr.headers[1].szName = "Connection"; - nlhr.headers[1].szValue = "close"; - nlhr.headers[2].szName = "Cache-Control"; - nlhr.headers[2].szValue = "no-cache"; - nlhr.headers[3].szName = "Pragma"; - nlhr.headers[3].szValue = "no-cache"; - - bool ret = false; + nlhr.m_szUrl = _T2A(tszURL); + nlhr.AddHeader("User-Agent", NETLIB_USER_AGENT); + nlhr.AddHeader("Connection", "close"); + nlhr.AddHeader("Cache-Control", "no-cache"); + nlhr.AddHeader("Pragma", "no-cache"); + NLHR_PTR pReply(Netlib_HttpTransaction(hNetlibUser, &nlhr)); if (pReply) { - if ((200 == pReply->resultCode) && (pReply->dataLength > 0)) { - char *date = nullptr, *size = nullptr; - for (int i = 0; i < pReply->headersCount; i++) { - if (!mir_strcmpi(pReply->headers[i].szName, "Last-Modified")) { - date = pReply->headers[i].szValue; - continue; - } - else if (!mir_strcmpi(pReply->headers[i].szName, "Content-Length")) { - size = pReply->headers[i].szValue; - continue; - } - } + if (200 == pReply->resultCode && !pReply->body.IsEmpty()) { + const char *date = pReply->FindHeader("Last-Modified"); + const char *size = pReply->FindHeader("Content-Length"); if (date != nullptr && size != nullptr) { - wchar_t *tsize = mir_a2u(size); struct _stat buf; - int fh = _wopen(tszLocal, _O_RDONLY); if (fh != -1) { _fstat(fh, &buf); + _close(fh); + time_t modtime = DateToUnixTime(date, 0); time_t filemodtime = mktime(localtime(&buf.st_atime)); - if (modtime > filemodtime && buf.st_size != _wtoi(tsize)) { - DWORD dwBytes; - HANDLE hFile = CreateFile(tszLocal, GENERIC_READ | GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - WriteFile(hFile, pReply->pData, (uint32_t)pReply->dataLength, &dwBytes, nullptr); - ret = true; - if (hFile) - CloseHandle(hFile); - } - _close(fh); + if (modtime <= filemodtime || buf.st_size == atoi(size)) + return false; } - else { - DWORD dwBytes; - HANDLE hFile = CreateFile(tszLocal, GENERIC_READ | GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - WriteFile(hFile, pReply->pData, (uint32_t)pReply->dataLength, &dwBytes, nullptr); - ret = true; - if (hFile) - CloseHandle(hFile); - } - mir_free(tsize); - } - else { - DWORD dwBytes; - HANDLE hFile = CreateFile(tszLocal, GENERIC_READ | GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); - WriteFile(hFile, pReply->pData, (uint32_t)pReply->dataLength, &dwBytes, nullptr); - ret = true; - if (hFile) - CloseHandle(hFile); } + + DWORD dwBytes; + HANDLE hFile = CreateFile(tszLocal, GENERIC_READ | GENERIC_WRITE, NULL, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + WriteFile(hFile, pReply->body, pReply->body.GetLength(), &dwBytes, nullptr); + if (hFile) + CloseHandle(hFile); } } - - mir_free(szUrl); - - return ret; + return true; } typedef HRESULT(MarkupCallback)(IHTMLDocument3 *, BSTR &message); diff --git a/protocols/Non-IM Contact/src/http.cpp b/protocols/Non-IM Contact/src/http.cpp index 70804521b4..5aba5bbd8d 100644 --- a/protocols/Non-IM Contact/src/http.cpp +++ b/protocols/Non-IM Contact/src/http.cpp @@ -35,16 +35,13 @@ HNETLIBUSER hNetlibUser; int InternetDownloadFile(char *szUrl) { // initialize the netlib request - NETLIBHTTPREQUEST nlhr = {}; + MHttpRequest nlhr; nlhr.requestType = REQUEST_GET; nlhr.flags = NLHRF_DUMPASTEXT; - nlhr.szUrl = szUrl; + nlhr.m_szUrl = szUrl; // change the header so the plugin is pretended to be IE 6 + WinXP - nlhr.headersCount++; - nlhr.headers = (NETLIBHTTPHEADER*)malloc(sizeof(NETLIBHTTPHEADER)*nlhr.headersCount); - nlhr.headers[nlhr.headersCount - 1].szName = "User-Agent"; - nlhr.headers[nlhr.headersCount - 1].szValue = NETLIB_USER_AGENT; + nlhr.AddHeader("User-Agent", NETLIB_USER_AGENT); // download the page NLHR_PTR nlhrReply(Netlib_HttpTransaction(hNetlibUser, &nlhr)); @@ -57,14 +54,14 @@ int InternetDownloadFile(char *szUrl) // if the recieved code is 200 OK else if (nlhrReply->resultCode == 200) { // allocate memory and save the retrieved data - szData = (char *)malloc(mir_strlen(nlhrReply->pData) + 2); - mir_strncpy(szData, nlhrReply->pData, mir_strlen(nlhrReply->pData)); + szData = (char *)malloc(nlhrReply->body.GetLength() + 2); + mir_strncpy(szData, nlhrReply->body, nlhrReply->body.GetLength()); } // if the recieved code is 302 Moved, Found, etc else if (nlhrReply->resultCode == 302) { // page moved // get the url for the new location and save it to szInfo // look for the reply header "Location" - if (auto *pszHdr = Netlib_GetHeader(nlhrReply, "Location")) { + if (auto *pszHdr = nlhrReply->FindHeader("Location")) { szData = (char *)malloc(512); // add "Moved/Location:" in front of the new URL for identification mir_snprintf(szData, 512, "Moved/Location: %s\n", pszHdr); diff --git a/protocols/SkypeWeb/src/request_queue.cpp b/protocols/SkypeWeb/src/request_queue.cpp index d6240e7cee..9dd5ecd71e 100644 --- a/protocols/SkypeWeb/src/request_queue.cpp +++ b/protocols/SkypeWeb/src/request_queue.cpp @@ -73,7 +73,7 @@ void CSkypeProto::PushRequest(AsyncHttpRequest *request) ///////////////////////////////////////////////////////////////////////////////////////// -NETLIBHTTPREQUEST* CSkypeProto::DoSend(AsyncHttpRequest *pReq) +MHttpResponse* CSkypeProto::DoSend(AsyncHttpRequest *pReq) { if (pReq->m_host != HOST_OTHER) pReq->m_szUrl.Insert(0, ((pReq->flags & NLHRF_SSL) ? "https://" : "http://")); @@ -88,17 +88,12 @@ NETLIBHTTPREQUEST* CSkypeProto::DoSend(AsyncHttpRequest *pReq) case REQUEST_PUT: case REQUEST_POST: - if (Netlib_GetHeader(pReq, "Content-Type") == nullptr) { + if (!pReq->FindHeader("Content-Type")) { if (pReq->m_szParam[0] == '[' || pReq->m_szParam[0] == '{') pReq->AddHeader("Content-Type", "application/json; charset=UTF-8"); else pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); } - __fallthrough; - - default: - pReq->pData = pReq->m_szParam.Detach(); - pReq->dataLength = (int)mir_strlen(pReq->pData); } } @@ -126,8 +121,8 @@ NETLIBHTTPREQUEST* CSkypeProto::DoSend(AsyncHttpRequest *pReq) break; } - pReq->szUrl = pReq->m_szUrl.GetBuffer(); - debugLogA("Send request to %s", pReq->szUrl); + pReq->m_szUrl = pReq->m_szUrl.GetBuffer(); + debugLogA("Send request to %s", pReq->m_szUrl.c_str()); return Netlib_HttpTransaction(m_hNetlibUser, pReq); } diff --git a/protocols/SkypeWeb/src/requests/avatars.h b/protocols/SkypeWeb/src/requests/avatars.h index cdf5ac7b6e..aeffbf8ab0 100644 --- a/protocols/SkypeWeb/src/requests/avatars.h +++ b/protocols/SkypeWeb/src/requests/avatars.h @@ -30,21 +30,15 @@ struct GetAvatarRequest : public AsyncHttpRequest struct SetAvatarRequest : public AsyncHttpRequest { - SetAvatarRequest(const uint8_t *data, size_t dataSize, const char *szMime, CSkypeProto *ppro) : + SetAvatarRequest(const uint8_t *data, int dataSize, const char *szMime, CSkypeProto *ppro) : AsyncHttpRequest(REQUEST_PUT, HOST_API, 0, &CSkypeProto::OnSentAvatar) { m_szUrl.AppendFormat("/users/%s/profile/avatar", ppro->m_szSkypename.MakeLower().c_str()); AddHeader("Content-Type", szMime); - pData = (char *)mir_alloc(dataSize); - memcpy(pData, data, dataSize); - dataLength = (int)dataSize; - } - - ~SetAvatarRequest() - { - mir_free(pData); + m_szParam.Truncate(dataSize); + memcpy(m_szParam.GetBuffer(), data, dataSize); } }; diff --git a/protocols/SkypeWeb/src/requests/files.h b/protocols/SkypeWeb/src/requests/files.h index 72c47b4788..d47b3637f3 100644 --- a/protocols/SkypeWeb/src/requests/files.h +++ b/protocols/SkypeWeb/src/requests/files.h @@ -28,7 +28,7 @@ struct ASMObjectCreateRequest : public AsyncHttpRequest struct ASMObjectUploadRequest : public AsyncHttpRequest { - ASMObjectUploadRequest(CSkypeProto *ppro, const char *szObject, const uint8_t *data, const size_t size, CFileUploadParam *fup) : + ASMObjectUploadRequest(CSkypeProto *ppro, const char *szObject, const uint8_t *data, int size, CFileUploadParam *fup) : AsyncHttpRequest(REQUEST_PUT, HOST_OTHER, 0, &CSkypeProto::OnASMObjectUploaded) { m_szUrl.AppendFormat("https://api.asm.skype.com/v1/objects/%s/content/original", szObject); @@ -37,13 +37,7 @@ struct ASMObjectUploadRequest : public AsyncHttpRequest AddHeader("Authorization", CMStringA(FORMAT, "skype_token %s", ppro->m_szApiToken.get())); AddHeader("Content-Type", "application/octet-stream"); - pData = (char*)mir_alloc(size); - memcpy(pData, data, size); - dataLength = (int)size; - } - - ~ASMObjectUploadRequest() - { - mir_free(pData); + m_szParam.Truncate(size); + memcpy(m_szParam.GetBuffer(), data, size); } }; diff --git a/protocols/SkypeWeb/src/skype_avatars.cpp b/protocols/SkypeWeb/src/skype_avatars.cpp index 94d097c852..50c1207803 100644 --- a/protocols/SkypeWeb/src/skype_avatars.cpp +++ b/protocols/SkypeWeb/src/skype_avatars.cpp @@ -52,9 +52,9 @@ void CSkypeProto::ReloadAvatarInfo(MCONTACT hContact) SvcGetAvatarInfo(0, (LPARAM)&ai); } -void CSkypeProto::OnReceiveAvatar(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) +void CSkypeProto::OnReceiveAvatar(MHttpResponse *response, AsyncHttpRequest *pRequest) { - if (response == nullptr || response->pData == nullptr) + if (response == nullptr || response->body.IsEmpty()) return; MCONTACT hContact = (DWORD_PTR)pRequest->pUserInfo; @@ -62,7 +62,7 @@ void CSkypeProto::OnReceiveAvatar(NETLIBHTTPREQUEST *response, AsyncHttpRequest return; PROTO_AVATAR_INFORMATION ai = { 0 }; - ai.format = ProtoGetBufferFormat(response->pData); + ai.format = ProtoGetBufferFormat(response->body); setByte(hContact, "AvatarType", ai.format); GetAvatarFileName(hContact, ai.filename, _countof(ai.filename)); @@ -72,13 +72,13 @@ void CSkypeProto::OnReceiveAvatar(NETLIBHTTPREQUEST *response, AsyncHttpRequest return; } - fwrite(response->pData, 1, response->dataLength, out); + fwrite(response->body, 1, response->body.GetLength(), out); fclose(out); setByte(hContact, "NeedNewAvatar", 0); ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &ai, 0); } -void CSkypeProto::OnSentAvatar(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnSentAvatar(MHttpResponse *response, AsyncHttpRequest*) { JsonReply root(response); if (root.error()) @@ -175,7 +175,7 @@ INT_PTR CSkypeProto::SvcSetMyAvatar(WPARAM, LPARAM lParam) if (data != NULL && fread(data, sizeof(uint8_t), length, hFile) == length) { const char *szMime = FreeImage_GetFIFMimeType(FreeImage_GetFIFFromFilenameU(path)); - PushRequest(new SetAvatarRequest(data, length, szMime, this)); + PushRequest(new SetAvatarRequest(data, (int)length, szMime, this)); fclose(hFile); return 0; } diff --git a/protocols/SkypeWeb/src/skype_chatrooms.cpp b/protocols/SkypeWeb/src/skype_chatrooms.cpp index 2d1fc6c3b8..243257353e 100644 --- a/protocols/SkypeWeb/src/skype_chatrooms.cpp +++ b/protocols/SkypeWeb/src/skype_chatrooms.cpp @@ -51,7 +51,7 @@ SESSION_INFO* CSkypeProto::StartChatRoom(const wchar_t *tid, const wchar_t *tnam return si; } -void CSkypeProto::OnLoadChats(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnLoadChats(MHttpResponse *response, AsyncHttpRequest*) { JsonReply reply(response); if (reply.error()) @@ -380,7 +380,7 @@ void CSkypeProto::AddMessageToChat(SESSION_INFO *si, const wchar_t *from, const Chat_Event(&gce); } -void CSkypeProto::OnGetChatInfo(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnGetChatInfo(MHttpResponse *response, AsyncHttpRequest*) { JsonReply reply(response); if (reply.error()) diff --git a/protocols/SkypeWeb/src/skype_contacts.cpp b/protocols/SkypeWeb/src/skype_contacts.cpp index c249c6e281..f5f83e6fa9 100644 --- a/protocols/SkypeWeb/src/skype_contacts.cpp +++ b/protocols/SkypeWeb/src/skype_contacts.cpp @@ -100,7 +100,7 @@ MCONTACT CSkypeProto::AddContact(const char *skypeId, const char *nick, bool isT return hContact; } -void CSkypeProto::LoadContactsAuth(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::LoadContactsAuth(MHttpResponse *response, AsyncHttpRequest*) { JsonReply reply(response); if (reply.error()) @@ -142,7 +142,7 @@ void CSkypeProto::LoadContactsAuth(NETLIBHTTPREQUEST *response, AsyncHttpRequest //[{"skypeId":"echo123", "authorized" : true, "blocked" : false, ...},...] // other properties is exists but empty -void CSkypeProto::LoadContactList(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::LoadContactList(MHttpResponse *response, AsyncHttpRequest*) { JsonReply reply(response); if (reply.error()) @@ -255,7 +255,7 @@ INT_PTR CSkypeProto::BlockContact(WPARAM hContact, LPARAM) return 0; } -void CSkypeProto::OnBlockContact(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) +void CSkypeProto::OnBlockContact(MHttpResponse *response, AsyncHttpRequest *pRequest) { MCONTACT hContact = (DWORD_PTR)pRequest->pUserInfo; if (response != nullptr) @@ -268,7 +268,7 @@ INT_PTR CSkypeProto::UnblockContact(WPARAM hContact, LPARAM) return 0; } -void CSkypeProto::OnUnblockContact(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) +void CSkypeProto::OnUnblockContact(MHttpResponse *response, AsyncHttpRequest *pRequest) { if (response == nullptr) return; diff --git a/protocols/SkypeWeb/src/skype_files.cpp b/protocols/SkypeWeb/src/skype_files.cpp index 358a337e90..9eaef8b665 100644 --- a/protocols/SkypeWeb/src/skype_files.cpp +++ b/protocols/SkypeWeb/src/skype_files.cpp @@ -28,10 +28,10 @@ void CSkypeProto::SendFileThread(void *p) PushRequest(new ASMObjectCreateRequest(this, fup)); } -void CSkypeProto::OnASMObjectCreated(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) +void CSkypeProto::OnASMObjectCreated(MHttpResponse *response, AsyncHttpRequest *pRequest) { auto *fup = (CFileUploadParam*)pRequest->pUserInfo; - if (response == nullptr || response->pData == nullptr) { + if (response == nullptr || response->body.IsEmpty()) { LBL_Error: FILETRANSFER_FAILED(fup); return; @@ -42,7 +42,7 @@ LBL_Error: goto LBL_Error; } - JSONNode node = JSONNode::parse((char*)response->pData); + JSONNode node = JSONNode::parse(response->body); std::string strObjectId = node["id"].as_string(); if (strObjectId.empty()) { debugLogA("Invalid server response (empty object id)"); @@ -74,7 +74,7 @@ LBL_Error: fclose(pFile); } -void CSkypeProto::OnASMObjectUploaded(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) +void CSkypeProto::OnASMObjectUploaded(MHttpResponse *response, AsyncHttpRequest *pRequest) { auto *fup = (CFileUploadParam*)pRequest->pUserInfo; if (response == nullptr) { diff --git a/protocols/SkypeWeb/src/skype_history_sync.cpp b/protocols/SkypeWeb/src/skype_history_sync.cpp index b10897b0d3..7497d8f7a1 100644 --- a/protocols/SkypeWeb/src/skype_history_sync.cpp +++ b/protocols/SkypeWeb/src/skype_history_sync.cpp @@ -19,7 +19,7 @@ along with this program. If not, see . /* HISTORY SYNC */ -void CSkypeProto::OnGetServerHistory(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) +void CSkypeProto::OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest *pRequest) { JsonReply reply(response); if (reply.error()) @@ -140,7 +140,7 @@ INT_PTR CSkypeProto::GetContactHistory(WPARAM hContact, LPARAM) return 0; } -void CSkypeProto::OnSyncHistory(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnSyncHistory(MHttpResponse *response, AsyncHttpRequest*) { JsonReply reply(response); if (reply.error()) diff --git a/protocols/SkypeWeb/src/skype_login.cpp b/protocols/SkypeWeb/src/skype_login.cpp index 76977ab6cd..f9f2ecab57 100644 --- a/protocols/SkypeWeb/src/skype_login.cpp +++ b/protocols/SkypeWeb/src/skype_login.cpp @@ -66,18 +66,18 @@ void CSkypeProto::Login() PushRequest(new OAuthRequest()); } -void CSkypeProto::OnLoginOAuth(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnLoginOAuth(MHttpResponse *response, AsyncHttpRequest*) { if (!IsStatusConnecting(m_iStatus)) return; - if (response == nullptr || response->pData == nullptr) { + if (response == nullptr || response->body.IsEmpty()) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } - JSONNode json = JSONNode::parse(response->pData); + JSONNode json = JSONNode::parse(response->body); if (!json) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); @@ -148,7 +148,7 @@ void CSkypeProto::OnLoginSuccess() PushRequest(new CreateEndpointRequest(this)); } -void CSkypeProto::OnEndpointCreated(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnEndpointCreated(MHttpResponse *response, AsyncHttpRequest*) { if (IsStatusConnecting(m_iStatus)) m_iStatus++; @@ -167,7 +167,7 @@ void CSkypeProto::OnEndpointCreated(NETLIBHTTPREQUEST *response, AsyncHttpReques case 301: case 302: // redirect to the closest data center - if (auto *hdr = Netlib_GetHeader(response, "Location")) { + if (auto *hdr = response->FindHeader("Location")) { CMStringA szUrl(hdr+8); int iEnd = szUrl.Find('/'); g_plugin.szDefaultServer = (iEnd != -1) ? szUrl.Left(iEnd) : szUrl; @@ -176,7 +176,7 @@ void CSkypeProto::OnEndpointCreated(NETLIBHTTPREQUEST *response, AsyncHttpReques return; case 401: // unauthorized - if (auto *szStatus = Netlib_GetHeader(response, "StatusText")) + if (auto *szStatus = response->FindHeader("StatusText")) if (strstr(szStatus, "SkypeTokenExpired")) delSetting("TokenSecret"); delSetting("TokenExpiresIn"); @@ -191,7 +191,7 @@ void CSkypeProto::OnEndpointCreated(NETLIBHTTPREQUEST *response, AsyncHttpReques } // Succeeded, decode the answer - if (auto *hdr = Netlib_GetHeader(response, "Set-RegistrationToken")) { + if (auto *hdr = response->FindHeader("Set-RegistrationToken")) { CMStringA szValue = hdr; int iStart = 0; while (true) { @@ -215,13 +215,13 @@ void CSkypeProto::OnEndpointCreated(NETLIBHTTPREQUEST *response, AsyncHttpReques PushRequest(new CreateSubscriptionsRequest()); } -void CSkypeProto::OnEndpointDeleted(NETLIBHTTPREQUEST *, AsyncHttpRequest *) +void CSkypeProto::OnEndpointDeleted(MHttpResponse *, AsyncHttpRequest *) { m_szId = nullptr; m_szToken = nullptr; } -void CSkypeProto::OnSubscriptionsCreated(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnSubscriptionsCreated(MHttpResponse *response, AsyncHttpRequest*) { if (response == nullptr) { debugLogA(__FUNCTION__ ": failed to create subscription"); @@ -249,9 +249,9 @@ void CSkypeProto::SendPresence() PushRequest(new SendCapabilitiesRequest(epname, this)); } -void CSkypeProto::OnCapabilitiesSended(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnCapabilitiesSended(MHttpResponse *response, AsyncHttpRequest*) { - if (response == nullptr || response->pData == nullptr) { + if (response == nullptr || response->body.IsEmpty()) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; @@ -277,23 +277,23 @@ void CSkypeProto::OnCapabilitiesSended(NETLIBHTTPREQUEST *response, AsyncHttpReq if (bAutoHistorySync) PushRequest(new SyncHistoryFirstRequest(100)); - JSONNode root = JSONNode::parse(response->pData); + JSONNode root = JSONNode::parse(response->body); if (root) setString("SelfEndpointName", UrlToSkypeId(root["selfLink"].as_string().c_str())); PushRequest(new GetProfileRequest(this, 0)); } -void CSkypeProto::OnStatusChanged(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnStatusChanged(MHttpResponse *response, AsyncHttpRequest*) { - if (response == nullptr || response->pData == nullptr) { + if (response == nullptr || response->body.IsEmpty()) { debugLogA(__FUNCTION__ ": failed to change status"); ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } - JSONNode json = JSONNode::parse(response->pData); + JSONNode json = JSONNode::parse(response->body); if (!json) { debugLogA(__FUNCTION__ ": failed to change status"); ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); diff --git a/protocols/SkypeWeb/src/skype_messages.cpp b/protocols/SkypeWeb/src/skype_messages.cpp index 16d9b2cb03..6504224c21 100644 --- a/protocols/SkypeWeb/src/skype_messages.cpp +++ b/protocols/SkypeWeb/src/skype_messages.cpp @@ -45,7 +45,7 @@ int CSkypeProto::SendMsg(MCONTACT hContact, MEVENT, const char *szMessage) return param->hMessage; } -void CSkypeProto::OnMessageSent(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) +void CSkypeProto::OnMessageSent(MHttpResponse *response, AsyncHttpRequest *pRequest) { auto *param = (SendMessageParam*)pRequest->pUserInfo; MCONTACT hContact = param->hContact; @@ -56,8 +56,8 @@ void CSkypeProto::OnMessageSent(NETLIBHTTPREQUEST *response, AsyncHttpRequest *p if (response->resultCode != 201) { std::string strError = Translate("Unknown error!"); - if (response->pData != nullptr) { - JSONNode jRoot = JSONNode::parse(response->pData); + if (!response->body.IsEmpty()) { + JSONNode jRoot = JSONNode::parse(response->body); const JSONNode &jErr = jRoot["errorCode"]; if (jErr) strError = jErr.as_string(); diff --git a/protocols/SkypeWeb/src/skype_oauth.cpp b/protocols/SkypeWeb/src/skype_oauth.cpp index 0a1f8908d3..d767496efa 100644 --- a/protocols/SkypeWeb/src/skype_oauth.cpp +++ b/protocols/SkypeWeb/src/skype_oauth.cpp @@ -28,9 +28,9 @@ static std::string sub(const std::string &str, const char *start, const char *en return (i2 == -1) ? "" : str.substr(i1, i2 - i1); } -void CSkypeProto::OnOAuthStart(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnOAuthStart(MHttpResponse *response, AsyncHttpRequest*) { - if (response == nullptr || response->pData == nullptr) { + if (response == nullptr || response->body.IsEmpty()) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; @@ -38,7 +38,7 @@ void CSkypeProto::OnOAuthStart(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) std::regex regex; std::smatch match; - std::string content = response->pData; + std::string content = response->body.c_str(); regex = ""; @@ -52,11 +52,11 @@ void CSkypeProto::OnOAuthStart(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) std::map scookies; regex = "^(.+?)=(.*?);"; - for (int i = 0; i < response->headersCount; i++) { - if (mir_strcmpi(response->headers[i].szName, "Set-Cookie")) + for (auto &it : *response) { + if (mir_strcmpi(it->szName, "Set-Cookie")) continue; - content = response->headers[i].szValue; + content = it->szValue; if (std::regex_search(content, match, regex)) scookies[match[1]] = match[2]; } @@ -83,18 +83,18 @@ bool CSkypeProto::CheckOauth(const char *szResponse) return true; } -void CSkypeProto::OnOAuthConfirm(NETLIBHTTPREQUEST *response, AsyncHttpRequest *) +void CSkypeProto::OnOAuthConfirm(MHttpResponse *response, AsyncHttpRequest *) { - if (response == nullptr || response->pData == nullptr) { + if (response == nullptr || response->body.IsEmpty()) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } - if (CheckOauth(response->pData)) + if (CheckOauth(response->body)) return; - std::string content = response->pData; + std::string content = response->body.c_str(); std::string PPFT = sub(content, "sFT:'", "'"); std::string opid = sub(content, "opid=", "&"); if (PPFT.empty() || opid.empty()) { @@ -107,11 +107,11 @@ void CSkypeProto::OnOAuthConfirm(NETLIBHTTPREQUEST *response, AsyncHttpRequest * std::smatch match; CMStringA mscookies; - for (int i = 0; i < response->headersCount; i++) { - if (mir_strcmpi(response->headers[i].szName, "Set-Cookie")) + for (auto &it : *response) { + if (mir_strcmpi(it->szName, "Set-Cookie")) continue; - content = response->headers[i].szValue; + content = it->szValue; if (std::regex_search(content, match, regex)) mscookies.Append(match[1].str().c_str()); } @@ -119,23 +119,23 @@ void CSkypeProto::OnOAuthConfirm(NETLIBHTTPREQUEST *response, AsyncHttpRequest * PushRequest(new OAuthRequest(mscookies.c_str(), PPFT.c_str(), opid.c_str())); } -void CSkypeProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnOAuthAuthorize(MHttpResponse *response, AsyncHttpRequest*) { - if (response == nullptr || response->pData == nullptr) { + if (response == nullptr || response->body.IsEmpty()) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } - if (!CheckOauth(response->pData)) { + if (!CheckOauth(response->body)) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); } } -void CSkypeProto::OnOAuthEnd(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnOAuthEnd(MHttpResponse *response, AsyncHttpRequest*) { - if (response == nullptr || response->pData == nullptr) { + if (response == nullptr || response->body.IsEmpty()) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; @@ -143,7 +143,7 @@ void CSkypeProto::OnOAuthEnd(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) std::regex regex; std::smatch match; - std::string content = response->pData; + std::string content = response->body; regex = ""; if (!std::regex_search(content, match, regex)) { diff --git a/protocols/SkypeWeb/src/skype_polling.cpp b/protocols/SkypeWeb/src/skype_polling.cpp index 0000de3b20..b850cffb23 100644 --- a/protocols/SkypeWeb/src/skype_polling.cpp +++ b/protocols/SkypeWeb/src/skype_polling.cpp @@ -39,14 +39,14 @@ void CSkypeProto::PollingThread(void *) if (response->resultCode == 200) { nErrors = 0; - if (response->pData) - ParsePollData(response->pData); + if (!response->body.IsEmpty()) + ParsePollData(response->body); } else { nErrors++; - if (response->pData) { - JSONNode root = JSONNode::parse(response->pData); + if (!response->body.IsEmpty()) { + JSONNode root = JSONNode::parse(response->body); const JSONNode &error = root["errorCode"]; if (error && error.as_int() == 729) break; diff --git a/protocols/SkypeWeb/src/skype_profile.cpp b/protocols/SkypeWeb/src/skype_profile.cpp index f8fbaa2fbe..16fda7b0c8 100644 --- a/protocols/SkypeWeb/src/skype_profile.cpp +++ b/protocols/SkypeWeb/src/skype_profile.cpp @@ -397,7 +397,7 @@ void CSkypeProto::UpdateProfileAvatar(const JSONNode &root, MCONTACT hContact) } //{"firstname":"Echo \/ Sound Test Service", "lastname" : null, "birthday" : null, "gender" : null, "country" : null, "city" : null, "language" : null, "homepage" : null, "about" : null, "province" : null, "jobtitle" : null, "emails" : [], "phoneMobile" : null, "phoneHome" : null, "phoneOffice" : null, "mood" : null, "richMood" : null, "avatarUrl" : null, "username" : "echo123"} -void CSkypeProto::LoadProfile(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) +void CSkypeProto::LoadProfile(MHttpResponse *response, AsyncHttpRequest *pRequest) { MCONTACT hContact = (DWORD_PTR)pRequest->pUserInfo; diff --git a/protocols/SkypeWeb/src/skype_proto.cpp b/protocols/SkypeWeb/src/skype_proto.cpp index 59ad914aaa..536744f36f 100644 --- a/protocols/SkypeWeb/src/skype_proto.cpp +++ b/protocols/SkypeWeb/src/skype_proto.cpp @@ -125,7 +125,7 @@ int CSkypeProto::SetAwayMsg(int, const wchar_t *msg) ///////////////////////////////////////////////////////////////////////////////////////// -void CSkypeProto::OnReceiveAwayMsg(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest) +void CSkypeProto::OnReceiveAwayMsg(MHttpResponse *response, AsyncHttpRequest *pRequest) { JsonReply reply(response); if (reply.error()) diff --git a/protocols/SkypeWeb/src/skype_proto.h b/protocols/SkypeWeb/src/skype_proto.h index 5686aad69c..113e22b228 100644 --- a/protocols/SkypeWeb/src/skype_proto.h +++ b/protocols/SkypeWeb/src/skype_proto.h @@ -120,48 +120,48 @@ public: return getMStringA(hContact, SKYPE_SETTINGS_ID); } - void OnReceiveAvatar(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnSentAvatar(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnSearch(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void OnReceiveAvatar(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnSentAvatar(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnSearch(MHttpResponse *response, AsyncHttpRequest *pRequest); // login - void OnLoginOAuth(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnSubscriptionsCreated(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnCapabilitiesSended(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnReceiveStatus(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnStatusChanged(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void OnLoginOAuth(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnSubscriptionsCreated(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnCapabilitiesSended(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnReceiveStatus(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnStatusChanged(MHttpResponse *response, AsyncHttpRequest *pRequest); - void OnEndpointCreated(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnEndpointDeleted(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void OnEndpointCreated(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnEndpointDeleted(MHttpResponse *response, AsyncHttpRequest *pRequest); // oauth - void OnOAuthStart(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnOAuthConfirm(NETLIBHTTPREQUEST* response, AsyncHttpRequest* pRequest); - void OnOAuthAuthorize(NETLIBHTTPREQUEST* response, AsyncHttpRequest* pRequest); - void OnOAuthEnd(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void OnOAuthStart(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnOAuthConfirm(MHttpResponse* response, AsyncHttpRequest* pRequest); + void OnOAuthAuthorize(MHttpResponse* response, AsyncHttpRequest* pRequest); + void OnOAuthEnd(MHttpResponse *response, AsyncHttpRequest *pRequest); - void OnASMObjectCreated(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnASMObjectUploaded(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void OnASMObjectCreated(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnASMObjectUploaded(MHttpResponse *response, AsyncHttpRequest *pRequest); - void LoadContactsAuth(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void LoadContactList(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void LoadContactsAuth(MHttpResponse *response, AsyncHttpRequest *pRequest); + void LoadContactList(MHttpResponse *response, AsyncHttpRequest *pRequest); - void OnBlockContact(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnUnblockContact(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void OnBlockContact(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnUnblockContact(MHttpResponse *response, AsyncHttpRequest *pRequest); - void OnMessageSent(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void OnMessageSent(MHttpResponse *response, AsyncHttpRequest *pRequest); - void OnGetServerHistory(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnSyncHistory(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void OnGetServerHistory(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnSyncHistory(MHttpResponse *response, AsyncHttpRequest *pRequest); - void OnLoadChats(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnGetChatInfo(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); - void OnReceiveAwayMsg(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void OnLoadChats(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnGetChatInfo(MHttpResponse *response, AsyncHttpRequest *pRequest); + void OnReceiveAwayMsg(MHttpResponse *response, AsyncHttpRequest *pRequest); void CheckConvert(void); bool CheckOauth(const char *szResponse); - void LoadProfile(NETLIBHTTPREQUEST *response, AsyncHttpRequest *pRequest); + void LoadProfile(MHttpResponse *response, AsyncHttpRequest *pRequest); static INT_PTR __cdecl GlobalParseSkypeUriService(WPARAM, LPARAM lParam); @@ -206,7 +206,7 @@ private: void StartQueue(); void StopQueue(); - NETLIBHTTPREQUEST* DoSend(AsyncHttpRequest *request); + MHttpResponse* DoSend(AsyncHttpRequest *request); void Execute(AsyncHttpRequest *request); void PushRequest(AsyncHttpRequest *request); diff --git a/protocols/SkypeWeb/src/skype_search.cpp b/protocols/SkypeWeb/src/skype_search.cpp index 51a4952021..8dc34dc62c 100644 --- a/protocols/SkypeWeb/src/skype_search.cpp +++ b/protocols/SkypeWeb/src/skype_search.cpp @@ -30,7 +30,7 @@ void CSkypeProto::SearchBasicThread(void *id) PushRequest(new GetSearchRequest(T2Utf((wchar_t *)id))); } -void CSkypeProto::OnSearch(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnSearch(MHttpResponse *response, AsyncHttpRequest*) { debugLogA(__FUNCTION__); diff --git a/protocols/SkypeWeb/src/skype_trouter.cpp b/protocols/SkypeWeb/src/skype_trouter.cpp index 65e38d4d41..567e449da1 100644 --- a/protocols/SkypeWeb/src/skype_trouter.cpp +++ b/protocols/SkypeWeb/src/skype_trouter.cpp @@ -26,7 +26,7 @@ void CSkypeProto::ProcessTimer() SendPresence(); } -void CSkypeProto::OnReceiveStatus(NETLIBHTTPREQUEST *response, AsyncHttpRequest*) +void CSkypeProto::OnReceiveStatus(MHttpResponse *response, AsyncHttpRequest*) { JsonReply reply(response); if (reply.error()) diff --git a/protocols/SkypeWeb/src/skype_utils.cpp b/protocols/SkypeWeb/src/skype_utils.cpp index acd02c6892..e2a751568c 100644 --- a/protocols/SkypeWeb/src/skype_utils.cpp +++ b/protocols/SkypeWeb/src/skype_utils.cpp @@ -653,7 +653,7 @@ INT_PTR CSkypeProto::GlobalParseSkypeUriService(WPARAM wParam, LPARAM lParam) ///////////////////////////////////////////////////////////////////////////////////////// -JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) +JsonReply::JsonReply(MHttpResponse *pReply) { if (pReply == nullptr) { m_errorCode = 500; @@ -664,7 +664,7 @@ JsonReply::JsonReply(NETLIBHTTPREQUEST *pReply) if (m_errorCode != 200) return; - m_root = json_parse(pReply->pData); + m_root = json_parse(pReply->body); if (m_root == nullptr) { m_errorCode = 500; return; diff --git a/protocols/SkypeWeb/src/skype_utils.h b/protocols/SkypeWeb/src/skype_utils.h index e8a1f05836..4162a8ec35 100644 --- a/protocols/SkypeWeb/src/skype_utils.h +++ b/protocols/SkypeWeb/src/skype_utils.h @@ -59,7 +59,7 @@ class JsonReply int m_errorCode = 0; public: - JsonReply(NETLIBHTTPREQUEST *response); + JsonReply(MHttpResponse *response); ~JsonReply(); __forceinline JSONNode &data() const { return *m_root; } diff --git a/protocols/Steam/src/http_request.h b/protocols/Steam/src/http_request.h index 4c7b83509d..843ed94cda 100644 --- a/protocols/Steam/src/http_request.h +++ b/protocols/Steam/src/http_request.h @@ -5,10 +5,10 @@ class HttpResponse { - NETLIBHTTPREQUEST *m_response; + MHttpResponse *m_response; public: - HttpResponse(NETLIBHTTPREQUEST *response) : + HttpResponse(MHttpResponse *response) : m_response(response) { } @@ -20,12 +20,12 @@ public: bool operator!() const { - return !m_response || !m_response->pData; + return !m_response || m_response->body.IsEmpty(); } operator bool() const { - return m_response && m_response->pData; + return m_response && !m_response->body.IsEmpty(); } bool IsSuccess() const @@ -37,16 +37,14 @@ public: char* data() const { - return (m_response) ? m_response->pData : nullptr; + return (m_response) ? m_response->body.GetBuffer() : nullptr; } unsigned length() const { - return (m_response) ? m_response->dataLength : 0; + return (m_response) ? m_response->body.GetLength() : 0; } - LIST Headers() const; - int GetStatusCode() const { if (m_response) diff --git a/protocols/Steam/src/steam_proto.h b/protocols/Steam/src/steam_proto.h index 234ae44e88..ed7978e890 100644 --- a/protocols/Steam/src/steam_proto.h +++ b/protocols/Steam/src/steam_proto.h @@ -45,7 +45,7 @@ struct HttpRequest : public MTHttpRequest { HttpRequest(int iRequestType, const char *pszUrl); - NETLIBHTTPREQUEST* Get(); + MHttpRequest* Get(); }; struct ProtoRequest diff --git a/protocols/Steam/src/steam_request.cpp b/protocols/Steam/src/steam_request.cpp index b91283198a..918e01ca16 100644 --- a/protocols/Steam/src/steam_request.cpp +++ b/protocols/Steam/src/steam_request.cpp @@ -2,7 +2,7 @@ bool CSteamProto::SendRequest(HttpRequest *request) { - NETLIBHTTPREQUEST *pResp = Netlib_HttpTransaction(m_hNetlibUser, request->Get()); + auto *pResp = Netlib_HttpTransaction(m_hNetlibUser, request->Get()); HttpResponse response(pResp); delete request; return response.IsSuccess(); @@ -10,7 +10,7 @@ bool CSteamProto::SendRequest(HttpRequest *request) bool CSteamProto::SendRequest(HttpRequest *request, HttpCallback callback, void *param) { - NETLIBHTTPREQUEST *pResp = Netlib_HttpTransaction(m_hNetlibUser, request->Get()); + auto *pResp = Netlib_HttpTransaction(m_hNetlibUser, request->Get()); HttpResponse response(pResp); if (callback) (this->*callback)(response, param); @@ -20,7 +20,7 @@ bool CSteamProto::SendRequest(HttpRequest *request, HttpCallback callback, void bool CSteamProto::SendRequest(HttpRequest *request, JsonCallback callback, void *param) { - NETLIBHTTPREQUEST *pResp = Netlib_HttpTransaction(m_hNetlibUser, request->Get()); + auto *pResp = Netlib_HttpTransaction(m_hNetlibUser, request->Get()); HttpResponse response(pResp); if (callback) { JSONNode root = JSONNode::parse(response.data()); @@ -42,26 +42,11 @@ HttpRequest::HttpRequest(int iRequestType, const char *szUrl) m_szUrl = szUrl; } -NETLIBHTTPREQUEST* HttpRequest::Get() +MHttpRequest* HttpRequest::Get() { if (m_szUrl[0]== '/') { m_szUrl.Insert(0, STEAM_API_URL); AddHeader("User-Agent", STEAM_USER_AGENT); } - szUrl = m_szUrl.GetBuffer(); return this; } - -///////////////////////////////////////////////////////////////////////////////////////// -// HttpResponse - -LIST HttpResponse::Headers() const -{ - LIST ret(10); - - if (m_response) - for (int i = 0; i < m_response->headersCount; i++) - ret.insert(&m_response->headers[i]); - - return ret; -} diff --git a/protocols/Tox/src/http_request.h b/protocols/Tox/src/http_request.h index bba9f0591c..1e140b2ef0 100644 --- a/protocols/Tox/src/http_request.h +++ b/protocols/Tox/src/http_request.h @@ -17,22 +17,12 @@ public: } }; -class HttpRequest : protected NETLIBHTTPREQUEST +class HttpRequest : public MHttpRequest { -private: - CMStringA m_szUrl; - void Init(int type) { requestType = type; flags = NLHRF_HTTP11 | NLHRF_SSL | NLHRF_NODUMPSEND | NLHRF_DUMPASTEXT; - szUrl = nullptr; - headers = nullptr; - headersCount = 0; - pData = nullptr; - dataLength = 0; - resultCode = 0; - szResultDescr = nullptr; nlc = nullptr; timeout = 0; } @@ -60,22 +50,6 @@ public: ~HttpRequest() { - for (int i = 0; i < headersCount; i++) - { - mir_free(headers[i].szName); - mir_free(headers[i].szValue); - } - mir_free(headers); - if (pData) - mir_free(pData); - } - - void 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 AddUrlParameter(const char *urlFormat, ...) @@ -87,20 +61,9 @@ public: va_end(urlArgs); } - void SetData(const char *data, size_t size) - { - if (pData != nullptr) - mir_free(pData); - - dataLength = (int)size; - pData = (char*)mir_alloc(size); - memcpy(pData, data, size); - } - - NETLIBHTTPREQUEST* Send(HNETLIBUSER hNetlibConnection) + MHttpResponse* Send(HNETLIBUSER hNetlibConnection) { m_szUrl.Replace('\\', '/'); - szUrl = m_szUrl.GetBuffer(); return Netlib_HttpTransaction(hNetlibConnection, this); } }; diff --git a/protocols/Tox/src/tox_bootstrap.cpp b/protocols/Tox/src/tox_bootstrap.cpp index 663e46a8ab..6e8a5d774e 100644 --- a/protocols/Tox/src/tox_bootstrap.cpp +++ b/protocols/Tox/src/tox_bootstrap.cpp @@ -121,12 +121,12 @@ void CToxProto::UpdateNodes() debugLogA(__FUNCTION__": updating nodes"); HttpRequest request(REQUEST_GET, "https://nodes.tox.chat/json"); NLHR_PTR response(request.Send(m_hNetlibUser)); - if (!response || response->resultCode != HTTP_CODE_OK || !response->pData) { + if (!response || response->resultCode != HTTP_CODE_OK || response->body.IsEmpty()) { debugLogA(__FUNCTION__": failed to dowload tox.json"); return; } - JSONNode root = JSONNode::parse(response->pData); + JSONNode root = JSONNode::parse(response->body); if (root.empty()) { debugLogA(__FUNCTION__": failed to dowload tox.json"); return; @@ -142,7 +142,7 @@ void CToxProto::UpdateNodes() return; } - if (fwrite(response->pData, sizeof(char), response->dataLength, hFile) != (size_t)response->dataLength) + if (fwrite(response->body, sizeof(char), response->body.GetLength(), hFile) != (size_t)response->body.GetLength()) debugLogA(__FUNCTION__": failed to write tox.json"); fclose(hFile); diff --git a/protocols/Twitter/src/http.cpp b/protocols/Twitter/src/http.cpp index 888afdfa84..71aa265954 100644 --- a/protocols/Twitter/src/http.cpp +++ b/protocols/Twitter/src/http.cpp @@ -39,9 +39,6 @@ void CTwitterProto::Execute(AsyncHttpRequest *pReq) } else pReq->AddHeader("Content-Type", "application/x-www-form-urlencoded"); pReq->AddHeader("Cache-Control", "no-cache"); - - pReq->dataLength = (int)pReq->m_szParam.GetLength(); - pReq->pData = pReq->m_szParam.Detach(); } else { if (pReq->requestType == REQUEST_PATCH) @@ -60,7 +57,6 @@ void CTwitterProto::Execute(AsyncHttpRequest *pReq) // auth = OAuthWebRequestSubmit(pReq->m_szUrl, "POST", (bIsJson) ? "" : pReq->pData); // pReq->AddHeader("Authorization", auth); - pReq->szUrl = pReq->m_szUrl.GetBuffer(); pReq->flags = NLHRF_HTTP11 | NLHRF_PERSISTENT | NLHRF_REDIRECT; pReq->nlc = m_hConnHttp; diff --git a/protocols/Twitter/src/oauth.cpp b/protocols/Twitter/src/oauth.cpp index 9ef2c9bf7c..6e919d3b47 100644 --- a/protocols/Twitter/src/oauth.cpp +++ b/protocols/Twitter/src/oauth.cpp @@ -163,7 +163,7 @@ CMStringA CTwitterProto::OAuthCreateSignature(const CMStringA &signatureBase, co ///////////////////////////////////////////////////////////////////////////////////////// -void CTwitterProto::Oauth2RequestToken(NETLIBHTTPREQUEST *pResp, AsyncHttpRequest *) +void CTwitterProto::Oauth2RequestToken(MHttpResponse *pResp, AsyncHttpRequest *) { if (pResp->resultCode != 200) { OnLoggedFail(); @@ -196,7 +196,7 @@ void CTwitterProto::RequestOauthToken(const char *szPin) ///////////////////////////////////////////////////////////////////////////////////////// -void CTwitterProto::Oauth2RequestAuth(NETLIBHTTPREQUEST *pResp, AsyncHttpRequest *) +void CTwitterProto::Oauth2RequestAuth(MHttpResponse *pResp, AsyncHttpRequest *) { if (pResp->resultCode != 200) { OnLoggedFail(); diff --git a/protocols/Twitter/src/proto.h b/protocols/Twitter/src/proto.h index e3e5650b4d..fd09b49147 100644 --- a/protocols/Twitter/src/proto.h +++ b/protocols/Twitter/src/proto.h @@ -119,8 +119,8 @@ class CTwitterProto : public PROTO void RequestOauthToken(const char *szPin = nullptr); void ResetOauthKeys(); - void Oauth2RequestAuth(NETLIBHTTPREQUEST *, AsyncHttpRequest *); - void Oauth2RequestToken(NETLIBHTTPREQUEST *, AsyncHttpRequest *); + void Oauth2RequestAuth(MHttpResponse *, AsyncHttpRequest *); + void Oauth2RequestToken(MHttpResponse *, AsyncHttpRequest *); CMStringA OAuthWebRequestSubmit(const CMStringA &url, const char *httpMethod, const char *postData); diff --git a/protocols/Twitter/src/utility.cpp b/protocols/Twitter/src/utility.cpp index d9031b51ce..737278bf0a 100644 --- a/protocols/Twitter/src/utility.cpp +++ b/protocols/Twitter/src/utility.cpp @@ -71,10 +71,10 @@ void CTwitterProto::ShowPopup(const char *text, int Error) bool save_url(HNETLIBUSER hNetlib, const CMStringA &url, const CMStringW &filename) { - NETLIBHTTPREQUEST req = { sizeof(req) }; + MHttpRequest req; req.requestType = REQUEST_GET; req.flags = NLHRF_HTTP11 | NLHRF_REDIRECT; - req.szUrl = const_cast(url.c_str()); + req.m_szUrl = const_cast(url.c_str()); NLHR_PTR resp(Netlib_HttpTransaction(hNetlib, &req)); if (!resp) @@ -89,7 +89,7 @@ bool save_url(HNETLIBUSER hNetlib, const CMStringA &url, const CMStringW &filena // Write to file if (FILE *f = _wfopen(filename, L"wb")) { - fwrite(resp->pData, 1, resp->dataLength, f); + fwrite(resp->body, 1, resp->body.GetLength(), f); fclose(f); } else return false; diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp index 4378651b6f..01e6046a43 100644 --- a/protocols/VKontakte/src/misc.cpp +++ b/protocols/VKontakte/src/misc.cpp @@ -315,14 +315,14 @@ bool CVkProto::IsGroupUser(MCONTACT hContact) ///////////////////////////////////////////////////////////////////////////////////////// -JSONNode& CVkProto::CheckJsonResponse(AsyncHttpRequest *pReq, NETLIBHTTPREQUEST *reply, JSONNode &root) +JSONNode& CVkProto::CheckJsonResponse(AsyncHttpRequest *pReq, MHttpResponse *reply, JSONNode &root) { debugLogA("CVkProto::CheckJsonResponse"); - if (!reply || !reply->pData) + if (!reply || reply->body.IsEmpty()) return nullNode; - root = JSONNode::parse(reply->pData); + root = JSONNode::parse(reply->body); if (!CheckJsonResult(pReq, root)) return nullNode; @@ -442,7 +442,7 @@ bool CVkProto::CheckJsonResult(AsyncHttpRequest *pReq, const JSONNode &jnNode) return (iErrorCode == 0); } -void CVkProto::OnReceiveSmth(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveSmth(MHttpResponse *reply, AsyncHttpRequest *pReq) { JSONNode jnRoot; const JSONNode &jnResponse = CheckJsonResponse(pReq, reply, jnRoot); @@ -575,14 +575,15 @@ CMStringW CVkProto::RunRenameNick(LPCWSTR pwszOldName) ///////////////////////////////////////////////////////////////////////////////////////// -void CVkProto::GrabCookies(NETLIBHTTPREQUEST *nhr, CMStringA szDefDomain) +void CVkProto::GrabCookies(MHttpResponse *nhr, CMStringA szDefDomain) { debugLogA("CVkProto::GrabCookies"); - for (int i = 0; i < nhr->headersCount; i++) { - if (_stricmp(nhr->headers[i].szName, "Set-cookie")) + + for (auto &hdr : *nhr) { + if (_stricmp(hdr->szName, "Set-cookie")) continue; - CMStringA szValue = nhr->headers[i].szValue, szCookieName, szCookieVal, szDomain; + CMStringA szValue = hdr->szValue, szCookieName, szCookieVal, szDomain; int iStart = 0; while (true) { bool bFirstToken = (iStart == 0); @@ -1468,16 +1469,16 @@ CMStringW CVkProto::GetAttachmentDescr(const JSONNode &jnAttachments, BBCSupport if (GetFileAttributesW(wszFileName) == INVALID_FILE_ATTRIBUTES) { T2Utf szUrl(wszUrl); - NETLIBHTTPREQUEST req = {}; + MHttpRequest req; req.flags = NLHRF_NODUMP | NLHRF_SSL | NLHRF_HTTP11 | NLHRF_REDIRECT; req.requestType = REQUEST_GET; - req.szUrl = szUrl; + req.m_szUrl = szUrl.get(); - NETLIBHTTPREQUEST* pReply = Netlib_HttpTransaction(m_hNetlibUser, &req); - if (pReply != nullptr && pReply->resultCode == 200 && pReply->pData && pReply->dataLength) { + MHttpResponse *pReply = Netlib_HttpTransaction(m_hNetlibUser, &req); + if (pReply != nullptr && pReply->resultCode == 200 && !pReply->body.IsEmpty()) { bSuccess = true; FILE* out = _wfopen(wszFileName, L"wb"); - fwrite(pReply->pData, 1, pReply->dataLength, out); + fwrite(pReply->body, 1, pReply->body.GetLength(), out); fclose(out); } } diff --git a/protocols/VKontakte/src/vk_avatars.cpp b/protocols/VKontakte/src/vk_avatars.cpp index 29288a2a3a..53c33f8250 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 . #include "stdafx.h" -void CVkProto::OnReceiveAvatar(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveAvatar(MHttpResponse *reply, AsyncHttpRequest *pReq) { if (reply->resultCode != 200 || !pReq->pUserInfo) return; @@ -25,7 +25,7 @@ void CVkProto::OnReceiveAvatar(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) PROTO_AVATAR_INFORMATION ai = { 0 }; CVkSendMsgParam *param = (CVkSendMsgParam *)pReq->pUserInfo; GetAvatarFileName(param->hContact, ai.filename, _countof(ai.filename)); - ai.format = ProtoGetBufferFormat(reply->pData); + ai.format = ProtoGetBufferFormat(reply->body); FILE *out = _wfopen(ai.filename, L"wb"); if (out == nullptr) { @@ -35,7 +35,7 @@ void CVkProto::OnReceiveAvatar(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) return; } - fwrite(reply->pData, 1, reply->dataLength, out); + fwrite(reply->body, 1, reply->body.GetLength(), out); fclose(out); setByte(param->hContact, "NeedNewAvatar", 0); ProtoBroadcastAck(param->hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, &ai); diff --git a/protocols/VKontakte/src/vk_captcha.cpp b/protocols/VKontakte/src/vk_captcha.cpp index e82d1a3400..06e1d451e0 100644 --- a/protocols/VKontakte/src/vk_captcha.cpp +++ b/protocols/VKontakte/src/vk_captcha.cpp @@ -33,12 +33,12 @@ bool CVkProto::RunCaptchaForm(LPCSTR szUrl, CMStringA &result) Utils_OpenUrl(szCaptchaAssistant); } else { - NETLIBHTTPREQUEST req = { sizeof(req) }; + MHttpRequest req; req.requestType = REQUEST_GET; - req.szUrl = (LPSTR)szUrl; + req.m_szUrl = (LPSTR)szUrl; req.flags = VK_NODUMPHEADERS; - NETLIBHTTPREQUEST *reply = Netlib_HttpTransaction(m_hNetlibUser, &req); + auto *reply = Netlib_HttpTransaction(m_hNetlibUser, &req); if (reply == nullptr) return false; @@ -47,7 +47,7 @@ bool CVkProto::RunCaptchaForm(LPCSTR szUrl, CMStringA &result) return false; } - param.bmp = Image_LoadFromMem(reply->pData, reply->dataLength, FIF_UNKNOWN); + param.bmp = Image_LoadFromMem(reply->body, reply->body.GetLength(), FIF_UNKNOWN); BITMAP bmp = { 0 }; GetObject(param.bmp, sizeof(bmp), &bmp); diff --git a/protocols/VKontakte/src/vk_chats.cpp b/protocols/VKontakte/src/vk_chats.cpp index 1fa6d8b774..0264ffad89 100644 --- a/protocols/VKontakte/src/vk_chats.cpp +++ b/protocols/VKontakte/src/vk_chats.cpp @@ -195,7 +195,7 @@ void CVkProto::RetrieveChatInfo(CVkChatInfo *cc) )->pUserInfo = cc; } -void CVkProto::OnReceiveChatInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveChatInfo(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveChatInfo %d", reply->resultCode); if (reply->resultCode != 200) @@ -644,7 +644,7 @@ int CVkProto::OnChatEvent(WPARAM, LPARAM lParam) return 1; } -void CVkProto::OnSendChatMsg(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnSendChatMsg(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnSendChatMsg %d", reply->resultCode); int iResult = ACKRESULT_FAILED; @@ -784,7 +784,7 @@ void CVkProto::KickFromChat(VKUserID_t iChatId, VKUserID_t iUserId, const JSONNo LeaveChat(iChatId); } -void CVkProto::OnChatLeave(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnChatLeave(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnChatLeave %d", reply->resultCode); if (reply->resultCode != 200) @@ -795,7 +795,7 @@ void CVkProto::OnChatLeave(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) } -void CVkProto::OnChatDestroy(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnChatDestroy(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnChatDestroy %d", reply->resultCode); if (reply->resultCode != 200) @@ -1031,7 +1031,7 @@ void CVkProto::CreateNewChat(LPCSTR uids, LPCWSTR pwszTitle) << CHAR_PARAM("user_ids", uids)); } -void CVkProto::OnCreateNewChat(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnCreateNewChat(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnCreateNewChat %d", reply->resultCode); if (reply->resultCode != 200) diff --git a/protocols/VKontakte/src/vk_feed.cpp b/protocols/VKontakte/src/vk_feed.cpp index c5e6701ef1..53f5755057 100644 --- a/protocols/VKontakte/src/vk_feed.cpp +++ b/protocols/VKontakte/src/vk_feed.cpp @@ -642,7 +642,7 @@ static int sttCompareVKNotificationItems(const CVKNewsItem *p1, const CVKNewsIte return compareType ? compareDate : (compareId ? (int)compareDate : 0); } -void CVkProto::OnReceiveUnreadNews(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveUnreadNews(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveUnreadNews %d", reply->resultCode); db_unset(0, m_szModuleName, "LastNewsReqTime"); @@ -747,7 +747,7 @@ void CVkProto::NotificationMarkAsViewed() Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/notifications.markAsViewed.json", true, &CVkProto::OnReceiveSmth)); } -void CVkProto::OnReceiveUnreadNotifications(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveUnreadNotifications(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveUnreadNotifications %d", reply->resultCode); db_unset(0, m_szModuleName, "LastNotificationsReqTime"); diff --git a/protocols/VKontakte/src/vk_files.cpp b/protocols/VKontakte/src/vk_files.cpp index 5c83372d51..34bdfd5504 100644 --- a/protocols/VKontakte/src/vk_files.cpp +++ b/protocols/VKontakte/src/vk_files.cpp @@ -127,7 +127,7 @@ void CVkProto::SendFileFiled(CVkFileUploadParam *fup, int ErrorCode) } -void CVkProto::OnReciveUploadServer(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReciveUploadServer(MHttpResponse *reply, AsyncHttpRequest *pReq) { CVkFileUploadParam *fup = (CVkFileUploadParam *)pReq->pUserInfo; if (!IsOnline()) { @@ -201,9 +201,9 @@ void CVkProto::OnReciveUploadServer(NETLIBHTTPREQUEST *reply, AsyncHttpRequest * // Body size long dataLength = iFileLen + DataBegin.GetLength() + DataEnd.GetLength(); // Body { - char *pData = (char *)mir_alloc(dataLength); + pUploadReq->m_szParam.Truncate(dataLength); + char *pData = pUploadReq->m_szParam.GetBuffer(); memcpy(pData, (void *)DataBegin.GetBuffer(), DataBegin.GetLength()); - pUploadReq->pData = pData; pData += DataBegin.GetLength(); long lBytes = (long)fread(pData, 1, iFileLen, pFile); @@ -211,7 +211,6 @@ void CVkProto::OnReciveUploadServer(NETLIBHTTPREQUEST *reply, AsyncHttpRequest * if (lBytes != iFileLen) { SendFileFiled(fup, VKERR_ERR_READ_FILE); - mir_free(pUploadReq->pData); delete pUploadReq; return; } @@ -220,12 +219,11 @@ void CVkProto::OnReciveUploadServer(NETLIBHTTPREQUEST *reply, AsyncHttpRequest * memcpy(pData, (void *)DataEnd.GetBuffer(), DataEnd.GetLength()); // } Body - pUploadReq->dataLength = (int)dataLength; pUploadReq->pUserInfo = pReq->pUserInfo; Push(pUploadReq); } -void CVkProto::OnReciveUpload(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReciveUpload(MHttpResponse *reply, AsyncHttpRequest *pReq) { CVkFileUploadParam *fup = (CVkFileUploadParam *)pReq->pUserInfo; if (!IsOnline()) { @@ -303,7 +301,7 @@ void CVkProto::OnReciveUpload(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) Push(pUploadReq); } -void CVkProto::OnReciveUploadFile(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReciveUploadFile(MHttpResponse *reply, AsyncHttpRequest *pReq) { CVkFileUploadParam *fup = (CVkFileUploadParam *)pReq->pUserInfo; if (!IsOnline()) { diff --git a/protocols/VKontakte/src/vk_history.cpp b/protocols/VKontakte/src/vk_history.cpp index 4e967f319e..64ea57b002 100644 --- a/protocols/VKontakte/src/vk_history.cpp +++ b/protocols/VKontakte/src/vk_history.cpp @@ -166,7 +166,7 @@ void CVkProto::GetHistoryDlg(MCONTACT hContact, VKMessageID_t iLastMsg) } } -void CVkProto::OnReceiveHistoryMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveHistoryMessages(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveHistoryMessages %d", reply->resultCode); if (reply->resultCode != 200 || !pReq->pUserInfo) { diff --git a/protocols/VKontakte/src/vk_messages.cpp b/protocols/VKontakte/src/vk_messages.cpp index 3549a77a8b..3030df3b9f 100644 --- a/protocols/VKontakte/src/vk_messages.cpp +++ b/protocols/VKontakte/src/vk_messages.cpp @@ -186,7 +186,7 @@ int CVkProto::SendMsg(MCONTACT hContact, MEVENT hReplyEvent, const char *szMsg) return uMsgId; } -void CVkProto::OnSendMessage(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnSendMessage(MHttpResponse *reply, AsyncHttpRequest *pReq) { int iResult = ACKRESULT_FAILED; if (pReq->pUserInfo == nullptr) { @@ -299,7 +299,7 @@ void CVkProto::RetrieveUnreadMessages() Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.RetrieveUnreadConversations", true, &CVkProto::OnReceiveDlgs, AsyncHttpRequest::rpHigh)); } -void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveMessages(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveMessages %d", reply->resultCode); if (reply->resultCode != 200) @@ -487,7 +487,7 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe } } -void CVkProto::OnReceiveDlgs(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveDlgs(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveDlgs %d", reply->resultCode); if (reply->resultCode != 200) diff --git a/protocols/VKontakte/src/vk_pollserver.cpp b/protocols/VKontakte/src/vk_pollserver.cpp index 1597b439ca..3030816b1c 100644 --- a/protocols/VKontakte/src/vk_pollserver.cpp +++ b/protocols/VKontakte/src/vk_pollserver.cpp @@ -28,7 +28,7 @@ void CVkProto::RetrievePollingInfo() ); } -void CVkProto::OnReceivePollingInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceivePollingInfo(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceivePollingInfo %d", reply->resultCode); if (reply->resultCode != 200) @@ -253,9 +253,9 @@ int CVkProto::PollServer() CMStringA szReqUrl(FORMAT, "https://%s?act=a_check&key=%s&ts=%s&wait=25&access_token=%s&mode=%d&version=%d", m_szPollingServer, m_szPollingKey, m_szPollingTs, m_szAccessToken, 106, 2); // see mode parametr description on https://vk.com/dev/using_longpoll (Russian version) - NETLIBHTTPREQUEST req = {}; + MHttpRequest req; req.requestType = REQUEST_GET; - req.szUrl = szReqUrl.GetBuffer(); + req.m_szUrl = szReqUrl.GetBuffer(); req.flags = VK_NODUMPHEADERS | NLHRF_PERSISTENT | NLHRF_HTTP11 | NLHRF_SSL; req.timeout = 30000; req.nlc = m_hPollingConn; @@ -290,7 +290,7 @@ int CVkProto::PollServer() int retVal = 0; if (reply->resultCode == 200) { - JSONNode jnRoot = JSONNode::parse(reply->pData); + JSONNode jnRoot = JSONNode::parse(reply->body); const JSONNode &jnFailed = jnRoot["failed"]; if (jnFailed && jnFailed.as_int() > 1) { RetrievePollingInfo(); diff --git a/protocols/VKontakte/src/vk_proto.cpp b/protocols/VKontakte/src/vk_proto.cpp index 372e8690a8..285ee996ae 100644 --- a/protocols/VKontakte/src/vk_proto.cpp +++ b/protocols/VKontakte/src/vk_proto.cpp @@ -651,7 +651,7 @@ int CVkProto::AuthRequest(MCONTACT hContact, const wchar_t *message) return 0; } -void CVkProto::OnReceiveAuthRequest(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveAuthRequest(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveAuthRequest %d", reply->resultCode); CVkSendMsgParam *param = (CVkSendMsgParam*)pReq->pUserInfo; diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index bc07b1dbc2..4d19cb7d29 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -82,8 +82,8 @@ struct CVkProto : public PROTO //==== Events ======================================================================== int __cdecl OnOptionsInit(WPARAM, LPARAM); - void OnOAuthAuthorize(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveAvatar(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnOAuthAuthorize(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveAvatar(MHttpResponse*, AsyncHttpRequest*); //==== Services ====================================================================== @@ -284,15 +284,15 @@ private: //==== Search ======================================================================== void FreeProtoShearchStruct(PROTOSEARCHBYNAME *pParam); - void OnSearch(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnSearchByMail(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnSearch(MHttpResponse*, AsyncHttpRequest*); + void OnSearchByMail(MHttpResponse*, AsyncHttpRequest*); //==== Files Upload ================================================================== void SendFileFiled(CVkFileUploadParam *fup, int ErrorCode); - void OnReciveUploadServer(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReciveUpload(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReciveUploadFile(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReciveUploadServer(MHttpResponse*, AsyncHttpRequest*); + void OnReciveUpload(MHttpResponse*, AsyncHttpRequest*); + void OnReciveUploadFile(MHttpResponse*, AsyncHttpRequest*); //==== Feed ========================================================================== @@ -308,11 +308,11 @@ private: CMStringW GetVkFeedback(const JSONNode &jnFeedback, VKObjType vkFeedbackType, OBJLIST &vkUsers, CVkUserInfo *vkUser); CVKNewsItem* GetVkParent(const JSONNode &jnParent, VKObjType vkParentType, LPCWSTR pwszReplyText = nullptr, LPCWSTR pwszReplyLink = nullptr); void RetrieveUnreadNews(time_t tLastNewsTime); - void OnReceiveUnreadNews(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveUnreadNews(MHttpResponse*, AsyncHttpRequest*); void RetrieveUnreadNotifications(time_t tLastNotificationsTime); bool FilterNotification(CVKNewsItem *vkNotificationItem, bool& bIsCommented); void NotificationMarkAsViewed(); - void OnReceiveUnreadNotifications(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveUnreadNotifications(MHttpResponse*, AsyncHttpRequest*); void RetrieveUnreadEvents(); void NewsClearHistory(); INT_PTR __cdecl SvcLoadVKNews(WPARAM, LPARAM); @@ -323,50 +323,50 @@ private: void RetrieveUsersInfo(bool bFlag = false, bool bRepeat = false); void RetrieveStatusMsg(const CMStringW &StatusMsg); void RetrieveStatusMusic(const CMStringW &StatusMsg); - void OnReceiveStatus(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveStatusMsg(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveStatus(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveStatusMsg(MHttpResponse*, AsyncHttpRequest*); MCONTACT SetContactInfo(const JSONNode &jnItem, bool bFlag = false, VKContactType vkContactType = VKContactType::vkContactNormal); void TrackVisitor(); void RetrieveMyInfo(void); - void OnReceiveMyInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveMyInfo(MHttpResponse*, AsyncHttpRequest*); void RetrieveUserInfo(VKUserID_t iUserId); void RetrieveGroupInfo(VKUserID_t iGroupID); void RetrieveGroupInfo(CMStringA & groupIDs); - void OnReceiveUserInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveGroupInfo(NETLIBHTTPREQUEST * reply, AsyncHttpRequest * pReq); + void OnReceiveUserInfo(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveGroupInfo(MHttpResponse * reply, AsyncHttpRequest * pReq); void RetrieveFriends(bool bCleanNonFriendContacts = false); - void OnReceiveFriends(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveFriends(MHttpResponse*, AsyncHttpRequest*); void MarkMessagesRead(const MCONTACT hContact); void RetrieveMessagesByIds(const CMStringA &szMids); void RetrieveUnreadMessages(); - void OnReceiveMessages(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveDlgs(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnSendMessage(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveMessages(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveDlgs(MHttpResponse*, AsyncHttpRequest*); + void OnSendMessage(MHttpResponse*, AsyncHttpRequest*); void WallPost(MCONTACT hContact, wchar_t *pwszMsg, wchar_t *pwszUrl, bool bFriendsOnly); void GetServerHistoryLastNDay(MCONTACT hContact, int iNDay); void GetServerHistory(MCONTACT hContact, int iOffset, int iCount, time_t tTime, VKMessageID_t iLastMsgId, bool bOnce = false); - void OnReceiveHistoryMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq); + void OnReceiveHistoryMessages(MHttpResponse *reply, AsyncHttpRequest *pReq); void GetHistoryDlg(MCONTACT hContact, VKMessageID_t iLastMsg); void RetrievePollingInfo(); - void OnReceivePollingInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceivePollingInfo(MHttpResponse*, AsyncHttpRequest*); void __cdecl PollingThread(void*); int PollServer(); void PollUpdates(const JSONNode&); - void OnReceiveAuthRequest(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnReceiveDeleteFriend(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveAuthRequest(MHttpResponse*, AsyncHttpRequest*); + void OnReceiveDeleteFriend(MHttpResponse*, AsyncHttpRequest*); //==== Misc ========================================================================== void SetAllContactStatuses(int iStatus); MCONTACT FindUser(VKUserID_t iUserId, bool bCreate = false); MCONTACT FindChat(VKUserID_t iUserId); - JSONNode& CheckJsonResponse(AsyncHttpRequest *pReq, NETLIBHTTPREQUEST *reply, JSONNode &root); + JSONNode& CheckJsonResponse(AsyncHttpRequest *pReq, MHttpResponse *reply, JSONNode &root); bool CheckJsonResult(AsyncHttpRequest *pReq, const JSONNode &Node); - void OnReceiveSmth(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveSmth(MHttpResponse*, AsyncHttpRequest*); bool AutoFillForm(char*, CMStringA&, CMStringA&); CMStringW RunConfirmationCode(LPCWSTR pwszTitle); CMStringW RunRenameNick(LPCWSTR pwszOldName); - void GrabCookies(NETLIBHTTPREQUEST *nhr, CMStringA szDefDomain = ""); + void GrabCookies(MHttpResponse *nhr, CMStringA szDefDomain = ""); void ApplyCookies(AsyncHttpRequest*); bool IsAuthContactLater(MCONTACT hContact); bool AddAuthContactLater(MCONTACT hContact); @@ -417,16 +417,16 @@ private: void StopChatContactTyping(VKUserID_t iChatId, VKUserID_t iUserId); - void OnCreateNewChat(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnCreateNewChat(MHttpResponse*, AsyncHttpRequest*); CVkChatInfo* AppendConversationChat(VKUserID_t iChatId, const JSONNode& jnItem); void SetChatTitle(CVkChatInfo *cc, LPCWSTR wszTopic); void AppendChatConversationMessage(VKUserID_t iChatId, const JSONNode& jnMsg, const JSONNode& jnFUsers, bool bIsHistory); void AppendChatMessage(CVkChatInfo* vkChatInfo, VKMessageID_t iMessageId, VKUserID_t iUserId, time_t tMsgTime, LPCWSTR pwszBody, bool bIsHistory, bool bIsAction = false); void RetrieveChatInfo(CVkChatInfo*); - void OnReceiveChatInfo(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnSendChatMsg(NETLIBHTTPREQUEST*, AsyncHttpRequest*); - void OnChatLeave(NETLIBHTTPREQUEST*, AsyncHttpRequest *); - void OnChatDestroy(NETLIBHTTPREQUEST*, AsyncHttpRequest*); + void OnReceiveChatInfo(MHttpResponse*, AsyncHttpRequest*); + void OnSendChatMsg(MHttpResponse*, AsyncHttpRequest*); + void OnChatLeave(MHttpResponse*, AsyncHttpRequest *); + void OnChatDestroy(MHttpResponse*, AsyncHttpRequest*); int __cdecl OnChatEvent(WPARAM, LPARAM); int __cdecl OnGcMenuHook(WPARAM, LPARAM); void KickFromChat(VKUserID_t iChatId, VKUserID_t iUserId, const JSONNode &jnMsg, const JSONNode &jnFUsers); diff --git a/protocols/VKontakte/src/vk_queue.cpp b/protocols/VKontakte/src/vk_queue.cpp index 94e85b826d..e42bd1db42 100644 --- a/protocols/VKontakte/src/vk_queue.cpp +++ b/protocols/VKontakte/src/vk_queue.cpp @@ -38,15 +38,11 @@ bool CVkProto::ExecuteRequest(AsyncHttpRequest *pReq) do { pReq->bNeedsRestart = false; pReq->m_iErrorCode = 0; - pReq->szUrl = pReq->m_szUrl.GetBuffer(); + pReq->m_szUrl = pReq->m_szUrl.GetBuffer(); if (!pReq->m_szParam.IsEmpty()) { if (pReq->requestType == REQUEST_GET) { str.Format("%s?%s", pReq->m_szUrl.c_str(), pReq->m_szParam.c_str()); - pReq->szUrl = str.GetBuffer(); - } - else { - pReq->pData = mir_strdup(pReq->m_szParam); - pReq->dataLength = pReq->m_szParam.GetLength(); + pReq->m_szUrl = str.GetBuffer(); } } @@ -64,7 +60,7 @@ bool CVkProto::ExecuteRequest(AsyncHttpRequest *pReq) tLocalWorkThreadTimer = m_tWorkThreadTimer = time(0); } - debugLogA("CVkProto::ExecuteRequest \n====\n%s\n====\n", pReq->szUrl); + debugLogA("CVkProto::ExecuteRequest \n====\n%s\n====\n", pReq->m_szUrl.c_str()); NLHR_PTR reply(Netlib_HttpTransaction(m_hNetlibUser, pReq)); { mir_cslock lck(m_csWorkThreadTimer); diff --git a/protocols/VKontakte/src/vk_search.cpp b/protocols/VKontakte/src/vk_search.cpp index f5da64438c..399e58945d 100644 --- a/protocols/VKontakte/src/vk_search.cpp +++ b/protocols/VKontakte/src/vk_search.cpp @@ -69,7 +69,7 @@ void CVkProto::FreeProtoShearchStruct(PROTOSEARCHBYNAME *pParam) delete pParam; } -void CVkProto::OnSearch(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnSearch(MHttpResponse *reply, AsyncHttpRequest *pReq) { PROTOSEARCHBYNAME *pParam = (PROTOSEARCHBYNAME *)pReq->pUserInfo; debugLogA("CVkProto::OnSearch %d", reply->resultCode); @@ -124,7 +124,7 @@ void CVkProto::OnSearch(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) FreeProtoShearchStruct(pParam); } -void CVkProto::OnSearchByMail(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnSearchByMail(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnSearch %d", reply->resultCode); if (reply->resultCode != 200) { diff --git a/protocols/VKontakte/src/vk_status.cpp b/protocols/VKontakte/src/vk_status.cpp index 4fb2405aa2..10e55835b9 100644 --- a/protocols/VKontakte/src/vk_status.cpp +++ b/protocols/VKontakte/src/vk_status.cpp @@ -124,7 +124,7 @@ INT_PTR __cdecl CVkProto::SvcSetStatusMsg(WPARAM, LPARAM) return 0; } -void CVkProto::OnReceiveStatusMsg(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveStatusMsg(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveStatusMsg %d", reply->resultCode); if (reply->resultCode != 200) @@ -153,7 +153,7 @@ void CVkProto::OnReceiveStatusMsg(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pR setWString("OldStatusMsg", pwszOldStatusMsg); } -void CVkProto::OnReceiveStatus(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveStatus(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveStatus %d", reply->resultCode); if (reply->resultCode != 200) diff --git a/protocols/VKontakte/src/vk_struct.cpp b/protocols/VKontakte/src/vk_struct.cpp index 2b5eb9e121..153aac408d 100644 --- a/protocols/VKontakte/src/vk_struct.cpp +++ b/protocols/VKontakte/src/vk_struct.cpp @@ -68,9 +68,9 @@ AsyncHttpRequest::AsyncHttpRequest(CVkProto *ppro, int iRequestType, LPCSTR _url m_priority = rpPriority; } -void AsyncHttpRequest::Redirect(NETLIBHTTPREQUEST *nhr) +void AsyncHttpRequest::Redirect(MHttpResponse *nhr) { - if (auto *pszHdr = Netlib_GetHeader(nhr, "Location")) + if (auto *pszHdr = nhr->FindHeader("Location")) m_szUrl = pszHdr; } diff --git a/protocols/VKontakte/src/vk_struct.h b/protocols/VKontakte/src/vk_struct.h index f25072f89f..73683a652a 100644 --- a/protocols/VKontakte/src/vk_struct.h +++ b/protocols/VKontakte/src/vk_struct.h @@ -25,7 +25,7 @@ struct AsyncHttpRequest : public MTHttpRequest AsyncHttpRequest(); AsyncHttpRequest(CVkProto*, int iRequestType, LPCSTR szUrl, bool bSecure, MTHttpRequestHandler pFunc, RequestPriority rpPriority = rpMedium); - void Redirect(NETLIBHTTPREQUEST*); + void Redirect(MHttpResponse*); int m_iRetry; int m_iErrorCode; diff --git a/protocols/VKontakte/src/vk_thread.cpp b/protocols/VKontakte/src/vk_thread.cpp index 393a215079..6f7d0b7791 100644 --- a/protocols/VKontakte/src/vk_thread.cpp +++ b/protocols/VKontakte/src/vk_thread.cpp @@ -200,7 +200,7 @@ void CVkProto::OnLoggedOut() ///////////////////////////////////////////////////////////////////////////////////////// -void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, AsyncHttpRequest*) +void CVkProto::OnOAuthAuthorize(MHttpResponse *reply, AsyncHttpRequest*) { debugLogA("CVkProto::OnOAuthAuthorize %d", reply->resultCode); GrabCookies(reply, szVKCookieDomain); @@ -225,7 +225,7 @@ void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, AsyncHttpRequest*) } if (reply->resultCode == 302) { // manual redirect - LPCSTR pszLocation = Netlib_GetHeader(reply, "Location"); + LPCSTR pszLocation = reply->FindHeader("Location"); if (pszLocation) { if (!_strnicmp(pszLocation, szBlankUrl, sizeof(szBlankUrl) - 1)) { m_szAccessToken = nullptr; @@ -283,12 +283,12 @@ void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, AsyncHttpRequest*) return; } - if (reply->resultCode != 200 || !reply->pData || (!(strstr(reply->pData, "method=\"post\"") || strstr(reply->pData, "method=\"POST\"")) && !strstr(reply->pData, "meta http-equiv=\"refresh\""))) { // something went wrong + if (reply->resultCode != 200 || reply->body.IsEmpty() || (!(strstr(reply->body, "method=\"post\"") || strstr(reply->body, "method=\"POST\"")) && !strstr(reply->body, "meta http-equiv=\"refresh\""))) { // something went wrong ConnectionFailed(LOGINERR_NOSERVER); return; } - LPCSTR pBlankUrl = strstr(reply->pData, szBlankUrl); + LPCSTR pBlankUrl = strstr(reply->body, szBlankUrl); if (pBlankUrl) { debugLogA("CVkProto::OnOAuthAuthorize blank ulr found"); m_szAccessToken = nullptr; @@ -311,10 +311,10 @@ void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, AsyncHttpRequest*) return; } - char* pMsgWarning = strstr(reply->pData, "service_msg_warning"); + auto *pMsgWarning = strstr(reply->body, "service_msg_warning"); if (pMsgWarning) { - char *p1 = strchr(pMsgWarning, '>'); - char *p2 = strchr(pMsgWarning, '<'); + auto *p1 = strchr(pMsgWarning, '>'); + auto *p2 = strchr(pMsgWarning, '<'); if (p1 && p2 && (p1 + 1 < p2)) { CMStringA szMsg(p1 + 1, (int)(p2 - p1 - 1)); MsgPopup(ptrW(mir_utf8decodeW(szMsg)), TranslateT("Service message"), true); @@ -325,7 +325,7 @@ void CVkProto::OnOAuthAuthorize(NETLIBHTTPREQUEST *reply, AsyncHttpRequest*) } CMStringA szAction, szBody; - bool bSuccess = AutoFillForm(reply->pData, szAction, szBody); + bool bSuccess = AutoFillForm(reply->body.GetBuffer(), szAction, szBody); if (!bSuccess || szAction.IsEmpty() || szBody.IsEmpty()) { if (m_bPrevError) { ConnectionFailed(LOGINERR_NOSERVER); @@ -381,7 +381,7 @@ void CVkProto::RetrieveMyInfo() Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/users.get.json", true, &CVkProto::OnReceiveMyInfo, AsyncHttpRequest::rpHigh)); } -void CVkProto::OnReceiveMyInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveMyInfo(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveMyInfo %d", reply->resultCode); if (reply->resultCode != 200) { @@ -723,7 +723,7 @@ void CVkProto::RetrieveUsersInfo(bool bFreeOffline, bool bRepeat) } -void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveUserInfo(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveUserInfo %d", reply->resultCode); @@ -801,7 +801,7 @@ void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe } } -void CVkProto::OnReceiveGroupInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveGroupInfo(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveUserInfo %d", reply->resultCode); @@ -887,7 +887,7 @@ void CVkProto::RetrieveFriends(bool bCleanNonFriendContacts) << CHAR_PARAM("fields", szFieldsName))->pUserInfo = new CVkSendMsgParam(0, bCleanNonFriendContacts ? 1 : 0); } -void CVkProto::OnReceiveFriends(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveFriends(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveFriends %d", reply->resultCode); if (reply->resultCode != 200 || !IsOnline()) @@ -983,7 +983,7 @@ INT_PTR __cdecl CVkProto::SvcDeleteFriend(WPARAM hContact, LPARAM flag) return 0; } -void CVkProto::OnReceiveDeleteFriend(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) +void CVkProto::OnReceiveDeleteFriend(MHttpResponse *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveDeleteFriend %d", reply->resultCode); CVkSendMsgParam *param = (CVkSendMsgParam*)pReq->pUserInfo; diff --git a/protocols/Weather/src/weather_http.cpp b/protocols/Weather/src/weather_http.cpp index a306315011..99c262ec6a 100644 --- a/protocols/Weather/src/weather_http.cpp +++ b/protocols/Weather/src/weather_http.cpp @@ -39,28 +39,17 @@ int InternetDownloadFile(char *szUrl, char *cookie, char *userAgent, wchar_t **s if (userAgent == nullptr || userAgent[0] == 0) userAgent = NETLIB_USER_AGENT; - NETLIBHTTPHEADER headers[5]; - headers[0].szName = "User-Agent"; - headers[0].szValue = userAgent; - headers[1].szName = "Cache-Control"; - headers[1].szValue = "no-cache"; - headers[2].szName = "Pragma"; - headers[2].szValue = "no-cache"; - headers[3].szName = "Connection"; - headers[3].szValue = "close"; - headers[4].szName = "Cookie"; - headers[4].szValue = cookie; - // initialize the netlib request - NETLIBHTTPREQUEST nlhr = { sizeof(nlhr) }; + MHttpRequest nlhr; nlhr.requestType = REQUEST_GET; nlhr.flags = NLHRF_DUMPASTEXT | NLHRF_HTTP11 | NLHRF_REDIRECT; - nlhr.szUrl = szUrl; - nlhr.headers = headers; - nlhr.headersCount = _countof(headers); - - if (cookie == nullptr || cookie[0] == 0) - --nlhr.headersCount; + nlhr.m_szUrl = szUrl; + nlhr.AddHeader("User-Agent", userAgent); + nlhr.AddHeader("Cache-Control", "no-cache"); + nlhr.AddHeader("Pragma", "no-cache"); + nlhr.AddHeader("Connection", "close"); + if (mir_strlen(cookie) > 0) + nlhr.AddHeader("Cookie", cookie); // download the page NLHR_PTR nlhrReply(Netlib_HttpTransaction(hNetlibUser, &nlhr)); @@ -75,17 +64,17 @@ int InternetDownloadFile(char *szUrl, char *cookie, char *userAgent, wchar_t **s // if the recieved code is 200 OK int result; if (nlhrReply->resultCode == 200) { - if (nlhrReply->dataLength) { + if (!nlhrReply->body.IsEmpty()) { bool bIsUtf = false; result = 0; // allocate memory and save the retrieved data - auto *pszHdr = Netlib_GetHeader(nlhrReply, "Content-Type"); + auto *pszHdr = nlhrReply->FindHeader("Content-Type"); // look for Content-Type=utf-8 in header if (pszHdr && strstr(_strlwr(pszHdr), "utf-8")) bIsUtf = true; else { - char *end = nlhrReply->pData; + char *end = nlhrReply->body.GetBuffer(); while (end) { // look for // @@ -112,9 +101,9 @@ int InternetDownloadFile(char *szUrl, char *cookie, char *userAgent, wchar_t **s wchar_t *retVal = nullptr; if (bIsUtf) - retVal = mir_utf8decodeW(nlhrReply->pData); + retVal = mir_utf8decodeW(nlhrReply->body); if (retVal == nullptr) - retVal = mir_a2u(nlhrReply->pData); + retVal = mir_a2u(nlhrReply->body); *szData = retVal; } else result = DATA_EMPTY; diff --git a/protocols/WebView/src/webview_getdata.cpp b/protocols/WebView/src/webview_getdata.cpp index ae29e134ef..babfe3cca8 100644 --- a/protocols/WebView/src/webview_getdata.cpp +++ b/protocols/WebView/src/webview_getdata.cpp @@ -104,20 +104,12 @@ void GetData(void *param) if (mir_strlen(url) < 3) WErrorPopup(hContact, TranslateT("URL not supplied")); - NETLIBHTTPREQUEST nlhr = { sizeof(nlhr) }; + MHttpRequest nlhr; nlhr.requestType = REQUEST_GET; nlhr.flags = NLHRF_DUMPASTEXT; - nlhr.szUrl = url; - nlhr.headersCount = 2; - - NETLIBHTTPHEADER headers[2]; - headers[0].szName = "User-Agent"; - headers[0].szValue = NETLIB_USER_AGENT; - - headers[1].szName = "Content-Length"; - headers[1].szValue = nullptr; - - nlhr.headers = headers; + nlhr.m_szUrl = url; + nlhr.AddHeader("User-Agent", NETLIB_USER_AGENT); + nlhr.AddHeader("Content-Length", nullptr); if ( g_plugin.getByte(NO_PROTECT_KEY, 0)) // disable AlreadyDownloading = 0; @@ -144,10 +136,10 @@ void GetData(void *param) WErrorPopup(hContact, statusText); db_set_ws(hContact, "CList", "StatusMsg", statusText); } - if (nlhrReply->dataLength) { + if (nlhrReply->body.GetLength()) { trunccount = 0; - downloadsize = (ULONG)mir_strlen(nlhrReply->pData); - strncpy_s(truncated2, nlhrReply->pData, _TRUNCATE); + downloadsize = nlhrReply->body.GetLength(); + strncpy_s(truncated2, nlhrReply->body, _TRUNCATE); AlreadyDownloading = 1; } // END DATELENGTH } // END REPLY diff --git a/protocols/WhatsApp/src/avatars.cpp b/protocols/WhatsApp/src/avatars.cpp index 9bb7e926aa..077414e8e0 100644 --- a/protocols/WhatsApp/src/avatars.cpp +++ b/protocols/WhatsApp/src/avatars.cpp @@ -130,10 +130,10 @@ void WhatsAppProto::ServerFetchAvatar(const char *jid) bool CMPlugin::SaveFile(const char *pszUrl, PROTO_AVATAR_INFORMATION &ai) { - NETLIBHTTPREQUEST req = {}; + MHttpRequest req; req.flags = NLHRF_NODUMP | NLHRF_PERSISTENT | NLHRF_SSL | NLHRF_HTTP11 | NLHRF_REDIRECT; req.requestType = REQUEST_GET; - req.szUrl = (char*)pszUrl; + req.m_szUrl = pszUrl; req.nlc = hAvatarConn; NLHR_PTR pReply(Netlib_HttpTransaction(hAvatarUser, &req)); @@ -146,14 +146,14 @@ bool CMPlugin::SaveFile(const char *pszUrl, PROTO_AVATAR_INFORMATION &ai) hAvatarConn = pReply->nlc; bool bSuccess = false; - if (pReply->resultCode == 200 && pReply->pData && pReply->dataLength) { - if (auto *pszHdr = Netlib_GetHeader(pReply, "Content-Type")) + if (pReply->resultCode == 200 && !pReply->body.IsEmpty()) { + if (auto *pszHdr = pReply->FindHeader("Content-Type")) ai.format = ProtoGetAvatarFormatByMimeType(pszHdr); if (ai.format != PA_FORMAT_UNKNOWN) { FILE *fout = _wfopen(ai.filename, L"wb"); if (fout) { - fwrite(pReply->pData, 1, pReply->dataLength, fout); + fwrite(pReply->body, 1, pReply->body.GetLength(), fout); fclose(fout); bSuccess = true; } diff --git a/protocols/WhatsApp/src/server.cpp b/protocols/WhatsApp/src/server.cpp index 857666b2e4..e653ac95ba 100644 --- a/protocols/WhatsApp/src/server.cpp +++ b/protocols/WhatsApp/src/server.cpp @@ -24,13 +24,10 @@ void WhatsAppProto::ServerThread(void *) void WhatsAppProto::ServerThreadWorker() { // connect websocket - NETLIBHTTPHEADER hdrs[] = - { - { "Origin", "https://web.whatsapp.com" }, - { 0, 0 } - }; + MHttpHeaders hdrs; + hdrs.AddHeader("Origin", "https://web.whatsapp.com"); - NLHR_PTR pReply(WebSocket_Connect(m_hNetlibUser, "web.whatsapp.com/ws/chat", hdrs)); + NLHR_PTR pReply(WebSocket_Connect(m_hNetlibUser, "web.whatsapp.com/ws/chat", &hdrs)); if (pReply == nullptr) { debugLogA("Server connection failed, exiting"); return; diff --git a/protocols/WhatsApp/src/utils.cpp b/protocols/WhatsApp/src/utils.cpp index 3d3650c043..8e9a19b936 100644 --- a/protocols/WhatsApp/src/utils.cpp +++ b/protocols/WhatsApp/src/utils.cpp @@ -260,7 +260,7 @@ MBinBuffer decodeBufStr(const std::string &buf) uint32_t decodeBigEndian(const uint8_t *buf, size_t len) { uint32_t ret = 0; - for (int i = 0; i < len; i++) { + for (size_t i = 0; i < len; i++) { ret <<= 8; ret += buf[i]; } @@ -271,7 +271,7 @@ uint32_t decodeBigEndian(const uint8_t *buf, size_t len) std::string encodeBigEndian(uint32_t num, size_t len) { std::string res; - for (int i = 0; i < len; i++) { + for (size_t i = 0; i < len; i++) { char c = num & 0xFF; res = c + res; num >>= 8; @@ -519,20 +519,17 @@ WAMediaKeys::WAMediaKeys(const uint8_t *pKey, size_t keyLen, const char *pszMedi MBinBuffer WhatsAppProto::DownloadEncryptedFile(const char *url, const ProtobufCBinaryData &mediaKeys, const char *pszMediaType) { - NETLIBHTTPHEADER headers[1] = {{"Origin", "https://web.whatsapp.com"}}; - - NETLIBHTTPREQUEST req = {}; + MHttpRequest req; req.requestType = REQUEST_GET; - req.szUrl = (char*)url; - req.headersCount = _countof(headers); - req.headers = headers; + req.m_szUrl = url; + req.AddHeader("Origin", "https://web.whatsapp.com"); MBinBuffer ret; auto *pResp = Netlib_HttpTransaction(m_hNetlibUser, &req); if (pResp) { if (pResp->resultCode == 200) { WAMediaKeys out(mediaKeys.data, mediaKeys.len, pszMediaType); - ret = aesDecrypt(EVP_aes_256_cbc(), out.cipherKey, out.iv, pResp->pData, pResp->dataLength); + ret = aesDecrypt(EVP_aes_256_cbc(), out.cipherKey, out.iv, pResp->body, pResp->body.GetLength()); } } diff --git a/src/mir_app/mir_app.vcxproj b/src/mir_app/mir_app.vcxproj index 4cecba6fe2..ed4ea3b3e1 100644 --- a/src/mir_app/mir_app.vcxproj +++ b/src/mir_app/mir_app.vcxproj @@ -117,7 +117,9 @@ + + diff --git a/src/mir_app/mir_app.vcxproj.filters b/src/mir_app/mir_app.vcxproj.filters index b1c74d0b08..35a50fb760 100644 --- a/src/mir_app/mir_app.vcxproj.filters +++ b/src/mir_app/mir_app.vcxproj.filters @@ -428,6 +428,12 @@ Source Files\SRMM + + Source Files\Netlib + + + Source Files\Netlib + diff --git a/src/mir_app/src/MHttpHeaders.cpp b/src/mir_app/src/MHttpHeaders.cpp new file mode 100644 index 0000000000..7681f2aa1b --- /dev/null +++ b/src/mir_app/src/MHttpHeaders.cpp @@ -0,0 +1,82 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 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" + +static int CompareHeaders(const MHttpHeader *p1, const MHttpHeader *p2) +{ + return strcmp(p1->szName, p2->szName); +} + +MHttpHeaders::MHttpHeaders() : + OBJLIST(10, CompareHeaders) +{ +} + +MHttpHeaders::~MHttpHeaders() +{ +} + +void MHttpHeaders::AddHeader(const char *pszName, const char *pszValue) +{ + MHttpHeader tmp(pszName, 0); + if (auto *p = find(&tmp)) + p->szValue = mir_strdup(pszValue); + else + insert(new MHttpHeader(pszName, pszValue)); +} + +void MHttpHeaders::DeleteHeader(const char *pszName) +{ + MHttpHeader tmp(pszName, 0); + int idx = getIndex(&tmp); + if (idx != -1) + remove(idx); +} + +char* MHttpHeaders::FindHeader(const char *pszName) const +{ + MHttpHeader tmp(pszName, 0); + if (auto *p = find(&tmp)) + return p->szValue; + return nullptr; +} + +CMStringA MHttpHeaders::GetCookies() const +{ + CMStringA ret; + + for (auto &it : *this) { + if (mir_strcmpi(it->szName, "Set-Cookie")) + continue; + + if (!ret.IsEmpty()) + ret.Append("; "); + + if (const char *p = strchr(it->szValue, ';')) + ret.Append(it->szValue, p - it->szValue.get()); + else + ret.Append(it->szValue); + } + return ret; +} diff --git a/src/mir_app/src/MHttpRequest.cpp b/src/mir_app/src/MHttpRequest.cpp index 5c165a5130..e6445549b2 100644 --- a/src/mir_app/src/MHttpRequest.cpp +++ b/src/mir_app/src/MHttpRequest.cpp @@ -25,33 +25,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. MHttpRequest::MHttpRequest() { - 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) +void MHttpRequest::SetData(const void *pData, size_t cbLen) { - 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++; + m_szParam.Truncate((int)cbLen); + memcpy(m_szParam.GetBuffer(), pData, cbLen); } + ///////////////////////////////////////////////////////////////////////////////////////// MIR_APP_DLL(MHttpRequest*) operator<<(MHttpRequest *pReq, const INT_PARAM ¶m) diff --git a/src/mir_app/src/MHttpResponse.cpp b/src/mir_app/src/MHttpResponse.cpp new file mode 100644 index 0000000000..1ac1e35c74 --- /dev/null +++ b/src/mir_app/src/MHttpResponse.cpp @@ -0,0 +1,60 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (C) 2012-23 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" + +MHttpResponse::MHttpResponse() +{ +} + +MHttpResponse::~MHttpResponse() +{ + mir_free(szUrl); + mir_free(szResultDescr); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// MHttpResponse helpers for Pascal +// declared only in m_netlib.inc + +EXTERN_C MIR_APP_DLL(int) Netlib_HttpResult(MHttpResponse *nlhr) +{ + return (nlhr) ? nlhr->resultCode : 500; +} + +EXTERN_C MIR_APP_DLL(char *) Netlib_HttpBuffer(MHttpResponse *nlhr, int &cbLen) +{ + if (!nlhr) + return nullptr; + + cbLen = nlhr->body.GetLength(); + return nlhr->body.Detach(); +} + +EXTERN_C MIR_APP_DLL(char *) Netlib_HttpCookies(MHttpResponse *nlhr) +{ + if (!nlhr) + return nullptr; + + return nlhr->GetCookies().Detach(); +} diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def index bb3a1dec8e..7565cfe960 100644 --- a/src/mir_app/src/mir_app.def +++ b/src/mir_app/src/mir_app.def @@ -234,7 +234,6 @@ Font_RegisterW @326 Options_AddPage @327 Options_Open @328 Options_OpenPage @329 -Netlib_GetHeader @330 Srmm_ModifyButton @331 Srmm_AddButton @332 Srmm_GetButtonState @333 @@ -584,15 +583,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 db_mc_addToMeta @716 db_mc_convertToMeta @717 db_mc_enable @718 @@ -919,10 +915,50 @@ _CallContactService@20 @1048 NONAME ??0MDatabaseExport@@QAE@XZ @1049 NONAME ??1MDatabaseExport@@UAE@XZ @1050 NONAME ??_7MDatabaseExport@@6B@ @1051 NONAME -??4NETLIBHTTPREQUEST@@QAEAAU0@$$QAU0@@Z @1052 NONAME -??4NETLIBHTTPREQUEST@@QAEAAU0@ABU0@@Z @1053 NONAME -??ANETLIBHTTPREQUEST@@QAEPBDPBD@Z @1054 NONAME -?GetCookies@NETLIBHTTPREQUEST@@QBE?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@XZ @1055 NONAME -Netlib_HttpBuffer @1056 -Netlib_HttpCookies @1057 -Netlib_HttpResult @1058 +??0?$LIST@UMHttpHeader@@@@QAE@ABU0@@Z @1052 NONAME +??0?$LIST@UMHttpHeader@@@@QAE@HH@Z @1053 NONAME +??0?$LIST@UMHttpHeader@@@@QAE@HP6AHPBUMHttpHeader@@0@Z@Z @1054 NONAME +??0?$OBJLIST@UMHttpHeader@@@@QAE@ABU0@@Z @1055 NONAME +??0?$OBJLIST@UMHttpHeader@@@@QAE@HH@Z @1056 NONAME +??0?$OBJLIST@UMHttpHeader@@@@QAE@HP6AHPBUMHttpHeader@@0@Z@Z @1057 NONAME +??0MHttpHeaders@@QAE@ABU0@@Z @1058 NONAME +??0MHttpHeaders@@QAE@XZ @1059 NONAME +??0MHttpResponse@@QAE@XZ @1060 NONAME +??1?$LIST@UMHttpHeader@@@@QAE@XZ @1061 NONAME +??1?$OBJLIST@UMHttpHeader@@@@QAE@XZ @1062 NONAME +??1MHttpHeaders@@QAE@XZ @1063 NONAME +??1MHttpResponse@@QAE@XZ @1064 NONAME +??4?$LIST@UMHttpHeader@@@@QAEAAU0@ABU0@@Z @1065 NONAME +??4?$OBJLIST@UMHttpHeader@@@@QAEAAU0@ABU0@@Z @1066 NONAME +??4MHttpHeaders@@QAEAAU0@ABU0@@Z @1067 NONAME +??A?$LIST@UMHttpHeader@@@@QBEPAUMHttpHeader@@H@Z @1068 NONAME +??A?$OBJLIST@UMHttpHeader@@@@QBEAAUMHttpHeader@@H@Z @1069 NONAME +??AMHttpHeaders@@QAEPBDPBD@Z @1070 NONAME +?AddHeader@MHttpHeaders@@QAEXPBD0@Z @1071 NONAME +?FindHeader@MHttpHeaders@@QBEPADPBD@Z @1072 NONAME +?GetCookies@MHttpHeaders@@QBE?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@XZ @1073 NONAME +?begin@?$LIST@UMHttpHeader@@@@QBEPAPAUMHttpHeader@@XZ @1074 NONAME +?destroy@?$LIST@UMHttpHeader@@@@QAEXXZ @1075 NONAME +?destroy@?$OBJLIST@UMHttpHeader@@@@QAEXXZ @1076 NONAME +?end@?$LIST@UMHttpHeader@@@@QBEPAPAUMHttpHeader@@XZ @1077 NONAME +?find@?$LIST@UMHttpHeader@@@@QBEPAUMHttpHeader@@PAU2@@Z @1078 NONAME +?getArray@?$LIST@UMHttpHeader@@@@QBEPAPAUMHttpHeader@@XZ @1079 NONAME +?getCount@?$LIST@UMHttpHeader@@@@QBEHXZ @1080 NONAME +?getIndex@?$LIST@UMHttpHeader@@@@QBEHPAUMHttpHeader@@@Z @1081 NONAME +?indexOf@?$LIST@UMHttpHeader@@@@QBEHPAPAUMHttpHeader@@@Z @1082 NONAME +?indexOf@?$LIST@UMHttpHeader@@@@QBEHPAUMHttpHeader@@@Z @1083 NONAME +?insert@?$LIST@UMHttpHeader@@@@QAEHPAUMHttpHeader@@@Z @1084 NONAME +?insert@?$LIST@UMHttpHeader@@@@QAEHPAUMHttpHeader@@H@Z @1085 NONAME +?put@?$LIST@UMHttpHeader@@@@QAEXHPAUMHttpHeader@@@Z @1086 NONAME +?remove@?$LIST@UMHttpHeader@@@@QAEHH@Z @1087 NONAME +?remove@?$LIST@UMHttpHeader@@@@QAEHPAUMHttpHeader@@@Z @1088 NONAME +?remove@?$OBJLIST@UMHttpHeader@@@@QAEHH@Z @1089 NONAME +?remove@?$OBJLIST@UMHttpHeader@@@@QAEHPAUMHttpHeader@@@Z @1090 NONAME +?removeItem@?$LIST@UMHttpHeader@@@@QAEPAUMHttpHeader@@PAPAU2@@Z @1091 NONAME +?removeItem@?$OBJLIST@UMHttpHeader@@@@QAEXPAPAUMHttpHeader@@@Z @1092 NONAME +?rev_iter@?$LIST@UMHttpHeader@@@@QBE?AVreverse_iterator@1@XZ @1093 NONAME +_Netlib_HttpBuffer@8 @1094 NONAME +_Netlib_HttpCookies@4 @1095 NONAME +_Netlib_HttpResult@4 @1096 NONAME +?SetData@MHttpRequest@@QAEXPBXI@Z @1097 NONAME +?DeleteHeader@MHttpHeaders@@QAEXPBD@Z @1098 NONAME diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def index 26f860b889..f1161f7878 100644 --- a/src/mir_app/src/mir_app64.def +++ b/src/mir_app/src/mir_app64.def @@ -234,7 +234,6 @@ Font_RegisterW @326 Options_AddPage @327 Options_Open @328 Options_OpenPage @329 -Netlib_GetHeader @330 Srmm_ModifyButton @331 Srmm_AddButton @332 Srmm_GetButtonState @333 @@ -584,15 +583,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 db_mc_addToMeta @716 db_mc_convertToMeta @717 db_mc_enable @718 @@ -919,10 +915,50 @@ CallContactService @1042 NONAME ??0MDatabaseExport@@QEAA@XZ @1043 NONAME ??1MDatabaseExport@@UEAA@XZ @1044 NONAME ??_7MDatabaseExport@@6B@ @1045 NONAME -??4NETLIBHTTPREQUEST@@QEAAAEAU0@$$QEAU0@@Z @1046 NONAME -??4NETLIBHTTPREQUEST@@QEAAAEAU0@AEBU0@@Z @1047 NONAME -??ANETLIBHTTPREQUEST@@QEAAPEBDPEBD@Z @1048 NONAME -?GetCookies@NETLIBHTTPREQUEST@@QEBA?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@XZ @1049 NONAME -Netlib_HttpBuffer @1050 -Netlib_HttpCookies @1051 -Netlib_HttpResult @1052 +??0?$LIST@UMHttpHeader@@@@QEAA@AEBU0@@Z @1046 NONAME +??0?$LIST@UMHttpHeader@@@@QEAA@HP6AHPEBUMHttpHeader@@0@Z@Z @1047 NONAME +??0?$LIST@UMHttpHeader@@@@QEAA@H_J@Z @1048 NONAME +??0?$OBJLIST@UMHttpHeader@@@@QEAA@AEBU0@@Z @1049 NONAME +??0?$OBJLIST@UMHttpHeader@@@@QEAA@HP6AHPEBUMHttpHeader@@0@Z@Z @1050 NONAME +??0?$OBJLIST@UMHttpHeader@@@@QEAA@H_J@Z @1051 NONAME +??0MHttpHeaders@@QEAA@AEBU0@@Z @1052 NONAME +??0MHttpHeaders@@QEAA@XZ @1053 NONAME +??0MHttpResponse@@QEAA@XZ @1054 NONAME +??1?$LIST@UMHttpHeader@@@@QEAA@XZ @1055 NONAME +??1?$OBJLIST@UMHttpHeader@@@@QEAA@XZ @1056 NONAME +??1MHttpHeaders@@QEAA@XZ @1057 NONAME +??1MHttpResponse@@QEAA@XZ @1058 NONAME +??4?$LIST@UMHttpHeader@@@@QEAAAEAU0@AEBU0@@Z @1059 NONAME +??4?$OBJLIST@UMHttpHeader@@@@QEAAAEAU0@AEBU0@@Z @1060 NONAME +??4MHttpHeaders@@QEAAAEAU0@AEBU0@@Z @1061 NONAME +??A?$LIST@UMHttpHeader@@@@QEBAPEAUMHttpHeader@@H@Z @1062 NONAME +??A?$OBJLIST@UMHttpHeader@@@@QEBAAEAUMHttpHeader@@H@Z @1063 NONAME +??AMHttpHeaders@@QEAAPEBDPEBD@Z @1064 NONAME +?AddHeader@MHttpHeaders@@QEAAXPEBD0@Z @1065 NONAME +?FindHeader@MHttpHeaders@@QEBAPEADPEBD@Z @1066 NONAME +?GetCookies@MHttpHeaders@@QEBA?AV?$CMStringT@DV?$ChTraitsCRT@D@@@@XZ @1067 NONAME +?begin@?$LIST@UMHttpHeader@@@@QEBAPEAPEAUMHttpHeader@@XZ @1068 NONAME +?destroy@?$LIST@UMHttpHeader@@@@QEAAXXZ @1069 NONAME +?destroy@?$OBJLIST@UMHttpHeader@@@@QEAAXXZ @1070 NONAME +?end@?$LIST@UMHttpHeader@@@@QEBAPEAPEAUMHttpHeader@@XZ @1071 NONAME +?find@?$LIST@UMHttpHeader@@@@QEBAPEAUMHttpHeader@@PEAU2@@Z @1072 NONAME +?getArray@?$LIST@UMHttpHeader@@@@QEBAPEAPEAUMHttpHeader@@XZ @1073 NONAME +?getCount@?$LIST@UMHttpHeader@@@@QEBAHXZ @1074 NONAME +?getIndex@?$LIST@UMHttpHeader@@@@QEBAHPEAUMHttpHeader@@@Z @1075 NONAME +?indexOf@?$LIST@UMHttpHeader@@@@QEBAHPEAPEAUMHttpHeader@@@Z @1076 NONAME +?indexOf@?$LIST@UMHttpHeader@@@@QEBAHPEAUMHttpHeader@@@Z @1077 NONAME +?insert@?$LIST@UMHttpHeader@@@@QEAAHPEAUMHttpHeader@@@Z @1078 NONAME +?insert@?$LIST@UMHttpHeader@@@@QEAAHPEAUMHttpHeader@@H@Z @1079 NONAME +?put@?$LIST@UMHttpHeader@@@@QEAAXHPEAUMHttpHeader@@@Z @1080 NONAME +?remove@?$LIST@UMHttpHeader@@@@QEAAHH@Z @1081 NONAME +?remove@?$LIST@UMHttpHeader@@@@QEAAHPEAUMHttpHeader@@@Z @1082 NONAME +?remove@?$OBJLIST@UMHttpHeader@@@@QEAAHH@Z @1083 NONAME +?remove@?$OBJLIST@UMHttpHeader@@@@QEAAHPEAUMHttpHeader@@@Z @1084 NONAME +?removeItem@?$LIST@UMHttpHeader@@@@QEAAPEAUMHttpHeader@@PEAPEAU2@@Z @1085 NONAME +?removeItem@?$OBJLIST@UMHttpHeader@@@@QEAAXPEAPEAUMHttpHeader@@@Z @1086 NONAME +?rev_iter@?$LIST@UMHttpHeader@@@@QEBA?AVreverse_iterator@1@XZ @1087 NONAME +Netlib_HttpBuffer @1088 NONAME +Netlib_HttpCookies @1089 NONAME +Netlib_HttpResult @1090 NONAME +?SetData@MHttpRequest@@QEAAXPEBX_K@Z @1091 NONAME +?DeleteHeader@MHttpHeaders@@QEAAXPEBD@Z @1092 NONAME diff --git a/src/mir_app/src/netlib.h b/src/mir_app/src/netlib.h index 1ce7394cfb..fc11fb8546 100644 --- a/src/mir_app/src/netlib.h +++ b/src/mir_app/src/netlib.h @@ -71,6 +71,56 @@ struct NetlibUrl int flags = 0, port = 0; }; +///////////////////////////////////////////////////////////////////////////////////////// + +struct MChunkHandler +{ + virtual int getTotal() const = 0; + virtual void updateChunk(const void *pData, size_t cbLen) = 0; + virtual void apply(MHttpResponse *nlhr) = 0; +}; + +class MMemoryChunkStorage : public MChunkHandler +{ + MBinBuffer buf; + + int getTotal() const override + { + return (int)buf.length(); + } + + void updateChunk(const void *pData, size_t cbLen) override + { + buf.append(pData, cbLen); + } + + void apply(MHttpResponse *nlhr) override + { + unsigned dataLen = (unsigned)buf.length(); + nlhr->body.Truncate(dataLen+1); + memcpy(nlhr->body.GetBuffer(), buf.data(), dataLen); + nlhr->body.SetAt(dataLen, 0); + } + +public: + MMemoryChunkStorage() {} +}; + +class MFileChunkStorage : public MChunkHandler +{ + CMStringW filePath; + + void updateChunk(const void *pData, size_t cbLen) override; + void apply(MHttpResponse *nlhr) override; + +public: + MFileChunkStorage(const wchar_t *pwszFileName) : + filePath(pwszFileName) + {} +}; + +///////////////////////////////////////////////////////////////////////////////////////// + struct NetlibConnection : public MZeroedObject { NetlibConnection(); @@ -86,6 +136,7 @@ struct NetlibConnection : public MZeroedObject NetlibUrl url; int timeout; + MChunkHandler *pChunkHandler; char *szNewUrl; mir_cs csHttpSequenceNums; @@ -164,9 +215,9 @@ bool BindSocketToPort(const char *szPorts, SOCKET s, SOCKET s6, int* portn); // netlibhttp.cpp void NetlibHttpSetLastErrorUsingHttpResult(int result); -int Netlib_SendHttpRequest(HNETLIBCONN hConnection, NETLIBHTTPREQUEST *pRec); +int Netlib_SendHttpRequest(HNETLIBCONN hConnection, MHttpRequest *pRec, MChunkHandler *pHandler); -NETLIBHTTPREQUEST* NetlibHttpRecv(NetlibConnection *nlc, uint32_t hflags, uint32_t dflags, bool isConnect = false); +MHttpResponse* NetlibHttpRecv(NetlibConnection *nlc, uint32_t hflags, uint32_t dflags, bool isConnect = false); // netliblog.cpp void NetlibLogShowOptions(void); diff --git a/src/mir_app/src/netlib_autoproxy.cpp b/src/mir_app/src/netlib_autoproxy.cpp index c725166c5c..5e4e7deff0 100644 --- a/src/mir_app/src/netlib_autoproxy.cpp +++ b/src/mir_app/src/netlib_autoproxy.cpp @@ -52,20 +52,16 @@ static void GetFile(char *szUrl, AUTO_PROXY_SCRIPT_BUFFER &buf) nlu.toLog = 1; // initialize the netlib request - NETLIBHTTPREQUEST nlhr = {}; - nlhr.requestType = REQUEST_GET; + MHttpRequest nlhr; nlhr.flags = NLHRF_HTTP11 | NLHRF_DUMPASTEXT | NLHRF_REDIRECT; - nlhr.szUrl = szUrl; + nlhr.m_szUrl = szUrl; // download the page NLHR_PTR nlhrReply(Netlib_HttpTransaction(&nlu, &nlhr)); if (nlhrReply) { if (nlhrReply->resultCode == 200) { - buf.lpszScriptBuffer = nlhrReply->pData; - buf.dwScriptBufferSize = nlhrReply->dataLength + 1; - - nlhrReply->dataLength = 0; - nlhrReply->pData = nullptr; + buf.dwScriptBufferSize = nlhrReply->body.GetLength() + 1; + buf.lpszScriptBuffer = nlhrReply->body.Detach(); } } } diff --git a/src/mir_app/src/netlib_http.cpp b/src/mir_app/src/netlib_http.cpp index 9e8e6759cb..a5bd0aaf92 100644 --- a/src/mir_app/src/netlib_http.cpp +++ b/src/mir_app/src/netlib_http.cpp @@ -82,61 +82,17 @@ ProxyAuthList proxyAuthList; ///////////////////////////////////////////////////////////////////////////////////////// // Module exports -MIR_APP_DLL(bool) Netlib_FreeHttpRequest(NETLIBHTTPREQUEST *nlhr) +MIR_APP_DLL(bool) Netlib_FreeHttpRequest(MHttpResponse *nlhr) { - if (nlhr == nullptr || nlhr->requestType != REQUEST_RESPONSE) { + if (nlhr == nullptr) { SetLastError(ERROR_INVALID_PARAMETER); return false; } - if (nlhr->headers) { - for (int i = 0; i < nlhr->headersCount; i++) { - NETLIBHTTPHEADER &p = nlhr->headers[i]; - mir_free(p.szName); - mir_free(p.szValue); - } - mir_free(nlhr->headers); - } - mir_free(nlhr->pData); - mir_free(nlhr->szResultDescr); - mir_free(nlhr->szUrl); - mir_free(nlhr); + delete nlhr; return true; } -MIR_APP_DLL(char*) Netlib_GetHeader(const NETLIBHTTPREQUEST *nlhr, const char *hdr) -{ - if (nlhr == nullptr || hdr == nullptr) - return nullptr; - - for (int i = 0; i < nlhr->headersCount; i++) { - NETLIBHTTPHEADER &p = nlhr->headers[i]; - if (_stricmp(p.szName, hdr) == 0) - return p.szValue; - } - - return nullptr; -} - -///////////////////////////////////////////////////////////////////////////////////////// - -CMStringA NETLIBHTTPREQUEST::GetCookies() const -{ - CMStringA ret; - - for (int i = 0; i < headersCount; i++) { - if (!mir_strcmpi(headers[i].szName, "Set-Cookie")) { - char *p = strchr(headers[i].szValue, ';'); - if (p) *p = 0; - if (!ret.IsEmpty()) - ret.Append("; "); - - ret.Append(headers[i].szValue); - } - } - return ret; -} - ///////////////////////////////////////////////////////////////////////////////////////// static int RecvWithTimeoutTime(NetlibConnection *nlc, int dwTimeoutTime, char *buf, int len, int flags) @@ -165,22 +121,22 @@ static int RecvWithTimeoutTime(NetlibConnection *nlc, int dwTimeoutTime, char *b return Netlib_Recv(nlc, buf, len, flags); } -static char* NetlibHttpFindAuthHeader(NETLIBHTTPREQUEST *nlhrReply, const char *hdr, const char *szProvider) +static char* NetlibHttpFindAuthHeader(MHttpResponse *nlhrReply, const char *hdr, const char *szProvider) { char *szBasicHdr = nullptr; char *szNegoHdr = nullptr; char *szNtlmHdr = nullptr; - for (int i=0; i < nlhrReply->headersCount; i++) { - NETLIBHTTPHEADER &p = nlhrReply->headers[i]; - if (_stricmp(p.szName, hdr) == 0) { - if (_strnicmp(p.szValue, "Negotiate", 9) == 0) - szNegoHdr = p.szValue; - else if (_strnicmp(p.szValue, "NTLM", 4) == 0) - szNtlmHdr = p.szValue; - else if (_strnicmp(p.szValue, "Basic", 5) == 0) - szBasicHdr = p.szValue; - } + for (auto &it : *nlhrReply) { + if (_stricmp(it->szName, hdr)) + continue; + + if (!_strnicmp(it->szValue, "Negotiate", 9)) + szNegoHdr = it->szValue; + else if (!_strnicmp(it->szValue, "NTLM", 4)) + szNtlmHdr = it->szValue; + else if (!_strnicmp(it->szValue, "Basic", 5)) + szBasicHdr = it->szValue; } if (szNegoHdr && (!szProvider || !_stricmp(szProvider, "Negotiate"))) return szNegoHdr; @@ -210,12 +166,12 @@ static void NetlibConnFromUrl(const char *szUrl, bool secur, NetlibUrl &url) url.flags = (secur ? NLOCF_SSL : 0); } -static NetlibConnection* NetlibHttpProcessUrl(NETLIBHTTPREQUEST *nlhr, NetlibUser *nlu, NetlibConnection *nlc, const char *szUrl = nullptr) +static NetlibConnection* NetlibHttpProcessUrl(MHttpRequest *nlhr, NetlibUser *nlu, NetlibConnection *nlc, const char *szUrl = nullptr) { NetlibUrl url; if (szUrl == nullptr) - NetlibConnFromUrl(nlhr->szUrl, (nlhr->flags & NLHRF_SSL) != 0, url); + NetlibConnFromUrl(nlhr->m_szUrl, (nlhr->flags & NLHRF_SSL) != 0, url); else NetlibConnFromUrl(szUrl, false, url); @@ -385,12 +341,12 @@ static int HttpPeekFirstResponseLine(NetlibConnection *nlc, uint32_t dwTimeoutTi return 1; } -static int SendHttpRequestAndData(NetlibConnection *nlc, CMStringA &httpRequest, NETLIBHTTPREQUEST *nlhr, int sendContentLengthHeader) +static int SendHttpRequestAndData(NetlibConnection *nlc, CMStringA &httpRequest, MHttpRequest *nlhr, int sendContentLengthHeader) { bool sendData = (nlhr->requestType == REQUEST_POST || nlhr->requestType == REQUEST_PUT || nlhr->requestType == REQUEST_PATCH); if (sendContentLengthHeader && sendData) - httpRequest.AppendFormat("Content-Length: %d\r\n\r\n", nlhr->dataLength); + httpRequest.AppendFormat("Content-Length: %d\r\n\r\n", nlhr->m_szParam.GetLength()); else httpRequest.AppendFormat("\r\n"); @@ -400,13 +356,13 @@ static int SendHttpRequestAndData(NetlibConnection *nlc, CMStringA &httpRequest, (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); int bytesSent = Netlib_Send(nlc, httpRequest, httpRequest.GetLength(), hflags); - if (bytesSent != SOCKET_ERROR && sendData && nlhr->dataLength) { + if (bytesSent != SOCKET_ERROR && sendData && nlhr->m_szParam.GetLength()) { uint32_t sflags = MSG_NOTITLE | (nlhr->flags & NLHRF_DUMPASTEXT ? MSG_DUMPASTEXT : 0) | (nlhr->flags & (NLHRF_NODUMP | NLHRF_NODUMPSEND) ? MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); - int sendResult = Netlib_Send(nlc, nlhr->pData, nlhr->dataLength, sflags); + int sendResult = Netlib_Send(nlc, nlhr->m_szParam, nlhr->m_szParam.GetLength(), sflags); bytesSent = sendResult != SOCKET_ERROR ? bytesSent + sendResult : SOCKET_ERROR; } @@ -417,7 +373,7 @@ static int SendHttpRequestAndData(NetlibConnection *nlc, CMStringA &httpRequest, ///////////////////////////////////////////////////////////////////////////////////////// // Receives HTTP headers // -// Returns a pointer to a NETLIBHTTPREQUEST structure on success, NULL on failure. +// Returns a pointer to a MHttpRequest structure on success, NULL on failure. // Call Netlib_FreeHttpRequest() to free this. // hConnection must have been returned by MS_NETLIB_OPENCONNECTION // nlhr->pData = NULL and nlhr->dataLength = 0 always. The requested data should @@ -433,21 +389,18 @@ static int SendHttpRequestAndData(NetlibConnection *nlc, CMStringA &httpRequest, #define NHRV_BUF_SIZE 8192 -static NETLIBHTTPREQUEST* Netlib_RecvHttpHeaders(HNETLIBCONN hConnection, int flags) +static MHttpResponse* Netlib_RecvHttpHeaders(NetlibConnection *nlc, int flags) { - NetlibConnection *nlc = (NetlibConnection *)hConnection; if (!NetlibEnterNestedCS(nlc, NLNCS_RECV)) return nullptr; uint32_t dwRequestTimeoutTime = GetTickCount() + HTTPRECVDATATIMEOUT; - NETLIBHTTPREQUEST *nlhr = (NETLIBHTTPREQUEST *)mir_calloc(sizeof(NETLIBHTTPREQUEST)); + std::unique_ptr nlhr(new MHttpResponse()); nlhr->nlc = nlc; // Needed to id connection in the protocol HTTP gateway wrapper functions - nlhr->requestType = REQUEST_RESPONSE; int firstLineLength = 0; if (!HttpPeekFirstResponseLine(nlc, dwRequestTimeoutTime, flags | MSG_PEEK, &nlhr->resultCode, &nlhr->szResultDescr, &firstLineLength)) { NetlibLeaveNestedCS(&nlc->ncsRecv); - Netlib_FreeHttpRequest(nlhr); return nullptr; } @@ -455,7 +408,6 @@ static NETLIBHTTPREQUEST* Netlib_RecvHttpHeaders(HNETLIBCONN hConnection, int fl int bytesPeeked = Netlib_Recv(nlc, buffer, min(firstLineLength, NHRV_BUF_SIZE), flags | MSG_DUMPASTEXT); if (bytesPeeked != firstLineLength) { NetlibLeaveNestedCS(&nlc->ncsRecv); - Netlib_FreeHttpRequest(nlhr); if (bytesPeeked != SOCKET_ERROR) SetLastError(ERROR_HANDLE_EOF); return nullptr; @@ -492,14 +444,10 @@ static NETLIBHTTPREQUEST* Netlib_RecvHttpHeaders(HNETLIBCONN hConnection, int fl if (bytesPeeked <= 0) { NetlibLeaveNestedCS(&nlc->ncsRecv); - Netlib_FreeHttpRequest(nlhr); return nullptr; } // Receive headers - nlhr->headersCount = headersCount; - nlhr->headers = (NETLIBHTTPHEADER *)mir_calloc(sizeof(NETLIBHTTPHEADER) * headersCount); - headersCount = 0; for (char *pbuffer = (char *)buf.data();; headersCount++) { char *peol = strchr(pbuffer, '\n'); @@ -509,14 +457,12 @@ static NETLIBHTTPREQUEST* Netlib_RecvHttpHeaders(HNETLIBCONN hConnection, int fl char *pColon = strchr(pbuffer, ':'); if (pColon == nullptr) { - Netlib_FreeHttpRequest(nlhr); nlhr = nullptr; SetLastError(ERROR_INVALID_DATA); - break; + return nullptr; } *pColon = 0; - nlhr->headers[headersCount].szName = mir_strdup(rtrim(pbuffer)); - nlhr->headers[headersCount].szValue = mir_strdup(lrtrimp(pColon + 1)); + nlhr->AddHeader(rtrim(pbuffer), lrtrimp(pColon + 1)); pbuffer = peol + 1; } @@ -525,7 +471,7 @@ static NETLIBHTTPREQUEST* Netlib_RecvHttpHeaders(HNETLIBCONN hConnection, int fl nlc->foreBuf.appendBefore(buf.data(), buf.length()); NetlibLeaveNestedCS(&nlc->ncsRecv); - return nlhr; + return nlhr.release(); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -539,9 +485,9 @@ static NETLIBHTTPREQUEST* Netlib_RecvHttpHeaders(HNETLIBCONN hConnection, int fl // nlhr.resultCode and nlhr.szResultDescr are ignored by this function. // Errors: ERROR_INVALID_PARAMETER, anything returned by MS_NETLIB_SEND -int Netlib_SendHttpRequest(HNETLIBCONN nlc, NETLIBHTTPREQUEST *nlhr) +int Netlib_SendHttpRequest(HNETLIBCONN nlc, MHttpRequest *nlhr, MChunkHandler *pHandler) { - NETLIBHTTPREQUEST *nlhrReply = nullptr; + MHttpResponse *nlhrReply = nullptr; HttpSecurityContext httpSecurity; char *szHost = nullptr, *szNewUrl = nullptr; @@ -549,7 +495,7 @@ int Netlib_SendHttpRequest(HNETLIBCONN nlc, NETLIBHTTPREQUEST *nlhr) int bytesSent = 0; bool lastFirstLineFail = false; - if (nlhr == nullptr || nlhr->szUrl == nullptr || nlhr->szUrl[0] == '\0') { + if (nlhr == nullptr || nlhr->m_szUrl.IsEmpty()) { SetLastError(ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } @@ -579,9 +525,11 @@ int Netlib_SendHttpRequest(HNETLIBCONN nlc, NETLIBHTTPREQUEST *nlhr) if (!NetlibEnterNestedCS(nlc, NLNCS_SEND)) return SOCKET_ERROR; - const char *pszFullUrl = nlhr->szUrl; + const char *pszFullUrl = nlhr->m_szUrl; const char *pszUrl = nullptr; + nlc->pChunkHandler = pHandler; + unsigned complete = false; int count = 11; while (--count) { @@ -650,15 +598,14 @@ int Netlib_SendHttpRequest(HNETLIBCONN nlc, NETLIBHTTPREQUEST *nlhr) // HTTP headers bool doneHostHeader = false, doneContentLengthHeader = false, doneProxyAuthHeader = false, doneAuthHeader = false, doneConnection = false; - for (int i = 0; i < nlhr->headersCount; i++) { - NETLIBHTTPHEADER &p = nlhr->headers[i]; - if (!mir_strcmpi(p.szName, "Host")) doneHostHeader = true; - else if (!mir_strcmpi(p.szName, "Content-Length")) doneContentLengthHeader = true; - else if (!mir_strcmpi(p.szName, "Proxy-Authorization")) doneProxyAuthHeader = true; - else if (!mir_strcmpi(p.szName, "Authorization")) doneAuthHeader = true; - else if (!mir_strcmpi(p.szName, "Connection")) doneConnection = true; - if (p.szValue == nullptr) continue; - httpRequest.AppendFormat("%s: %s\r\n", p.szName, p.szValue); + for (auto &it : *nlhr) { + if (!mir_strcmpi(it->szName, "Host")) doneHostHeader = true; + else if (!mir_strcmpi(it->szName, "Content-Length")) doneContentLengthHeader = true; + else if (!mir_strcmpi(it->szName, "Proxy-Authorization")) doneProxyAuthHeader = true; + else if (!mir_strcmpi(it->szName, "Authorization")) doneAuthHeader = true; + else if (!mir_strcmpi(it->szName, "Connection")) doneConnection = true; + if (it->szValue == nullptr) continue; + httpRequest.AppendFormat("%s: %s\r\n", it->szName, it->szValue); } if (szHost && !doneHostHeader) httpRequest.AppendFormat("%s: %s\r\n", "Host", szHost); @@ -683,9 +630,10 @@ int Netlib_SendHttpRequest(HNETLIBCONN nlc, NETLIBHTTPREQUEST *nlhr) if (doneContentLengthHeader && nlhr->requestType != REQUEST_HEAD) break; + int resultCode; uint32_t fflags = MSG_PEEK | MSG_NODUMP | ((nlhr->flags & NLHRF_NOPROXY) ? MSG_RAW : 0); uint32_t dwTimeOutTime = hdrTimeout < 0 ? -1 : GetTickCount() + hdrTimeout; - if (!HttpPeekFirstResponseLine(nlc, dwTimeOutTime, fflags, &nlhr->resultCode, nullptr, nullptr)) { + if (!HttpPeekFirstResponseLine(nlc, dwTimeOutTime, fflags, &resultCode, nullptr, nullptr)) { uint32_t err = GetLastError(); Netlib_Logf(nlu, "%s %d: %s Failed (%u %u)", __FILE__, __LINE__, "HttpPeekFirstResponseLine", err, count); @@ -704,7 +652,6 @@ int Netlib_SendHttpRequest(HNETLIBCONN nlc, NETLIBHTTPREQUEST *nlhr) continue; } - int resultCode = nlhr->resultCode; lastFirstLineFail = false; uint32_t hflags = (nlhr->flags & (NLHRF_NODUMP | NLHRF_NODUMPHEADERS | NLHRF_NODUMPSEND) ? @@ -726,7 +673,7 @@ int Netlib_SendHttpRequest(HNETLIBCONN nlc, NETLIBHTTPREQUEST *nlhr) nlhrReply = NetlibHttpRecv(nlc, hflags, dflags); if (nlhrReply) { - auto *tmpUrl = Netlib_GetHeader(nlhrReply, "Location"); + auto *tmpUrl = nlhrReply->FindHeader("Location"); if (tmpUrl) { size_t rlen = 0; if (tmpUrl[0] == '/') { @@ -838,14 +785,14 @@ int Netlib_SendHttpRequest(HNETLIBCONN nlc, NETLIBHTTPREQUEST *nlhr) replaceStr(pszAuthHdr, nullptr); if (nlhrReply) { - Netlib_FreeHttpRequest(nlhrReply); + delete nlhrReply; nlhrReply = nullptr; } } if (count == 0) bytesSent = SOCKET_ERROR; - if (nlhrReply) - Netlib_FreeHttpRequest(nlhrReply); + + delete nlhrReply; //clean up mir_free(pszProxyAuthHdr); @@ -960,90 +907,70 @@ static int NetlibHttpRecvChunkHeader(NetlibConnection *nlc, bool first, uint32_t } } -NETLIBHTTPREQUEST* NetlibHttpRecv(NetlibConnection *nlc, uint32_t hflags, uint32_t dflags, bool isConnect) +MHttpResponse* NetlibHttpRecv(NetlibConnection *nlc, uint32_t hflags, uint32_t dflags, bool isConnect) { - int dataLen = -1, i, chunkhdr = 0; + int dataLen = -1; bool chunked = false; int cenc = 0, cenctype = 0, close = 0; next: - NETLIBHTTPREQUEST *nlhrReply = Netlib_RecvHttpHeaders(nlc, hflags); + std::unique_ptr nlhrReply(Netlib_RecvHttpHeaders(nlc, hflags)); if (nlhrReply == nullptr) return nullptr; - if (nlhrReply->resultCode == 100) { - Netlib_FreeHttpRequest(nlhrReply); + if (nlhrReply->resultCode == 100) goto next; - } if (nlhrReply->resultCode == 204) dataLen = 0; - for (i = 0; i < nlhrReply->headersCount; i++) { - NETLIBHTTPHEADER &p = nlhrReply->headers[i]; - if (!mir_strcmpi(p.szName, "Content-Length")) - dataLen = atoi(p.szValue); + for (auto &it : *nlhrReply) { + if (!mir_strcmpi(it->szName, "Content-Length")) + dataLen = atoi(it->szValue); - if (!mir_strcmpi(p.szName, "Content-Encoding")) { - cenc = i; - if (strstr(p.szValue, "gzip")) + if (!mir_strcmpi(it->szName, "Content-Encoding")) { + cenc = nlhrReply->indexOf(&it); + if (strstr(it->szValue, "gzip")) cenctype = 1; - else if (strstr(p.szValue, "deflate")) + else if (strstr(it->szValue, "deflate")) cenctype = 2; } - if (!mir_strcmpi(p.szName, "Connection")) - close = !mir_strcmpi(p.szValue, "close"); + if (!mir_strcmpi(it->szName, "Connection")) + close = mir_strcmpi(it->szValue, "close") == 0; - if (!mir_strcmpi(p.szName, "Transfer-Encoding") && !mir_strcmpi(p.szValue, "chunked")) { + if (!mir_strcmpi(it->szName, "Transfer-Encoding") && !mir_strcmpi(it->szValue, "chunked")) { chunked = true; - chunkhdr = i; dataLen = -1; } } if (nlhrReply->resultCode >= 200 && (dataLen > 0 || (!isConnect && dataLen < 0))) { int recvResult, chunksz = -1; - int dataBufferAlloced; if (chunked) { chunksz = NetlibHttpRecvChunkHeader(nlc, true, dflags | (cenctype ? MSG_NODUMP : 0)); - if (chunksz == SOCKET_ERROR) { - Netlib_FreeHttpRequest(nlhrReply); + if (chunksz == SOCKET_ERROR) return nullptr; - } + dataLen = chunksz; } - dataBufferAlloced = dataLen < 0 ? 2048 : dataLen + 1; - nlhrReply->pData = (char*)mir_realloc(nlhrReply->pData, dataBufferAlloced); + ptrA tmpBuf((char *)mir_alloc(65536)); while (chunksz != 0) { while (true) { recvResult = RecvWithTimeoutTime(nlc, GetTickCount() + HTTPRECVDATATIMEOUT, - nlhrReply->pData + nlhrReply->dataLength, - dataBufferAlloced - nlhrReply->dataLength - 1, - dflags | (cenctype ? MSG_NODUMP : 0)); + tmpBuf, (chunked) ? chunksz : 65536, dflags | (cenctype ? MSG_NODUMP : 0)); if (recvResult == 0) break; - if (recvResult == SOCKET_ERROR) { - Netlib_FreeHttpRequest(nlhrReply); + if (recvResult == SOCKET_ERROR) return nullptr; - } - nlhrReply->dataLength += recvResult; - if (dataLen >= 0) { - if (nlhrReply->dataLength >= dataLen) + nlc->pChunkHandler->updateChunk(tmpBuf, recvResult); + if (dataLen >= 0) + if (nlc->pChunkHandler->getTotal() >= dataLen) break; - } - else if ((dataBufferAlloced - nlhrReply->dataLength) < 256) { - dataBufferAlloced += 2048; - nlhrReply->pData = (char*)mir_realloc(nlhrReply->pData, dataBufferAlloced); - if (nlhrReply->pData == nullptr) { - SetLastError(ERROR_OUTOFMEMORY); - Netlib_FreeHttpRequest(nlhrReply); - return nullptr; - } - } + Sleep(10); } @@ -1051,60 +978,46 @@ next: break; chunksz = NetlibHttpRecvChunkHeader(nlc, false, dflags | MSG_NODUMP); - if (chunksz == SOCKET_ERROR) { - Netlib_FreeHttpRequest(nlhrReply); + if (chunksz == SOCKET_ERROR) return nullptr; - } - dataLen += chunksz; - dataBufferAlloced += chunksz; - nlhrReply->pData = (char*)mir_realloc(nlhrReply->pData, dataBufferAlloced); + dataLen += chunksz; } - - nlhrReply->pData[nlhrReply->dataLength] = '\0'; } - if (chunked) { - nlhrReply->headers[chunkhdr].szName = (char*)mir_realloc(nlhrReply->headers[chunkhdr].szName, 16); - mir_strcpy(nlhrReply->headers[chunkhdr].szName, "Content-Length"); + nlc->pChunkHandler->apply(nlhrReply.get()); - nlhrReply->headers[chunkhdr].szValue = (char*)mir_realloc(nlhrReply->headers[chunkhdr].szValue, 16); - mir_snprintf(nlhrReply->headers[chunkhdr].szValue, 16, "%u", nlhrReply->dataLength); - } + if (chunked) + nlhrReply->AddHeader("Content-Length", CMStringA(FORMAT, "%u", dataLen)); - if (cenctype) { - int bufsz = nlhrReply->dataLength; + if (cenctype && !nlhrReply->body.IsEmpty()) { + int bufsz = nlhrReply->body.GetLength(); char* szData = nullptr; switch (cenctype) { case 1: - szData = gzip_decode(nlhrReply->pData, &bufsz, 0x10 | MAX_WBITS); + szData = gzip_decode(nlhrReply->body.GetBuffer(), &bufsz, 0x10 | MAX_WBITS); break; case 2: - szData = gzip_decode(nlhrReply->pData, &bufsz, -MAX_WBITS); + szData = gzip_decode(nlhrReply->body.GetBuffer(), &bufsz, -MAX_WBITS); if (bufsz < 0) { - bufsz = nlhrReply->dataLength; - szData = gzip_decode(nlhrReply->pData, &bufsz, MAX_WBITS); + bufsz = nlhrReply->body.GetLength();; + szData = gzip_decode(nlhrReply->body.GetBuffer(), &bufsz, MAX_WBITS); } break; } if (bufsz > 0) { Netlib_Dump(nlc, (uint8_t*)szData, bufsz, false, dflags | MSG_NOTITLE); - mir_free(nlhrReply->pData); - nlhrReply->pData = szData; - nlhrReply->dataLength = bufsz; + nlhrReply->body.Truncate(bufsz); + memcpy(nlhrReply->body.GetBuffer(), szData, bufsz); + nlhrReply->body.SetAt(bufsz, 0); - mir_free(nlhrReply->headers[cenc].szName); - mir_free(nlhrReply->headers[cenc].szValue); - memmove(&nlhrReply->headers[cenc], &nlhrReply->headers[cenc+1], (--nlhrReply->headersCount-cenc)*sizeof(nlhrReply->headers[0])); - } - else if (bufsz == 0) { - mir_free(nlhrReply->pData); - nlhrReply->pData = nullptr; - nlhrReply->dataLength = 0; + nlhrReply->remove(cenc); } + else if (bufsz == 0) + nlhrReply->body.Empty(); } if (close && @@ -1112,15 +1025,15 @@ next: (!isConnect || nlhrReply->resultCode != 200)) NetlibDoCloseSocket(nlc); - return nlhrReply; + return nlhrReply.release(); } ///////////////////////////////////////////////////////////////////////////////////////// // Module entry point -MIR_APP_DLL(NETLIBHTTPREQUEST *) Netlib_HttpTransaction(HNETLIBUSER nlu, NETLIBHTTPREQUEST *nlhr) +MIR_APP_DLL(MHttpResponse *) Netlib_HttpTransaction(HNETLIBUSER nlu, MHttpRequest *nlhr) { - if (GetNetlibHandleType(nlu) != NLH_USER || !(nlu->user.flags & NUF_OUTGOING) || !nlhr || !nlhr->szUrl || nlhr->szUrl[0] == 0) { + if (GetNetlibHandleType(nlu) != NLH_USER || !(nlu->user.flags & NUF_OUTGOING) || !nlhr || nlhr->m_szUrl.IsEmpty()) { SetLastError(ERROR_INVALID_PARAMETER); return nullptr; } @@ -1128,27 +1041,14 @@ MIR_APP_DLL(NETLIBHTTPREQUEST *) Netlib_HttpTransaction(HNETLIBUSER nlu, NETLIBH if (nlhr->nlc != nullptr && GetNetlibHandleType(nlhr->nlc) != NLH_CONNECTION) nlhr->nlc = nullptr; - NetlibConnection *nlc = NetlibHttpProcessUrl(nlhr, nlu, (NetlibConnection *)nlhr->nlc); + NetlibConnection *nlc = NetlibHttpProcessUrl(nlhr, nlu, nlhr->nlc); if (nlc == nullptr) return nullptr; - NETLIBHTTPREQUEST nlhrSend = *nlhr; - nlhrSend.flags |= NLHRF_SMARTREMOVEHOST; - - bool doneUserAgentHeader = Netlib_GetHeader(nlhr, "User-Agent") != nullptr; - bool doneAcceptEncoding = Netlib_GetHeader(nlhr, "Accept-Encoding") != nullptr; - if (!doneUserAgentHeader || !doneAcceptEncoding) { - nlhrSend.headers = (NETLIBHTTPHEADER *)mir_alloc(sizeof(NETLIBHTTPHEADER) * (nlhrSend.headersCount + 2)); - memcpy(nlhrSend.headers, nlhr->headers, sizeof(NETLIBHTTPHEADER) * nlhr->headersCount); - } + nlhr->flags |= NLHRF_SMARTREMOVEHOST; - char szUserAgent[64]; - if (!doneUserAgentHeader) { - nlhrSend.headers[nlhrSend.headersCount].szName = "User-Agent"; - nlhrSend.headers[nlhrSend.headersCount].szValue = szUserAgent; - ++nlhrSend.headersCount; - - char szMirandaVer[64]; + if (!nlhr->FindHeader("User-Agent")) { + char szUserAgent[64], szMirandaVer[64]; strncpy_s(szMirandaVer, MIRANDA_VERSION_STRING, _TRUNCATE); #if defined(_WIN64) strncat_s(szMirandaVer, " x64", _TRUNCATE); @@ -1160,20 +1060,18 @@ MIR_APP_DLL(NETLIBHTTPREQUEST *) Netlib_HttpTransaction(HNETLIBUSER nlu, NETLIBH mir_snprintf(szUserAgent, "Miranda/%s (%s)", szMirandaVer, pspace); } else mir_snprintf(szUserAgent, "Miranda/%s", szMirandaVer); + + nlhr->AddHeader("User-Agent", szUserAgent); } - if (!doneAcceptEncoding) { - nlhrSend.headers[nlhrSend.headersCount].szName = "Accept-Encoding"; - nlhrSend.headers[nlhrSend.headersCount].szValue = "deflate, gzip"; - ++nlhrSend.headersCount; - } - if (Netlib_SendHttpRequest(nlc, &nlhrSend) == SOCKET_ERROR) { - if (!doneUserAgentHeader || !doneAcceptEncoding) mir_free(nlhrSend.headers); - nlhr->resultCode = nlhrSend.resultCode; + + if (!nlhr->FindHeader("Accept-Encoding")) + nlhr->AddHeader("Accept-Encoding", "deflate, gzip"); + + MMemoryChunkStorage storage; + if (Netlib_SendHttpRequest(nlc, nlhr, &storage) == SOCKET_ERROR) { Netlib_CloseHandle(nlc); return nullptr; } - if (!doneUserAgentHeader || !doneAcceptEncoding) - mir_free(nlhrSend.headers); uint32_t dflags = (nlhr->flags & NLHRF_DUMPASTEXT ? MSG_DUMPASTEXT : 0) | (nlhr->flags & NLHRF_NODUMP ? MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | @@ -1183,7 +1081,7 @@ MIR_APP_DLL(NETLIBHTTPREQUEST *) Netlib_HttpTransaction(HNETLIBUSER nlu, NETLIBH (nlhr->flags & NLHRF_NODUMP ? MSG_NODUMP : (nlhr->flags & NLHRF_DUMPPROXY ? MSG_DUMPPROXY : 0)) | (nlhr->flags & NLHRF_NOPROXY ? MSG_RAW : 0); - NETLIBHTTPREQUEST *nlhrReply; + MHttpResponse *nlhrReply; if (nlhr->requestType == REQUEST_HEAD) nlhrReply = Netlib_RecvHttpHeaders(nlc, 0); else @@ -1203,25 +1101,3 @@ MIR_APP_DLL(NETLIBHTTPREQUEST *) Netlib_HttpTransaction(HNETLIBUSER nlu, NETLIBH return nlhrReply; } - -EXTERN_C MIR_APP_DLL(int) Netlib_HttpResult(NETLIBHTTPREQUEST *nlhr) -{ - return (nlhr) ? nlhr->resultCode : 500; -} - -EXTERN_C MIR_APP_DLL(char *) Netlib_HttpBuffer(NETLIBHTTPREQUEST *nlhr, int &cbLen) -{ - if (!nlhr) - return nullptr; - - cbLen = nlhr->dataLength; - return nlhr->pData; -} - -EXTERN_C MIR_APP_DLL(char *) Netlib_HttpCookies(NETLIBHTTPREQUEST *nlhr) -{ - if (!nlhr) - return nullptr; - - return nlhr->GetCookies().Detach(); -} diff --git a/src/mir_app/src/netlib_openconn.cpp b/src/mir_app/src/netlib_openconn.cpp index adbde4d07e..210c94cb71 100644 --- a/src/mir_app/src/netlib_openconn.cpp +++ b/src/mir_app/src/netlib_openconn.cpp @@ -308,15 +308,16 @@ static bool NetlibInitHttpsConnection(NetlibConnection *nlc) szUrl.Format("%s:%u", inet_ntoa(*(PIN_ADDR)&ip), url.port); } - NETLIBHTTPREQUEST nlhrSend = {}; + MMemoryChunkStorage storage; + MHttpRequest nlhrSend; nlhrSend.requestType = REQUEST_CONNECT; nlhrSend.flags = NLHRF_DUMPPROXY | NLHRF_HTTP11 | NLHRF_NOPROXY | NLHRF_REDIRECT; - nlhrSend.szUrl = szUrl.GetBuffer(); + nlhrSend.m_szUrl = szUrl; - if (Netlib_SendHttpRequest(nlc, &nlhrSend) == SOCKET_ERROR) + if (Netlib_SendHttpRequest(nlc, &nlhrSend, &storage) == SOCKET_ERROR) return false; - NETLIBHTTPREQUEST *nlhrReply = NetlibHttpRecv(nlc, MSG_DUMPPROXY | MSG_RAW, MSG_DUMPPROXY | MSG_RAW, true); + auto *nlhrReply = NetlibHttpRecv(nlc, MSG_DUMPPROXY | MSG_RAW, MSG_DUMPPROXY | MSG_RAW, true); if (nlhrReply == nullptr) return false; diff --git a/src/mir_app/src/netlib_websocket.cpp b/src/mir_app/src/netlib_websocket.cpp index cd3aaaef4e..a0f7465f0e 100644 --- a/src/mir_app/src/netlib_websocket.cpp +++ b/src/mir_app/src/netlib_websocket.cpp @@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../../libs/zlib/src/zlib.h" -MIR_APP_DLL(NETLIBHTTPREQUEST*) WebSocket_Connect(HNETLIBUSER nlu, const char *szHost, NETLIBHTTPHEADER *pHeaders) +MIR_APP_DLL(MHttpResponse*) WebSocket_Connect(HNETLIBUSER nlu, const char *szHost, const MHttpHeaders *pHeaders) { CMStringA tmpHost(szHost); @@ -37,7 +37,7 @@ MIR_APP_DLL(NETLIBHTTPREQUEST*) WebSocket_Connect(HNETLIBUSER nlu, const char *s auto *nlr = new MHttpRequest; nlr->flags = NLHRF_PERSISTENT | NLHRF_HTTP11 | NLHRF_SSL; - nlr->szUrl = tmpHost.GetBuffer(); + nlr->m_szUrl = tmpHost.GetBuffer(); nlr->AddHeader("Accept", "*/*"); nlr->AddHeader("Upgrade", "websocket"); nlr->AddHeader("Pragma", "no-cache"); @@ -50,12 +50,9 @@ MIR_APP_DLL(NETLIBHTTPREQUEST*) WebSocket_Connect(HNETLIBUSER nlu, const char *s nlr->AddHeader("Sec-WebSocket-Version", "13"); nlr->AddHeader("Sec-WebSocket-Extensions", "permessage-deflate; client_max_window_bits"); - if (pHeaders) { - while (pHeaders->szName != nullptr) { - nlr->AddHeader(pHeaders->szName, pHeaders->szValue); - pHeaders++; - } - } + if (pHeaders) + for (auto &it: *pHeaders) + nlr->AddHeader(it->szName, it->szValue); auto *pReply = Netlib_HttpTransaction(nlu, nlr); delete nlr; -- cgit v1.2.3