让curl支持IE代理

  CURL支持HTTP代理,SOCKET4代理,SOCKET5代理,但是在windows平台最经常的还是IE代理。也就是设置在IE浏览器中的代理。

  由于curl没有直接的支持选项,因此如果要在curl之中实现IE代理,那么需要一些小工作需要做。

  思路如下,通过windows提供的API获取IE浏览器中的代理类型、代理IP地址,代理端口信息,通过url提供的函数设置代理就好。

 一、先来认识三个函数 

   1、WinHttpGetIEProxyConfigForCurrentUser 函数

BOOL WINAPI WinHttpGetIEProxyConfigForCurrentUser(
  _Inout_  WINHTTP_CURRENT_USER_IE_PROXY_CONFIG *pProxyConfig
);
typedef struct {
  BOOL   fAutoDetect;      --对应“自动坚持设置”
  LPWSTR lpszAutoConfigUrl;   --当“使用自动脚本设置”选中时,的地址文本框内容
  LPWSTR lpszProxy;  --对应“代理服务器” 中的ip地址与端口
  LPWSTR lpszProxyBypass;  --当选中“跳过本地地址的服务器”时,对应到,点击“高级”按钮后出现的“代理设置”的“例外”文本框
} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;

 该函数用于获取当前用户的代理设置,根据 pProxyConfig 的返回值,以及对这个结构中每个成员的注释应该就很清楚其含义了。

  2、WinHttpOpen 函数

HINTERNET WINAPI WinHttpOpen(
  _In_opt_  LPCWSTR pwszUserAgent,
  _In_      DWORD dwAccessType,
  _In_      LPCWSTR pwszProxyName,
  _In_      LPCWSTR pwszProxyBypass,
  _In_      DWORD dwFlags
);

   我们使用该函数,只是为了获取一个WinHttp的Session,因此这里面的参数我们都不需要特别的设置,如

  HINTERNET session = ::WinHttpOpen(0, // no agent string

    WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
    WINHTTP_NO_PROXY_NAME,
    WINHTTP_NO_PROXY_BYPASS,
    WINHTTP_FLAG_ASYNC);

  3、WinHttpGetProxyForUrl 当代理设置为“使用自动配置脚本”选项时使用    

BOOL WINAPI WinHttpGetProxyForUrl(
  _In_   HINTERNET hSession,    --为从WinHttpOpen函数返回的一个handle
  _In_   LPCWSTR lpcwszUrl,    --表示需要访问的url地址
  _In_   WINHTTP_AUTOPROXY_OPTIONS *pAutoProxyOptions,    --一些选项
  _Out_  WINHTTP_PROXY_INFO *pProxyInfo   --当查找对应的proxy时的返回值
);   
typedef struct {
  DWORD   dwFlags;
  DWORD   dwAutoDetectFlags;
  LPCWSTR lpszAutoConfigUrl;    --当选中“使用自动脚本设置”,时的“地址”文本框中的内容
  LPVOID  lpvReserved;
  DWORD   dwReserved;
  BOOL    fAutoLogonIfChallenged;
} WINHTTP_AUTOPROXY_OPTIONS;

char *w2c(char *pcstr, size_t len, const wchar_t *pwstr)
{
#ifdef WIN32
int nlength=wcslen(pwstr);
int nbytes = WideCharToMultiByte( CP_UTF8, // specify the code page used to perform the conversion
0, // no special flags to handle unmapped characters
pwstr, // wide character string to convert
nlength, // the number of wide characters in that string
NULL, // no output buffer given, we just want to know how long it needs to be
0,
NULL, // no replacement character given
NULL ); // we don't want to know if a character didn't make it through the translation

// make sure the buffer is big enough for this, making it larger if necessary

if(nbytes>len) nbytes=len;


WideCharToMultiByte( CP_UTF8, // specify the code page used to perform the conversion
0, // no special flags to handle unmapped characters
pwstr, // wide character string to convert
nlength, // the number of wide characters in that string
pcstr, // put the output ascii characters at the end of the buffer
nbytes, // there is at least this much space there
NULL, // no replacement character given
NULL );

pcstr[nbytes] = 0;
#else
sprintf(pcstr, "%s", pwstr);
#endif
return pcstr ;
}


typedef enum _MX_CS_PROXY_TYPE {
MX_CS_PROXY_TYPE_NOPROXY = 0,
MX_CS_PROXY_TYPE_HTTP,
MX_CS_PROXY_TYPE_SOCKS4,
MX_CS_PROXY_TYPE_SOCKS4A,
MX_CS_PROXY_TYPE_SOCKS5,
#ifdef WIN32
MX_CS_PROXY_TYPE_USEIE,
#endif
}MX_CS_PROXY_TYPE;


bool getProxyAddr(const string& strAddr,char* strDestAddr,const char* type)
{
int nStart = strAddr.find(type);
if(nStart != -1)
{
nStart += strlen(type);
int nLen = strAddr.find(';',nStart+1) - nStart;
strcpy(strDestAddr,strAddr.substr(nStart,nLen).c_str());
return true;
}
return false;
}

int getIEProxy(const wchar_t* host,int& proxytype,int& port,char* strAddr,bool bUserHttps)
{
bool fAutoProxy = false;
WINHTTP_PROXY_INFO autoProxyInfo = {0};

WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions = {0};
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieProxyConfig = {0};
if( WinHttpGetIEProxyConfigForCurrentUser( &ieProxyConfig ) )
{
if( ieProxyConfig.fAutoDetect )
{
fAutoProxy = true;
}

if( ieProxyConfig.lpszAutoConfigUrl != NULL )
{
fAutoProxy = true;
autoProxyOptions.lpszAutoConfigUrl = ieProxyConfig.lpszAutoConfigUrl;
}
}
else
{
// use autoproxy
fAutoProxy = true;
}

if( fAutoProxy )
{
if ( autoProxyOptions.lpszAutoConfigUrl != NULL )
{
autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
}
else
{
autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
}

// basic flags you almost always want
autoProxyOptions.fAutoLogonIfChallenged = TRUE;

HINTERNET session = ::WinHttpOpen(0, // no agent string
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
WINHTTP_FLAG_ASYNC);

// here we reset fAutoProxy in case an auto-proxy isn't actually
// configured for this url

fAutoProxy = WinHttpGetProxyForUrl(session, host, &autoProxyOptions, &autoProxyInfo );
if(session) WinHttpCloseHandle(session);
}

if ( fAutoProxy )
{
// set proxy options for libcurl based on autoProxyInfo
//autoProxyInfo.lpszProxy
//curl_easy_setopt(curl,CURLOPT_PROXY,autoProxyInfo.lpszProxy);
if(autoProxyInfo.lpszProxy)
{
w2c(strAddr, 256, autoProxyInfo.lpszProxy);
proxytype = MX_CS_PROXY_TYPE_HTTP;
port = 0;
}
else
{
return -1;
}
}
else
{
if( ieProxyConfig.lpszProxy != NULL )
{
// IE has an explicit proxy. set proxy options for libcurl here
// based on ieProxyConfig
//
// note that sometimes IE gives just a single or double colon
// for proxy or bypass list, which means "no proxy"
w2c(strAddr, 256, ieProxyConfig.lpszProxy);
proxytype = MX_CS_PROXY_TYPE_HTTP;
port = 0;

///may be like this: "http=127.0.0.1:8888;https=127.0.0.1:8888;ftp=127.0.0.1:8888;socks=127.0.0.1:8888" "127.0.0.1:8888"
string strProxyAddr(strAddr);
if(strProxyAddr.find('=') != -1)
{
bool bFind = false;
if(bUserHttps && getProxyAddr(strProxyAddr,strAddr,"https=")) bFind = true;
if(bFind == false && getProxyAddr(strProxyAddr,strAddr,"http=")) bFind = true;
if(bFind == false && getProxyAddr(strProxyAddr,strAddr,"socks="))
{
proxytype = MX_CS_PROXY_TYPE_SOCKS5;
}
}
}
else
{
proxytype = MX_CS_PROXY_TYPE_NOPROXY;
// there is no auto proxy and no manually configured proxy
}
}

if(autoProxyInfo.lpszProxy != NULL) GlobalFree(autoProxyInfo.lpszProxy);
if(autoProxyInfo.lpszProxyBypass !=NULL ) GlobalFree(autoProxyInfo.lpszProxyBypass);
//if(autoProxyOptions.lpszAutoConfigUrl != NULL) GlobalFree(autoProxyOptions.lpszAutoConfigUrl);
if(ieProxyConfig.lpszAutoConfigUrl != NULL) GlobalFree(ieProxyConfig.lpszAutoConfigUrl);
if(ieProxyConfig.lpszProxy != NULL) GlobalFree(ieProxyConfig.lpszProxy);
if(ieProxyConfig.lpszProxyBypass != NULL) GlobalFree(ieProxyConfig.lpszProxyBypass);

return proxytype;
}

  参考:http://msdn.microsoft.com/en-us/library/windows/desktop/aa384096(v=vs.85).aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/aa384098(v=vs.85).aspx

http://msdn.microsoft.com/en-us/library/windows/desktop/aa384097(v=vs.85).aspx

  http://www.fengfly.com/plus/view-75365-1.html

原文地址:https://www.cnblogs.com/chang290/p/2857426.html