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

Pierre Lamot pierre at videolabs.io
Thu Feb 8 18:58:29 CET 2018


---
 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])
+])
+
+
 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>])
+ */
+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;
+}
+
+char *vlc_getProxyUrl(const char *psz_url)
+{
+    char *proxy = config_GetPsz( (vlc_object_t *)(NULL), "http-proxy" );
+    if (proxy != NULL)
+    {
 
-    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;
 }
-- 
2.14.1



More information about the vlc-devel mailing list