• 让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

  • 相关阅读:
    ScheduledExecutorService改为一次性延时任务
    layer弹框倒计时结束后执行
    pom.xml如何使用本地库的jar-jar包上传到远程库-jar包安装到本地库
    Windows+WinRAR 压缩后备份文件夹
    java DES加密
    JAVA RSA加密公私钥
    Microsoft 语音服务异常 java.lang.UnsatisfiedLinkError: com.micros oft.cognitiveservices.speech.internal.carbon_javaJNI.swig_module_init()
    Java 线程池
    jsp页面导入excel文件的步骤及配置
    正则表达式校验时间格式(2018-01-02)
  • 原文地址:https://www.cnblogs.com/chang290/p/2857426.html
Copyright © 2020-2023  润新知