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; --- 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 +- 12 files changed, 417 insertions(+), 288 deletions(-) create mode 100644 src/mir_app/src/MHttpHeaders.cpp create mode 100644 src/mir_app/src/MHttpResponse.cpp (limited to 'src') 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