Commit a1c16d28 authored by Mike McCormack's avatar Mike McCormack Committed by Alexandre Julliard

Implement support for proxies with usernames and passwords.

parent d8c5f2bd
Makefile
rsrc.res
version.res
wininet.dll.dbg.c
wininet.spec.c
......
......@@ -4,7 +4,7 @@ TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = wininet.dll
IMPORTS = shlwapi user32 advapi32 kernel32
IMPORTS = mpr shlwapi user32 advapi32 kernel32
EXTRALIBS = $(LIBUNICODE)
LDDLLFLAGS = @LDDLLFLAGS@
......@@ -12,6 +12,7 @@ SYMBOLFILE = $(MODULE).tmp.o
C_SRCS = \
cookie.c \
dialogs.c \
ftp.c \
http.c \
internet.c \
......@@ -20,7 +21,9 @@ C_SRCS = \
utility.c \
wininet_main.c
RC_SRCS = version.rc
RC_SRCS = \
rsrc.rc \
version.rc
SUBDIRS = tests
......
/*
* 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) &params );
case ERROR_INTERNET_INCORRECT_PASSWORD:
return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
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;
}
......@@ -83,8 +83,9 @@ BOOL HTTP_ProcessHeader(LPWININETHTTPREQA lpwhr, LPCSTR field, LPCSTR value, DWO
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 @@ end:
}
/***********************************************************************
* 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 + 15]; /* 15 == "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 15 see above */
url = HeapAlloc(GetProcessHeap(), 0,
strlen(lpwhs->lpszServerName) + strlen(lpwhr->lpszPath) + 15);
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 @@ HINTERNET WINAPI HTTP_HttpOpenRequestA(HINTERNET hHttpSession,
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 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQA lpwhr, LPCSTR lpszUrl, LPCSTR
/* 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,22 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQA lpwhr, LPCSTR lpszUrl, LPCSTR
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 +1225,13 @@ BOOL WINAPI HTTP_HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
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 +1409,6 @@ BOOL WINAPI HTTP_HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
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 +1790,8 @@ INT HTTP_GetStdHeaderIndex(LPCSTR lpszField)
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 +1850,7 @@ BOOL HTTP_ProcessHeader(LPWININETHTTPREQA lpwhr, LPCSTR field, LPCSTR value, DWO
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 +2103,11 @@ INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQA lpwhr, LPCSTR lpszField)
* 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 +2124,14 @@ INT HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr)
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 +2139,21 @@ INT HTTP_InsertCustomHeader(LPWININETHTTPREQA lpwhr, LPHTTPHEADERA lpHdr)
* 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;
}
/***********************************************************************
......
......@@ -209,6 +209,68 @@ BOOL WINAPI DetectAutoProxyUrl(LPSTR lpszAutoProxyUrl,
/***********************************************************************
* 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 @@ HINTERNET WINAPI InternetOpenA(LPCSTR lpszAgent, DWORD dwAccessType,
lpwai = HeapAlloc(GetProcessHeap(), 0, sizeof(WININETAPPINFOA));
if (NULL == lpwai)
{
INTERNET_SetLastError(ERROR_OUTOFMEMORY);
else
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)
{
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;
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 @@ VOID INTERNET_CloseHandle(LPWININETAPPINFOA lpwai)
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);
}
......
......@@ -73,6 +73,8 @@ typedef struct
LPSTR lpszAgent;
LPSTR lpszProxy;
LPSTR lpszProxyBypass;
LPSTR lpszProxyUsername;
LPSTR lpszProxyPassword;
DWORD dwAccessType;
INTERNET_STATUS_CALLBACK lpfnStatusCB;
} WININETAPPINFOA, *LPWININETAPPINFOA;
......@@ -281,6 +283,8 @@ VOID SendAsyncCallbackInt(LPWININETAPPINFOA hIC, HINTERNET hHttpSession,
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);
......
/*
* Wininet resource definitions
*
* 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
*/
#define IDD_PROXYDLG 0x400
#define IDC_PROXY 0x401
#define IDC_REALM 0x402
#define IDC_USERNAME 0x403
#define IDC_PASSWORD 0x404
#define IDC_SAVEPASSWORD 0x405
/*
* 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"
......@@ -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
......
/*
* 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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment