diff options
author | Daniel Wilhelm <shieldwed@outlook.com> | 2016-10-29 11:41:53 +0200 |
---|---|---|
committer | Daniel Wilhelm <shieldwed@outlook.com> | 2016-10-29 11:41:53 +0200 |
commit | 7302bb4484d517a72cdffbd13ec7a9f2324cde01 (patch) | |
tree | 17d2964c6768d49510206836a496fb1802a63e08 /wx+/http.cpp | |
parent | 8.5 (diff) | |
download | FreeFileSync-7302bb4484d517a72cdffbd13ec7a9f2324cde01.tar.gz FreeFileSync-7302bb4484d517a72cdffbd13ec7a9f2324cde01.tar.bz2 FreeFileSync-7302bb4484d517a72cdffbd13ec7a9f2324cde01.zip |
8.6
Diffstat (limited to 'wx+/http.cpp')
-rw-r--r-- | wx+/http.cpp | 85 |
1 files changed, 51 insertions, 34 deletions
diff --git a/wx+/http.cpp b/wx+/http.cpp index af51090c..ce3de482 100644 --- a/wx+/http.cpp +++ b/wx+/http.cpp @@ -6,11 +6,12 @@ #include "http.h" #ifdef ZEN_WIN - #include <zen/win.h> //tame wininet.h include - #include <wininet.h> + #include <zen/win.h> //tame WinINet.h include + #include <WinINet.h> #endif #if defined ZEN_LINUX || defined ZEN_MAC + #include <wx/app.h> #include <zen/thread.h> //std::thread::id #include <wx/protocol/http.h> #endif @@ -31,7 +32,7 @@ namespace #endif -std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError +std::string sendHttpRequestImpl(const std::wstring& url, //throw SysError const std::wstring& userAgent, const std::string* postParams, //issue POST if bound, GET otherwise int level = 0) @@ -49,7 +50,7 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError nullptr, //_In_ LPCTSTR lpszProxyBypass, 0); //_In_ DWORD dwFlags if (!hInternet) - THROW_LAST_FILE_ERROR(_("Internet access failed."), L"InternetOpen"); + THROW_LAST_SYS_ERROR(L"InternetOpen"); ZEN_ON_SCOPE_EXIT(::InternetCloseHandle(hInternet)); HINTERNET hSession = ::InternetConnect(hInternet, //_In_ HINTERNET hInternet, @@ -61,16 +62,28 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError 0, //_In_ DWORD dwFlags, 0); //_In_ DWORD_PTR dwContext if (!hSession) - THROW_LAST_FILE_ERROR(_("Internet access failed."), L"InternetConnect"); + THROW_LAST_SYS_ERROR(L"InternetConnect"); ZEN_ON_SCOPE_EXIT(::InternetCloseHandle(hSession)); const wchar_t* acceptTypes[] = { L"*/*", nullptr }; - DWORD requestFlags = INTERNET_FLAG_KEEP_CONNECTION | - INTERNET_FLAG_NO_UI | - INTERNET_FLAG_RELOAD | // - INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS; //relevant for GET only + DWORD requestFlags = + //INTERNET_FLAG_KEEP_CONNECTION | + // the combination 1. INTERNET_FLAG_KEEP_CONNECTION (= adds "Connection: Keep-Alive" but NOT "Keep-Alive: timeout" to the header) + // 2. *no* "Keep-Alive: timeout" header entry 3. call from within VM and 4. *no* Fiddler running 5. HTTP POST + // leads to Godaddy blocking the IP: http://www.freefilesync.org/forum/viewtopic.php?t=3855 + // => it seems a broken keep alive header is the trigger: But why is it then working outside the VM or when Fiddler is running??? Why not a problem for HTTP GET? + // note: HTTP/1.1 has keep-alive semantics by default, so this flag is probably useless anyway + INTERNET_FLAG_NO_UI; + if (postParams) - requestFlags |= INTERNET_FLAG_NO_AUTO_REDIRECT; //POST would be re-issued as GET during auto-redirect => handle ourselves! + { + requestFlags |= INTERNET_FLAG_NO_AUTO_REDIRECT; //POST would be re-issued as GET during auto-redirect => handle ourselves! + } + else //HTTP GET + { + requestFlags |= INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP; + requestFlags |= INTERNET_FLAG_RELOAD; //not relevant for POST (= never cached) + } HINTERNET hRequest = ::HttpOpenRequest(hSession, //_In_ HINTERNET hConnect, postParams ? L"POST" : L"GET", //_In_ LPCTSTR lpszVerb, @@ -81,18 +94,22 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError requestFlags, //_In_ DWORD dwFlags, 0); //_In_ DWORD_PTR dwContext if (!hRequest) - THROW_LAST_FILE_ERROR(_("Internet access failed."), L"HttpOpenRequest"); + THROW_LAST_SYS_ERROR(L"HttpOpenRequest"); ZEN_ON_SCOPE_EXIT(::InternetCloseHandle(hRequest)); - const std::wstring headers = postParams ? L"Content-type: application/x-www-form-urlencoded" : L""; - std::string postParamsTmp = postParams ? *postParams : ""; - char* postParamBuf = postParamsTmp.empty() ? nullptr : &*postParamsTmp.begin(); + const std::wstring headers = postParams ? L"Content-type: application/x-www-form-urlencoded" : L""; + + assert(std::all_of(headers.begin(), headers.end(), [](wchar_t c){ return makeUnsigned(c) < 128; })); + //HttpSendRequest has finicky behavior for non-ASCII headers: https://msdn.microsoft.com/en-us/library/windows/desktop/aa384247 + + std::string postParamsBuf = postParams ? *postParams : ""; + if (!::HttpSendRequest(hRequest, //_In_ HINTERNET hRequest, headers.c_str(), //_In_ LPCTSTR lpszHeaders, - static_cast<DWORD>(headers.size()), //_In_ DWORD dwHeadersLength, - postParamBuf, //_In_ LPVOID lpOptional, - static_cast<DWORD>(postParamsTmp.size()))) //_In_ DWORD dwOptionalLength - THROW_LAST_FILE_ERROR(_("Internet access failed."), L"HttpSendRequest"); + static_cast<DWORD>(headers.size()), //_In_ DWORD dwHeadersLength, + postParamsBuf.empty() ? nullptr : &postParamsBuf[0], //_In_ LPVOID lpOptional, + static_cast<DWORD>(postParamsBuf.size()))) //_In_ DWORD dwOptionalLength + THROW_LAST_SYS_ERROR(L"HttpSendRequest"); DWORD sc = 0; { @@ -102,7 +119,7 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError &sc, //_Inout_ LPVOID lpvBuffer, &bufLen, //_Inout_ LPDWORD lpdwBufferLength, nullptr)) //_Inout_ LPDWORD lpdwIndex - THROW_LAST_FILE_ERROR(_("Internet access failed."), L"HttpQueryInfo: HTTP_QUERY_STATUS_CODE"); + THROW_LAST_SYS_ERROR(L"HttpQueryInfo: HTTP_QUERY_STATUS_CODE"); } //http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_Redirection @@ -113,19 +130,19 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError DWORD bufLen = 10000; std::wstring location(bufLen, L'\0'); if (!::HttpQueryInfo(hRequest, HTTP_QUERY_LOCATION, &*location.begin(), &bufLen, nullptr)) - THROW_LAST_FILE_ERROR(_("Internet access failed."), L"HttpQueryInfo: HTTP_QUERY_LOCATION"); + THROW_LAST_SYS_ERROR(L"HttpQueryInfo: HTTP_QUERY_LOCATION"); if (bufLen >= location.size()) //HttpQueryInfo expected to write terminating zero - throw FileError(_("Internet access failed."), L"HttpQueryInfo: HTTP_QUERY_LOCATION, buffer overflow"); + throw SysError(L"HttpQueryInfo: HTTP_QUERY_LOCATION, buffer overflow"); location.resize(bufLen); if (!location.empty()) return sendHttpRequestImpl(location, userAgent, postParams, level + 1); } - throw FileError(_("Internet access failed."), L"Unresolvable redirect."); + throw SysError(L"Unresolvable redirect."); } if (sc != HTTP_STATUS_OK) //200 - throw FileError(_("Internet access failed."), replaceCpy<std::wstring>(L"HTTP status code %x.", L"%x", numberTo<std::wstring>(sc))); + throw SysError(replaceCpy<std::wstring>(L"HTTP status code %x.", L"%x", numberTo<std::wstring>(sc))); //e.g. 404 - HTTP_STATUS_NOT_FOUND std::string buffer; @@ -140,10 +157,10 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError &*(buffer.begin() + buffer.size() - blockSize), //_Out_ LPVOID lpBuffer, blockSize, //_In_ DWORD dwNumberOfBytesToRead, &bytesRead)) //_Out_ LPDWORD lpdwNumberOfBytesRead - THROW_LAST_FILE_ERROR(_("Internet access failed."), L"InternetReadFile"); + THROW_LAST_SYS_ERROR(L"InternetReadFile"); if (bytesRead > blockSize) //better safe than sorry - throw FileError(_("Internet access failed."), L"InternetReadFile: buffer overflow."); + throw SysError(L"InternetReadFile: buffer overflow."); if (bytesRead < blockSize) buffer.resize(buffer.size() - (blockSize - bytesRead)); //caveat: unsigned arithmetics @@ -161,11 +178,11 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError webAccess.SetTimeout(10 /*[s]*/); //default: 10 minutes: WTF are these wxWidgets people thinking??? if (!webAccess.Connect(server)) //will *not* fail for non-reachable url here! - throw FileError(_("Internet access failed."), L"wxHTTP::Connect"); + throw SysError(L"wxHTTP::Connect"); if (postParams) if (!webAccess.SetPostText(L"application/x-www-form-urlencoded", utfCvrtTo<wxString>(*postParams))) - throw FileError(_("Internet access failed."), L"wxHTTP::SetPostText"); + throw SysError(L"wxHTTP::SetPostText"); std::unique_ptr<wxInputStream> httpStream(webAccess.GetInputStream(page)); //must be deleted BEFORE webAccess is closed const int sc = webAccess.GetResponse(); @@ -179,14 +196,14 @@ std::string sendHttpRequestImpl(const std::wstring& url, //throw FileError if (!newUrl.empty()) return sendHttpRequestImpl(newUrl, userAgent, postParams, level + 1); } - throw FileError(_("Internet access failed."), L"Unresolvable redirect."); + throw SysError(L"Unresolvable redirect."); } if (sc != 200) //HTTP_STATUS_OK - throw FileError(_("Internet access failed."), replaceCpy<std::wstring>(L"HTTP status code %x.", L"%x", numberTo<std::wstring>(sc))); + throw SysError(replaceCpy<std::wstring>(L"HTTP status code %x.", L"%x", numberTo<std::wstring>(sc))); if (!httpStream || webAccess.GetError() != wxPROTO_NOERR) - throw FileError(_("Internet access failed."), L"wxHTTP::GetError"); + throw SysError(L"wxHTTP::GetError"); std::string buffer; int newValue = 0; @@ -221,7 +238,7 @@ std::string urlencode(const std::string& str) } -std::string zen::sendHttpPost(const std::wstring& url, const std::wstring& userAgent, const std::vector<std::pair<std::string, std::string>>& postParams) //throw FileError +std::string zen::sendHttpPost(const std::wstring& url, const std::wstring& userAgent, const std::vector<std::pair<std::string, std::string>>& postParams) //throw SysError { //convert post parameters into "application/x-www-form-urlencoded" std::string flatParams; @@ -231,13 +248,13 @@ std::string zen::sendHttpPost(const std::wstring& url, const std::wstring& userA if (!flatParams.empty()) flatParams.pop_back(); - return sendHttpRequestImpl(url, userAgent, &flatParams); //throw FileError + return sendHttpRequestImpl(url, userAgent, &flatParams); //throw SysError } -std::string zen::sendHttpGet(const std::wstring& url, const std::wstring& userAgent) //throw FileError +std::string zen::sendHttpGet(const std::wstring& url, const std::wstring& userAgent) //throw SysError { - return sendHttpRequestImpl(url, userAgent, nullptr); //throw FileError + return sendHttpRequestImpl(url, userAgent, nullptr); //throw SysError } |