[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