This depends upon mpr-total.diff, and assumes wininet-stubs.diff has been applied.
This implementation uses the win95 method of requesting the proxy password. In win95, the username password dialog appears to be in wininet.dll, however in win98 it is in mpr.dll (NPSAuthenticationDialogA).
Mike
ChangeLog: * implement support for proxies with usernames and passwords
Only in dlls/wininet: .cvsignore Only in dlls/wininet: CVS Only in dlls/wininet: Makefile diff -ur dlls/wininet-old/Makefile.in dlls/wininet/Makefile.in --- dlls/wininet-old/Makefile.in 2003-07-17 13:17:04.000000000 -0500 +++ dlls/wininet/Makefile.in 2003-07-17 13:24:34.000000000 -0500 @@ -4,7 +4,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = wininet.dll -IMPORTS = shlwapi user32 advapi32 kernel32 +IMPORTS = shlwapi user32 advapi32 kernel32 mpr EXTRALIBS = $(LIBUNICODE) LDDLLFLAGS = @LDDLLFLAGS@ @@ -12,6 +12,7 @@ C_SRCS = \ cookie.c \ + dialogs.c \ ftp.c \ http.c \ internet.c \ @@ -20,7 +21,7 @@ utility.c \ wininet_main.c -RC_SRCS = version.rc +RC_SRCS = rsrc.rc version.rc SUBDIRS = tests Only in dlls/wininet: cookie.o Only in dlls/wininet: dialogs.o Only in dlls/wininet: ftp.o diff -ur dlls/wininet-old/http.c dlls/wininet/http.c --- dlls/wininet-old/http.c 2003-07-17 13:16:58.000000000 -0500 +++ dlls/wininet/http.c 2003-07-17 13:24:34.000000000 -0500 @@ -83,8 +83,9 @@ void HTTP_CloseConnection(LPWININETHTTPREQA lpwhr); BOOL HTTP_InterpretHttpHeader(LPSTR buffer, LPSTR field, INT fieldlen, LPSTR value, INT valuelen); INT HTTP_GetStdHeaderIndex(LPCSTR lpszField); -INT HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr); +BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr); INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQA lpwhr, LPCSTR lpszField); +BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQA lpwhr, INT index); inline static LPSTR HTTP_strdup( LPCSTR str ) { @@ -374,6 +375,160 @@ } /*********************************************************************** + * HTTP_Base64 + */ +static UINT HTTP_Base64( LPCSTR bin, LPSTR base64 ) +{ + UINT n = 0, x; + static LPSTR HTTP_Base64Enc = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + while( bin[0] ) + { + /* first 6 bits, all from bin[0] */ + base64[n++] = HTTP_Base64Enc[(bin[0] & 0xfc) >> 2]; + x = (bin[0] & 3) << 4; + + /* next 6 bits, 2 from bin[0] and 4 from bin[1] */ + if( !bin[1] ) + { + base64[n++] = HTTP_Base64Enc[x]; + base64[n++] = '='; + base64[n++] = '='; + break; + } + base64[n++] = HTTP_Base64Enc[ x | ( (bin[1]&0xf0) >> 4 ) ]; + x = ( bin[1] & 0x0f ) << 2; + + /* next 6 bits 4 from bin[1] and 2 from bin[2] */ + if( !bin[2] ) + { + base64[n++] = HTTP_Base64Enc[x]; + base64[n++] = '='; + break; + } + base64[n++] = HTTP_Base64Enc[ x | ( (bin[2]&0xc0 ) >> 6 ) ]; + + /* last 6 bits, all from bin [2] */ + base64[n++] = HTTP_Base64Enc[ bin[2] & 0x3f ]; + bin += 3; + } + base64[n] = 0; + return n; +} + +/*********************************************************************** + * HTTP_EncodeBasicAuth + * + * Encode the basic authentication string for HTTP 1.1 + */ +static LPSTR HTTP_EncodeBasicAuth( LPCSTR username, LPCSTR password) +{ + UINT len; + LPSTR in, out, szBasic = "Basic "; + + len = strlen( username ) + 1 + strlen ( password ) + 1; + in = HeapAlloc( GetProcessHeap(), 0, len ); + if( !in ) + return NULL; + + len = strlen(szBasic) + + (strlen( username ) + 1 + strlen ( password ))*2 + 1 + 1; + out = HeapAlloc( GetProcessHeap(), 0, len ); + if( out ) + { + strcpy( in, username ); + strcat( in, ":" ); + strcat( in, password ); + strcpy( out, szBasic ); + HTTP_Base64( in, &out[strlen(out)] ); + } + HeapFree( GetProcessHeap(), 0, in ); + + return out; +} + +/*********************************************************************** + * HTTP_InsertProxyAuthorization + * + * Insert the basic authorization field in the request header + */ +BOOL HTTP_InsertProxyAuthorization( LPWININETHTTPREQA lpwhr, + LPCSTR username, LPCSTR password ) +{ + HTTPHEADERA hdr; + INT index; + + hdr.lpszField = "Proxy-Authorization"; + hdr.lpszValue = HTTP_EncodeBasicAuth( username, password ); + hdr.wFlags = HDR_ISREQUEST; + hdr.wCount = 0; + if( !hdr.lpszValue ) + return FALSE; + + TRACE("Inserting %s = %s\n", + debugstr_a( hdr.lpszField ), debugstr_a( hdr.lpszValue ) ); + + /* remove the old proxy authorization header */ + index = HTTP_GetCustomHeaderIndex( lpwhr, hdr.lpszField ); + if( index >=0 ) + HTTP_DeleteCustomHeader( lpwhr, index ); + + HTTP_InsertCustomHeader(lpwhr, &hdr); + HeapFree( GetProcessHeap(), 0, hdr.lpszValue ); + + return TRUE; +} + +/*********************************************************************** + * HTTP_DealWithProxy + */ +static BOOL HTTP_DealWithProxy( LPWININETAPPINFOA hIC, + LPWININETHTTPSESSIONA lpwhs, LPWININETHTTPREQA lpwhr) +{ + char buf[MAXHOSTNAME]; + char proxy[MAXHOSTNAME + 13]; /* 13 == "http://" + sizeof(port#) + ":/\0" */ + char* url, *szNul = ""; + URL_COMPONENTSA UrlComponents; + + memset( &UrlComponents, 0, sizeof UrlComponents ); + UrlComponents.dwStructSize = sizeof UrlComponents; + UrlComponents.lpszHostName = buf; + UrlComponents.dwHostNameLength = MAXHOSTNAME; + + sprintf(proxy, "http://%s/", hIC->lpszProxy); + if( !InternetCrackUrlA(proxy, 0, 0, &UrlComponents) ) + return FALSE; + if( UrlComponents.dwHostNameLength == 0 ) + return FALSE; + + if( !lpwhr->lpszPath ) + lpwhr->lpszPath = szNul; + TRACE("server='%s' path='%s'\n", + lpwhs->lpszServerName, lpwhr->lpszPath); + /* for constant 13 see above */ + url = HeapAlloc(GetProcessHeap(), 0, + strlen(lpwhs->lpszServerName) + strlen(lpwhr->lpszPath) + 13); + + if(UrlComponents.nPort == INTERNET_INVALID_PORT_NUMBER) + UrlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; + + sprintf(url, "http://%s:%d", lpwhs->lpszServerName, + lpwhs->nServerPort); + if( lpwhr->lpszPath[0] != '/' ) + strcat( url, "/" ); + strcat(url, lpwhr->lpszPath); + if(lpwhr->lpszPath != szNul) + HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath); + lpwhr->lpszPath = url; + /* FIXME: Do I have to free lpwhs->lpszServerName here ? */ + lpwhs->lpszServerName = HTTP_strdup(UrlComponents.lpszHostName); + lpwhs->nServerPort = UrlComponents.nPort; + + return TRUE; +} + +/*********************************************************************** * HTTP_HttpOpenRequestA (internal) * * Open a HTTP request handle @@ -454,54 +609,19 @@ char buf[MAXHOSTNAME]; URL_COMPONENTSA UrlComponents; - UrlComponents.lpszExtraInfo = NULL; - UrlComponents.lpszPassword = NULL; - UrlComponents.lpszScheme = NULL; - UrlComponents.lpszUrlPath = NULL; - UrlComponents.lpszUserName = NULL; + memset( &UrlComponents, 0, sizeof UrlComponents ); + UrlComponents.dwStructSize = sizeof UrlComponents; UrlComponents.lpszHostName = buf; UrlComponents.dwHostNameLength = MAXHOSTNAME; InternetCrackUrlA(lpszReferrer, 0, 0, &UrlComponents); if (strlen(UrlComponents.lpszHostName)) lpwhr->lpszHostName = HTTP_strdup(UrlComponents.lpszHostName); - } else if (NULL != hIC->lpszProxy && hIC->lpszProxy[0] != 0) { - char buf[MAXHOSTNAME]; - char proxy[MAXHOSTNAME + 15]; /* 15 == "http://" + sizeof(port#) + ":/\0" */ - URL_COMPONENTSA UrlComponents; - - UrlComponents.lpszExtraInfo = NULL; - UrlComponents.lpszPassword = NULL; - UrlComponents.lpszScheme = NULL; - UrlComponents.lpszUrlPath = NULL; - UrlComponents.lpszUserName = NULL; - UrlComponents.lpszHostName = buf; - UrlComponents.dwHostNameLength = MAXHOSTNAME; - - sprintf(proxy, "http://%s/", hIC->lpszProxy); - InternetCrackUrlA(proxy, 0, 0, &UrlComponents); - if (strlen(UrlComponents.lpszHostName)) { - /* for constant 15 see above */ - char* url = HeapAlloc(GetProcessHeap(), 0, strlen(lpwhs->lpszServerName) + strlen(lpwhr->lpszPath) + 15); - - if(UrlComponents.nPort == INTERNET_INVALID_PORT_NUMBER) - UrlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; - - if(lpwhr->lpszHostName != 0) { - HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName); - lpwhr->lpszHostName = 0; - } - sprintf(url, "http://%s:%d/%s", lpwhs->lpszServerName, lpwhs->nServerPort, lpwhr->lpszPath); - if(lpwhr->lpszPath) - HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath); - lpwhr->lpszPath = url; - /* FIXME: Do I have to free lpwhs->lpszServerName here ? */ - lpwhs->lpszServerName = HTTP_strdup(UrlComponents.lpszHostName); - lpwhs->nServerPort = UrlComponents.nPort; - } } else { lpwhr->lpszHostName = HTTP_strdup(lpwhs->lpszServerName); } + if (NULL != hIC->lpszProxy && hIC->lpszProxy[0] != 0) + HTTP_DealWithProxy( hIC, lpwhs, lpwhr ); if (hIC->lpszAgent) { @@ -913,6 +1033,11 @@ /* if it's an absolute path, keep the same session info */ strcpy(path,lpszUrl); } + else if (NULL != hIC->lpszProxy && hIC->lpszProxy[0] != 0) + { + TRACE("Redirect through proxy\n"); + strcpy(path,lpszUrl); + } else { URL_COMPONENTSA urlComponents; @@ -937,9 +1062,23 @@ if (urlComponents.nPort == INTERNET_INVALID_PORT_NUMBER) urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; - /* consider the current host as the referef */ +#if 0 + /* + * This upsets redirects to binary files on sourceforge.net + * and gives an html page instead of the target file + * Examination of the HTTP request sent by native wininet.dll + * reveals that it doesn't send a referrer in that case. + & + * Maybe there's a flag that enables this, or maybe a referrer + * shouldn't be added in case of a redirect. + */ + + /* consider the current host as the referrer */ if (NULL != lpwhs->lpszServerName && strlen(lpwhs->lpszServerName)) - HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpwhs->lpszServerName, HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE|HTTP_ADDHDR_FLAG_ADD_IF_NEW); + HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpwhs->lpszServerName, + HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE| + HTTP_ADDHDR_FLAG_ADD_IF_NEW); +#endif if (NULL != lpwhs->lpszServerName) HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName); @@ -1087,6 +1226,13 @@ requestStringLen += headerLength + 2; /* \r\n */ } + + /* if there isa proxy username and password, add it to the headers */ + if( hIC && (hIC->lpszProxyUsername || hIC->lpszProxyPassword ) ) + { + HTTP_InsertProxyAuthorization( lpwhr, hIC->lpszProxyUsername, hIC->lpszProxyPassword ); + } + /* Calculate length of custom request headers */ for (i = 0; i < lpwhr->nCustHeaders; i++) { @@ -1264,60 +1410,6 @@ nPosStart = nPosEnd; } } - - /* FIXME: is this right? I'm not sure if this should be here or elsewhere (the loop, too) - * FIXME: don't do this if they specify INTERNET_FLAG_NO_AUTO_REDIRECT */ - if (lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue) - { - URL_COMPONENTSA urlComponents; - char protocol[32], hostName[MAXHOSTNAME], userName[1024]; - char password[1024], path[2048], extra[1024]; - - TRACE("Got a Location header: Going around to a new location: %s", - debugstr_a(lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue)); - - urlComponents.dwStructSize = sizeof(URL_COMPONENTSA); - urlComponents.lpszScheme = protocol; - urlComponents.dwSchemeLength = 32; - urlComponents.lpszHostName = hostName; - urlComponents.dwHostNameLength = MAXHOSTNAME; - urlComponents.lpszUserName = userName; - urlComponents.dwUserNameLength = 1024; - urlComponents.lpszPassword = password; - urlComponents.dwPasswordLength = 1024; - urlComponents.lpszUrlPath = path; - urlComponents.dwUrlPathLength = 2048; - urlComponents.lpszExtraInfo = extra; - urlComponents.dwExtraInfoLength = 1024; - if (!InternetCrackUrlA(lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue, - strlen(lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue), - 0, &urlComponents)) - goto lend; - - if (urlComponents.nScheme != INTERNET_SCHEME_HTTP) - { - FIXME("cannot redirect to non HTTP page\n"); - goto lend; - } - - HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath); - HeapAlloc(GetProcessHeap(), 0, strlen(path) + 1); - strcpy(lpwhr->lpszPath, path); - - if (urlComponents.dwHostNameLength) - { - HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName); - HeapAlloc(GetProcessHeap(), 0, strlen(hostName) + 1); - strcpy(lpwhr->lpszHostName, hostName); - } - - SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext, - INTERNET_STATUS_REDIRECT, NULL, 0); - - HeapFree(GetProcessHeap(), 0, lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue); - lpwhr->StdHeaders[HTTP_QUERY_LOCATION].lpszValue = NULL; - loop_next = TRUE; - } } while (loop_next); @@ -1699,6 +1791,8 @@ index = HTTP_QUERY_CONTENT_LENGTH; else if (!strcasecmp(lpszField,"User-Agent")) index = HTTP_QUERY_USER_AGENT; + else if (!strcasecmp(lpszField,"Proxy-Authenticate")) + index = HTTP_QUERY_PROXY_AUTHENTICATE; else { TRACE("Couldn't find %s in standard header table\n", lpszField); @@ -1757,8 +1851,7 @@ if (dwModifier & HTTP_ADDHDR_FLAG_REQ) hdr.wFlags |= HDR_ISREQUEST; - index = HTTP_InsertCustomHeader(lpwhr, &hdr); - return index >= 0; + return HTTP_InsertCustomHeader(lpwhr, &hdr); } } @@ -2011,10 +2104,11 @@ * Insert header into array * */ -INT HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr) +BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr) { INT count; LPHTTPHEADERA lph = NULL; + BOOL r = FALSE; TRACE("--> %s: %s\n", lpHdr->lpszField, lpHdr->lpszValue); count = lpwhr->nCustHeaders + 1; @@ -2031,15 +2125,14 @@ lpwhr->pCustHeaders[count-1].wFlags = lpHdr->wFlags; lpwhr->pCustHeaders[count-1].wCount= lpHdr->wCount; lpwhr->nCustHeaders++; + r = TRUE; } else { INTERNET_SetLastError(ERROR_OUTOFMEMORY); - count = 0; } - TRACE("%d <--\n", count-1); - return count - 1; + return r; } @@ -2047,12 +2140,21 @@ * HTTP_DeleteCustomHeader (internal) * * Delete header from array - * + * If this function is called, the indexs may change. */ -BOOL HTTP_DeleteCustomHeader(INT index) +BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQA lpwhr, INT index) { - FIXME("STUB\n"); - return FALSE; + if( lpwhr->nCustHeaders <= 0 ) + return FALSE; + if( lpwhr->nCustHeaders >= index ) + return FALSE; + lpwhr->nCustHeaders--; + + memmove( &lpwhr->pCustHeaders[index], &lpwhr->pCustHeaders[index+1], + (lpwhr->nCustHeaders - index)* sizeof(HTTPHEADERA) ); + memset( &lpwhr->pCustHeaders[lpwhr->nCustHeaders], 0, sizeof(HTTPHEADERA) ); + + return TRUE; } /*********************************************************************** Only in dlls/wininet: http.o diff -ur dlls/wininet-old/internet.c dlls/wininet/internet.c --- dlls/wininet-old/internet.c 2003-07-17 13:16:58.000000000 -0500 +++ dlls/wininet/internet.c 2003-07-17 13:24:34.000000000 -0500 @@ -209,6 +209,68 @@ /*********************************************************************** + * INTERNET_ConfigureProxyFromReg + * + * FIXME: + * The proxy may be specified in the form 'http=proxy.my.org' + * Presumably that means there can be ftp=ftpproxy.my.org too. + */ +static BOOL INTERNET_ConfigureProxyFromReg( LPWININETAPPINFOA lpwai ) +{ + HKEY key; + DWORD r, keytype, len, enabled; + LPSTR lpszInternetSettings = + "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"; + + r = RegOpenKeyA(HKEY_CURRENT_USER, lpszInternetSettings, &key); + if ( r != ERROR_SUCCESS ) + return FALSE; + + len = sizeof enabled; + r = RegQueryValueExA( key, "ProxyEnable", NULL, &keytype, + (BYTE*)&enabled, &len); + if( (r == ERROR_SUCCESS) && enabled ) + { + TRACE("Proxy is enabled.\n"); + + /* figure out how much memory the proxy setting takes */ + r = RegQueryValueExA( key, "ProxyServer", NULL, &keytype, + NULL, &len); + if( (r == ERROR_SUCCESS) && len && (keytype == REG_SZ) ) + { + LPSTR szProxy, p, szHttp = "http="; + + szProxy=HeapAlloc( GetProcessHeap(), 0, len+1 ); + RegQueryValueExA( key, "ProxyServer", NULL, &keytype, + (BYTE*)szProxy, &len); + + /* find the http proxy, and strip away everything else */ + p = strstr( szProxy, szHttp ); + if( p ) + { + p += strlen(szHttp); + strcpy( szProxy, p ); + } + p = strchr( szProxy, ' ' ); + if( p ) + *p = 0; + + lpwai->dwAccessType = INTERNET_OPEN_TYPE_PROXY; + lpwai->lpszProxy = szProxy; + + TRACE("http proxy = %s\n", lpwai->lpszProxy); + } + else + ERR("Couldn't read proxy server settings.\n"); + } + else + TRACE("Proxy is not enabled.\n"); + RegCloseKey(key); + + return enabled; +} + +/*********************************************************************** * InternetOpenA (WININET.@) * * Per-application initialization of wininet @@ -231,53 +293,42 @@ lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA)); if (NULL == lpwai) - INTERNET_SetLastError(ERROR_OUTOFMEMORY); - else { - memset(lpwai, 0, sizeof(WININETAPPINFOA)); - lpwai->hdr.htype = WH_HINIT; - lpwai->hdr.lpwhparent = NULL; - lpwai->hdr.dwFlags = dwFlags; - if (NULL != lpszAgent) - { - if ((lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0,strlen(lpszAgent)+1))) - strcpy( lpwai->lpszAgent, lpszAgent ); - } - if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG) - { - HKEY key; - if (!RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", &key)) - { - DWORD keytype, len, enabled; - RegQueryValueExA(key, "ProxyEnable", NULL, NULL, (BYTE*)&enabled, NULL); - if(enabled) - { - if(!RegQueryValueExA(key, "ProxyServer", NULL, &keytype, NULL, &len) && len && keytype == REG_SZ) - { - lpwai->lpszProxy=HeapAlloc( GetProcessHeap(), 0, len+1 ); - RegQueryValueExA(key, "ProxyServer", NULL, &keytype, (BYTE*)lpwai->lpszProxy, &len); - TRACE("Proxy = %s\n", lpwai->lpszProxy); - dwAccessType = INTERNET_OPEN_TYPE_PROXY; - } - } - else - { - TRACE("Proxy is not enabled.\n"); - } - RegCloseKey(key); - } - } - else if (NULL != lpszProxy) - { - if ((lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxy)+1 ))) - strcpy( lpwai->lpszProxy, lpszProxy ); - } - if (NULL != lpszProxyBypass) - { - if ((lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0, strlen(lpszProxyBypass)+1))) - strcpy( lpwai->lpszProxyBypass, lpszProxyBypass ); - } - lpwai->dwAccessType = dwAccessType; + INTERNET_SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + + memset(lpwai, 0, sizeof(WININETAPPINFOA)); + lpwai->hdr.htype = WH_HINIT; + lpwai->hdr.lpwhparent = NULL; + lpwai->hdr.dwFlags = dwFlags; + lpwai->dwAccessType = dwAccessType; + lpwai->lpszProxyUsername = NULL; + lpwai->lpszProxyPassword = NULL; + + if (NULL != lpszAgent) + { + lpwai->lpszAgent = HeapAlloc( GetProcessHeap(),0, + strlen(lpszAgent)+1); + if (lpwai->lpszAgent) + strcpy( lpwai->lpszAgent, lpszAgent ); + } + if(dwAccessType == INTERNET_OPEN_TYPE_PRECONFIG) + INTERNET_ConfigureProxyFromReg( lpwai ); + else if (NULL != lpszProxy) + { + lpwai->lpszProxy = HeapAlloc( GetProcessHeap(), 0, + strlen(lpszProxy)+1); + if (lpwai->lpszProxy) + strcpy( lpwai->lpszProxy, lpszProxy ); + } + + if (NULL != lpszProxyBypass) + { + lpwai->lpszProxyBypass = HeapAlloc( GetProcessHeap(), 0, + strlen(lpszProxyBypass)+1); + if (lpwai->lpszProxyBypass) + strcpy( lpwai->lpszProxyBypass, lpszProxyBypass ); } TRACE("returning %p\n", (HINTERNET)lpwai); @@ -648,6 +699,12 @@ if (lpwai->lpszProxyBypass) HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyBypass); + if (lpwai->lpszProxyUsername) + HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyUsername); + + if (lpwai->lpszProxyPassword) + HeapFree(GetProcessHeap(), 0, lpwai->lpszProxyPassword); + HeapFree(GetProcessHeap(), 0, lpwai); } diff -ur dlls/wininet-old/internet.h dlls/wininet/internet.h --- dlls/wininet-old/internet.h 2003-07-17 13:16:58.000000000 -0500 +++ dlls/wininet/internet.h 2003-07-17 13:24:34.000000000 -0500 @@ -73,6 +73,8 @@ LPSTR lpszAgent; LPSTR lpszProxy; LPSTR lpszProxyBypass; + LPSTR lpszProxyUsername; + LPSTR lpszProxyPassword; DWORD dwAccessType; INTERNET_STATUS_CALLBACK lpfnStatusCB; } WININETAPPINFOA, *LPWININETAPPINFOA; @@ -278,6 +280,8 @@ DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInfo , DWORD dwStatusInfoLength); +BOOL HTTP_InsertProxyAuthorization( LPWININETHTTPREQA lpwhr, + LPCSTR username, LPCSTR password ); BOOL NETCON_connected(WININET_NETCONNECTION *connection); void NETCON_init(WININET_NETCONNECTION *connnection, BOOL useSSL); Only in dlls/wininet: internet.o Only in dlls/wininet: netconnection.o Only in dlls/wininet: rsrc.res Only in dlls/wininet: tests Only in dlls/wininet: urlcache.o Only in dlls/wininet: utility.o Only in dlls/wininet: version.res Only in dlls/wininet: wininet.dll.dbg.c Only in dlls/wininet: wininet.dll.dbg.o Only in dlls/wininet: wininet.dll.so Only in dlls/wininet: wininet.dll.tmp.o diff -ur dlls/wininet-old/wininet.spec dlls/wininet/wininet.spec --- dlls/wininet-old/wininet.spec 2003-07-17 13:17:42.000000000 -0500 +++ dlls/wininet/wininet.spec 2003-07-17 13:24:34.000000000 -0500 @@ -101,7 +101,7 @@ @ stdcall InternetCreateUrlW(ptr long ptr ptr) @ stub InternetDebugGetLocalTime @ stub InternetDial -@ stub InternetErrorDlg +@ stdcall InternetErrorDlg(long long long long ptr) @ stdcall InternetFindNextFileA(ptr ptr) @ stub InternetFindNextFileW @ stub InternetGetCertByURL Only in dlls/wininet: wininet.spec.c Only in dlls/wininet: wininet.spec.def Only in dlls/wininet: wininet.spec.o Only in dlls/wininet: wininet_main.o --- /dev/null 1994-07-17 18:46:18.000000000 -0500 +++ dlls/wininet/resource.h 2003-07-17 12:59:04.000000000 -0500 @@ -0,0 +1,9 @@ + +#define IDD_PROXYDLG 0x400 + +#define IDC_PROXY 0x401 +#define IDC_REALM 0x402 +#define IDC_USERNAME 0x403 +#define IDC_PASSWORD 0x404 +#define IDC_SAVEPASSWORD 0x405 + --- /dev/null 1994-07-17 18:46:18.000000000 -0500 +++ dlls/wininet/rsrc.rc 2003-07-17 12:58:51.000000000 -0500 @@ -0,0 +1,42 @@ +/* + * Top level resource file for Wininet + * + * Copyright 2003 Mike McCormack for Codeweavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "windef.h" +#include "winuser.h" +#include "winnls.h" + +#include "resource.h" + +/* + * Everything that does not depend on language, + * like textless bitmaps etc, go into the + * neutral language. This will prevent them from + * being duplicated for each language. + */ +/* #include "wininet_xx.rc" */ + +/* + * Everything specific to any language goes + * in one of the specific files. + * Note that you can and may override resources + * which also have a neutral version. This is to + * get localized bitmaps for example. + */ +#include "wininet_En.rc" --- /dev/null 1994-07-17 18:46:18.000000000 -0500 +++ dlls/wininet/wininet_En.rc 2003-07-17 12:58:58.000000000 -0500 @@ -0,0 +1,41 @@ +/* + * Copyright 2003 Mike McCormack for Codeweavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +IDD_PROXYDLG DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 250, 154 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Enter Network Password" +FONT 8, "Helv" +{ + LTEXT "Please enter your username and password:", -1, 40, 6, 150, 15 + LTEXT "Proxy", -1, 40, 26, 50, 10 + LTEXT "Realm", -1, 40, 46, 50, 10 + LTEXT "User", -1, 40, 66, 50, 10 + LTEXT "Password", -1, 40, 86, 50, 10 + LTEXT "" IDC_PROXY, 80, 26, 150, 14, 0 + LTEXT "" IDC_REALM, 80, 46, 150, 14, 0 + EDITTEXT IDC_USERNAME, 80, 66, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP + EDITTEXT IDC_PASSWORD, 80, 86, 150, 14, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP | ES_PASSWORD + CHECKBOX "&Save this password (insecure)", IDC_SAVEPASSWORD, + 80, 106, 150, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP + PUSHBUTTON "OK", IDOK, 98, 126, 56, 14, WS_GROUP | WS_TABSTOP | BS_DEFPUSHBUTTON + PUSHBUTTON "Cancel", IDCANCEL, 158, 126, 56, 14, WS_GROUP | WS_TABSTOP +} + + --- /dev/null 1994-07-17 18:46:18.000000000 -0500 +++ dlls/wininet/dialogs.c 2003-07-17 12:58:43.000000000 -0500 @@ -0,0 +1,364 @@ +/* + * Wininet + * + * Copyright 2003 Mike McCormack for CodeWeavers Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "wininet.h" +#include "winnetwk.h" +#include "winnls.h" +#include "wine/debug.h" +#include "winerror.h" +#define NO_SHLWAPI_STREAM +#include "shlwapi.h" + +#include "internet.h" + +#include "wine/unicode.h" + +#include "resource.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wininet); + +struct WININET_ErrorDlgParams +{ + HWND hWnd; + HINTERNET hRequest; + DWORD dwError; + DWORD dwFlags; + LPVOID* lppvData; +}; + +/*********************************************************************** + * WININET_GetProxyServer + * + * Determine the name of the proxy server the request is using + */ +static BOOL WININET_GetProxyServer( HINTERNET hRequest, LPSTR szBuf, DWORD sz ) +{ + LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hRequest; + LPWININETHTTPSESSIONA lpwhs = NULL; + LPWININETAPPINFOA hIC = NULL; + LPSTR p; + + if (NULL == lpwhr) + return FALSE; + + lpwhs = (LPWININETHTTPSESSIONA) lpwhr->hdr.lpwhparent; + if (NULL == lpwhs) + return FALSE; + + hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent; + if (NULL == hIC) + return FALSE; + + strncpy(szBuf, hIC->lpszProxy, sz); + + /* FIXME: perhaps it would be better to use InternetCrackUrl here */ + p = strchr(szBuf, ':'); + if(*p) + *p = 0; + + return TRUE; +} + +/*********************************************************************** + * WININET_GetAuthRealm + * + * Determine the name of the (basic) Authentication realm + */ +static BOOL WININET_GetAuthRealm( HINTERNET hRequest, LPSTR szBuf, DWORD sz ) +{ + LPSTR p, q; + DWORD index; + + /* extract the Realm from the proxy response and show it */ + index = 0; + if( !HttpQueryInfoA( hRequest, HTTP_QUERY_PROXY_AUTHENTICATE, + szBuf, &sz, &index) ) + return FALSE; + + /* + * FIXME: maybe we should check that we're + * dealing with 'Basic' Authentication + */ + p = strchr( szBuf, ' ' ); + if( p && !strncmp( p+1, "realm=", 6 ) ) + { + /* remove quotes */ + p += 7; + if( *p == '"' ) + { + p++; + q = strrchr( p, '"' ); + if( q ) + *q = 0; + } + } + + strcpy( szBuf, p ); + + return TRUE; +} + +/*********************************************************************** + * WININET_GetSetPassword + */ +static BOOL WININET_GetSetPassword( HWND hdlg, LPCSTR szServer, + LPCSTR szRealm, BOOL bSet ) +{ + CHAR szResource[0x80], szUserPass[0x40]; + LPSTR p; + HWND hUserItem, hPassItem; + DWORD r, dwMagic = 19; + UINT len; + WORD sz; + + hUserItem = GetDlgItem( hdlg, IDC_USERNAME ); + hPassItem = GetDlgItem( hdlg, IDC_PASSWORD ); + + /* now try fetch the username and password */ + strcpy( szResource, szServer); + strcat( szResource, "/"); + strcat( szResource, szRealm); + + if( bSet ) + { + szUserPass[0] = 0; + GetWindowTextA( hUserItem, szUserPass, sizeof szUserPass-1 ); + strcat(szUserPass, ":"); + len = strlen( szUserPass ); + GetWindowTextA( hPassItem, szUserPass+len, sizeof szUserPass-len ); + + r = WNetCachePassword( szResource, strlen( szResource ) + 1, + szUserPass, strlen( szUserPass ) + 1, dwMagic, 0 ); + + return ( r == WN_SUCCESS ); + } + + sz = sizeof szUserPass; + r = WNetGetCachedPassword( szResource, strlen( szResource ) + 1, + szUserPass, &sz, dwMagic ); + if( r != WN_SUCCESS ) + return FALSE; + + p = strchr( szUserPass, ':' ); + if( p ) + { + *p = 0; + SetWindowTextA( hUserItem, szUserPass ); + SetWindowTextA( hPassItem, p+1 ); + } + + return TRUE; +} + +/*********************************************************************** + * WININET_SetProxyAuthorization + */ +static BOOL WININET_SetProxyAuthorization( HINTERNET hRequest, + LPSTR username, LPSTR password ) +{ + LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) hRequest; + LPWININETHTTPSESSIONA lpwhs; + LPWININETAPPINFOA hIC; + LPSTR p; + + lpwhs = (LPWININETHTTPSESSIONA) lpwhr->hdr.lpwhparent; + if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION) + { + INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE); + return FALSE; + } + + hIC = (LPWININETAPPINFOA) lpwhs->hdr.lpwhparent; + + p = HeapAlloc( GetProcessHeap(), 0, strlen( username ) + 1 ); + if( !p ) + return FALSE; + + strcpy( p, username ); + hIC->lpszProxyUsername = p; + + p = HeapAlloc( GetProcessHeap(), 0, strlen( password ) + 1 ); + if( !p ) + return FALSE; + + strcpy( p, password ); + hIC->lpszProxyPassword = p; + + return TRUE; +} + +/*********************************************************************** + * WININET_ProxyPasswordDialog + */ +static INT_PTR WINAPI WININET_ProxyPasswordDialog( + HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + HWND hitem; + struct WININET_ErrorDlgParams *params; + CHAR szRealm[0x80], szServer[0x80]; + + if( uMsg == WM_INITDIALOG ) + { + TRACE("WM_INITDIALOG (%08lx)\n", lParam); + + /* save the parameter list */ + params = (struct WININET_ErrorDlgParams*) lParam; + SetWindowLongW( hdlg, GWL_USERDATA, lParam ); + + /* extract the Realm from the proxy response and show it */ + if( WININET_GetAuthRealm( params->hRequest, + szRealm, sizeof szRealm) ) + { + hitem = GetDlgItem( hdlg, IDC_REALM ); + SetWindowTextA( hitem, szRealm ); + } + + /* extract the name of the proxy server */ + if( WININET_GetProxyServer( params->hRequest, + szServer, sizeof szServer) ) + { + hitem = GetDlgItem( hdlg, IDC_PROXY ); + SetWindowTextA( hitem, szServer ); + } + + WININET_GetSetPassword( hdlg, szServer, szRealm, FALSE ); + + return TRUE; + } + + params = (struct WININET_ErrorDlgParams*) + GetWindowLongW( hdlg, GWL_USERDATA ); + + switch( uMsg ) + { + case WM_COMMAND: + if( wParam == IDOK ) + { + LPWININETHTTPREQA lpwhr = (LPWININETHTTPREQA) params->hRequest; + CHAR username[0x20], password[0x20]; + + username[0] = 0; + hitem = GetDlgItem( hdlg, IDC_USERNAME ); + if( hitem ) + GetWindowTextA( hitem, username, sizeof username ); + + password[0] = 0; + hitem = GetDlgItem( hdlg, IDC_PASSWORD ); + if( hitem ) + GetWindowTextA( hitem, password, sizeof password ); + + hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD ); + if( hitem && + SendMessageA( hitem, BM_GETSTATE, 0, 0 ) && + WININET_GetAuthRealm( params->hRequest, + szRealm, sizeof szRealm) && + WININET_GetProxyServer( params->hRequest, + szServer, sizeof szServer) ) + { + WININET_GetSetPassword( hdlg, szServer, szRealm, TRUE ); + } + WININET_SetProxyAuthorization( lpwhr, username, password ); + + EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY ); + return TRUE; + } + if( wParam == IDCANCEL ) + { + EndDialog( hdlg, 0 ); + return TRUE; + } + break; + } + return FALSE; +} + +/*********************************************************************** + * WININET_GetConnectionStatus + */ +static INT WININET_GetConnectionStatus( HINTERNET hRequest ) +{ + CHAR szStatus[0x20]; + DWORD sz, index, dwStatus; + + TRACE("%p\n", hRequest ); + + sz = sizeof szStatus; + index = 0; + if( !HttpQueryInfoA( hRequest, HTTP_QUERY_STATUS_CODE, + szStatus, &sz, &index)) + return -1; + dwStatus = atoi( szStatus ); + + TRACE("request %p status = %ld\n", hRequest, dwStatus ); + + return dwStatus; +} + + +/*********************************************************************** + * InternetErrorDlg + */ +DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest, + DWORD dwError, DWORD dwFlags, LPVOID* lppvData) +{ + struct WININET_ErrorDlgParams params; + HMODULE hwininet = GetModuleHandleA( "wininet.dll" ); + INT dwStatus; + + TRACE("%p %p %ld %08lx %p\n", hWnd, hRequest, dwError, dwFlags, lppvData); + + params.hWnd = hWnd; + params.hRequest = hRequest; + params.dwError = dwError; + params.dwFlags = dwFlags; + params.lppvData = lppvData; + + switch( dwError ) + { + case ERROR_SUCCESS: + if( !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) ) + return 0; + dwStatus = WININET_GetConnectionStatus( hRequest ); + if( HTTP_STATUS_PROXY_AUTH_REQ != dwStatus ) + return ERROR_SUCCESS; + return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ), + hWnd, WININET_ProxyPasswordDialog, (LPARAM) ¶ms ); + + case ERROR_INTERNET_INCORRECT_PASSWORD: + return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ), + hWnd, WININET_ProxyPasswordDialog, (LPARAM) ¶ms ); + + case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR: + case ERROR_INTERNET_INVALID_CA: + case ERROR_INTERNET_POST_IS_NON_SECURE: + case ERROR_INTERNET_SEC_CERT_CN_INVALID: + case ERROR_INTERNET_SEC_CERT_DATE_INVALID: + FIXME("Need to display dialog for error %ld\n", dwError); + return ERROR_SUCCESS; + } + return ERROR_INVALID_PARAMETER; +} +