Index: net/wininet.cc |
diff --git a/net/wininet.cc b/net/wininet.cc |
deleted file mode 100644 |
index 7182ab35bb042b12c3a8b74f579e2421f6ef477a..0000000000000000000000000000000000000000 |
--- a/net/wininet.cc |
+++ /dev/null |
@@ -1,1541 +0,0 @@ |
-// Copyright 2004-2009 Google Inc. |
-// |
-// Licensed under the Apache License, Version 2.0 (the "License"); |
-// you may not use this file except in compliance with the License. |
-// You may obtain a copy of the License at |
-// |
-// http://www.apache.org/licenses/LICENSE-2.0 |
-// |
-// Unless required by applicable law or agreed to in writing, software |
-// distributed under the License is distributed on an "AS IS" BASIS, |
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-// See the License for the specific language governing permissions and |
-// limitations under the License. |
-// ======================================================================== |
- |
-#include <windows.h> |
-#include <wininet.h> |
-#include <atlstr.h> |
-#include <vector> // NOLINT |
- |
-#include "omaha/net/http_client.h" |
- |
-#include "base/scoped_ptr.h" |
-#include "omaha/base/atl_regexp.h" |
-#include "omaha/base/debug.h" |
-#include "omaha/base/logging.h" |
-#include "omaha/base/scoped_any.h" |
-#include "omaha/base/string.h" |
-#include "omaha/base/synchronized.h" |
-#include "omaha/base/utils.h" |
- |
-namespace omaha { |
- |
-class WinInet : public HttpClient { |
- public: |
- static HttpClient* Create() { return new WinInet; } |
- |
- virtual HRESULT Initialize(); |
- |
- virtual HRESULT Open(const TCHAR* user_agent, |
- uint32 access_type, |
- const TCHAR* proxy_name, |
- const TCHAR* proxy_bypass); |
- |
- virtual HRESULT Close(); |
- |
- virtual HRESULT Connect(const TCHAR* server, int port); |
- |
- virtual HRESULT OpenRequest(const TCHAR* verb, |
- const TCHAR* uri, |
- const TCHAR* version, |
- const TCHAR* referrer, |
- const TCHAR** accept_types, |
- uint32 flags); |
- |
- virtual HRESULT SendRequest(const TCHAR* headers, |
- int headers_length, |
- const void* optional_data, |
- size_t optional_data_length, |
- size_t content_length); |
- |
- virtual HRESULT SetTimeouts(int resolve_timeout_ms, |
- int connect_timeout_ms, |
- int send_timeout_ms, |
- int receive_timeout_ms); |
- |
- virtual HRESULT ReceiveResponse(); |
- |
- virtual HRESULT QueryDataAvailable(int* num_bytes); |
- |
- virtual HRESULT ReadData(std::vector<uint8>* data); |
- |
- virtual HRESULT WriteData(const std::vector<uint8>& data, int* bytes_written); |
- |
- virtual HRESULT SetCredentials(uint32 auth_targets, |
- uint32 auth_scheme, |
- const TCHAR* user_name, |
- const TCHAR* password); |
- |
- virtual HRESULT DetectAutoProxyConfigUrl(uint32 flags, |
- CString* auto_config_url); |
- |
- virtual HRESULT GetDefaultProxyConfiguration(ProxyInfo* proxy_info); |
- |
- virtual HRESULT SetDefaultProxyConfiguration(const ProxyInfo& proxy_info); |
- |
- virtual HRESULT GetIEProxyConfiguration(CurrentUserIEProxyConfig* proxy_info); |
- |
- virtual HRESULT GetProxyForUrl(const TCHAR* url, |
- const AutoProxyOptions* auto_proxy_options, |
- ProxyInfo* pProxyInfo); |
- |
- virtual HRESULT QueryAuthSchemes(uint32* supported_schemes, |
- uint32* first_scheme, |
- uint32* auth_target); |
- |
- virtual HRESULT AddRequestHeaders(const TCHAR* headers, |
- int length, |
- uint32 modifiers); |
- |
- virtual HRESULT QueryHeaders(uint32 info_level, |
- const TCHAR* name, |
- CString* value, |
- int* index); |
- virtual HRESULT QueryHeaders(uint32 info_level, |
- const TCHAR* name, |
- int* value, |
- int* index); |
- |
- virtual HRESULT QueryOption(bool is_session_option, |
- uint32 option, |
- std::vector<uint8>* val); |
- |
- virtual HRESULT QueryOptionString(bool is_session_option, |
- uint32 option, |
- CString* value); |
- |
- virtual HRESULT QueryOptionInt(bool is_session_option, |
- uint32 option, |
- int* value); |
- |
- virtual HRESULT SetOption(bool is_session_option, |
- uint32 option, |
- const void* buffer, |
- size_t buffer_length); |
- |
- virtual HRESULT SetOption(bool is_session_option, |
- uint32 option, |
- const std::vector<uint8>* val); |
- |
- virtual HRESULT SetOptionString(bool is_session_option, |
- uint32 option, |
- const TCHAR* value); |
- |
- virtual HRESULT SetOptionInt(bool is_session_option, |
- uint32 option, |
- int value); |
- |
- virtual HRESULT CrackUrl(const TCHAR* url, |
- uint32 flags, |
- CString* scheme, |
- CString* server, |
- int* port, |
- CString* url_path, |
- CString* extra_info); |
- |
- virtual HRESULT CreateUrl(const TCHAR* scheme, |
- const TCHAR* server, |
- int port, |
- const TCHAR* url_path, |
- const TCHAR* extra_info, |
- uint32 flags, |
- CString* url); |
- |
- |
- typedef void (*StatusCallback)(uint32 context, |
- int status, |
- void* status_information, |
- size_t status_info_length); |
- virtual StatusCallback SetStatusCallback(StatusCallback callback, |
- uint32 flags); |
- private: |
- WinInet(); |
- DISALLOW_EVIL_CONSTRUCTORS(WinInet); |
-}; |
- |
- |
-// TODO(omaha): remove after the implementation is complete. |
-// 4100: unreferenced formal parameter |
-#pragma warning(disable : 4100) |
- |
-WinInet::WinInet() { |
-} |
- |
-HRESULT WinInet::Initialize() { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::Open(const TCHAR* user_agent, |
- uint32 access_type, |
- const TCHAR* proxy_name, |
- const TCHAR* proxy_bypass) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::Close() { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::Connect(const TCHAR* server, int port) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::OpenRequest(const TCHAR* verb, |
- const TCHAR* uri, |
- const TCHAR* version, |
- const TCHAR* referrer, |
- const TCHAR** accept_types, |
- uint32 flags) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::SendRequest(const TCHAR* headers, |
- int headers_length, |
- const void* optional_data, |
- size_t optional_data_length, |
- size_t content_length) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::SetTimeouts(int resolve_timeout_ms, |
- int connect_timeout_ms, |
- int send_timeout_ms, |
- int receive_timeout_ms) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::ReceiveResponse() { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::QueryDataAvailable(int* num_bytes) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::ReadData(std::vector<uint8>* data) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::WriteData(const std::vector<uint8>& data, int* bytes_written) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::SetCredentials(uint32 auth_targets, |
- uint32 auth_scheme, |
- const TCHAR* user_name, |
- const TCHAR* password) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::DetectAutoProxyConfigUrl(uint32 flags, |
- CString* auto_config_url) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::GetDefaultProxyConfiguration(ProxyInfo* proxy_info) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::SetDefaultProxyConfiguration(const ProxyInfo& proxy_info) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::GetIEProxyConfiguration(CurrentUserIEProxyConfig* proxy_info) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::GetProxyForUrl(const TCHAR* url, |
- const AutoProxyOptions* auto_proxy_options, |
- ProxyInfo* pProxyInfo) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::QueryAuthSchemes(uint32* supported_schemes, |
- uint32* first_scheme, |
- uint32* auth_target) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::AddRequestHeaders(const TCHAR* headers, |
- int length, |
- uint32 modifiers) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::QueryHeaders(uint32 info_level, |
- const TCHAR* name, |
- CString* value, |
- int* index) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::QueryHeaders(uint32 info_level, |
- const TCHAR* name, |
- int* value, |
- int* index) { |
- return E_NOTIMPL; |
-} |
- |
- |
-HRESULT WinInet::QueryOption(bool is_session_option, |
- uint32 option, |
- std::vector<uint8>* val) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::QueryOptionString(bool is_session_option, |
- uint32 option, |
- CString* value) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::QueryOptionInt(bool is_session_option, |
- uint32 option, |
- int* value) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::SetOption(bool is_session_option, |
- uint32 option, |
- const void* buffer, |
- size_t buffer_length) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::SetOption(bool is_session_option, |
- uint32 option, |
- const std::vector<uint8>* val) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::SetOptionString(bool is_session_option, |
- uint32 option, |
- const TCHAR* value) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::SetOptionInt(bool is_session_option, |
- uint32 option, |
- int value) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::CrackUrl(const TCHAR* url, |
- uint32 flags, |
- CString* scheme, |
- CString* server, |
- int* port, |
- CString* url_path, |
- CString* extra_info) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT WinInet::CreateUrl(const TCHAR* scheme, |
- const TCHAR* server, |
- int port, |
- const TCHAR* url_path, |
- const TCHAR* extra_info, |
- uint32 flags, |
- CString* url) { |
- return E_NOTIMPL; |
-} |
- |
-HttpClient::StatusCallback WinInet::SetStatusCallback( |
- HttpClient::StatusCallback callback, |
- uint32 flags) { |
- return NULL; |
-} |
- |
-extern "C" const bool kRegisterWinInet = |
- HttpClient::GetFactory().Register(HttpClient::WININET, &WinInet::Create); |
- |
- |
-} // namespace omaha |
- |
-#if 0 |
-// Constants |
-const uint32 kInternetRequestCachingDefaultFlags = INTERNET_FLAG_NO_UI | |
- INTERNET_FLAG_NO_COOKIES; |
-const uint32 kInternetRequestNoCacheDefaultFlags = |
- INTERNET_FLAG_NO_UI | |
- INTERNET_FLAG_NO_COOKIES | |
- INTERNET_FLAG_NO_CACHE_WRITE | |
- INTERNET_FLAG_PRAGMA_NOCACHE | |
- INTERNET_FLAG_RELOAD; |
-const TCHAR kProxyAuthenticateHeader[] = _T("Proxy-Authenticate:"); |
-const TCHAR kNegotiateAuthScheme[] = _T("Negotiate"); |
-const TCHAR kNTLMAuthScheme[] = _T("NTLM"); |
-const TCHAR kDigestAuthScheme[] = _T("Digest"); |
-const TCHAR kBasicAuthScheme[] = _T("Basic"); |
- |
-// Provides dynamic loading of WinInet.dll |
-// |
-// Delay loading wininet.dll would be nice but would (tediously) involve |
-// modifying the mk_file for all DLLs/EXEs that use any of the functions that |
-// use InetGet. Which is all of them (since it is used in debug.cpp). So |
-// instead, we do it the old-fashioned way. |
-// |
-// N.B.: When WinInetVTable has been Load()ed, the wininet.dll is loaded - |
-// which adds significantly to the working set of your process. So beware of |
-// loading the WinInetVTable and leaving it loaded, esp. if you have a static |
-// instance of WinInetVTable. And on the other hand, the load/unload operation |
-// is expensive (slow) so you want to reuse your Load()ed WinInetVTable if |
-// you're going to be needing it frequently. Note that that cost is in the |
-// loading/unloading of the DLL, thus 'nested' uses (which only need to 'snap' |
-// the links) are cheap. |
-class WinInetVTable { |
- public: |
- // Functions are simply reflected through data members holding function |
- // pointers, taking advantage of C-syntax (you can call indirectly through a |
- // function pointer without a '*'). No error checking is done: call through |
- // only when Loaded() == true. |
- BOOL HttpAddRequestHeaders(HINTERNET, const TCHAR*, DWORD, DWORD); |
- BOOL HttpEndRequest(HINTERNET, LPINTERNET_BUFFERS, DWORD, DWORD_PTR); |
- HINTERNET HttpOpenRequest(HINTERNET, |
- const TCHAR*, |
- const TCHAR*, |
- const TCHAR*, |
- const TCHAR*, |
- const TCHAR**, |
- DWORD, |
- DWORD_PTR); |
- BOOL HttpQueryInfo(HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD); |
- BOOL HttpSendRequestEx(HINTERNET, |
- LPINTERNET_BUFFERS, |
- LPINTERNET_BUFFERS, |
- DWORD, |
- DWORD_PTR); |
- BOOL HttpSendRequest(HINTERNET, const TCHAR*, DWORD, LPVOID, DWORD); |
- BOOL InternetCloseHandle(HINTERNET); |
- HINTERNET InternetConnect(HINTERNET, |
- const TCHAR*, |
- INTERNET_PORT, |
- const TCHAR*, |
- const TCHAR*, |
- DWORD, |
- DWORD, |
- DWORD); |
- BOOL InternetGetConnectedStateEx(LPDWORD, char*, DWORD, DWORD); |
- HINTERNET InternetOpen(const TCHAR*, |
- DWORD, |
- const TCHAR*, |
- const TCHAR*, |
- DWORD); |
- HINTERNET InternetOpenUrl(HINTERNET, |
- const TCHAR*, |
- const TCHAR*, |
- DWORD, |
- DWORD, |
- DWORD_PTR); |
- BOOL InternetQueryDataAvailable(HINTERNET, LPDWORD, DWORD, DWORD); |
- BOOL InternetReadFile(HINTERNET, LPVOID, DWORD, LPDWORD); |
- HINTERNET InternetReadFileEx(HINTERNET, LPINTERNET_BUFFERS, DWORD, DWORD_PTR); |
- BOOL InternetGetCookie(const TCHAR*, const TCHAR*, TCHAR*, LPDWORD); |
- BOOL InternetSetCookie(const TCHAR*, const TCHAR*, const TCHAR*); |
- BOOL InternetAutodial(DWORD, HWND); |
- BOOL InternetAutodialHangup(DWORD); |
- BOOL InternetQueryOption(HINTERNET hInternet, |
- DWORD dwOption, |
- LPVOID lpBuffer, |
- LPDWORD lpdwBufferLength); |
- BOOL InternetSetOption(HINTERNET hInternet, |
- DWORD dwOption, |
- LPVOID lpBuffer, |
- DWORD dwBufferLength); |
- BOOL InternetCheckConnection(const TCHAR*, |
- DWORD, DWORD); |
- BOOL InternetCrackUrl(const TCHAR*, |
- DWORD, |
- DWORD, |
- LPURL_COMPONENTS); |
- INTERNET_STATUS_CALLBACK InternetSetStatusCallback(HINTERNET, INTERNET_STATUS_CALLBACK); |
- |
- WinInetVTable(); |
- ~WinInetVTable(); |
- |
- bool Load(); // Load library, snap links |
- void Unload(); // Unload library, clear links |
- |
- bool Loaded() { return NULL != library_; } |
- |
- protected: |
- BOOL (CALLBACK *HttpAddRequestHeaders_pointer)(HINTERNET, const TCHAR*, DWORD, DWORD); |
- BOOL (CALLBACK *HttpEndRequest_pointer)(HINTERNET, LPINTERNET_BUFFERS, DWORD, DWORD_PTR); |
- HINTERNET (CALLBACK *HttpOpenRequest_pointer)(HINTERNET, const TCHAR*, const TCHAR*, const TCHAR*, const TCHAR*, const TCHAR**, DWORD, DWORD_PTR); |
- BOOL (CALLBACK *HttpQueryInfo_pointer)(HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD); |
- BOOL (CALLBACK *HttpSendRequestEx_pointer)(HINTERNET, LPINTERNET_BUFFERS, LPINTERNET_BUFFERS, DWORD, DWORD_PTR); |
- BOOL (CALLBACK *HttpSendRequest_pointer)(HINTERNET, const TCHAR*, DWORD, LPVOID, DWORD); |
- BOOL (CALLBACK *InternetCloseHandle_pointer)(HINTERNET); |
- HINTERNET (CALLBACK *InternetConnect_pointer)(HINTERNET, const TCHAR*, INTERNET_PORT, const TCHAR*, const TCHAR*, DWORD, DWORD, DWORD); |
- BOOL (CALLBACK *InternetGetConnectedStateEx_pointer)(LPDWORD, char*, DWORD, DWORD); |
- HINTERNET (CALLBACK *InternetOpen_pointer)(const TCHAR*, DWORD, const TCHAR*, const TCHAR*, DWORD); |
- HINTERNET (CALLBACK *InternetOpenUrl_pointer)(HINTERNET, const TCHAR*, const TCHAR*, DWORD, DWORD, DWORD_PTR); |
- BOOL (CALLBACK *InternetQueryDataAvailable_pointer)(HINTERNET, LPDWORD, DWORD, DWORD); |
- BOOL (CALLBACK *InternetReadFile_pointer)(HINTERNET, LPVOID, DWORD, LPDWORD); |
- HINTERNET (CALLBACK *InternetReadFileEx_pointer)(HINTERNET, LPINTERNET_BUFFERS, DWORD, DWORD_PTR); |
- BOOL (CALLBACK *InternetGetCookie_pointer)(const TCHAR*, const TCHAR*, TCHAR*, LPDWORD); |
- BOOL (CALLBACK *InternetSetCookie_pointer)(const TCHAR*, const TCHAR*, const TCHAR*); |
- BOOL (CALLBACK *InternetAutodial_pointer)(DWORD, HWND); |
- BOOL (CALLBACK *InternetAutodialHangup_pointer)(DWORD); |
- BOOL (CALLBACK *InternetQueryOption_pointer)(HINTERNET hInternet, DWORD dwOption, LPVOID lpBuffer, LPDWORD lpdwBufferLength); |
- BOOL (CALLBACK *InternetSetOption_pointer)(HINTERNET hInternet, DWORD dwOption, LPVOID lpBuffer, DWORD dwBufferLength); |
- BOOL (CALLBACK *InternetCheckConnection_pointer)(const TCHAR*, DWORD, DWORD); |
- BOOL (CALLBACK *InternetCrackUrl_pointer)(const TCHAR*, DWORD, DWORD, LPURL_COMPONENTS); |
- INTERNET_STATUS_CALLBACK (CALLBACK *InternetSetStatusCallback_pointer)(HINTERNET, INTERNET_STATUS_CALLBACK); |
- |
- HINSTANCE library_; |
- |
- void Clear(); |
- |
- // Simple wrapper around GetProcAddress() |
- template <typename T> |
- bool GPA(const char* function_name, T& function_pointer); // NO LINT |
- |
- private: |
- DISALLOW_EVIL_CONSTRUCTORS(WinInetVTable); |
-}; |
- |
- |
-class InetHttpClient : public HttpClient { |
- public: |
- static InetHttpClient* Create(); |
- virtual ~InetHttpClient(); |
- virtual HRESULT Abort(); |
- virtual uint32 GetStatus(); |
- virtual HRESULT GetResponseHeader(const TCHAR* name, CString* value); |
- virtual HRESULT GetAllResponseHeaders(CString* response_headers); |
- virtual HRESULT GetResponseText(CString* response_text, uint32 max_size); |
- virtual HRESULT GetRawResponseBody(std::vector<byte>* response_body, |
- uint32 max_size); |
- virtual HRESULT SaveRawResponseBody(const TCHAR* response_filename, |
- uint32 max_size); |
- virtual HRESULT QueryProxyAuthScheme(AuthScheme* auth_scheme); |
- virtual HRESULT GetAutoProxyForUrl(const TCHAR* url, CString* proxy); |
- virtual HRESULT GetDefaultProxyConfiguration(AccessType* access_type, |
- CString* proxy, |
- CString* proxy_bypass); |
- protected: |
- virtual HRESULT InternalCrackUrl(const CString& url, |
- bool to_escape, |
- URL_COMPONENTS* url_components); |
- virtual HRESULT SendRequest(const TCHAR* server, |
- uint32 port, |
- const TCHAR* path); |
- virtual bool CheckConnection(); |
- private: |
- InetHttpClient(); |
- HRESULT Init(); |
- void Close(); |
- HRESULT SetTimeouts(); |
- HRESULT SetHttpProxyCredentials(const TCHAR* username, const TCHAR* password); |
- HRESULT SkipSSLCertErrorIfNeeded(); |
- HRESULT InternalSend(const TCHAR* server, |
- uint32 port, |
- const TCHAR* path, |
- bool use_proxy); |
- HRESULT InternalGetRawResponseBody(std::vector<byte>* response_body, |
- const TCHAR* response_filename, |
- uint32 max_size); |
- static void CALLBACK StatusCallback(HINTERNET handle, |
- DWORD_PTR context, |
- DWORD status, |
- void* info, |
- DWORD info_len); |
- |
- WinInetVTable wininet_; |
- HINTERNET session_handle_; |
- HINTERNET connection_handle_; |
- HINTERNET request_handle_; |
- uint32 status_; |
- bool is_initialized_; |
- bool is_aborted_; |
- LLock lock_; |
- |
- // Parses the header "Proxy-Authenticate:" |
- static AtlRE proxy_auth_header_regex_; |
- |
- DISALLOW_EVIL_CONSTRUCTORS(InetHttpClient); |
-}; |
- |
-AtlRE InetHttpClient::proxy_auth_header_regex_( |
- _T("\\n*Proxy\\-Authenticate\\:\\b*{\\w}\\n*"), false); |
- |
-HttpClient* CreateInetHttpClient() { |
- return InetHttpClient::Create(); |
-} |
- |
-InetHttpClient* InetHttpClient::Create() { |
- scoped_ptr<InetHttpClient> http_client(new InetHttpClient()); |
- if (http_client.get()) { |
- if (SUCCEEDED(http_client->Init())) { |
- return http_client.release(); |
- } |
- } |
- return NULL; |
-} |
- |
-InetHttpClient::InetHttpClient() |
- : session_handle_(NULL), |
- connection_handle_(NULL), |
- request_handle_(NULL), |
- status_(0), |
- is_initialized_(false), |
- is_aborted_(false) { |
-} |
- |
-InetHttpClient::~InetHttpClient() { |
- Close(); |
- wininet_.Unload(); |
-} |
- |
-HRESULT InetHttpClient::Abort() { |
- UTIL_LOG(L6, (_T("[InetHttpClient::Abort]"))); |
- |
- is_aborted_ = true; |
- Close(); |
- return S_OK; |
-} |
- |
-void InetHttpClient::Close() { |
- // Closing the handles will unblock all WinInet calls unless a call is |
- // waiting for DNS lookup, or in other words, when the state is where |
- // between INTERNET_STATUS_RESOLVING_NAME and INTERNET_STATUS_NAME_RESOLVED. |
- // In that case, closing the handles does not have any effect. |
- // This is also the case even we use async WinInet calls. |
- |
- __mutexScope(lock_); |
- |
- if (request_handle_) { |
- wininet_.InternetCloseHandle(request_handle_); |
- request_handle_ = NULL; |
- } |
- |
- if (connection_handle_) { |
- wininet_.InternetCloseHandle(connection_handle_); |
- connection_handle_ = NULL; |
- } |
- |
- if (session_handle_) { |
- wininet_.InternetCloseHandle(session_handle_); |
- session_handle_ = NULL; |
- } |
-} |
- |
-HRESULT InetHttpClient::Init() { |
- if (is_initialized_) { |
- return E_UNEXPECTED; |
- } |
- |
- is_initialized_ = true; |
- |
- if (!wininet_.Load()) { |
- HRESULT hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[Failed to load wininet][0x%08x]"), hr)); |
- return hr; |
- } |
- |
- return S_OK; |
-} |
- |
-HRESULT InetHttpClient::SetTimeouts() { |
- ASSERT1(session_handle_); |
- |
- uint32 connect_timeout_ms = connect_timeout_ms_; |
- uint32 send_timeout_ms = send_timeout_ms_; |
- uint32 receive_timeout_ms = receive_timeout_ms_; |
-#if DEBUG |
- ConfigProfile::GetValue(kServerSettings, |
- kConfigConnectTimeoutMs, |
- &connect_timeout_ms); |
- ConfigProfile::GetValue(kServerSettings, |
- kConfigSendTimeoutMs, |
- &send_timeout_ms); |
- ConfigProfile::GetValue(kServerSettings, |
- kConfigReceiveTimeoutMs, |
- &receive_timeout_ms); |
-#endif |
- if (connect_timeout_ms || send_timeout_ms || receive_timeout_ms) { |
- if (!wininet_.InternetSetOption(session_handle_, |
- INTERNET_OPTION_CONNECT_TIMEOUT, |
- &connect_timeout_ms, |
- sizeof(connect_timeout_ms))) { |
- UTIL_LOG(LEVEL_ERROR, (_T("[Failed to set connection timeout]") |
- _T("[0x%08x]"), HRESULTFromLastError())); |
- } |
- if (!wininet_.InternetSetOption(session_handle_, |
- INTERNET_OPTION_SEND_TIMEOUT, |
- &send_timeout_ms, |
- sizeof(send_timeout_ms))) { |
- UTIL_LOG(LEVEL_ERROR, (_T("[Failed to set send timeout]") |
- _T("[0x%08x]"), HRESULTFromLastError())); |
- } |
- if (!wininet_.InternetSetOption(session_handle_, |
- INTERNET_OPTION_RECEIVE_TIMEOUT, |
- &receive_timeout_ms, |
- sizeof(receive_timeout_ms))) { |
- UTIL_LOG(LEVEL_ERROR, (_T("[Failed to set receive timeout]") |
- _T("[0x%08x]"), HRESULTFromLastError())); |
- } |
- } |
- return S_OK; |
-} |
- |
-HRESULT InetHttpClient::SetHttpProxyCredentials(const TCHAR* username, |
- const TCHAR* password) { |
- ASSERT1(connection_handle_); |
- |
- if (username && *username && password && *password) { |
- if (!wininet_.InternetSetOption(connection_handle_, |
- INTERNET_OPTION_PROXY_USERNAME, |
- const_cast<TCHAR*>(username), |
- _tcslen(username))) { |
- UTIL_LOG(LEVEL_ERROR, (_T("[Failed to set proxy authentication username]") |
- _T("[0x%08x]"), HRESULTFromLastError())); |
- } |
- if (!wininet_.InternetSetOption(connection_handle_, |
- INTERNET_OPTION_PROXY_PASSWORD, |
- const_cast<TCHAR*>(password), |
- _tcslen(password))) { |
- UTIL_LOG(LEVEL_ERROR, (_T("[Failed to set proxy authentication password]") |
- _T("[0x%08x]"), HRESULTFromLastError())); |
- } |
- } |
- return S_OK; |
-} |
- |
-HRESULT InetHttpClient::SkipSSLCertErrorIfNeeded() { |
-#if DEBUG |
- ASSERT1(request_handle_); |
- |
- bool ignore_certificate_errors = false; |
- ConfigProfile::GetValue(kServerSettings, |
- kConfigSecurityIgnoreCertificateErrors, |
- &ignore_certificate_errors); |
- if (ignore_certificate_errors) { |
- UTIL_LOG(L6, (_T("[InetHttpClient::SkipSSLCertErrorIfNeeded]") |
- _T("[ignore certificate error]"))); |
- DWORD flags = 0; |
- DWORD flags_len = sizeof(flags); |
- if (wininet_.InternetQueryOption(request_handle_, |
- INTERNET_OPTION_SECURITY_FLAGS, |
- &flags, |
- &flags_len)) { |
- flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA | |
- SECURITY_FLAG_IGNORE_CERT_CN_INVALID; |
- if (!wininet_.InternetSetOption(request_handle_, |
- INTERNET_OPTION_SECURITY_FLAGS, |
- &flags, |
- sizeof(flags))) { |
- UTIL_LOG(LEVEL_ERROR, (_T("[Failed to set ignore SSL cert error]") |
- _T("[0x%08x]"), HRESULTFromLastError())); |
- } |
- } else { |
- UTIL_LOG(LEVEL_ERROR, (_T("[InternetQueryOption failed]") |
- _T("[0x%08x]"), HRESULTFromLastError())); |
- } |
- } |
-#endif |
- |
- return S_OK; |
-} |
- |
-HRESULT InetHttpClient::SendRequest(const TCHAR* server, |
- uint32 port, |
- const TCHAR* path) { |
- ASSERT1(server && *server); |
- ASSERT1(path && *path); |
- |
- UTIL_LOG(L6, (_T("[InetHttpClient::SendRequest]") |
- _T("[%s:%u%s]"), server, port, path)); |
- |
- // When we are using WinInet http client, we will encouter auto-dial if the |
- // user sets "Always dial my default connection" in Internet Explorer. |
- // To fix this problem, we will check whether there is an active Internet |
- // connection first. |
- if (!IsMachineConnected()) { |
- return HRESULT_FROM_WIN32(ERROR_INTERNET_CANNOT_CONNECT); |
- } |
- |
- HRESULT hr = S_OK; |
- |
- for (uint32 i = 0; i < 1 + retries_; ++i) { |
- if (i > 0) { |
- ::Sleep(retry_delay_ms_); |
- UTIL_LOG(L6, (_T("[InetHttpClient::SendRequest - retry %u]"), i)); |
- } |
- |
- hr = InternalSend(server, port, path, true); |
- if (retry_without_proxy_ && !proxy_server_.IsEmpty() && |
- (FAILED(hr) || (status_ != HTTP_STATUS_OK && |
- status_ != HTTP_STATUS_NOT_MODIFIED))) { |
- UTIL_LOG(L6, (_T("[failed with proxy]") |
- _T("[%s][%u][0x%08x]"), proxy_server_, hr)); |
- hr = InternalSend(server, port, path, false); |
- if (SUCCEEDED(hr)) { |
- UTIL_LOG(L6, (_T("[switch to direct connection]"))); |
- GetProxyConfig()->SwitchAutoProxyToDirectConnection(); |
- } |
- } |
- if (SUCCEEDED(hr)) { |
- break; |
- } |
- } |
- |
- if (FAILED(hr)) { |
- // Convert hresults to be of the CI_E format. |
- // If you need to be aware of another error code, then |
- // add another CI_E_ error to this type of switch statment |
- // in every HttpClient::Send method. |
- // |
- // __HRESULT_FROM_WIN32 will always be a macro where as |
- // HRESULT_FROM_WIN32 can be an inline function. Using HRESULT_FROM_WIN32 |
- // can break the switch statement. |
- // |
- // TODO(omaha): refactor weird switch. |
- switch (hr) { |
- case __HRESULT_FROM_WIN32(ERROR_INTERNET_SEC_CERT_DATE_INVALID): |
- hr = CI_E_HTTPS_CERT_FAILURE; |
- break; |
- } |
- } |
- |
- return hr; |
-} |
- |
-HRESULT InetHttpClient::InternalSend(const TCHAR* server, |
- uint32 port, |
- const TCHAR* path, |
- bool use_proxy) { |
- ASSERT1(server && *server); |
- ASSERT1(path && *path); |
- |
- UTIL_LOG(L6, (_T("[InetHttpClient::InternalSend]") |
- _T("[%s:%u%s][%u]"), server, port, path, use_proxy)); |
- |
- HRESULT hr = S_OK; |
- |
- // Close all handles from previous request. |
- Close(); |
- |
- // Open the Internet session. |
- if (!use_proxy || proxy_server_.IsEmpty()) { |
- session_handle_ = wininet_.InternetOpen(NULL, |
- INTERNET_OPEN_TYPE_DIRECT, |
- NULL, |
- NULL, |
- 0); |
- } else { |
- session_handle_ = wininet_.InternetOpen(NULL, |
- INTERNET_OPEN_TYPE_PROXY, |
- proxy_server_, |
- NULL, |
- 0); |
- } |
- if (!session_handle_) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[InternetOpen failed][0x%08x]"), hr)); |
- return hr; |
- } |
- |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- // Set timeouts. |
- SetTimeouts(); |
- |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- // Connect to the server |
- connection_handle_ = wininet_.InternetConnect( |
- session_handle_, |
- server, |
- static_cast<INTERNET_PORT>(port), |
- NULL, |
- NULL, |
- INTERNET_SERVICE_HTTP, |
- 0, |
- NULL); |
- if (!connection_handle_) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[InternetConnect failed]") |
- _T("[%s:%u%s][0x%08x]"), server, port, path, hr)); |
- return hr; |
- } |
- |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- // Set proxy credentials. |
- if (use_proxy) { |
- SetHttpProxyCredentials(proxy_auth_username_, proxy_auth_password_); |
- } |
- |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- // Prepare the flags. |
- DWORD flags = no_cache_ ? kInternetRequestNoCacheDefaultFlags : |
- kInternetRequestCachingDefaultFlags; |
- if (port == kDefaultSslProxyPort) { |
- flags |= INTERNET_FLAG_SECURE; |
- } |
- |
- // Send the request. A context is required otherwise the callback won't happen |
- // even if the WinInet is used in synchronous mode. |
- DWORD_PTR context = reinterpret_cast<DWORD_PTR>(this); |
- if (post_data_.empty()) { |
- // For GET. |
- request_handle_ = wininet_.HttpOpenRequest(connection_handle_, |
- kHttpGetMethod, |
- path, |
- NULL, |
- NULL, |
- NULL, |
- flags, |
- context); |
- if (!request_handle_) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[HttpOpenRequest failed to open GET request]") |
- _T("[%s:%u%s][0x%08x]"), server, port, path, hr)); |
- return hr; |
- } |
- |
- INTERNET_STATUS_CALLBACK old_callback = |
- wininet_.InternetSetStatusCallback(request_handle_, &StatusCallback); |
- ASSERT1(old_callback == NULL); |
- if (old_callback != INTERNET_INVALID_STATUS_CALLBACK) { |
- UTIL_LOG(L6, (_T("[InternetSetStatusCallback succeeded]") |
- _T("[0x%08x]"), request_handle_)); |
- } else { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_WARNING, (_T("[InternetSetStatusCallback failed]") |
- _T("[%s:%u%s][0x%08x]"), |
- server, port, path, hr)); |
- } |
- |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- if (port == kDefaultSslProxyPort) { |
- SkipSSLCertErrorIfNeeded(); |
- } |
- |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- if (!wininet_.HttpSendRequest(request_handle_, |
- additional_headers_.GetString(), |
- additional_headers_.GetLength(), |
- NULL, |
- 0)) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[HttpSendRequest failed to send GET request]") |
- _T("[%s:%u%s][0x%08x]"), server, port, path, hr)); |
- |
- // Occasionally setting the option to skip SSL certificate error before |
- // sending the request does not work. We have to set it again after |
- // failed to send the request. |
- if (port == kDefaultSslProxyPort) { |
- SkipSSLCertErrorIfNeeded(); |
- if (!wininet_.HttpSendRequest(request_handle_, |
- additional_headers_.GetString(), |
- additional_headers_.GetLength(), |
- NULL, |
- 0)) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[HttpSendRequest failed to resend GET]") |
- _T("[%s:%u%s][0x%08x]"), |
- server, port, path, hr)); |
- } else { |
- hr = S_OK; |
- } |
- } |
- |
- if (FAILED(hr)) { |
- return hr; |
- } |
- } |
- } else { |
- // For post |
- request_handle_ = wininet_.HttpOpenRequest(connection_handle_, |
- kHttpPostMethod, |
- path, |
- NULL, |
- NULL, |
- NULL, |
- flags, |
- context); |
- if (!request_handle_) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[HttpOpenRequest failed to open POST request]") |
- _T("[%s:%u%s][0x%08x]"), server, port, path, hr)); |
- return hr; |
- } |
- |
- INTERNET_STATUS_CALLBACK old_callback = |
- wininet_.InternetSetStatusCallback(request_handle_, StatusCallback); |
- ASSERT1(old_callback == NULL); |
- if (old_callback != INTERNET_INVALID_STATUS_CALLBACK) { |
- UTIL_LOG(L6, (_T("[InternetSetStatusCallback succeeded]") |
- _T("[0x%08x]"), request_handle_)); |
- } else { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_WARNING, (_T("[InternetSetStatusCallback failed]") |
- _T("[%s:%u%s][0x%08x]"), |
- server, port, path, hr)); |
- } |
- |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- SkipSSLCertErrorIfNeeded(); |
- |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- if (!wininet_.HttpSendRequest(request_handle_, |
- additional_headers_.GetString(), |
- additional_headers_.GetLength(), |
- &post_data_.front(), |
- post_data_.size())) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[HttpSendRequest failed to send POST request]") |
- _T("[%s:%u%s][0x%08x]"), server, port, path, hr)); |
- return hr; |
- } |
- } |
- |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- // Get the response status. |
- DWORD value = 0; |
- DWORD value_size = sizeof(value); |
- if (!wininet_.HttpQueryInfo(request_handle_, |
- HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, |
- &value, |
- &value_size, |
- 0)) { |
- HRESULT hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[HttpQueryInfo failed to get status]") |
- _T("[%s:%u%s][0x%08x]"), server, port, path, hr)); |
- return hr; |
- } |
- |
- status_ = static_cast<uint32>(value); |
- return S_OK; |
-} |
- |
-uint32 InetHttpClient::GetStatus() { |
- return status_; |
-} |
- |
-HRESULT InetHttpClient::GetResponseHeader(const TCHAR* name, CString* value) { |
- ASSERT1(name && *name); |
- ASSERT1(value); |
- |
- if (!status_) { |
- return E_FAIL; |
- } |
- |
- HRESULT hr = S_OK; |
- |
- value->SetString(name); |
- TCHAR* buf = value->GetBuffer(); |
- DWORD size = value->GetLength() * sizeof(TCHAR); |
- if (wininet_.HttpQueryInfo(request_handle_, |
- HTTP_QUERY_CUSTOM, |
- buf, |
- &size, |
- 0)) { |
- value->ReleaseBuffer(size / sizeof(TCHAR)); |
- } else { |
- DWORD error = ::GetLastError(); |
- if (error == ERROR_INSUFFICIENT_BUFFER) { |
- buf = value->GetBufferSetLength(size / sizeof(TCHAR)); |
- if (!wininet_.HttpQueryInfo(request_handle_, |
- HTTP_QUERY_CUSTOM, |
- buf, |
- &size, |
- 0)) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[HttpQueryInfo failed][0x%08x]"), hr)); |
- } |
- value->ReleaseBuffer(size / sizeof(TCHAR)); |
- } else { |
- hr = HRESULT_FROM_WIN32(error); |
- UTIL_LOG(LEVEL_ERROR, (_T("[HttpQueryInfo failed][0x%08x]"), hr)); |
- } |
- } |
- |
- return hr; |
-} |
- |
-HRESULT InetHttpClient::GetAllResponseHeaders(CString* response_headers) { |
- ASSERT1(response_headers); |
- ASSERT1(request_handle_); |
- |
- if (!status_) { |
- return E_FAIL; |
- } |
- |
- HRESULT hr = S_OK; |
- |
- DWORD size = 0; |
- if (!wininet_.HttpQueryInfo(request_handle_, |
- HTTP_QUERY_RAW_HEADERS_CRLF, |
- NULL, |
- &size, |
- 0)) { |
- DWORD error = ::GetLastError(); |
- if (error == ERROR_INSUFFICIENT_BUFFER) { |
- TCHAR* buf = response_headers->GetBufferSetLength(size / sizeof(TCHAR)); |
- if (!wininet_.HttpQueryInfo(request_handle_, |
- HTTP_QUERY_RAW_HEADERS_CRLF, |
- buf, |
- &size, |
- 0)) { |
- hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[HttpQueryInfo failed][0x%08x]"), hr)); |
- } |
- response_headers->ReleaseBuffer(size / sizeof(TCHAR)); |
- } else { |
- hr = HRESULT_FROM_WIN32(error); |
- UTIL_LOG(LEVEL_ERROR, (_T("[HttpQueryInfo failed][0x%08x]"), hr)); |
- } |
- } |
- |
- return hr; |
-} |
- |
-HRESULT InetHttpClient::GetResponseText(CString* response_text, |
- uint32 max_size) { |
- ASSERT1(response_text); |
- ASSERT1(request_handle_); |
- |
- if (!status_) { |
- return E_FAIL; |
- } |
- |
- const int kBufferSize = 1024; |
- char buffer[kBufferSize] = {0}; |
- |
- CStringA ansi_response_text; |
- uint32 size = 0; |
- while (true) { |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- DWORD bytes_read = 0; |
- if (wininet_.InternetReadFile(request_handle_, |
- buffer, |
- kBufferSize, |
- &bytes_read) && bytes_read) { |
- size += bytes_read; |
- if (max_size && size > max_size) { |
- return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); |
- } |
- ansi_response_text.Append(buffer, bytes_read); |
- } else { |
- break; |
- } |
- } |
- |
- response_text->SetString(Utf8ToWideChar(ansi_response_text.GetString(), |
- ansi_response_text.GetLength())); |
- |
- return S_OK; |
-} |
- |
-HRESULT InetHttpClient::GetRawResponseBody(std::vector<byte>* response_body, |
- uint32 max_size) { |
- return InternalGetRawResponseBody(response_body, NULL, max_size); |
-} |
- |
-HRESULT InetHttpClient::SaveRawResponseBody(const TCHAR* response_filename, |
- uint32 max_size) { |
- return InternalGetRawResponseBody(NULL, response_filename, max_size); |
-} |
- |
-HRESULT InetHttpClient::InternalGetRawResponseBody( |
- std::vector<byte>* response_body, |
- const TCHAR* response_filename, |
- uint32 max_size) { |
- ASSERT((response_body != NULL) ^ (response_filename != NULL), (_T(""))); |
- ASSERT1(request_handle_); |
- |
- if (!status_) { |
- return E_FAIL; |
- } |
- |
- HRESULT hr = S_OK; |
- scoped_hfile file; |
- |
- if (response_body) { |
- response_body->clear(); |
- } else { |
- reset(file, ::CreateFile(response_filename, |
- FILE_WRITE_DATA, |
- 0, |
- NULL, |
- CREATE_ALWAYS, |
- 0, |
- NULL)); |
- if (!file) { |
- return HRESULTFromLastError(); |
- } |
- } |
- |
- const int kBufferSize = 1024; |
- char buffer[kBufferSize]; |
- uint32 size = 0; |
- while (true) { |
- if (is_aborted_) { |
- return E_ABORT; |
- } |
- |
- DWORD bytes_read = 0; |
- if (wininet_.InternetReadFile(request_handle_, |
- buffer, |
- kBufferSize, |
- &bytes_read) && bytes_read) { |
- size += bytes_read; |
- if (max_size && size > max_size) { |
- return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); |
- } |
- if (response_body) { |
- response_body->insert(response_body->end(), |
- buffer, |
- buffer + bytes_read); |
- } else { |
- DWORD bytes_written = 0; |
- if (!::WriteFile(get(file), buffer, bytes_read, &bytes_written, NULL)) { |
- hr = HRESULTFromLastError(); |
- break; |
- } |
- } |
- } else { |
- break; |
- } |
- } |
- |
- return hr; |
-} |
- |
-HRESULT InetHttpClient::QueryProxyAuthScheme(AuthScheme* auth_scheme) { |
- ASSERT1(auth_scheme); |
- |
- *auth_scheme = NO_AUTH_SCHEME; |
- |
- // Find out authentication scheme by communicating with google server via |
- // proxy server and checking the response header to find out the |
- // authentication scheme the proxy server requires. |
- |
- // Send the request to query google server only if we have not got 407 error. |
- HRESULT hr = S_OK; |
- if (status_ != HTTP_STATUS_PROXY_AUTH_REQ) { |
- hr = SendRequest(kGoogleHttpServer, kDefaultHttpProxyPort, _T("/")); |
- } |
- if (SUCCEEDED(hr) && status_ == HTTP_STATUS_PROXY_AUTH_REQ) { |
- CString response_headers; |
- hr = GetAllResponseHeaders(&response_headers); |
- if (SUCCEEDED(hr)) { |
- const TCHAR* response_headers_str = response_headers.GetString(); |
- CString auth_scheme_str; |
- AuthScheme curr_auth_scheme = NO_AUTH_SCHEME; |
- while (AtlRE::FindAndConsume(&response_headers_str, |
- proxy_auth_header_regex_, |
- &auth_scheme_str)) { |
- AuthScheme other_auth_scheme = NO_AUTH_SCHEME; |
- if (auth_scheme_str.CompareNoCase(kNegotiateAuthScheme) == 0) { |
- other_auth_scheme = AUTH_SCHEME_NEGOTIATE; |
- } else if (auth_scheme_str.CompareNoCase(kNTLMAuthScheme) == 0) { |
- other_auth_scheme = AUTH_SCHEME_NTLM; |
- } else if (auth_scheme_str.CompareNoCase(kDigestAuthScheme) == 0) { |
- other_auth_scheme = AUTH_SCHEME_DIGEST; |
- } else if (auth_scheme_str.CompareNoCase(kBasicAuthScheme) == 0) { |
- other_auth_scheme = AUTH_SCHEME_BASIC; |
- } else { |
- other_auth_scheme = UNKNOWN_AUTH_SCHEME; |
- } |
- if (static_cast<int>(other_auth_scheme) > |
- static_cast<int>(curr_auth_scheme)) { |
- curr_auth_scheme = other_auth_scheme; |
- } |
- } |
- *auth_scheme = curr_auth_scheme; |
- return S_OK; |
- } |
- } |
- |
- return E_FAIL; |
-} |
- |
-// We do not support Auto-proxy for WinInet because jsproxy.dll seems to be |
-// very instable and cause crashes from time to time. |
-HRESULT InetHttpClient::GetAutoProxyForUrl(const TCHAR*, CString*) { |
- return E_NOTIMPL; |
-} |
- |
-HRESULT InetHttpClient::GetDefaultProxyConfiguration(AccessType* access_type, |
- CString* proxy, |
- CString* proxy_bypass) { |
- DWORD size_needed = 0; |
- if (wininet_.InternetQueryOption(NULL, |
- INTERNET_OPTION_PROXY, |
- NULL, |
- &size_needed) || |
- ::GetLastError() != ERROR_INSUFFICIENT_BUFFER) { |
- UTIL_LOG(LEVEL_ERROR, (_T("[InternetQueryOption failed]"))); |
- return E_FAIL; |
- } |
- |
- scoped_array<byte> proxy_info_buffer(new byte[size_needed]); |
- if (!wininet_.InternetQueryOption(NULL, |
- INTERNET_OPTION_PROXY, |
- proxy_info_buffer.get(), |
- &size_needed)) { |
- HRESULT hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[InternetQueryOption failed][0x%08x]"), hr)); |
- return hr; |
- } |
- |
- INTERNET_PROXY_INFO* proxy_info = reinterpret_cast<INTERNET_PROXY_INFO*>( |
- proxy_info_buffer.get()); |
- |
- if (access_type) { |
- if (proxy_info->dwAccessType == INTERNET_OPEN_TYPE_DIRECT) { |
- *access_type = NO_PROXY; |
- } else if (proxy_info->dwAccessType == INTERNET_OPEN_TYPE_PROXY) { |
- *access_type = NAMED_PROXY; |
- } else { |
- *access_type = AUTO_PROXY_AUTO_DETECT; |
- } |
- } |
- |
- if (proxy) { |
- // proxy_info->lpszProxy points to an ASCII string. |
- *proxy = reinterpret_cast<const char*>(proxy_info->lpszProxy); |
- } |
- |
- if (proxy_bypass) { |
- // proxy_info->lpszProxyBypass points to an ASCII string. |
- *proxy_bypass = reinterpret_cast<const char*>(proxy_info->lpszProxyBypass); |
- } |
- |
- return S_OK; |
-} |
- |
-// TODO(omaha): check connection by requesting a well known url instead of |
-// using WinInet. The WinInet code does an ICMP ping apparently, which is |
-// usually blocked by firewalls. |
-bool InetHttpClient::CheckConnection() { |
- return wininet_.InternetCheckConnection( |
- kHttpProtoScheme kProtoSuffix kGoogleHttpServer _T("/"), |
- FLAG_ICC_FORCE_CONNECTION, 0) == TRUE; |
-} |
- |
-HRESULT InetHttpClient::InternalCrackUrl(const CString& url, bool to_escape, |
- URL_COMPONENTS* url_components) { |
- ASSERT(!url.IsEmpty(), (_T(""))); |
- ASSERT1(url_components); |
- |
- if (!wininet_.InternetCrackUrl(url.GetString(), |
- url.GetLength(), |
- to_escape ? ICU_ESCAPE : 0, |
- url_components)) { |
- HRESULT hr = HRESULTFromLastError(); |
- UTIL_LOG(LEVEL_ERROR, (_T("[InternetCrackUrl failed][0x%08x]"), hr)); |
- return hr; |
- } |
- |
- return S_OK; |
-} |
- |
-void CALLBACK InetHttpClient::StatusCallback(HINTERNET handle, |
- DWORD_PTR context, |
- DWORD status, |
- void* info, |
- DWORD info_len) { |
- // Unlike WinHttp, the ip addresses are not unicode strings. |
- CString info_string; |
- switch (status) { |
- case INTERNET_STATUS_RESOLVING_NAME: |
- status = CALLBACK_STATUS_RESOLVING_NAME; |
- break; |
- case INTERNET_STATUS_NAME_RESOLVED: |
- info_string = static_cast<char*>(info); |
- info = info_string.GetBuffer(); |
- status = CALLBACK_STATUS_NAME_RESOLVED; |
- break; |
- case INTERNET_STATUS_CONNECTING_TO_SERVER: |
- info_string = static_cast<char*>(info); |
- info = info_string.GetBuffer(); |
- status = CALLBACK_STATUS_CONNECTING_TO_SERVER; |
- break; |
- case INTERNET_STATUS_CONNECTED_TO_SERVER: |
- info_string = static_cast<char*>(info); |
- info = info_string.GetBuffer(); |
- status = CALLBACK_STATUS_CONNECTED_TO_SERVER; |
- break; |
- case INTERNET_STATUS_SENDING_REQUEST: |
- status = CALLBACK_STATUS_SENDING_REQUEST; |
- break; |
- case INTERNET_STATUS_REQUEST_SENT: |
- status = CALLBACK_STATUS_REQUEST_SENT; |
- break; |
- case INTERNET_STATUS_RECEIVING_RESPONSE: |
- status = CALLBACK_STATUS_RECEIVING_RESPONSE; |
- break; |
- case INTERNET_STATUS_RESPONSE_RECEIVED: |
- status = CALLBACK_STATUS_RESPONSE_RECEIVED; |
- break; |
- case INTERNET_STATUS_CLOSING_CONNECTION: |
- status = CALLBACK_STATUS_CLOSING_CONNECTION; |
- break; |
- case INTERNET_STATUS_CONNECTION_CLOSED: |
- status = CALLBACK_STATUS_CONNECTION_CLOSED; |
- break; |
- case INTERNET_STATUS_REDIRECT: |
- status = CALLBACK_STATUS_REDIRECT; |
- break; |
- default: |
- return; |
- }; |
- HttpClient::StatusCallback(handle, context, status, info, info_len); |
-} |
- |
-// WinInetVTable: delay-loading of WININET.DLL. |
-// Handling of and protection of Wininet APIs. |
-// Dynamically load to wininet.dll. |
-// Wrap all calls in an Structured Exception handler - wininet is buggy and |
-// throws access violations |
-WinInetVTable::WinInetVTable() { Clear(); } |
-WinInetVTable::~WinInetVTable() { Unload(); } |
- |
-template <typename T> |
-bool WinInetVTable::GPA(const char* function_name, |
- T& function_pointer) { // NO LINT |
- ASSERT(function_name, (L"")); |
- function_pointer = reinterpret_cast<T>(::GetProcAddress(library_, |
- function_name)); |
- return NULL != function_pointer; |
-} |
- |
-bool WinInetVTable::Load() { |
- if (Loaded()) { |
- return true; |
- } |
- |
- Clear(); |
- |
- { |
- library_ = ::LoadLibrary(_T("wininet")); |
- } |
- if (!library_) { |
- return false; |
- } |
- |
- bool all_valid = ( |
- GPA("HttpAddRequestHeadersW", HttpAddRequestHeaders_pointer)) |
- & (GPA("HttpEndRequestW", HttpEndRequest_pointer)) |
- & (GPA("HttpOpenRequestW", HttpOpenRequest_pointer)) |
- & (GPA("HttpQueryInfoW", HttpQueryInfo_pointer)) |
- & (GPA("HttpSendRequestExW", HttpSendRequestEx_pointer)) |
- & (GPA("HttpSendRequestW", HttpSendRequest_pointer)) |
- & (GPA("InternetCloseHandle", InternetCloseHandle_pointer)) |
- & (GPA("InternetConnectW", InternetConnect_pointer)) |
- & (GPA("InternetGetConnectedStateExW", InternetGetConnectedStateEx_pointer)) |
- & (GPA("InternetOpenW", InternetOpen_pointer)) |
- & (GPA("InternetOpenUrlW", InternetOpenUrl_pointer)) |
- & (GPA("InternetQueryDataAvailable", InternetQueryDataAvailable_pointer)) |
- & (GPA("InternetReadFile", InternetReadFile_pointer)) |
- & (GPA("InternetReadFileExW", InternetReadFileEx_pointer)) |
- & (GPA("InternetSetStatusCallbackW", InternetSetStatusCallback_pointer)) |
- & (GPA("InternetGetCookieW", InternetGetCookie_pointer)) |
- & (GPA("InternetSetCookieW", InternetSetCookie_pointer)) |
- & (GPA("InternetAutodial", InternetAutodial_pointer)) |
- & (GPA("InternetAutodialHangup", InternetAutodialHangup_pointer)) |
- & (GPA("InternetQueryOptionW", InternetQueryOption_pointer)) |
- & (GPA("InternetSetOptionW", InternetSetOption_pointer)) |
- & (GPA("InternetCheckConnectionW", InternetCheckConnection_pointer)) |
- & (GPA("InternetCrackUrlW", InternetCrackUrl_pointer)); |
- |
- if (!all_valid) { |
- Unload(); |
- } |
- |
- return all_valid; |
-} |
- |
-void WinInetVTable::Unload() { |
- if (library_) { |
- ::FreeLibrary(library_); |
- library_ = NULL; |
- } |
- Clear(); |
-} |
- |
-void WinInetVTable::Clear() { |
- ::memset(this, 0, sizeof(*this)); |
-} |
- |
-#define PROTECT_WRAP(function, proto, call, result_type, result_error_value) \ |
-result_type WinInetVTable::function proto { \ |
- result_type result; \ |
- __try { \ |
- result = function##_pointer call; \ |
- } \ |
- __except(EXCEPTION_EXECUTE_HANDLER) { \ |
- result = result_error_value; \ |
- } \ |
- return result; \ |
-} |
- |
-PROTECT_WRAP(HttpAddRequestHeaders, (HINTERNET a, const TCHAR* b, DWORD c, DWORD d), (a, b, c, d), BOOL, FALSE); |
-PROTECT_WRAP(HttpEndRequest, (HINTERNET a, LPINTERNET_BUFFERS b, DWORD c, DWORD_PTR d), (a, b, c, d), BOOL, FALSE); |
-PROTECT_WRAP(HttpOpenRequest, (HINTERNET a, const TCHAR* b, const TCHAR* c, const TCHAR* d, const TCHAR* e, const TCHAR** f, DWORD g, DWORD_PTR h), (a, b, c, d, e, f, g, h), HINTERNET, NULL); |
-PROTECT_WRAP(HttpQueryInfo, (HINTERNET a, DWORD b, LPVOID c, LPDWORD d, LPDWORD e), (a, b, c, d, e), BOOL, FALSE); |
-PROTECT_WRAP(HttpSendRequestEx, (HINTERNET a, LPINTERNET_BUFFERS b, LPINTERNET_BUFFERS c, DWORD d, DWORD_PTR e), (a, b, c, d, e), BOOL, FALSE); |
-PROTECT_WRAP(HttpSendRequest, (HINTERNET a, const TCHAR* b, DWORD c, LPVOID d, DWORD e), (a, b, c, d, e), BOOL, FALSE); |
-PROTECT_WRAP(InternetCloseHandle, (HINTERNET a), (a), BOOL, FALSE); |
-PROTECT_WRAP(InternetConnect, (HINTERNET a, const TCHAR* b, INTERNET_PORT c, const TCHAR* d, const TCHAR* e, DWORD f, DWORD g, DWORD h), (a, b, c, d, e, f, g, h), HINTERNET, NULL); |
-PROTECT_WRAP(InternetGetConnectedStateEx, (LPDWORD a, char* b, DWORD c, DWORD d), (a, b, c, d), BOOL, FALSE); |
-PROTECT_WRAP(InternetOpen, (const TCHAR* a, DWORD b, const TCHAR* c, const TCHAR* d, DWORD e), (a, b, c, d, e), HINTERNET, NULL); |
-PROTECT_WRAP(InternetOpenUrl, (HINTERNET a, const TCHAR* b, const TCHAR* c, DWORD d, DWORD e, DWORD_PTR f), (a, b, c, d, e, f), HINTERNET, NULL); |
-PROTECT_WRAP(InternetQueryDataAvailable, (HINTERNET a, LPDWORD b, DWORD c, DWORD d), (a, b, c, d), BOOL, FALSE); |
-PROTECT_WRAP(InternetReadFile, (HINTERNET a, LPVOID b, DWORD c, LPDWORD d), (a, b, c, d), BOOL, FALSE); |
-PROTECT_WRAP(InternetReadFileEx, (HINTERNET a, LPINTERNET_BUFFERS b, DWORD c, DWORD_PTR d), (a, b, c, d), HINTERNET, NULL); |
-PROTECT_WRAP(InternetSetStatusCallback, (HINTERNET a, INTERNET_STATUS_CALLBACK b), (a, b), INTERNET_STATUS_CALLBACK, INTERNET_INVALID_STATUS_CALLBACK); |
-PROTECT_WRAP(InternetGetCookie, (const TCHAR* a, const TCHAR* b, TCHAR* c, LPDWORD d), (a, b, c, d), BOOL, FALSE); |
-PROTECT_WRAP(InternetSetCookie, (const TCHAR* a, const TCHAR* b, const TCHAR* c), (a, b, c), BOOL, FALSE); |
-PROTECT_WRAP(InternetAutodial, (DWORD a, HWND b), (a, b), BOOL, FALSE); |
-PROTECT_WRAP(InternetAutodialHangup, (DWORD a), (a), BOOL, FALSE); |
-PROTECT_WRAP(InternetQueryOption, (HINTERNET a, DWORD b, LPVOID c, LPDWORD d), (a, b, c, d), BOOL, FALSE); |
-PROTECT_WRAP(InternetSetOption, (HINTERNET a, DWORD b, LPVOID c, DWORD d), (a, b, c, d), BOOL, FALSE); |
-PROTECT_WRAP(InternetCheckConnection, (const TCHAR* a, DWORD b, DWORD c), (a, b, c), BOOL, FALSE); |
-PROTECT_WRAP(InternetCrackUrl, (const TCHAR* a, DWORD b, DWORD c, LPURL_COMPONENTS d), (a, b, c, d), BOOL, FALSE); |
-#endif |
- |