Created
January 22, 2009 10:39
-
-
Save kuboon/50495 to your computer and use it in GitHub Desktop.
GetProxyForUrl.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
@file 現在のOSのProxy設定を読み取る | |
*/ | |
#include "StdAfx.h" | |
#include <Winhttp.h> | |
#pragma comment(lib, "Winhttp.lib") | |
#include <shlwapi.h> | |
#pragma comment(lib, "shlwapi.lib") | |
/** | |
文字列を区切り文字列で分割する。 | |
ex. | |
SplitString(L"ab<>cd<><>ef<>:", L"<>") | |
=> "ab", "cd" , "", "ef", "" | |
@return 分割された文字列。区切りは含まない。 | |
*/ | |
static std::vector<std::wstring> SplitString( | |
std::wstring input ///< 入力 | |
,const std::wstring& delimiter ///< 区切り文字。空文字のときは空vectorが返る | |
){ | |
std::vector<std::wstring> ret; | |
if(delimiter.empty())return ret; | |
input+=delimiter; | |
int end, begin=0; | |
while((end=input.find(delimiter, begin)) !=std::wstring::npos){ | |
ret.push_back(input.substr(begin, end-begin)); | |
begin=end+delimiter.length(); | |
} | |
return ret; | |
} | |
/** | |
URLからHostNameを取得 | |
ex. | |
HostNameOf(L"http://www.google.co.jp/hoge/path") | |
=> www.google.co.jp | |
*/ | |
static std::wstring HostNameOf(const std::wstring& url){ | |
URL_COMPONENTS urlComp={0}; | |
urlComp.dwStructSize=sizeof(urlComp); | |
wchar_t hostName[256]; | |
urlComp.lpszHostName=hostName; | |
urlComp.dwHostNameLength=255; | |
if(!::WinHttpCrackUrl(url.c_str(), url.length(), 0, &urlComp)){ | |
return L""; | |
} | |
return hostName; | |
} | |
/** | |
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG のリソースを自動解放するためのラッパー | |
*/ | |
class auto_WINHTTP_CURRENT_USER_IE_PROXY_CONFIG:public WINHTTP_CURRENT_USER_IE_PROXY_CONFIG{ | |
public: | |
auto_WINHTTP_CURRENT_USER_IE_PROXY_CONFIG(){ | |
ZeroMemory(this, sizeof(this)); | |
} | |
~auto_WINHTTP_CURRENT_USER_IE_PROXY_CONFIG(){ | |
if (lpszAutoConfigUrl) | |
GlobalFree(lpszAutoConfigUrl); | |
if (lpszProxy) | |
GlobalFree(lpszProxy); | |
if (lpszProxyBypass) | |
GlobalFree(lpszProxyBypass); | |
} | |
}; | |
/** | |
OSのプロキシ設定を元に、urlに対するプロキシホスト名を返す。 | |
WPADによる自動設定、JavaScriptによる自動構成スクリプト、スキーム別固定設定、例外指定に対応。 | |
スクリプトは本関数内部で呼び出される。 | |
Url毎に異なる値が返されうるので、接続毎に呼び出すこと。 | |
@return "hostname:port" 。直接接続もしくはエラー時は "" を返す。 | |
*/ | |
std::wstring GetProxyForUrl( | |
const std::wstring& url ///< http(s):// から始まるURL。パスを含んでいても良い。 | |
){ | |
auto_WINHTTP_CURRENT_USER_IE_PROXY_CONFIG iecfg; | |
if(!WinHttpGetIEProxyConfigForCurrentUser(&iecfg)) { | |
return L""; | |
} | |
if (iecfg.fAutoDetect || iecfg.lpszAutoConfigUrl) { | |
if (HINTERNET hWinHttp = WinHttpOpen(NULL, | |
WINHTTP_ACCESS_TYPE_NO_PROXY, | |
WINHTTP_NO_PROXY_NAME, | |
WINHTTP_NO_PROXY_BYPASS, | |
0)) { | |
WINHTTP_AUTOPROXY_OPTIONS options={0}; | |
if (iecfg.fAutoDetect) { | |
options.dwFlags |= WINHTTP_AUTOPROXY_AUTO_DETECT; | |
options.dwAutoDetectFlags |= WINHTTP_AUTO_DETECT_TYPE_DHCP; | |
//| WINHTTP_AUTO_DETECT_TYPE_DNS_A; | |
} | |
if (iecfg.lpszAutoConfigUrl) { | |
options.dwFlags |= WINHTTP_AUTOPROXY_CONFIG_URL; | |
options.lpszAutoConfigUrl = iecfg.lpszAutoConfigUrl; | |
} | |
options.fAutoLogonIfChallenged = TRUE; | |
WINHTTP_PROXY_INFO info={0}; | |
if(WinHttpGetProxyForUrl | |
(hWinHttp, url.c_str(), &options, &info)){ | |
if(info.lpszProxy){ | |
std::wstring ret=info.lpszProxy; | |
GlobalFree(info.lpszProxy); | |
return ret; | |
} | |
if (info.lpszProxyBypass) | |
GlobalFree(info.lpszProxyBypass); | |
} | |
WinHttpCloseHandle(hWinHttp); | |
} | |
} | |
if(!iecfg.lpszProxy){ | |
return L""; | |
} | |
if(iecfg.lpszProxyBypass){ | |
std::vector<std::wstring> sp=SplitString(iecfg.lpszProxyBypass, L";"); | |
for(std::vector<std::wstring>::iterator it=sp.begin(); it!=sp.end(); ++it){ | |
if(PathMatchSpecW(HostNameOf(url).c_str(),it->c_str())) | |
return L""; | |
} | |
} | |
if(wcschr(iecfg.lpszProxy, L'=')==NULL){ | |
return iecfg.lpszProxy; | |
} | |
bool isHttps=(url.find(L"https:")==0); //begin with https | |
std::vector<std::wstring> sp=SplitString(iecfg.lpszProxy, L";"); | |
for(std::vector<std::wstring>::iterator it=sp.begin(); it!=sp.end(); ++it){ | |
std::vector<std::wstring> sp2=SplitString(*it, L"="); | |
if( (isHttps && sp2[0]==L"https") | |
||(!isHttps&& sp2[0]==L"http") ){ | |
return sp2[1]; | |
} | |
} | |
return L""; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment