zoukankan      html  css  js  c++  java
  • 让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

  • 相关阅读:
    LeetCode 242. Valid Anagram (验证变位词)
    LeetCode 205. Isomorphic Strings (同构字符串)
    LeetCode 204. Count Primes (质数的个数)
    LeetCode 202. Happy Number (快乐数字)
    LeetCode 170. Two Sum III
    LeetCode 136. Single Number (落单的数)
    LeetCode 697. Degree of an Array (数组的度)
    LeetCode 695. Max Area of Island (岛的最大区域)
    Spark中的键值对操作
    各种排序算法总结
  • 原文地址:https://www.cnblogs.com/chang290/p/2857426.html
Copyright © 2011-2022 走看看