forked from 0ad/0ad
HTTP proxy discovery for Windows
This was SVN commit r8969.
This commit is contained in:
parent
25039d3aff
commit
9bbda8b80b
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2010 Wildfire Games
|
||||
/* Copyright (c) 2011 Wildfire Games
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@ -393,6 +393,11 @@ LibError sys_generate_random_bytes(u8* buf, size_t count)
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
LibError sys_get_proxy_config(const std::string& UNUSED(url), std::string& UNUSED(proxy))
|
||||
{
|
||||
return INFO::SKIPPED;
|
||||
}
|
||||
|
||||
LibError sys_open_url(const std::string& url)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2010 Wildfire Games
|
||||
/* Copyright (c) 2011 Wildfire Games
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
@ -32,15 +32,18 @@
|
||||
#include <shellapi.h> // open_url
|
||||
#include <Wincrypt.h>
|
||||
#include <WindowsX.h> // message crackers
|
||||
#include <winhttp.h>
|
||||
|
||||
#include "lib/sysdep/clipboard.h"
|
||||
#include "lib/sysdep/os/win/error_dialog.h"
|
||||
#include "lib/sysdep/os/win/wutil.h"
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
|
||||
#if MSC_VERSION
|
||||
#pragma comment(lib, "shell32.lib") // for sys_pick_directory SH* calls
|
||||
#pragma comment(lib, "winhttp.lib")
|
||||
#endif
|
||||
|
||||
|
||||
@ -469,3 +472,112 @@ LibError sys_generate_random_bytes(u8* buffer, size_t size)
|
||||
|
||||
return INFO::OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a string of the form
|
||||
* "example.com:80"
|
||||
* or
|
||||
* "ftp=ftp.example.com:80;http=example.com:80;https=example.com:80"
|
||||
* separated by semicolons or whitespace,
|
||||
* return the string "example.com:80".
|
||||
*/
|
||||
static std::wstring parse_proxy(const std::wstring& input)
|
||||
{
|
||||
if(input.find('=') == input.npos)
|
||||
return input;
|
||||
|
||||
std::vector<std::wstring> parts;
|
||||
split(parts, input, boost::algorithm::is_any_of("; \t\r\n"), boost::algorithm::token_compress_on);
|
||||
|
||||
for(size_t i = 0; i < parts.size(); ++i)
|
||||
if(boost::algorithm::starts_with(parts[i], "http="))
|
||||
return parts[i].substr(5);
|
||||
|
||||
// If we got this far, proxies were only set for non-HTTP protocols
|
||||
return L"";
|
||||
}
|
||||
|
||||
LibError sys_get_proxy_config(const std::wstring& url, std::wstring& proxy)
|
||||
{
|
||||
WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions;
|
||||
memset(&autoProxyOptions, 0, sizeof(autoProxyOptions));
|
||||
autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
|
||||
autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
|
||||
autoProxyOptions.fAutoLogonIfChallenged = TRUE;
|
||||
|
||||
WINHTTP_PROXY_INFO proxyInfo;
|
||||
memset(&proxyInfo, 0, sizeof(proxyInfo));
|
||||
|
||||
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieConfig;
|
||||
memset(&ieConfig, 0, sizeof(ieConfig));
|
||||
|
||||
HINTERNET hSession = NULL;
|
||||
|
||||
LibError err = INFO::SKIPPED;
|
||||
|
||||
bool useAutoDetect;
|
||||
|
||||
if(WinHttpGetIEProxyConfigForCurrentUser(&ieConfig))
|
||||
{
|
||||
if(ieConfig.lpszAutoConfigUrl)
|
||||
{
|
||||
// Use explicit auto-config script if specified
|
||||
useAutoDetect = true;
|
||||
autoProxyOptions.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL;
|
||||
autoProxyOptions.lpszAutoConfigUrl = ieConfig.lpszAutoConfigUrl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use auto-discovery if enabled
|
||||
useAutoDetect = (ieConfig.fAutoDetect == TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can't find IE config settings - fall back to auto-discovery
|
||||
useAutoDetect = true;
|
||||
}
|
||||
|
||||
if(useAutoDetect)
|
||||
{
|
||||
hSession = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
|
||||
|
||||
if(hSession && WinHttpGetProxyForUrl(hSession, url.c_str(), &autoProxyOptions, &proxyInfo))
|
||||
{
|
||||
proxy = parse_proxy(proxyInfo.lpszProxy);
|
||||
if(!proxy.empty())
|
||||
{
|
||||
err = INFO::OK;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No valid auto-config; try explicit proxy instead
|
||||
if(ieConfig.lpszProxy)
|
||||
{
|
||||
proxy = parse_proxy(ieConfig.lpszProxy);
|
||||
if(!proxy.empty())
|
||||
{
|
||||
err = INFO::OK;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if(ieConfig.lpszProxy)
|
||||
GlobalFree(ieConfig.lpszProxy);
|
||||
if(ieConfig.lpszProxyBypass)
|
||||
GlobalFree(ieConfig.lpszProxyBypass);
|
||||
if(ieConfig.lpszAutoConfigUrl)
|
||||
GlobalFree(ieConfig.lpszAutoConfigUrl);
|
||||
if(proxyInfo.lpszProxy)
|
||||
GlobalFree(proxyInfo.lpszProxy);
|
||||
if(proxyInfo.lpszProxyBypass)
|
||||
GlobalFree(proxyInfo.lpszProxyBypass);
|
||||
if(hSession)
|
||||
WinHttpCloseHandle(hSession);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -168,6 +168,15 @@ extern size_t sys_max_sector_size();
|
||||
**/
|
||||
LIB_API LibError sys_generate_random_bytes(u8* buf, size_t count);
|
||||
|
||||
/**
|
||||
* get the proxy address for accessing the given HTTP URL.
|
||||
*
|
||||
* this may be very slow (tens of seconds).
|
||||
*
|
||||
* @return INFO::OK on success; INFO::SKIPPED if no proxy found.
|
||||
**/
|
||||
LIB_API LibError sys_get_proxy_config(const std::wstring& url, std::wstring& proxy);
|
||||
|
||||
/**
|
||||
* directory separation character
|
||||
**/
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "UserReport.h"
|
||||
|
||||
#include "lib/timer.h"
|
||||
#include "lib/utf8.h"
|
||||
#include "lib/external_libraries/curl.h"
|
||||
#include "lib/external_libraries/sdl.h"
|
||||
#include "lib/external_libraries/zlib.h"
|
||||
@ -82,7 +83,7 @@ class CUserReporterWorker
|
||||
{
|
||||
public:
|
||||
CUserReporterWorker(const std::string& userID, const std::string& url) :
|
||||
m_UserID(userID), m_Enabled(false), m_Shutdown(false), m_Status("disabled"),
|
||||
m_URL(url), m_UserID(userID), m_Enabled(false), m_Shutdown(false), m_Status("disabled"),
|
||||
m_PauseUntilTime(timer_Time()), m_LastUpdateTime(timer_Time())
|
||||
{
|
||||
// Set up libcurl:
|
||||
@ -237,6 +238,15 @@ private:
|
||||
|
||||
void Run()
|
||||
{
|
||||
// Set libcurl's proxy configuration
|
||||
// (This has to be done in the thread because it's potentially very slow)
|
||||
SetStatus("proxy");
|
||||
std::wstring proxy;
|
||||
if (sys_get_proxy_config(wstring_from_utf8(m_URL), proxy) == INFO::OK)
|
||||
curl_easy_setopt(m_Curl, CURLOPT_PROXY, utf8_from_wstring(proxy).c_str());
|
||||
|
||||
SetStatus("waiting");
|
||||
|
||||
/*
|
||||
* We use a semaphore to let the thread be woken up when it has
|
||||
* work to do. Various actions from the main thread can wake it:
|
||||
@ -463,6 +473,7 @@ private:
|
||||
std::string m_Status;
|
||||
|
||||
// Initialised in constructor by main thread; otherwise used only by worker thread:
|
||||
std::string m_URL;
|
||||
std::string m_UserID;
|
||||
CURL* m_Curl;
|
||||
curl_slist* m_Headers;
|
||||
|
Loading…
Reference in New Issue
Block a user