[vlc-devel] [PATCH] win32/netconf: detect proxy URL from system configuration

Rémi Denis-Courmont remi at remlab.net
Fri Feb 9 18:51:35 CET 2018


Le torstaina 8. helmikuuta 2018, 19.58.29 EET Pierre Lamot a écrit :
> ---
>  configure.ac        |   6 ++
>  src/win32/netconf.c | 267
> ++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 215
> insertions(+), 58 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index 10fd5f91eb..ca6193ed77 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -668,6 +668,12 @@ AC_SEARCH_LIBS([inet_pton], [nsl], [
>    ])
>  ],, [${SOCKET_LIBS}])
> 
> +
> +AS_IF([test "${SYS}" = "mingw32" -a "${enable_winstore_app}" != "yes"], [
> +  VLC_ADD_LIBS([libvlccore], [-lwinhttp])
> +])

What´s the point in doing that here?

> +
> +
>  LIBS="${LIBS} ${SOCKET_LIBS}"
>  AC_LINK_IFELSE([
>      AC_LANG_PROGRAM([#ifdef _WIN32
> diff --git a/src/win32/netconf.c b/src/win32/netconf.c
> index 3a6dcda1ea..ec7b9a8b9e 100644
> --- a/src/win32/netconf.c
> +++ b/src/win32/netconf.c
> @@ -24,86 +24,237 @@
> 
>  #include <string.h>
>  #include <windows.h>
> +#if !VLC_WINSTORE_APP
> +#  include <winhttp.h>
> +#endif
> 
>  #include <vlc_common.h>
> +#include <vlc_charset.h>
>  #include <vlc_network.h>
>  #include <vlc_url.h>
> 
> -char *vlc_getProxyUrl(const char *psz_url)
> +#define PROXY_TYPE_UNKNOWNED 0
> +#define PROXY_TYPE_SOCKS 1
> +#define PROXY_TYPE_HTTP 2
> +#define PROXY_TYPE_HTTPS 3
> +
> +/**
> + * this function parses the proxy list returned by WinHttpGetProxyForUrl.
> + * it returns the first proxy found using the prefered protocol (https >
> http > socks) + *
> + * The proxy server list contains one or more of the following strings
> + * separated by semicolons or whitespace.
> + * ([<scheme>=][<scheme>"://"]<server>[":"<port>])
> + */

I guess that this is _not_ looking good in Doxygen.

> +static char* parse_proxy( char* psz_proxy )
>  {
> -    VLC_UNUSED(psz_url);
> +    int i_ret_proxy_type = PROXY_TYPE_UNKNOWNED;
> +    char* psz_ret_proxy = NULL;
> +    char* psz_next_proxy = NULL;
> +    char* psz_equal;
> 
> -    char *proxy = config_GetPsz( (vlc_object_t *)(NULL), "http-proxy" );
> -    if (proxy == NULL)
> -        return NULL;
> +    const char* psz_end = strchr( psz_proxy, '\0' );
> 
> -    char *proxy_pwd = config_GetPsz( (vlc_object_t *)(NULL),
> "http-proxy-pwd" );
> -    if (proxy_pwd == NULL)
> -        return proxy;
> +    while( psz_proxy < psz_end )
> +    {
> +        int i_proxy_type = PROXY_TYPE_HTTP;
> 
> -    vlc_url_t url;
> -    if (vlc_UrlParse(&url, proxy) < 0) {
> -        free (proxy);
> -        free (proxy_pwd);
> -        return NULL;
> +        //strip leading space / empty proxies
> +        psz_proxy += strspn( psz_proxy, " \t;" );
> +        if( psz_proxy == psz_end )
> +            return psz_ret_proxy;
> +
> +        //detect [<scheme>=]
> +        if( ( psz_equal =  strchr( psz_proxy, '=' ) ) )
> +        {
> +            *psz_equal = '\0';
> +            if( strcasecmp( psz_proxy, "https" ) == 0 )
> +                i_proxy_type = PROXY_TYPE_HTTPS;
> +            else if( strcasecmp( psz_proxy, "http" ) == 0 )
> +                i_proxy_type = PROXY_TYPE_HTTP;
> +            else if( strcasecmp( psz_proxy, "socks" ) == 0 )
> +                i_proxy_type = PROXY_TYPE_SOCKS;
> +            else
> +                i_proxy_type = PROXY_TYPE_UNKNOWNED;
> +            psz_proxy = psz_equal + 1;
> +        }
> +
> +        int i_proxylen = strcspn( psz_proxy, " \t;" );
> +        psz_proxy[i_proxylen] = '\0';
> +        psz_next_proxy = psz_proxy + i_proxylen + 1;
> +
> +        if( strncasecmp( psz_proxy, "http://", 7 ) == 0
> +            && PROXY_TYPE_HTTP > i_ret_proxy_type )
> +        {
> +            if(psz_ret_proxy)
> +                free( psz_ret_proxy );
> +            psz_ret_proxy = strdup( psz_proxy );
> +            i_ret_proxy_type = PROXY_TYPE_HTTP;
> +        }
> +        else if( strncasecmp( psz_proxy, "https://", 8 ) == 0
> +                 && PROXY_TYPE_HTTPS > i_ret_proxy_type )
> +        {
> +            if( psz_ret_proxy )
> +                free( psz_ret_proxy );
> +            psz_ret_proxy = strdup( psz_proxy );
> +            i_ret_proxy_type = PROXY_TYPE_HTTPS;
> +        }
> +        else if( strncasecmp( psz_proxy, "socks://", 8 ) == 0
> +                 && PROXY_TYPE_SOCKS > i_ret_proxy_type )
> +        {
> +            if( psz_ret_proxy )
> +                free( psz_ret_proxy );
> +            psz_ret_proxy = strdup( psz_proxy );
> +            i_ret_proxy_type = PROXY_TYPE_SOCKS;
> +        }
> +        else if( i_proxy_type > i_ret_proxy_type
> +                 && !strstr( psz_proxy, "://" ) )
> +        {
> +            switch ( i_proxy_type ) {
> +            case PROXY_TYPE_HTTPS:
> +                if( psz_ret_proxy )
> +                    free( psz_ret_proxy );
> +                if( asprintf( &psz_ret_proxy, "https://%s", psz_proxy ) ==
> -1 ) +                    return NULL;
> +                break;
> +            case PROXY_TYPE_SOCKS:
> +                if( psz_ret_proxy )
> +                    free( psz_ret_proxy );
> +                if( asprintf( &psz_ret_proxy, "socks://%s", psz_proxy ) ==
> -1 ) +                    return NULL;
> +                break;
> +            case PROXY_TYPE_UNKNOWNED:
> +                break;
> +            default:
> +                if( psz_ret_proxy )
> +                    free( psz_ret_proxy );
> +                if( asprintf( &psz_ret_proxy, "http://%s", psz_proxy ) ==
> -1 ) +                    return NULL;
> +                break;
> +            }
> +
> +            i_ret_proxy_type = i_proxy_type;
> +        }
> +
> +        psz_proxy = psz_next_proxy;
>      }
> +    return psz_ret_proxy;
> +}

Too repetitive. Also redundant checks.

> +
> +char *vlc_getProxyUrl(const char *psz_url)
> +{
> +    char *proxy = config_GetPsz( (vlc_object_t *)(NULL), "http-proxy" );
> +    if (proxy != NULL)
> +    {

Hmm no. On 4.0 upgrade, users who set a single proxy for lack of better 
option, will still end up using the single proxy instead of the more flexible 
Windows setting.

> -    if (url.psz_password == NULL )
> -        url.psz_password = vlc_uri_encode(proxy_pwd);
> +        char *proxy_pwd = config_GetPsz( (vlc_object_t *)(NULL),
> "http-proxy-pwd" ); +        if (proxy_pwd == NULL)
> +            return proxy;
> +
> +        vlc_url_t url;
> +        if (vlc_UrlParse(&url, proxy) < 0)
> +        {
> +            free (proxy);
> +            free (proxy_pwd);
> +            return NULL;
> +        }
> 
> -    char *proxy_url = vlc_uri_compose (&url);
> -    vlc_UrlClean (&url);
> +        if (url.psz_password == NULL )
> +            url.psz_password = vlc_uri_encode(proxy_pwd);
> 
> -    free (proxy_pwd);
> -    free (proxy);
> +        char *proxy_url = vlc_uri_compose (&url);
> +        vlc_UrlClean (&url);
> 
> -#if 0
> -    /* Try to get the proxy server address from Windows internet settings.
> */ -    HKEY h_key;
> +        free (proxy_pwd);
> +        free (proxy);
> +        return proxy_url;
> +    }
> 
> -    /* Open the key */
> -    if( RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Microsoft"
> -                      "\\Windows\\CurrentVersion\\Internet Settings",
> -                      0, KEY_READ, &h_key ) == ERROR_SUCCESS )
> +#if VLC_WINSTORE_APP
> +    return NULL;
> +#else
> +    if ( psz_url == NULL )
>          return NULL;
> 
> -    DWORD len = sizeof( DWORD );
> -    BYTE proxyEnable;
> -
> -    /* Get the proxy enable value */
> -    if( RegQueryValueEx( h_key, "ProxyEnable", NULL, NULL,
> -                         &proxyEnable, &len ) != ERROR_SUCCESS
> -     || !proxyEnable )
> -        goto out;
> -
> -    /* Proxy is enabled */
> -    /* Get the proxy URL :
> -       Proxy server value in the registry can be something like
> "address:port" -       or "ftp=address1:port1;http=address2:port2 ..."
> -       depending of the configuration. */
> -    unsigned char key[256];
> -
> -    len = sizeof( key );
> -    if( RegQueryValueEx( h_key, "ProxyServer", NULL, NULL,
> -                         key, &len ) == ERROR_SUCCESS )
> +    char *psz_proxy = NULL;
> +    wchar_t *pwsz_url = ToWide( psz_url );
> +    bool b_autoproxy = false;
> +
> +    WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ieConfig;
> +    WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions;
> +    WINHTTP_PROXY_INFO autoProxyInfo;
> +
> +    memset( &ieConfig, 0, sizeof(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG) );
> +    memset( &autoProxyOptions, 0, sizeof(WINHTTP_AUTOPROXY_OPTIONS) );
> +    memset( &autoProxyInfo, 0, sizeof(WINHTTP_PROXY_INFO) );
> +
> +    if( WinHttpGetIEProxyConfigForCurrentUser(&ieConfig) )
>      {
> -        /* FIXME: This is lame. The string should be tokenized. */
> -#warning FIXME.
> -        char *psz_proxy = strstr( (char *)key, "http=" );
> -        if( psz_proxy != NULL )
> +        if( ieConfig.fAutoDetect )
> +            b_autoproxy = true;
> +        if( ieConfig.lpszAutoConfigUrl != NULL )
>          {
> -            psz_proxy += 5;
> -            char *end = strchr( psz_proxy, ';' );
> -            if( end != NULL )
> -                *end = '\0';
> +            b_autoproxy = true;
> +            autoProxyOptions.lpszAutoConfigUrl =
> ieConfig.lpszAutoConfigUrl; }
> +    }
> +    else
> +        b_autoproxy = true;
> +
> +    if( b_autoproxy )
> +    {
> +        if( autoProxyOptions.lpszAutoConfigUrl != NULL )
> +            autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
>          else
> -            psz_proxy = (char *)key;
> -        proxy_url = strdup( psz_proxy );
> +        {
> +            autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
> +            autoProxyOptions.dwAutoDetectFlags =
> WINHTTP_AUTO_DETECT_TYPE_DHCP +                                            
>     | WINHTTP_AUTO_DETECT_TYPE_DNS_A; +        }
> +        autoProxyOptions.fAutoLogonIfChallenged = TRUE;
> +
> +        HINTERNET handle = WinHttpOpen( L"VLC Proxy Lookup/1.0",
> +                                        WINHTTP_ACCESS_TYPE_NO_PROXY,
> WINHTTP_NO_PROXY_NAME, +                                       
> WINHTTP_NO_PROXY_BYPASS, 0 ); +
> +        if( !handle )
> +            goto end;
> +
> +        b_autoproxy = WinHttpGetProxyForUrl( handle, pwsz_url,
> &autoProxyOptions, &autoProxyInfo ); +
> +        WinHttpCloseHandle(handle);
> +    }
> +
> +    if( b_autoproxy )
> +    {
> +        if( autoProxyInfo.dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY )
> +            psz_proxy = FromWide( autoProxyInfo.lpszProxy );
> +    }
> +    else if( ieConfig.lpszProxy )
> +        psz_proxy = FromWide( ieConfig.lpszProxy );;
> +
> +    if( psz_proxy )
> +    {
> +        char* tmp = parse_proxy( psz_proxy );
> +        free( psz_proxy );
> +        psz_proxy = tmp;
>      }
> 
> -out:
> -    RegCloseKey( h_key );
> +end:
> +    if( autoProxyInfo.lpszProxy != NULL )
> +        GlobalFree( autoProxyInfo.lpszProxy );
> +    if( autoProxyInfo.lpszProxyBypass != NULL )
> +        GlobalFree( autoProxyInfo.lpszProxyBypass );
> +
> +    if( ieConfig.lpszAutoConfigUrl != NULL )
> +        GlobalFree( ieConfig.lpszAutoConfigUrl );
> +    if( ieConfig.lpszProxy != NULL )
> +        GlobalFree( ieConfig.lpszProxy );
> +    if( ieConfig.lpszProxyBypass != NULL )
> +        GlobalFree( ieConfig.lpszProxyBypass );
> +
> +    free( pwsz_url );
> +
> +    return psz_proxy;
>  #endif
> -    return proxy_url;
>  }


-- 
雷米‧德尼-库尔蒙
https://www.remlab.net/



More information about the vlc-devel mailing list