Commit 34fcbb5f authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

wininet: Make HTTP_HttpSendRequestW static and avoid its forward declaration.

parent e9749651
......@@ -374,25 +374,6 @@ static void HTTP_FreeTokens(LPWSTR * token_array)
HeapFree(GetProcessHeap(), 0, token_array);
}
/* **********************************************************************
*
* Helper functions for the HttpSendRequest(Ex) functions
*
*/
static void AsyncHttpSendRequestProc(WORKREQUEST *workRequest)
{
struct WORKREQ_HTTPSENDREQUESTW const *req = &workRequest->u.HttpSendRequestW;
http_request_t *lpwhr = (http_request_t*) workRequest->hdr;
TRACE("%p\n", lpwhr);
HTTP_HttpSendRequestW(lpwhr, req->lpszHeader,
req->dwHeaderLength, req->lpOptional, req->dwOptionalLength,
req->dwContentLength, req->bEndRequest);
HeapFree(GetProcessHeap(), 0, req->lpszHeader);
}
static void HTTP_FixURL(http_request_t *lpwhr)
{
static const WCHAR szSlash[] = { '/',0 };
......@@ -1021,158 +1002,6 @@ BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest,
}
/***********************************************************************
* HttpEndRequestA (WININET.@)
*
* Ends an HTTP request that was started by HttpSendRequestEx
*
* RETURNS
* TRUE if successful
* FALSE on failure
*
*/
BOOL WINAPI HttpEndRequestA(HINTERNET hRequest,
LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
{
TRACE("(%p, %p, %08x, %08lx)\n", hRequest, lpBuffersOut, dwFlags, dwContext);
if (lpBuffersOut)
{
INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return HttpEndRequestW(hRequest, NULL, dwFlags, dwContext);
}
static BOOL HTTP_HttpEndRequestW(http_request_t *lpwhr, DWORD dwFlags, DWORD_PTR dwContext)
{
BOOL rc = FALSE;
INT responseLen;
DWORD dwBufferSize;
INTERNET_ASYNC_RESULT iar;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
if (responseLen)
rc = TRUE;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
/* process cookies here. Is this right? */
HTTP_ProcessCookies(lpwhr);
if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
{
DWORD dwCode,dwCodeLength = sizeof(DWORD);
if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &dwCode, &dwCodeLength, NULL) &&
(dwCode == 302 || dwCode == 301 || dwCode == 303))
{
WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
dwBufferSize=sizeof(szNewLocation);
if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_LOCATION, szNewLocation, &dwBufferSize, NULL))
{
if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
{
HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
lpwhr->lpszVerb = heap_strdupW(szGET);
}
HTTP_DrainContent(lpwhr);
if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
{
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
rc = HTTP_HandleRedirect(lpwhr, new_url);
if (rc)
rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
HeapFree( GetProcessHeap(), 0, new_url );
}
}
}
}
iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
iar.dwError = rc ? 0 : INTERNET_GetLastError();
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_COMPLETE, &iar,
sizeof(INTERNET_ASYNC_RESULT));
return rc;
}
static void AsyncHttpEndRequestProc(WORKREQUEST *work)
{
struct WORKREQ_HTTPENDREQUESTW const *req = &work->u.HttpEndRequestW;
http_request_t *lpwhr = (http_request_t*)work->hdr;
TRACE("%p\n", lpwhr);
HTTP_HttpEndRequestW(lpwhr, req->dwFlags, req->dwContext);
}
/***********************************************************************
* HttpEndRequestW (WININET.@)
*
* Ends an HTTP request that was started by HttpSendRequestEx
*
* RETURNS
* TRUE if successful
* FALSE on failure
*
*/
BOOL WINAPI HttpEndRequestW(HINTERNET hRequest,
LPINTERNET_BUFFERSW lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
{
BOOL rc = FALSE;
http_request_t *lpwhr;
TRACE("-->\n");
if (lpBuffersOut)
{
INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
lpwhr = (http_request_t*) WININET_GetObject( hRequest );
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
if (lpwhr)
WININET_Release( &lpwhr->hdr );
return FALSE;
}
lpwhr->hdr.dwFlags |= dwFlags;
if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST work;
struct WORKREQ_HTTPENDREQUESTW *request;
work.asyncproc = AsyncHttpEndRequestProc;
work.hdr = WININET_AddRef( &lpwhr->hdr );
request = &work.u.HttpEndRequestW;
request->dwFlags = dwFlags;
request->dwContext = dwContext;
INTERNET_AsyncCall(&work);
INTERNET_SetLastError(ERROR_IO_PENDING);
}
else
rc = HTTP_HttpEndRequestW(lpwhr, dwFlags, dwContext);
WININET_Release( &lpwhr->hdr );
TRACE("%i <--\n",rc);
return rc;
}
/***********************************************************************
* HttpOpenRequestA (WININET.@)
*
* Open a HTTP request handle
......@@ -3239,254 +3068,327 @@ BOOL WINAPI HttpQueryInfoA(HINTERNET hHttpRequest, DWORD dwInfoLevel,
}
/***********************************************************************
* HttpSendRequestExA (WININET.@)
*
* Sends the specified request to the HTTP server and allows chunked
* transfers.
*
* RETURNS
* Success: TRUE
* Failure: FALSE, call GetLastError() for more information.
* HTTP_GetRedirectURL (internal)
*/
BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest,
LPINTERNET_BUFFERSA lpBuffersIn,
LPINTERNET_BUFFERSA lpBuffersOut,
DWORD dwFlags, DWORD_PTR dwContext)
static LPWSTR HTTP_GetRedirectURL(http_request_t *lpwhr, LPCWSTR lpszUrl)
{
INTERNET_BUFFERSW BuffersInW;
BOOL rc = FALSE;
DWORD headerlen;
LPWSTR header = NULL;
static WCHAR szHttp[] = {'h','t','t','p',0};
static WCHAR szHttps[] = {'h','t','t','p','s',0};
http_session_t *lpwhs = lpwhr->lpHttpSession;
URL_COMPONENTSW urlComponents;
DWORD url_length = 0;
LPWSTR orig_url;
LPWSTR combined_url;
TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
lpBuffersOut, dwFlags, dwContext);
urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
urlComponents.lpszScheme = (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp;
urlComponents.dwSchemeLength = 0;
urlComponents.lpszHostName = lpwhs->lpszHostName;
urlComponents.dwHostNameLength = 0;
urlComponents.nPort = lpwhs->nHostPort;
urlComponents.lpszUserName = lpwhs->lpszUserName;
urlComponents.dwUserNameLength = 0;
urlComponents.lpszPassword = NULL;
urlComponents.dwPasswordLength = 0;
urlComponents.lpszUrlPath = lpwhr->lpszPath;
urlComponents.dwUrlPathLength = 0;
urlComponents.lpszExtraInfo = NULL;
urlComponents.dwExtraInfoLength = 0;
if (lpBuffersIn)
{
BuffersInW.dwStructSize = sizeof(LPINTERNET_BUFFERSW);
if (lpBuffersIn->lpcszHeader)
{
headerlen = MultiByteToWideChar(CP_ACP,0,lpBuffersIn->lpcszHeader,
lpBuffersIn->dwHeadersLength,0,0);
header = HeapAlloc(GetProcessHeap(),0,headerlen*sizeof(WCHAR));
if (!(BuffersInW.lpcszHeader = header))
if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) &&
(GetLastError() != ERROR_INSUFFICIENT_BUFFER))
return NULL;
orig_url = HeapAlloc(GetProcessHeap(), 0, url_length);
/* convert from bytes to characters */
url_length = url_length / sizeof(WCHAR) - 1;
if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length))
{
INTERNET_SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
BuffersInW.dwHeadersLength = MultiByteToWideChar(CP_ACP, 0,
lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
header, headerlen);
}
else
BuffersInW.lpcszHeader = NULL;
BuffersInW.dwHeadersTotal = lpBuffersIn->dwHeadersTotal;
BuffersInW.lpvBuffer = lpBuffersIn->lpvBuffer;
BuffersInW.dwBufferLength = lpBuffersIn->dwBufferLength;
BuffersInW.dwBufferTotal = lpBuffersIn->dwBufferTotal;
BuffersInW.Next = NULL;
HeapFree(GetProcessHeap(), 0, orig_url);
return NULL;
}
rc = HttpSendRequestExW(hRequest, lpBuffersIn ? &BuffersInW : NULL, NULL, dwFlags, dwContext);
HeapFree(GetProcessHeap(),0,header);
url_length = 0;
if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) &&
(GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
HeapFree(GetProcessHeap(), 0, orig_url);
return NULL;
}
combined_url = HeapAlloc(GetProcessHeap(), 0, url_length * sizeof(WCHAR));
return rc;
if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY))
{
HeapFree(GetProcessHeap(), 0, orig_url);
HeapFree(GetProcessHeap(), 0, combined_url);
return NULL;
}
HeapFree(GetProcessHeap(), 0, orig_url);
return combined_url;
}
/***********************************************************************
* HttpSendRequestExW (WININET.@)
*
* Sends the specified request to the HTTP server and allows chunked
* transfers
*
* RETURNS
* Success: TRUE
* Failure: FALSE, call GetLastError() for more information.
* HTTP_HandleRedirect (internal)
*/
BOOL WINAPI HttpSendRequestExW(HINTERNET hRequest,
LPINTERNET_BUFFERSW lpBuffersIn,
LPINTERNET_BUFFERSW lpBuffersOut,
DWORD dwFlags, DWORD_PTR dwContext)
static BOOL HTTP_HandleRedirect(http_request_t *lpwhr, LPCWSTR lpszUrl)
{
BOOL ret = FALSE;
http_request_t *lpwhr;
http_session_t *lpwhs;
appinfo_t *hIC;
TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
lpBuffersOut, dwFlags, dwContext);
lpwhr = (http_request_t*) WININET_GetObject( hRequest );
http_session_t *lpwhs = lpwhr->lpHttpSession;
appinfo_t *hIC = lpwhs->lpAppInfo;
BOOL using_proxy = hIC->lpszProxy && hIC->lpszProxy[0];
WCHAR path[INTERNET_MAX_URL_LENGTH];
int index;
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
if(lpszUrl[0]=='/')
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
goto lend;
/* if it's an absolute path, keep the same session info */
lstrcpynW(path, lpszUrl, INTERNET_MAX_URL_LENGTH);
}
else
{
URL_COMPONENTSW urlComponents;
WCHAR protocol[32], hostName[MAXHOSTNAME], userName[1024];
static WCHAR szHttp[] = {'h','t','t','p',0};
static WCHAR szHttps[] = {'h','t','t','p','s',0};
lpwhs = lpwhr->lpHttpSession;
assert(lpwhs->hdr.htype == WH_HHTTPSESSION);
hIC = lpwhs->lpAppInfo;
assert(hIC->hdr.htype == WH_HINIT);
userName[0] = 0;
hostName[0] = 0;
protocol[0] = 0;
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_HTTPSENDREQUESTW *req;
urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
urlComponents.lpszScheme = protocol;
urlComponents.dwSchemeLength = 32;
urlComponents.lpszHostName = hostName;
urlComponents.dwHostNameLength = MAXHOSTNAME;
urlComponents.lpszUserName = userName;
urlComponents.dwUserNameLength = 1024;
urlComponents.lpszPassword = NULL;
urlComponents.dwPasswordLength = 0;
urlComponents.lpszUrlPath = path;
urlComponents.dwUrlPathLength = 2048;
urlComponents.lpszExtraInfo = NULL;
urlComponents.dwExtraInfoLength = 0;
if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents))
return FALSE;
workRequest.asyncproc = AsyncHttpSendRequestProc;
workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
req = &workRequest.u.HttpSendRequestW;
if (lpBuffersIn)
if (!strncmpW(szHttp, urlComponents.lpszScheme, strlenW(szHttp)) &&
(lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE))
{
DWORD size = 0;
if (lpBuffersIn->lpcszHeader)
TRACE("redirect from secure page to non-secure page\n");
/* FIXME: warn about from secure redirect to non-secure page */
lpwhr->hdr.dwFlags &= ~INTERNET_FLAG_SECURE;
}
if (!strncmpW(szHttps, urlComponents.lpszScheme, strlenW(szHttps)) &&
!(lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE))
{
if (lpBuffersIn->dwHeadersLength == ~0u)
size = (strlenW( lpBuffersIn->lpcszHeader ) + 1) * sizeof(WCHAR);
else
size = lpBuffersIn->dwHeadersLength * sizeof(WCHAR);
req->lpszHeader = HeapAlloc( GetProcessHeap(), 0, size );
memcpy( req->lpszHeader, lpBuffersIn->lpcszHeader, size );
TRACE("redirect from non-secure page to secure page\n");
/* FIXME: notify about redirect to secure page */
lpwhr->hdr.dwFlags |= INTERNET_FLAG_SECURE;
}
else req->lpszHeader = NULL;
req->dwHeaderLength = size / sizeof(WCHAR);
req->lpOptional = lpBuffersIn->lpvBuffer;
req->dwOptionalLength = lpBuffersIn->dwBufferLength;
req->dwContentLength = lpBuffersIn->dwBufferTotal;
}
else
if (urlComponents.nPort == INTERNET_INVALID_PORT_NUMBER)
{
req->lpszHeader = NULL;
req->dwHeaderLength = 0;
req->lpOptional = NULL;
req->dwOptionalLength = 0;
req->dwContentLength = 0;
if (lstrlenW(protocol)>4) /*https*/
urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
else /*http*/
urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
}
req->bEndRequest = FALSE;
INTERNET_AsyncCall(&workRequest);
#if 0
/*
* This is from windows.
* 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.
*/
INTERNET_SetLastError(ERROR_IO_PENDING);
/* consider the current host as the referrer */
if (lpwhs->lpszServerName && *lpwhs->lpszServerName)
HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpwhs->lpszServerName,
HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE|
HTTP_ADDHDR_FLAG_ADD_IF_NEW);
#endif
HeapFree(GetProcessHeap(), 0, lpwhs->lpszHostName);
if (urlComponents.nPort != INTERNET_DEFAULT_HTTP_PORT &&
urlComponents.nPort != INTERNET_DEFAULT_HTTPS_PORT)
{
int len;
static const WCHAR fmt[] = {'%','s',':','%','i',0};
len = lstrlenW(hostName);
len += 7; /* 5 for strlen("65535") + 1 for ":" + 1 for '\0' */
lpwhs->lpszHostName = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
sprintfW(lpwhs->lpszHostName, fmt, hostName, urlComponents.nPort);
}
else
lpwhs->lpszHostName = heap_strdupW(hostName);
HTTP_ProcessHeader(lpwhr, hostW, lpwhs->lpszHostName, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ);
HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName);
lpwhs->lpszUserName = NULL;
if (userName[0])
lpwhs->lpszUserName = heap_strdupW(userName);
if (!using_proxy)
{
if (lpBuffersIn)
ret = HTTP_HttpSendRequestW(lpwhr, lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
lpBuffersIn->lpvBuffer, lpBuffersIn->dwBufferLength,
lpBuffersIn->dwBufferTotal, FALSE);
if (strcmpiW(lpwhs->lpszServerName, hostName) || lpwhs->nServerPort != urlComponents.nPort)
{
DWORD res;
HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName);
lpwhs->lpszServerName = heap_strdupW(hostName);
lpwhs->nServerPort = urlComponents.nPort;
NETCON_close(&lpwhr->netConnection);
if ((res = HTTP_ResolveName(lpwhr)) != ERROR_SUCCESS) {
INTERNET_SetLastError(res);
return FALSE;
}
res = NETCON_init(&lpwhr->netConnection, lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE);
if (res != ERROR_SUCCESS) {
INTERNET_SetLastError(res);
return FALSE;
}
lpwhr->read_pos = lpwhr->read_size = 0;
lpwhr->read_chunked = FALSE;
}
}
else
ret = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, FALSE);
TRACE("Redirect through proxy\n");
}
lend:
if ( lpwhr )
WININET_Release( &lpwhr->hdr );
HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
lpwhr->lpszPath=NULL;
if (*path)
{
DWORD needed = 0;
HRESULT rc;
TRACE("<---\n");
return ret;
rc = UrlEscapeW(path, NULL, &needed, URL_ESCAPE_SPACES_ONLY);
if (rc != E_POINTER)
needed = strlenW(path)+1;
lpwhr->lpszPath = HeapAlloc(GetProcessHeap(), 0, needed*sizeof(WCHAR));
rc = UrlEscapeW(path, lpwhr->lpszPath, &needed,
URL_ESCAPE_SPACES_ONLY);
if (rc != S_OK)
{
ERR("Unable to escape string!(%s) (%d)\n",debugstr_w(path),rc);
strcpyW(lpwhr->lpszPath,path);
}
}
/* Remove custom content-type/length headers on redirects. */
index = HTTP_GetCustomHeaderIndex(lpwhr, szContent_Type, 0, TRUE);
if (0 <= index)
HTTP_DeleteCustomHeader(lpwhr, index);
index = HTTP_GetCustomHeaderIndex(lpwhr, szContent_Length, 0, TRUE);
if (0 <= index)
HTTP_DeleteCustomHeader(lpwhr, index);
return TRUE;
}
/***********************************************************************
* HttpSendRequestW (WININET.@)
*
* Sends the specified request to the HTTP server
*
* RETURNS
* TRUE on success
* FALSE on failure
* HTTP_build_req (internal)
*
* concatenate all the strings in the request together
*/
BOOL WINAPI HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
static LPWSTR HTTP_build_req( LPCWSTR *list, int len )
{
http_request_t *lpwhr;
http_session_t *lpwhs = NULL;
appinfo_t *hIC = NULL;
DWORD res = ERROR_SUCCESS;
LPCWSTR *t;
LPWSTR str;
TRACE("%p, %s, %i, %p, %i)\n", hHttpRequest,
debugstr_wn(lpszHeaders, dwHeaderLength), dwHeaderLength, lpOptional, dwOptionalLength);
for( t = list; *t ; t++ )
len += strlenW( *t );
len++;
lpwhr = (http_request_t*) WININET_GetObject( hHttpRequest );
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
{
res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
goto lend;
}
str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
*str = 0;
lpwhs = lpwhr->lpHttpSession;
if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
{
res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
goto lend;
}
for( t = list; *t ; t++ )
strcatW( str, *t );
hIC = lpwhs->lpAppInfo;
if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
{
res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
goto lend;
}
return str;
}
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_HTTPSENDREQUESTW *req;
static DWORD HTTP_SecureProxyConnect(http_request_t *lpwhr)
{
LPWSTR lpszPath;
LPWSTR requestString;
INT len;
INT cnt;
INT responseLen;
char *ascii_req;
DWORD res;
static const WCHAR szConnect[] = {'C','O','N','N','E','C','T',0};
static const WCHAR szFormat[] = {'%','s',':','%','d',0};
http_session_t *lpwhs = lpwhr->lpHttpSession;
workRequest.asyncproc = AsyncHttpSendRequestProc;
workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
req = &workRequest.u.HttpSendRequestW;
if (lpszHeaders)
{
DWORD size;
TRACE("\n");
if (dwHeaderLength == ~0u) size = (strlenW(lpszHeaders) + 1) * sizeof(WCHAR);
else size = dwHeaderLength * sizeof(WCHAR);
lpszPath = HeapAlloc( GetProcessHeap(), 0, (lstrlenW( lpwhs->lpszHostName ) + 13)*sizeof(WCHAR) );
sprintfW( lpszPath, szFormat, lpwhs->lpszHostName, lpwhs->nHostPort );
requestString = HTTP_BuildHeaderRequestString( lpwhr, szConnect, lpszPath, g_szHttp1_1 );
HeapFree( GetProcessHeap(), 0, lpszPath );
req->lpszHeader = HeapAlloc(GetProcessHeap(), 0, size);
memcpy(req->lpszHeader, lpszHeaders, size);
}
else
req->lpszHeader = 0;
req->dwHeaderLength = dwHeaderLength;
req->lpOptional = lpOptional;
req->dwOptionalLength = dwOptionalLength;
req->dwContentLength = dwOptionalLength;
req->bEndRequest = TRUE;
len = WideCharToMultiByte( CP_ACP, 0, requestString, -1,
NULL, 0, NULL, NULL );
len--; /* the nul terminator isn't needed */
ascii_req = HeapAlloc( GetProcessHeap(), 0, len );
WideCharToMultiByte( CP_ACP, 0, requestString, -1,
ascii_req, len, NULL, NULL );
HeapFree( GetProcessHeap(), 0, requestString );
INTERNET_AsyncCall(&workRequest);
/*
* This is from windows.
*/
res = ERROR_IO_PENDING;
}
else
TRACE("full request -> %s\n", debugstr_an( ascii_req, len ) );
res = NETCON_send( &lpwhr->netConnection, ascii_req, len, 0, &cnt );
HeapFree( GetProcessHeap(), 0, ascii_req );
if (res != ERROR_SUCCESS)
return res;
responseLen = HTTP_GetResponseHeaders( lpwhr, TRUE );
if (!responseLen)
return ERROR_HTTP_INVALID_HEADER;
return ERROR_SUCCESS;
}
static void HTTP_InsertCookies(http_request_t *lpwhr)
{
static const WCHAR szUrlForm[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
LPWSTR lpszCookies, lpszUrl = NULL;
DWORD nCookieSize, size;
LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr, hostW);
size = (strlenW(Host->lpszValue) + strlenW(szUrlForm) + strlenW(lpwhr->lpszPath)) * sizeof(WCHAR);
if (!(lpszUrl = HeapAlloc(GetProcessHeap(), 0, size))) return;
sprintfW( lpszUrl, szUrlForm, Host->lpszValue, lpwhr->lpszPath);
if (InternetGetCookieW(lpszUrl, NULL, NULL, &nCookieSize))
{
BOOL r = HTTP_HttpSendRequestW(lpwhr, lpszHeaders,
dwHeaderLength, lpOptional, dwOptionalLength,
dwOptionalLength, TRUE);
if(!r)
res = INTERNET_GetLastError();
}
lend:
if( lpwhr )
WININET_Release( &lpwhr->hdr );
int cnt = 0;
static const WCHAR szCookie[] = {'C','o','o','k','i','e',':',' ',0};
if(res != ERROR_SUCCESS)
SetLastError(res);
return res == ERROR_SUCCESS;
size = sizeof(szCookie) + nCookieSize * sizeof(WCHAR) + sizeof(szCrLf);
if ((lpszCookies = HeapAlloc(GetProcessHeap(), 0, size)))
{
cnt += sprintfW(lpszCookies, szCookie);
InternetGetCookieW(lpszUrl, NULL, lpszCookies + cnt, &nCookieSize);
strcatW(lpszCookies, szCrLf);
HTTP_HttpAddRequestHeadersW(lpwhr, lpszCookies, strlenW(lpszCookies), HTTP_ADDREQ_FLAG_REPLACE);
HeapFree(GetProcessHeap(), 0, lpszCookies);
}
}
HeapFree(GetProcessHeap(), 0, lpszUrl);
}
/***********************************************************************
* HttpSendRequestA (WININET.@)
* HTTP_HttpSendRequestW (internal)
*
* Sends the specified request to the HTTP server
*
......@@ -3495,648 +3397,747 @@ lend:
* FALSE on failure
*
*/
BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
{
BOOL result;
LPWSTR szHeaders=NULL;
DWORD nLen=dwHeaderLength;
if(lpszHeaders!=NULL)
{
nLen=MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,NULL,0);
szHeaders=HeapAlloc(GetProcessHeap(),0,nLen*sizeof(WCHAR));
MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,szHeaders,nLen);
}
result=HttpSendRequestW(hHttpRequest, szHeaders, nLen, lpOptional, dwOptionalLength);
HeapFree(GetProcessHeap(),0,szHeaders);
return result;
}
/***********************************************************************
* HTTP_GetRedirectURL (internal)
*/
static LPWSTR HTTP_GetRedirectURL(http_request_t *lpwhr, LPCWSTR lpszUrl)
BOOL HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength,
DWORD dwContentLength, BOOL bEndRequest)
{
static WCHAR szHttp[] = {'h','t','t','p',0};
static WCHAR szHttps[] = {'h','t','t','p','s',0};
http_session_t *lpwhs = lpwhr->lpHttpSession;
URL_COMPONENTSW urlComponents;
DWORD url_length = 0;
LPWSTR orig_url;
LPWSTR combined_url;
INT cnt;
BOOL bSuccess = FALSE, redirected = FALSE;
LPWSTR requestString = NULL;
INT responseLen;
BOOL loop_next;
INTERNET_ASYNC_RESULT iar;
static const WCHAR szPost[] = { 'P','O','S','T',0 };
static const WCHAR szContentLength[] =
{ 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','l','i','\r','\n',0 };
WCHAR contentLengthStr[sizeof szContentLength/2 /* includes \r\n */ + 20 /* int */ ];
DWORD res;
urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
urlComponents.lpszScheme = (lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp;
urlComponents.dwSchemeLength = 0;
urlComponents.lpszHostName = lpwhs->lpszHostName;
urlComponents.dwHostNameLength = 0;
urlComponents.nPort = lpwhs->nHostPort;
urlComponents.lpszUserName = lpwhs->lpszUserName;
urlComponents.dwUserNameLength = 0;
urlComponents.lpszPassword = NULL;
urlComponents.dwPasswordLength = 0;
urlComponents.lpszUrlPath = lpwhr->lpszPath;
urlComponents.dwUrlPathLength = 0;
urlComponents.lpszExtraInfo = NULL;
urlComponents.dwExtraInfoLength = 0;
TRACE("--> %p\n", lpwhr);
if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) &&
(GetLastError() != ERROR_INSUFFICIENT_BUFFER))
return NULL;
assert(lpwhr->hdr.htype == WH_HHTTPREQ);
orig_url = HeapAlloc(GetProcessHeap(), 0, url_length);
/* if the verb is NULL default to GET */
if (!lpwhr->lpszVerb)
lpwhr->lpszVerb = heap_strdupW(szGET);
/* convert from bytes to characters */
url_length = url_length / sizeof(WCHAR) - 1;
if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length))
if (dwContentLength || strcmpW(lpwhr->lpszVerb, szGET))
{
HeapFree(GetProcessHeap(), 0, orig_url);
return NULL;
sprintfW(contentLengthStr, szContentLength, dwContentLength);
HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_REPLACE);
lpwhr->dwBytesToWrite = dwContentLength;
}
if (lpwhr->lpHttpSession->lpAppInfo->lpszAgent)
{
WCHAR *agent_header;
static const WCHAR user_agent[] = {'U','s','e','r','-','A','g','e','n','t',':',' ','%','s','\r','\n',0};
int len;
url_length = 0;
if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) &&
(GetLastError() != ERROR_INSUFFICIENT_BUFFER))
len = strlenW(lpwhr->lpHttpSession->lpAppInfo->lpszAgent) + strlenW(user_agent);
agent_header = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
sprintfW(agent_header, user_agent, lpwhr->lpHttpSession->lpAppInfo->lpszAgent);
HTTP_HttpAddRequestHeadersW(lpwhr, agent_header, strlenW(agent_header), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
HeapFree(GetProcessHeap(), 0, agent_header);
}
if (lpwhr->hdr.dwFlags & INTERNET_FLAG_PRAGMA_NOCACHE)
{
HeapFree(GetProcessHeap(), 0, orig_url);
return NULL;
static const WCHAR pragma_nocache[] = {'P','r','a','g','m','a',':',' ','n','o','-','c','a','c','h','e','\r','\n',0};
HTTP_HttpAddRequestHeadersW(lpwhr, pragma_nocache, strlenW(pragma_nocache), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
}
combined_url = HeapAlloc(GetProcessHeap(), 0, url_length * sizeof(WCHAR));
if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY))
if ((lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_CACHE_WRITE) && !strcmpW(lpwhr->lpszVerb, szPost))
{
HeapFree(GetProcessHeap(), 0, orig_url);
HeapFree(GetProcessHeap(), 0, combined_url);
return NULL;
static const WCHAR cache_control[] = {'C','a','c','h','e','-','C','o','n','t','r','o','l',':',
' ','n','o','-','c','a','c','h','e','\r','\n',0};
HTTP_HttpAddRequestHeadersW(lpwhr, cache_control, strlenW(cache_control), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
}
HeapFree(GetProcessHeap(), 0, orig_url);
return combined_url;
}
do
{
DWORD len;
char *ascii_req;
loop_next = FALSE;
/***********************************************************************
* HTTP_HandleRedirect (internal)
*/
static BOOL HTTP_HandleRedirect(http_request_t *lpwhr, LPCWSTR lpszUrl)
{
http_session_t *lpwhs = lpwhr->lpHttpSession;
appinfo_t *hIC = lpwhs->lpAppInfo;
BOOL using_proxy = hIC->lpszProxy && hIC->lpszProxy[0];
WCHAR path[INTERNET_MAX_URL_LENGTH];
int index;
/* like native, just in case the caller forgot to call InternetReadFile
* for all the data */
HTTP_DrainContent(lpwhr);
lpwhr->dwContentRead = 0;
if(lpszUrl[0]=='/')
if (TRACE_ON(wininet))
{
/* if it's an absolute path, keep the same session info */
lstrcpynW(path, lpszUrl, INTERNET_MAX_URL_LENGTH);
LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr, hostW);
TRACE("Going to url %s %s\n", debugstr_w(Host->lpszValue), debugstr_w(lpwhr->lpszPath));
}
else
{
URL_COMPONENTSW urlComponents;
WCHAR protocol[32], hostName[MAXHOSTNAME], userName[1024];
static WCHAR szHttp[] = {'h','t','t','p',0};
static WCHAR szHttps[] = {'h','t','t','p','s',0};
userName[0] = 0;
hostName[0] = 0;
protocol[0] = 0;
urlComponents.dwStructSize = sizeof(URL_COMPONENTSW);
urlComponents.lpszScheme = protocol;
urlComponents.dwSchemeLength = 32;
urlComponents.lpszHostName = hostName;
urlComponents.dwHostNameLength = MAXHOSTNAME;
urlComponents.lpszUserName = userName;
urlComponents.dwUserNameLength = 1024;
urlComponents.lpszPassword = NULL;
urlComponents.dwPasswordLength = 0;
urlComponents.lpszUrlPath = path;
urlComponents.dwUrlPathLength = 2048;
urlComponents.lpszExtraInfo = NULL;
urlComponents.dwExtraInfoLength = 0;
if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents))
return FALSE;
if (!strncmpW(szHttp, urlComponents.lpszScheme, strlenW(szHttp)) &&
(lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE))
HTTP_FixURL(lpwhr);
if (lpwhr->hdr.dwFlags & INTERNET_FLAG_KEEP_CONNECTION)
{
TRACE("redirect from secure page to non-secure page\n");
/* FIXME: warn about from secure redirect to non-secure page */
lpwhr->hdr.dwFlags &= ~INTERNET_FLAG_SECURE;
HTTP_ProcessHeader(lpwhr, szConnection, szKeepAlive, HTTP_ADDHDR_FLAG_REQ | HTTP_ADDHDR_FLAG_REPLACE);
}
if (!strncmpW(szHttps, urlComponents.lpszScheme, strlenW(szHttps)) &&
!(lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE))
HTTP_InsertAuthorization(lpwhr, lpwhr->pAuthInfo, szAuthorization);
HTTP_InsertAuthorization(lpwhr, lpwhr->pProxyAuthInfo, szProxy_Authorization);
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES))
HTTP_InsertCookies(lpwhr);
/* add the headers the caller supplied */
if( lpszHeaders && dwHeaderLength )
{
TRACE("redirect from non-secure page to secure page\n");
/* FIXME: notify about redirect to secure page */
lpwhr->hdr.dwFlags |= INTERNET_FLAG_SECURE;
HTTP_HttpAddRequestHeadersW(lpwhr, lpszHeaders, dwHeaderLength,
HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REPLACE);
}
if (urlComponents.nPort == INTERNET_INVALID_PORT_NUMBER)
if (lpwhr->lpHttpSession->lpAppInfo->lpszProxy && lpwhr->lpHttpSession->lpAppInfo->lpszProxy[0])
{
if (lstrlenW(protocol)>4) /*https*/
urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT;
else /*http*/
urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT;
WCHAR *url = HTTP_BuildProxyRequestUrl(lpwhr);
requestString = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, url, lpwhr->lpszVersion);
HeapFree(GetProcessHeap(), 0, url);
}
else
requestString = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, lpwhr->lpszVersion);
#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 (lpwhs->lpszServerName && *lpwhs->lpszServerName)
HTTP_ProcessHeader(lpwhr, HTTP_REFERER, lpwhs->lpszServerName,
HTTP_ADDHDR_FLAG_REQ|HTTP_ADDREQ_FLAG_REPLACE|
HTTP_ADDHDR_FLAG_ADD_IF_NEW);
#endif
TRACE("Request header -> %s\n", debugstr_w(requestString) );
HeapFree(GetProcessHeap(), 0, lpwhs->lpszHostName);
if (urlComponents.nPort != INTERNET_DEFAULT_HTTP_PORT &&
urlComponents.nPort != INTERNET_DEFAULT_HTTPS_PORT)
{
int len;
static const WCHAR fmt[] = {'%','s',':','%','i',0};
len = lstrlenW(hostName);
len += 7; /* 5 for strlen("65535") + 1 for ":" + 1 for '\0' */
lpwhs->lpszHostName = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
sprintfW(lpwhs->lpszHostName, fmt, hostName, urlComponents.nPort);
/* Send the request and store the results */
if ((res = HTTP_OpenConnection(lpwhr)) != ERROR_SUCCESS) {
INTERNET_SetLastError(res);
goto lend;
}
else
lpwhs->lpszHostName = heap_strdupW(hostName);
HTTP_ProcessHeader(lpwhr, hostW, lpwhs->lpszHostName, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ);
/* send the request as ASCII, tack on the optional data */
if (!lpOptional || redirected)
dwOptionalLength = 0;
len = WideCharToMultiByte( CP_ACP, 0, requestString, -1,
NULL, 0, NULL, NULL );
ascii_req = HeapAlloc( GetProcessHeap(), 0, len + dwOptionalLength );
WideCharToMultiByte( CP_ACP, 0, requestString, -1,
ascii_req, len, NULL, NULL );
if( lpOptional )
memcpy( &ascii_req[len-1], lpOptional, dwOptionalLength );
len = (len + dwOptionalLength - 1);
ascii_req[len] = 0;
TRACE("full request -> %s\n", debugstr_a(ascii_req) );
HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName);
lpwhs->lpszUserName = NULL;
if (userName[0])
lpwhs->lpszUserName = heap_strdupW(userName);
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
if (!using_proxy)
{
if (strcmpiW(lpwhs->lpszServerName, hostName) || lpwhs->nServerPort != urlComponents.nPort)
NETCON_send(&lpwhr->netConnection, ascii_req, len, 0, &cnt);
HeapFree( GetProcessHeap(), 0, ascii_req );
lpwhr->dwBytesWritten = dwOptionalLength;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_SENT,
&len, sizeof(DWORD));
if (bEndRequest)
{
DWORD res;
DWORD dwBufferSize;
DWORD dwStatusCode;
HeapFree(GetProcessHeap(), 0, lpwhs->lpszServerName);
lpwhs->lpszServerName = heap_strdupW(hostName);
lpwhs->nServerPort = urlComponents.nPort;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
NETCON_close(&lpwhr->netConnection);
if ((res = HTTP_ResolveName(lpwhr)) != ERROR_SUCCESS) {
INTERNET_SetLastError(res);
return FALSE;
if (cnt < 0)
goto lend;
responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
if (responseLen)
bSuccess = TRUE;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen,
sizeof(DWORD));
HTTP_ProcessCookies(lpwhr);
if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
dwBufferSize = sizeof(dwStatusCode);
if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,
&dwStatusCode,&dwBufferSize,NULL))
dwStatusCode = 0;
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess)
{
WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
dwBufferSize=sizeof(szNewLocation);
if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) &&
HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
{
if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
{
HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
lpwhr->lpszVerb = heap_strdupW(szGET);
}
HTTP_DrainContent(lpwhr);
if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
{
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
bSuccess = HTTP_HandleRedirect(lpwhr, new_url);
if (bSuccess)
{
HeapFree(GetProcessHeap(), 0, requestString);
loop_next = TRUE;
}
HeapFree( GetProcessHeap(), 0, new_url );
}
redirected = TRUE;
}
}
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTH) && bSuccess)
{
WCHAR szAuthValue[2048];
dwBufferSize=2048;
if (dwStatusCode == HTTP_STATUS_DENIED)
{
LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr, hostW);
DWORD dwIndex = 0;
while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_WWW_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex))
{
if (HTTP_DoAuthorization(lpwhr, szAuthValue,
&lpwhr->pAuthInfo,
lpwhr->lpHttpSession->lpszUserName,
lpwhr->lpHttpSession->lpszPassword,
Host->lpszValue))
{
loop_next = TRUE;
break;
}
}
}
if (dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ)
{
DWORD dwIndex = 0;
while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_PROXY_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex))
{
if (HTTP_DoAuthorization(lpwhr, szAuthValue,
&lpwhr->pProxyAuthInfo,
lpwhr->lpHttpSession->lpAppInfo->lpszProxyUsername,
lpwhr->lpHttpSession->lpAppInfo->lpszProxyPassword,
NULL))
{
loop_next = TRUE;
break;
}
}
res = NETCON_init(&lpwhr->netConnection, lpwhr->hdr.dwFlags & INTERNET_FLAG_SECURE);
if (res != ERROR_SUCCESS) {
INTERNET_SetLastError(res);
return FALSE;
}
lpwhr->read_pos = lpwhr->read_size = 0;
lpwhr->read_chunked = FALSE;
}
}
else
TRACE("Redirect through proxy\n");
bSuccess = TRUE;
}
while (loop_next);
HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
lpwhr->lpszPath=NULL;
if (*path)
{
DWORD needed = 0;
HRESULT rc;
if(bSuccess) {
WCHAR url[INTERNET_MAX_URL_LENGTH];
WCHAR cacheFileName[MAX_PATH+1];
BOOL b;
rc = UrlEscapeW(path, NULL, &needed, URL_ESCAPE_SPACES_ONLY);
if (rc != E_POINTER)
needed = strlenW(path)+1;
lpwhr->lpszPath = HeapAlloc(GetProcessHeap(), 0, needed*sizeof(WCHAR));
rc = UrlEscapeW(path, lpwhr->lpszPath, &needed,
URL_ESCAPE_SPACES_ONLY);
if (rc != S_OK)
b = HTTP_GetRequestURL(lpwhr, url);
if(!b) {
WARN("Could not get URL\n");
goto lend;
}
b = CreateUrlCacheEntryW(url, lpwhr->dwContentLength > 0 ? lpwhr->dwContentLength : 0, NULL, cacheFileName, 0);
if(b) {
lpwhr->lpszCacheFile = heap_strdupW(cacheFileName);
lpwhr->hCacheFile = CreateFileW(lpwhr->lpszCacheFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(lpwhr->hCacheFile == INVALID_HANDLE_VALUE) {
WARN("Could not create file: %u\n", GetLastError());
lpwhr->hCacheFile = NULL;
}
}else {
WARN("Could not create cache entry: %08x\n", GetLastError());
}
}
lend:
HeapFree(GetProcessHeap(), 0, requestString);
/* TODO: send notification for P3P header */
if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
ERR("Unable to escape string!(%s) (%d)\n",debugstr_w(path),rc);
strcpyW(lpwhr->lpszPath,path);
if (bSuccess)
{
if (lpwhr->dwBytesWritten == lpwhr->dwBytesToWrite) HTTP_ReceiveRequestData(lpwhr, TRUE);
else
{
iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
iar.dwError = 0;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_COMPLETE, &iar,
sizeof(INTERNET_ASYNC_RESULT));
}
}
else
{
iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
iar.dwError = INTERNET_GetLastError();
/* Remove custom content-type/length headers on redirects. */
index = HTTP_GetCustomHeaderIndex(lpwhr, szContent_Type, 0, TRUE);
if (0 <= index)
HTTP_DeleteCustomHeader(lpwhr, index);
index = HTTP_GetCustomHeaderIndex(lpwhr, szContent_Length, 0, TRUE);
if (0 <= index)
HTTP_DeleteCustomHeader(lpwhr, index);
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_COMPLETE, &iar,
sizeof(INTERNET_ASYNC_RESULT));
}
}
return TRUE;
TRACE("<--\n");
if (bSuccess) INTERNET_SetLastError(ERROR_SUCCESS);
return bSuccess;
}
/***********************************************************************
* HTTP_build_req (internal)
*
* concatenate all the strings in the request together
* Helper functions for the HttpSendRequest(Ex) functions
*
*/
static LPWSTR HTTP_build_req( LPCWSTR *list, int len )
static void AsyncHttpSendRequestProc(WORKREQUEST *workRequest)
{
LPCWSTR *t;
LPWSTR str;
for( t = list; *t ; t++ )
len += strlenW( *t );
len++;
struct WORKREQ_HTTPSENDREQUESTW const *req = &workRequest->u.HttpSendRequestW;
http_request_t *lpwhr = (http_request_t*) workRequest->hdr;
str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
*str = 0;
TRACE("%p\n", lpwhr);
for( t = list; *t ; t++ )
strcatW( str, *t );
HTTP_HttpSendRequestW(lpwhr, req->lpszHeader,
req->dwHeaderLength, req->lpOptional, req->dwOptionalLength,
req->dwContentLength, req->bEndRequest);
return str;
HeapFree(GetProcessHeap(), 0, req->lpszHeader);
}
static DWORD HTTP_SecureProxyConnect(http_request_t *lpwhr)
static BOOL HTTP_HttpEndRequestW(http_request_t *lpwhr, DWORD dwFlags, DWORD_PTR dwContext)
{
LPWSTR lpszPath;
LPWSTR requestString;
INT len;
INT cnt;
BOOL rc = FALSE;
INT responseLen;
char *ascii_req;
DWORD res;
static const WCHAR szConnect[] = {'C','O','N','N','E','C','T',0};
static const WCHAR szFormat[] = {'%','s',':','%','d',0};
http_session_t *lpwhs = lpwhr->lpHttpSession;
DWORD dwBufferSize;
INTERNET_ASYNC_RESULT iar;
TRACE("\n");
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
lpszPath = HeapAlloc( GetProcessHeap(), 0, (lstrlenW( lpwhs->lpszHostName ) + 13)*sizeof(WCHAR) );
sprintfW( lpszPath, szFormat, lpwhs->lpszHostName, lpwhs->nHostPort );
requestString = HTTP_BuildHeaderRequestString( lpwhr, szConnect, lpszPath, g_szHttp1_1 );
HeapFree( GetProcessHeap(), 0, lpszPath );
responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
if (responseLen)
rc = TRUE;
len = WideCharToMultiByte( CP_ACP, 0, requestString, -1,
NULL, 0, NULL, NULL );
len--; /* the nul terminator isn't needed */
ascii_req = HeapAlloc( GetProcessHeap(), 0, len );
WideCharToMultiByte( CP_ACP, 0, requestString, -1,
ascii_req, len, NULL, NULL );
HeapFree( GetProcessHeap(), 0, requestString );
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
TRACE("full request -> %s\n", debugstr_an( ascii_req, len ) );
/* process cookies here. Is this right? */
HTTP_ProcessCookies(lpwhr);
res = NETCON_send( &lpwhr->netConnection, ascii_req, len, 0, &cnt );
HeapFree( GetProcessHeap(), 0, ascii_req );
if (res != ERROR_SUCCESS)
return res;
if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
responseLen = HTTP_GetResponseHeaders( lpwhr, TRUE );
if (!responseLen)
return ERROR_HTTP_INVALID_HEADER;
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
{
DWORD dwCode,dwCodeLength = sizeof(DWORD);
if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &dwCode, &dwCodeLength, NULL) &&
(dwCode == 302 || dwCode == 301 || dwCode == 303))
{
WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
dwBufferSize=sizeof(szNewLocation);
if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_LOCATION, szNewLocation, &dwBufferSize, NULL))
{
if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
{
HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
lpwhr->lpszVerb = heap_strdupW(szGET);
}
HTTP_DrainContent(lpwhr);
if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
{
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
rc = HTTP_HandleRedirect(lpwhr, new_url);
if (rc)
rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
HeapFree( GetProcessHeap(), 0, new_url );
}
}
}
}
return ERROR_SUCCESS;
iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
iar.dwError = rc ? 0 : INTERNET_GetLastError();
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_COMPLETE, &iar,
sizeof(INTERNET_ASYNC_RESULT));
return rc;
}
static void HTTP_InsertCookies(http_request_t *lpwhr)
/***********************************************************************
* HttpEndRequestA (WININET.@)
*
* Ends an HTTP request that was started by HttpSendRequestEx
*
* RETURNS
* TRUE if successful
* FALSE on failure
*
*/
BOOL WINAPI HttpEndRequestA(HINTERNET hRequest,
LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
{
static const WCHAR szUrlForm[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
LPWSTR lpszCookies, lpszUrl = NULL;
DWORD nCookieSize, size;
LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr, hostW);
size = (strlenW(Host->lpszValue) + strlenW(szUrlForm) + strlenW(lpwhr->lpszPath)) * sizeof(WCHAR);
if (!(lpszUrl = HeapAlloc(GetProcessHeap(), 0, size))) return;
sprintfW( lpszUrl, szUrlForm, Host->lpszValue, lpwhr->lpszPath);
TRACE("(%p, %p, %08x, %08lx)\n", hRequest, lpBuffersOut, dwFlags, dwContext);
if (InternetGetCookieW(lpszUrl, NULL, NULL, &nCookieSize))
if (lpBuffersOut)
{
int cnt = 0;
static const WCHAR szCookie[] = {'C','o','o','k','i','e',':',' ',0};
INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
size = sizeof(szCookie) + nCookieSize * sizeof(WCHAR) + sizeof(szCrLf);
if ((lpszCookies = HeapAlloc(GetProcessHeap(), 0, size)))
{
cnt += sprintfW(lpszCookies, szCookie);
InternetGetCookieW(lpszUrl, NULL, lpszCookies + cnt, &nCookieSize);
strcatW(lpszCookies, szCrLf);
return HttpEndRequestW(hRequest, NULL, dwFlags, dwContext);
}
static void AsyncHttpEndRequestProc(WORKREQUEST *work)
{
struct WORKREQ_HTTPENDREQUESTW const *req = &work->u.HttpEndRequestW;
http_request_t *lpwhr = (http_request_t*)work->hdr;
TRACE("%p\n", lpwhr);
HTTP_HttpAddRequestHeadersW(lpwhr, lpszCookies, strlenW(lpszCookies), HTTP_ADDREQ_FLAG_REPLACE);
HeapFree(GetProcessHeap(), 0, lpszCookies);
}
}
HeapFree(GetProcessHeap(), 0, lpszUrl);
HTTP_HttpEndRequestW(lpwhr, req->dwFlags, req->dwContext);
}
/***********************************************************************
* HTTP_HttpSendRequestW (internal)
* HttpEndRequestW (WININET.@)
*
* Sends the specified request to the HTTP server
* Ends an HTTP request that was started by HttpSendRequestEx
*
* RETURNS
* TRUE on success
* TRUE if successful
* FALSE on failure
*
*/
BOOL WINAPI HTTP_HttpSendRequestW(http_request_t *lpwhr, LPCWSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength,
DWORD dwContentLength, BOOL bEndRequest)
BOOL WINAPI HttpEndRequestW(HINTERNET hRequest,
LPINTERNET_BUFFERSW lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
{
INT cnt;
BOOL bSuccess = FALSE, redirected = FALSE;
LPWSTR requestString = NULL;
INT responseLen;
BOOL loop_next;
INTERNET_ASYNC_RESULT iar;
static const WCHAR szPost[] = { 'P','O','S','T',0 };
static const WCHAR szContentLength[] =
{ 'C','o','n','t','e','n','t','-','L','e','n','g','t','h',':',' ','%','l','i','\r','\n',0 };
WCHAR contentLengthStr[sizeof szContentLength/2 /* includes \r\n */ + 20 /* int */ ];
DWORD res;
TRACE("--> %p\n", lpwhr);
assert(lpwhr->hdr.htype == WH_HHTTPREQ);
BOOL rc = FALSE;
http_request_t *lpwhr;
/* if the verb is NULL default to GET */
if (!lpwhr->lpszVerb)
lpwhr->lpszVerb = heap_strdupW(szGET);
TRACE("-->\n");
if (dwContentLength || strcmpW(lpwhr->lpszVerb, szGET))
if (lpBuffersOut)
{
sprintfW(contentLengthStr, szContentLength, dwContentLength);
HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L, HTTP_ADDREQ_FLAG_REPLACE);
lpwhr->dwBytesToWrite = dwContentLength;
INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (lpwhr->lpHttpSession->lpAppInfo->lpszAgent)
{
WCHAR *agent_header;
static const WCHAR user_agent[] = {'U','s','e','r','-','A','g','e','n','t',':',' ','%','s','\r','\n',0};
int len;
len = strlenW(lpwhr->lpHttpSession->lpAppInfo->lpszAgent) + strlenW(user_agent);
agent_header = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
sprintfW(agent_header, user_agent, lpwhr->lpHttpSession->lpAppInfo->lpszAgent);
lpwhr = (http_request_t*) WININET_GetObject( hRequest );
HTTP_HttpAddRequestHeadersW(lpwhr, agent_header, strlenW(agent_header), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
HeapFree(GetProcessHeap(), 0, agent_header);
}
if (lpwhr->hdr.dwFlags & INTERNET_FLAG_PRAGMA_NOCACHE)
{
static const WCHAR pragma_nocache[] = {'P','r','a','g','m','a',':',' ','n','o','-','c','a','c','h','e','\r','\n',0};
HTTP_HttpAddRequestHeadersW(lpwhr, pragma_nocache, strlenW(pragma_nocache), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
}
if ((lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_CACHE_WRITE) && !strcmpW(lpwhr->lpszVerb, szPost))
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
{
static const WCHAR cache_control[] = {'C','a','c','h','e','-','C','o','n','t','r','o','l',':',
' ','n','o','-','c','a','c','h','e','\r','\n',0};
HTTP_HttpAddRequestHeadersW(lpwhr, cache_control, strlenW(cache_control), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
if (lpwhr)
WININET_Release( &lpwhr->hdr );
return FALSE;
}
lpwhr->hdr.dwFlags |= dwFlags;
do
if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
DWORD len;
char *ascii_req;
WORKREQUEST work;
struct WORKREQ_HTTPENDREQUESTW *request;
loop_next = FALSE;
work.asyncproc = AsyncHttpEndRequestProc;
work.hdr = WININET_AddRef( &lpwhr->hdr );
/* like native, just in case the caller forgot to call InternetReadFile
* for all the data */
HTTP_DrainContent(lpwhr);
lpwhr->dwContentRead = 0;
request = &work.u.HttpEndRequestW;
request->dwFlags = dwFlags;
request->dwContext = dwContext;
if (TRACE_ON(wininet))
{
LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr, hostW);
TRACE("Going to url %s %s\n", debugstr_w(Host->lpszValue), debugstr_w(lpwhr->lpszPath));
INTERNET_AsyncCall(&work);
INTERNET_SetLastError(ERROR_IO_PENDING);
}
else
rc = HTTP_HttpEndRequestW(lpwhr, dwFlags, dwContext);
HTTP_FixURL(lpwhr);
if (lpwhr->hdr.dwFlags & INTERNET_FLAG_KEEP_CONNECTION)
{
HTTP_ProcessHeader(lpwhr, szConnection, szKeepAlive, HTTP_ADDHDR_FLAG_REQ | HTTP_ADDHDR_FLAG_REPLACE);
}
HTTP_InsertAuthorization(lpwhr, lpwhr->pAuthInfo, szAuthorization);
HTTP_InsertAuthorization(lpwhr, lpwhr->pProxyAuthInfo, szProxy_Authorization);
WININET_Release( &lpwhr->hdr );
TRACE("%i <--\n",rc);
return rc;
}
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES))
HTTP_InsertCookies(lpwhr);
/***********************************************************************
* HttpSendRequestExA (WININET.@)
*
* Sends the specified request to the HTTP server and allows chunked
* transfers.
*
* RETURNS
* Success: TRUE
* Failure: FALSE, call GetLastError() for more information.
*/
BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest,
LPINTERNET_BUFFERSA lpBuffersIn,
LPINTERNET_BUFFERSA lpBuffersOut,
DWORD dwFlags, DWORD_PTR dwContext)
{
INTERNET_BUFFERSW BuffersInW;
BOOL rc = FALSE;
DWORD headerlen;
LPWSTR header = NULL;
/* add the headers the caller supplied */
if( lpszHeaders && dwHeaderLength )
{
HTTP_HttpAddRequestHeadersW(lpwhr, lpszHeaders, dwHeaderLength,
HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REPLACE);
}
TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
lpBuffersOut, dwFlags, dwContext);
if (lpwhr->lpHttpSession->lpAppInfo->lpszProxy && lpwhr->lpHttpSession->lpAppInfo->lpszProxy[0])
if (lpBuffersIn)
{
WCHAR *url = HTTP_BuildProxyRequestUrl(lpwhr);
requestString = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, url, lpwhr->lpszVersion);
HeapFree(GetProcessHeap(), 0, url);
BuffersInW.dwStructSize = sizeof(LPINTERNET_BUFFERSW);
if (lpBuffersIn->lpcszHeader)
{
headerlen = MultiByteToWideChar(CP_ACP,0,lpBuffersIn->lpcszHeader,
lpBuffersIn->dwHeadersLength,0,0);
header = HeapAlloc(GetProcessHeap(),0,headerlen*sizeof(WCHAR));
if (!(BuffersInW.lpcszHeader = header))
{
INTERNET_SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
BuffersInW.dwHeadersLength = MultiByteToWideChar(CP_ACP, 0,
lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
header, headerlen);
}
else
requestString = HTTP_BuildHeaderRequestString(lpwhr, lpwhr->lpszVerb, lpwhr->lpszPath, lpwhr->lpszVersion);
TRACE("Request header -> %s\n", debugstr_w(requestString) );
/* Send the request and store the results */
if ((res = HTTP_OpenConnection(lpwhr)) != ERROR_SUCCESS) {
INTERNET_SetLastError(res);
goto lend;
BuffersInW.lpcszHeader = NULL;
BuffersInW.dwHeadersTotal = lpBuffersIn->dwHeadersTotal;
BuffersInW.lpvBuffer = lpBuffersIn->lpvBuffer;
BuffersInW.dwBufferLength = lpBuffersIn->dwBufferLength;
BuffersInW.dwBufferTotal = lpBuffersIn->dwBufferTotal;
BuffersInW.Next = NULL;
}
/* send the request as ASCII, tack on the optional data */
if (!lpOptional || redirected)
dwOptionalLength = 0;
len = WideCharToMultiByte( CP_ACP, 0, requestString, -1,
NULL, 0, NULL, NULL );
ascii_req = HeapAlloc( GetProcessHeap(), 0, len + dwOptionalLength );
WideCharToMultiByte( CP_ACP, 0, requestString, -1,
ascii_req, len, NULL, NULL );
if( lpOptional )
memcpy( &ascii_req[len-1], lpOptional, dwOptionalLength );
len = (len + dwOptionalLength - 1);
ascii_req[len] = 0;
TRACE("full request -> %s\n", debugstr_a(ascii_req) );
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
NETCON_send(&lpwhr->netConnection, ascii_req, len, 0, &cnt);
HeapFree( GetProcessHeap(), 0, ascii_req );
lpwhr->dwBytesWritten = dwOptionalLength;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_SENT,
&len, sizeof(DWORD));
if (bEndRequest)
{
DWORD dwBufferSize;
DWORD dwStatusCode;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
if (cnt < 0)
goto lend;
responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
if (responseLen)
bSuccess = TRUE;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen,
sizeof(DWORD));
HTTP_ProcessCookies(lpwhr);
rc = HttpSendRequestExW(hRequest, lpBuffersIn ? &BuffersInW : NULL, NULL, dwFlags, dwContext);
if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
HeapFree(GetProcessHeap(),0,header);
dwBufferSize = sizeof(dwStatusCode);
if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,
&dwStatusCode,&dwBufferSize,NULL))
dwStatusCode = 0;
return rc;
}
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess)
{
WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
dwBufferSize=sizeof(szNewLocation);
if ((dwStatusCode==HTTP_STATUS_REDIRECT || dwStatusCode==HTTP_STATUS_MOVED) &&
HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
{
if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
{
HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
lpwhr->lpszVerb = heap_strdupW(szGET);
}
HTTP_DrainContent(lpwhr);
if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
{
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
bSuccess = HTTP_HandleRedirect(lpwhr, new_url);
if (bSuccess)
/***********************************************************************
* HttpSendRequestExW (WININET.@)
*
* Sends the specified request to the HTTP server and allows chunked
* transfers
*
* RETURNS
* Success: TRUE
* Failure: FALSE, call GetLastError() for more information.
*/
BOOL WINAPI HttpSendRequestExW(HINTERNET hRequest,
LPINTERNET_BUFFERSW lpBuffersIn,
LPINTERNET_BUFFERSW lpBuffersOut,
DWORD dwFlags, DWORD_PTR dwContext)
{
BOOL ret = FALSE;
http_request_t *lpwhr;
http_session_t *lpwhs;
appinfo_t *hIC;
TRACE("(%p, %p, %p, %08x, %08lx)\n", hRequest, lpBuffersIn,
lpBuffersOut, dwFlags, dwContext);
lpwhr = (http_request_t*) WININET_GetObject( hRequest );
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
{
HeapFree(GetProcessHeap(), 0, requestString);
loop_next = TRUE;
}
HeapFree( GetProcessHeap(), 0, new_url );
}
redirected = TRUE;
}
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
goto lend;
}
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTH) && bSuccess)
{
WCHAR szAuthValue[2048];
dwBufferSize=2048;
if (dwStatusCode == HTTP_STATUS_DENIED)
lpwhs = lpwhr->lpHttpSession;
assert(lpwhs->hdr.htype == WH_HHTTPSESSION);
hIC = lpwhs->lpAppInfo;
assert(hIC->hdr.htype == WH_HINIT);
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
LPHTTPHEADERW Host = HTTP_GetHeader(lpwhr, hostW);
DWORD dwIndex = 0;
while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_WWW_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex))
WORKREQUEST workRequest;
struct WORKREQ_HTTPSENDREQUESTW *req;
workRequest.asyncproc = AsyncHttpSendRequestProc;
workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
req = &workRequest.u.HttpSendRequestW;
if (lpBuffersIn)
{
if (HTTP_DoAuthorization(lpwhr, szAuthValue,
&lpwhr->pAuthInfo,
lpwhr->lpHttpSession->lpszUserName,
lpwhr->lpHttpSession->lpszPassword,
Host->lpszValue))
DWORD size = 0;
if (lpBuffersIn->lpcszHeader)
{
loop_next = TRUE;
break;
}
if (lpBuffersIn->dwHeadersLength == ~0u)
size = (strlenW( lpBuffersIn->lpcszHeader ) + 1) * sizeof(WCHAR);
else
size = lpBuffersIn->dwHeadersLength * sizeof(WCHAR);
req->lpszHeader = HeapAlloc( GetProcessHeap(), 0, size );
memcpy( req->lpszHeader, lpBuffersIn->lpcszHeader, size );
}
else req->lpszHeader = NULL;
req->dwHeaderLength = size / sizeof(WCHAR);
req->lpOptional = lpBuffersIn->lpvBuffer;
req->dwOptionalLength = lpBuffersIn->dwBufferLength;
req->dwContentLength = lpBuffersIn->dwBufferTotal;
}
if (dwStatusCode == HTTP_STATUS_PROXY_AUTH_REQ)
{
DWORD dwIndex = 0;
while (HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_PROXY_AUTHENTICATE,szAuthValue,&dwBufferSize,&dwIndex))
{
if (HTTP_DoAuthorization(lpwhr, szAuthValue,
&lpwhr->pProxyAuthInfo,
lpwhr->lpHttpSession->lpAppInfo->lpszProxyUsername,
lpwhr->lpHttpSession->lpAppInfo->lpszProxyPassword,
NULL))
else
{
loop_next = TRUE;
break;
}
}
}
req->lpszHeader = NULL;
req->dwHeaderLength = 0;
req->lpOptional = NULL;
req->dwOptionalLength = 0;
req->dwContentLength = 0;
}
req->bEndRequest = FALSE;
INTERNET_AsyncCall(&workRequest);
/*
* This is from windows.
*/
INTERNET_SetLastError(ERROR_IO_PENDING);
}
else
bSuccess = TRUE;
{
if (lpBuffersIn)
ret = HTTP_HttpSendRequestW(lpwhr, lpBuffersIn->lpcszHeader, lpBuffersIn->dwHeadersLength,
lpBuffersIn->lpvBuffer, lpBuffersIn->dwBufferLength,
lpBuffersIn->dwBufferTotal, FALSE);
else
ret = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, FALSE);
}
while (loop_next);
if(bSuccess) {
WCHAR url[INTERNET_MAX_URL_LENGTH];
WCHAR cacheFileName[MAX_PATH+1];
BOOL b;
lend:
if ( lpwhr )
WININET_Release( &lpwhr->hdr );
b = HTTP_GetRequestURL(lpwhr, url);
if(!b) {
WARN("Could not get URL\n");
TRACE("<---\n");
return ret;
}
/***********************************************************************
* HttpSendRequestW (WININET.@)
*
* Sends the specified request to the HTTP server
*
* RETURNS
* TRUE on success
* FALSE on failure
*
*/
BOOL WINAPI HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
{
http_request_t *lpwhr;
http_session_t *lpwhs = NULL;
appinfo_t *hIC = NULL;
DWORD res = ERROR_SUCCESS;
TRACE("%p, %s, %i, %p, %i)\n", hHttpRequest,
debugstr_wn(lpszHeaders, dwHeaderLength), dwHeaderLength, lpOptional, dwOptionalLength);
lpwhr = (http_request_t*) WININET_GetObject( hHttpRequest );
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
{
res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
goto lend;
}
b = CreateUrlCacheEntryW(url, lpwhr->dwContentLength > 0 ? lpwhr->dwContentLength : 0, NULL, cacheFileName, 0);
if(b) {
lpwhr->lpszCacheFile = heap_strdupW(cacheFileName);
lpwhr->hCacheFile = CreateFileW(lpwhr->lpszCacheFile, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(lpwhr->hCacheFile == INVALID_HANDLE_VALUE) {
WARN("Could not create file: %u\n", GetLastError());
lpwhr->hCacheFile = NULL;
}
}else {
WARN("Could not create cache entry: %08x\n", GetLastError());
lpwhs = lpwhr->lpHttpSession;
if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
{
res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
goto lend;
}
hIC = lpwhs->lpAppInfo;
if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
{
res = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
goto lend;
}
lend:
if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
WORKREQUEST workRequest;
struct WORKREQ_HTTPSENDREQUESTW *req;
HeapFree(GetProcessHeap(), 0, requestString);
workRequest.asyncproc = AsyncHttpSendRequestProc;
workRequest.hdr = WININET_AddRef( &lpwhr->hdr );
req = &workRequest.u.HttpSendRequestW;
if (lpszHeaders)
{
DWORD size;
/* TODO: send notification for P3P header */
if (dwHeaderLength == ~0u) size = (strlenW(lpszHeaders) + 1) * sizeof(WCHAR);
else size = dwHeaderLength * sizeof(WCHAR);
if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
{
if (bSuccess)
{
if (lpwhr->dwBytesWritten == lpwhr->dwBytesToWrite) HTTP_ReceiveRequestData(lpwhr, TRUE);
req->lpszHeader = HeapAlloc(GetProcessHeap(), 0, size);
memcpy(req->lpszHeader, lpszHeaders, size);
}
else
{
iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
iar.dwError = 0;
req->lpszHeader = 0;
req->dwHeaderLength = dwHeaderLength;
req->lpOptional = lpOptional;
req->dwOptionalLength = dwOptionalLength;
req->dwContentLength = dwOptionalLength;
req->bEndRequest = TRUE;
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_COMPLETE, &iar,
sizeof(INTERNET_ASYNC_RESULT));
}
INTERNET_AsyncCall(&workRequest);
/*
* This is from windows.
*/
res = ERROR_IO_PENDING;
}
else
{
iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
iar.dwError = INTERNET_GetLastError();
INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_COMPLETE, &iar,
sizeof(INTERNET_ASYNC_RESULT));
}
BOOL r = HTTP_HttpSendRequestW(lpwhr, lpszHeaders,
dwHeaderLength, lpOptional, dwOptionalLength,
dwOptionalLength, TRUE);
if(!r)
res = INTERNET_GetLastError();
}
lend:
if( lpwhr )
WININET_Release( &lpwhr->hdr );
TRACE("<--\n");
if (bSuccess) INTERNET_SetLastError(ERROR_SUCCESS);
return bSuccess;
if(res != ERROR_SUCCESS)
SetLastError(res);
return res == ERROR_SUCCESS;
}
/***********************************************************************
* HttpSendRequestA (WININET.@)
*
* Sends the specified request to the HTTP server
*
* RETURNS
* TRUE on success
* FALSE on failure
*
*/
BOOL WINAPI HttpSendRequestA(HINTERNET hHttpRequest, LPCSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
{
BOOL result;
LPWSTR szHeaders=NULL;
DWORD nLen=dwHeaderLength;
if(lpszHeaders!=NULL)
{
nLen=MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,NULL,0);
szHeaders=HeapAlloc(GetProcessHeap(),0,nLen*sizeof(WCHAR));
MultiByteToWideChar(CP_ACP,0,lpszHeaders,dwHeaderLength,szHeaders,nLen);
}
result=HttpSendRequestW(hHttpRequest, szHeaders, nLen, lpOptional, dwOptionalLength);
HeapFree(GetProcessHeap(),0,szHeaders);
return result;
}
/***********************************************************************
......
......@@ -411,10 +411,6 @@ BOOL INTERNET_AsyncCall(LPWORKREQUEST lpWorkRequest);
LPSTR INTERNET_GetResponseBuffer(void);
LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen);
BOOLAPI HTTP_HttpSendRequestW(http_request_t *req, LPCWSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional, DWORD dwOptionalLength,
DWORD dwContentLength, BOOL bEndRequest);
VOID SendAsyncCallback(object_header_t *hdr, DWORD_PTR dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInfo,
DWORD dwStatusInfoLength);
......
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