Implement HttpSendRequestEx and HttpEndRequest. Restructure, breaking

some things out of HTTP_SendRequestW to avoid duplicate code.
This commit is contained in:
Aric Stewart 2005-11-21 15:17:55 +00:00 committed by Alexandre Julliard
parent 461fe11243
commit be918f48b6
2 changed files with 548 additions and 213 deletions

View File

@ -5,9 +5,9 @@
* Copyright 2002 CodeWeavers Inc.
* Copyright 2002 TransGaming Technologies Inc.
* Copyright 2004 Mike McCormack for CodeWeavers
* Copyright 2005 Aric Stewart for CodeWeavers
*
* Ulrich Czekalla
* Aric Stewart
* David Hammerton
*
* This library is free software; you can redistribute it and/or
@ -92,6 +92,9 @@ static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer);
static BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr);
static INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQW lpwhr, LPCWSTR lpszField);
static BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, DWORD index);
static LPWSTR HTTP_build_req( LPCWSTR *list, int len );
static BOOL HTTP_InsertProxyAuthorization( LPWININETHTTPREQW lpwhr,
LPCWSTR username, LPCWSTR password );
/***********************************************************************
@ -154,6 +157,235 @@ static void HTTP_FreeTokens(LPWSTR * token_array)
HeapFree(GetProcessHeap(), 0, token_array);
}
/* **********************************************************************
*
* Helper functions for the HttpSendRequest(Ex) functions
*
*/
static void HTTP_FixVerb( LPWININETHTTPREQW lpwhr )
{
/* if the verb is NULL default to GET */
if (NULL == lpwhr->lpszVerb)
{
static const WCHAR szGET[] = { 'G','E','T', 0 };
lpwhr->lpszVerb = WININET_strdupW(szGET);
}
}
static void HTTP_FixURL( LPWININETHTTPREQW lpwhr)
{
static const WCHAR szSlash[] = { '/',0 };
static const WCHAR szHttp[] = { 'h','t','t','p',':','/','/', 0 };
/* If we don't have a path we set it to root */
if (NULL == lpwhr->lpszPath)
lpwhr->lpszPath = WININET_strdupW(szSlash);
else /* remove \r and \n*/
{
int nLen = strlenW(lpwhr->lpszPath);
while ((nLen >0 ) && ((lpwhr->lpszPath[nLen-1] == '\r')||(lpwhr->lpszPath[nLen-1] == '\n')))
{
nLen--;
lpwhr->lpszPath[nLen]='\0';
}
/* Replace '\' with '/' */
while (nLen>0) {
nLen--;
if (lpwhr->lpszPath[nLen] == '\\') lpwhr->lpszPath[nLen]='/';
}
}
if(CSTR_EQUAL != CompareStringW( LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
lpwhr->lpszPath, strlenW(szHttp), szHttp, strlenW(szHttp) )
&& lpwhr->lpszPath[0] != '/') /* not an absolute path ?? --> fix it !! */
{
WCHAR *fixurl = HeapAlloc(GetProcessHeap(), 0,
(strlenW(lpwhr->lpszPath) + 2)*sizeof(WCHAR));
*fixurl = '/';
strcpyW(fixurl + 1, lpwhr->lpszPath);
HeapFree( GetProcessHeap(), 0, lpwhr->lpszPath );
lpwhr->lpszPath = fixurl;
}
}
static LPWSTR HTTP_BuildHeaderRequestString( LPWININETHTTPREQW lpwhr )
{
LPWSTR requestString;
DWORD len, n;
LPCWSTR *req;
INT i;
LPWSTR p;
static const WCHAR szSpace[] = { ' ',0 };
static const WCHAR szcrlf[] = {'\r','\n', 0};
static const WCHAR szColon[] = { ':',' ',0 };
static const WCHAR sztwocrlf[] = {'\r','\n','\r','\n', 0};
/* allocate space for an array of all the string pointers to be added */
len = (HTTP_QUERY_MAX + lpwhr->nCustHeaders)*4 + 9;
req = HeapAlloc( GetProcessHeap(), 0, len*sizeof(LPCWSTR) );
/* add the verb, path and HTTP/1.0 */
n = 0;
req[n++] = lpwhr->lpszVerb;
req[n++] = szSpace;
req[n++] = lpwhr->lpszPath;
req[n++] = HTTPHEADER;
/* Append standard request headers */
for (i = 0; i <= HTTP_QUERY_MAX; i++)
{
if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
{
req[n++] = szcrlf;
req[n++] = lpwhr->StdHeaders[i].lpszField;
req[n++] = szColon;
req[n++] = lpwhr->StdHeaders[i].lpszValue;
TRACE("Adding header %s (%s)\n",
debugstr_w(lpwhr->StdHeaders[i].lpszField),
debugstr_w(lpwhr->StdHeaders[i].lpszValue));
}
}
/* Append custom request heades */
for (i = 0; i < lpwhr->nCustHeaders; i++)
{
if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
{
req[n++] = szcrlf;
req[n++] = lpwhr->pCustHeaders[i].lpszField;
req[n++] = szColon;
req[n++] = lpwhr->pCustHeaders[i].lpszValue;
TRACE("Adding custom header %s (%s)\n",
debugstr_w(lpwhr->pCustHeaders[i].lpszField),
debugstr_w(lpwhr->pCustHeaders[i].lpszValue));
}
}
if( n >= len )
ERR("oops. buffer overrun\n");
req[n] = NULL;
requestString = HTTP_build_req( req, 4 );
HeapFree( GetProcessHeap(), 0, req );
/*
* Set (header) termination string for request
* Make sure there's exactly two new lines at the end of the request
*/
p = &requestString[strlenW(requestString)-1];
while ( (*p == '\n') || (*p == '\r') )
p--;
strcpyW( p+1, sztwocrlf );
return requestString;
}
static void HTTP_ProcessHeaders( LPWININETHTTPREQW lpwhr )
{
int CustHeaderIndex;
static const WCHAR szSetCookie[] = {'S','e','t','-','C','o','o','k','i','e',0 };
CustHeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSetCookie);
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES) && (CustHeaderIndex >= 0))
{
LPHTTPHEADERW setCookieHeader;
int nPosStart = 0, nPosEnd = 0, len;
static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','/',0};
setCookieHeader = &lpwhr->pCustHeaders[CustHeaderIndex];
while (setCookieHeader->lpszValue[nPosEnd] != '\0')
{
LPWSTR buf_cookie, cookie_name, cookie_data;
LPWSTR buf_url;
LPWSTR domain = NULL;
int nEqualPos = 0;
while (setCookieHeader->lpszValue[nPosEnd] != ';' && setCookieHeader->lpszValue[nPosEnd] != ',' &&
setCookieHeader->lpszValue[nPosEnd] != '\0')
{
nPosEnd++;
}
if (setCookieHeader->lpszValue[nPosEnd] == ';')
{
/* fixme: not case sensitive, strcasestr is gnu only */
int nDomainPosEnd = 0;
int nDomainPosStart = 0, nDomainLength = 0;
static const WCHAR szDomain[] = {'d','o','m','a','i','n','=',0};
LPWSTR lpszDomain = strstrW(&setCookieHeader->lpszValue[nPosEnd], szDomain);
if (lpszDomain)
{ /* they have specified their own domain, lets use it */
while (lpszDomain[nDomainPosEnd] != ';' && lpszDomain[nDomainPosEnd] != ',' &&
lpszDomain[nDomainPosEnd] != '\0')
{
nDomainPosEnd++;
}
nDomainPosStart = strlenW(szDomain);
nDomainLength = (nDomainPosEnd - nDomainPosStart) + 1;
domain = HeapAlloc(GetProcessHeap(), 0, (nDomainLength + 1)*sizeof(WCHAR));
lstrcpynW(domain, &lpszDomain[nDomainPosStart], nDomainLength + 1);
}
}
if (setCookieHeader->lpszValue[nPosEnd] == '\0') break;
buf_cookie = HeapAlloc(GetProcessHeap(), 0, ((nPosEnd - nPosStart) + 1)*sizeof(WCHAR));
lstrcpynW(buf_cookie, &setCookieHeader->lpszValue[nPosStart], (nPosEnd - nPosStart) + 1);
TRACE("%s\n", debugstr_w(buf_cookie));
while (buf_cookie[nEqualPos] != '=' && buf_cookie[nEqualPos] != '\0')
{
nEqualPos++;
}
if (buf_cookie[nEqualPos] == '\0' || buf_cookie[nEqualPos + 1] == '\0')
{
HeapFree(GetProcessHeap(), 0, buf_cookie);
break;
}
cookie_name = HeapAlloc(GetProcessHeap(), 0, (nEqualPos + 1)*sizeof(WCHAR));
lstrcpynW(cookie_name, buf_cookie, nEqualPos + 1);
cookie_data = &buf_cookie[nEqualPos + 1];
len = strlenW((domain ? domain : lpwhr->StdHeaders[HTTP_QUERY_HOST].lpszValue)) +
strlenW(lpwhr->lpszPath) + 9;
buf_url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
sprintfW(buf_url, szFmt, (domain ? domain : lpwhr->StdHeaders[HTTP_QUERY_HOST].lpszValue)); /* FIXME PATH!!! */
InternetSetCookieW(buf_url, cookie_name, cookie_data);
HeapFree(GetProcessHeap(), 0, buf_url);
HeapFree(GetProcessHeap(), 0, buf_cookie);
HeapFree(GetProcessHeap(), 0, cookie_name);
HeapFree(GetProcessHeap(), 0, domain);
nPosStart = nPosEnd;
}
}
}
static void HTTP_AddProxyInfo( LPWININETHTTPREQW lpwhr )
{
LPWININETHTTPSESSIONW lpwhs = NULL;
LPWININETAPPINFOW hIC = NULL;
lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
return;
}
hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
return;
}
if (hIC && (hIC->lpszProxyUsername || hIC->lpszProxyPassword ))
HTTP_InsertProxyAuthorization(lpwhr, hIC->lpszProxyUsername,
hIC->lpszProxyPassword);
}
/***********************************************************************
* HTTP_HttpAddRequestHeadersW (internal)
*/
@ -294,11 +526,58 @@ BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest,
* FALSE on failure
*
*/
BOOL WINAPI HttpEndRequestA(HINTERNET hRequest, LPINTERNET_BUFFERSA lpBuffersOut,
DWORD dwFlags, DWORD dwContext)
BOOL WINAPI HttpEndRequestA(HINTERNET hRequest,
LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD dwContext)
{
FIXME("stub\n");
return FALSE;
LPINTERNET_BUFFERSA ptr;
LPINTERNET_BUFFERSW lpBuffersOutW,ptrW;
BOOL rc = FALSE;
TRACE("(%p, %p, %08lx, %08lx): stub\n", hRequest, lpBuffersOut, dwFlags,
dwContext);
ptr = lpBuffersOut;
if (ptr)
lpBuffersOutW = (LPINTERNET_BUFFERSW)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(INTERNET_BUFFERSW));
else
lpBuffersOutW = NULL;
ptrW = lpBuffersOutW;
while (ptr)
{
if (ptr->lpvBuffer && ptr->dwBufferLength)
ptrW->lpvBuffer = HeapAlloc(GetProcessHeap(),0,ptr->dwBufferLength);
ptrW->dwBufferLength = ptr->dwBufferLength;
ptrW->dwBufferTotal= ptr->dwBufferTotal;
if (ptr->Next)
ptrW->Next = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
sizeof(INTERNET_BUFFERSW));
ptr = ptr->Next;
ptrW = ptrW->Next;
}
rc = HttpEndRequestW(hRequest, lpBuffersOutW, dwFlags, dwContext);
if (lpBuffersOutW)
{
ptrW = lpBuffersOutW;
while (ptrW)
{
LPINTERNET_BUFFERSW ptrW2;
FIXME("Do we need to translate info out of these buffer?\n");
HeapFree(GetProcessHeap(),0,(LPVOID)ptrW->lpvBuffer);
ptrW2 = ptrW->Next;
HeapFree(GetProcessHeap(),0,ptrW);
ptrW = ptrW2;
}
}
return rc;
}
/***********************************************************************
@ -311,11 +590,47 @@ BOOL WINAPI HttpEndRequestA(HINTERNET hRequest, LPINTERNET_BUFFERSA lpBuffersOut
* FALSE on failure
*
*/
BOOL WINAPI HttpEndRequestW(HINTERNET hRequest, LPINTERNET_BUFFERSW lpBuffersOut,
DWORD dwFlags, DWORD dwContext)
BOOL WINAPI HttpEndRequestW(HINTERNET hRequest,
LPINTERNET_BUFFERSW lpBuffersOut, DWORD dwFlags, DWORD dwContext)
{
FIXME("stub\n");
return FALSE;
BOOL rc = FALSE;
LPWININETHTTPREQW lpwhr;
INT responseLen;
INT cnt;
static const char nullbuff[] = "\0";
TRACE("-->\n");
lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
return FALSE;
}
lpwhr->hdr.dwFlags |= dwFlags;
lpwhr->hdr.dwContext = dwContext;
/* End the request by sending a NULL byte */
rc = NETCON_send(&lpwhr->netConnection, nullbuff, 1, 0, &cnt);
SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
responseLen = HTTP_GetResponseHeaders(lpwhr);
if (responseLen)
rc = TRUE;
SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
/* process headers here. Is this right? */
HTTP_ProcessHeaders(lpwhr);
/* We appear to do nothing with the buffer.. is that correct? */
TRACE("%i <--\n",rc);
return rc;
}
/***********************************************************************
@ -1195,9 +1510,63 @@ BOOL WINAPI HttpSendRequestExA(HINTERNET hRequest,
LPINTERNET_BUFFERSA lpBuffersOut,
DWORD dwFlags, DWORD dwContext)
{
FIXME("(%p, %p, %p, %08lx, %08lx): stub\n", hRequest, lpBuffersIn,
lpBuffersOut, dwFlags, dwContext);
return FALSE;
LPINTERNET_BUFFERSA ptr;
LPINTERNET_BUFFERSW lpBuffersInW,ptrW;
BOOL rc = FALSE;
TRACE("(%p, %p, %p, %08lx, %08lx): stub\n", hRequest, lpBuffersIn,
lpBuffersOut, dwFlags, dwContext);
ptr = lpBuffersIn;
if (ptr)
lpBuffersInW = (LPINTERNET_BUFFERSW)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(INTERNET_BUFFERSW));
else
lpBuffersInW = NULL;
ptrW = lpBuffersInW;
while (ptr)
{
DWORD headerlen;
ptrW->dwStructSize = sizeof(LPINTERNET_BUFFERSW);
if (ptr->lpcszHeader)
{
headerlen = MultiByteToWideChar(CP_ACP,0,ptr->lpcszHeader,
ptr->dwHeadersLength,0,0);
headerlen++;
ptrW->lpcszHeader = HeapAlloc(GetProcessHeap(),0,headerlen*
sizeof(WCHAR));
ptrW->dwHeadersLength = MultiByteToWideChar(CP_ACP, 0,
ptr->lpcszHeader, ptr->dwHeadersLength,
(LPWSTR)ptrW->lpcszHeader, headerlen);
}
ptrW->dwHeadersTotal = ptr->dwHeadersTotal;
ptrW->lpvBuffer = ptr->lpvBuffer;
ptrW->dwBufferLength = ptr->dwBufferLength;
ptrW->dwBufferTotal= ptr->dwBufferTotal;
if (ptr->Next)
ptrW->Next = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
sizeof(INTERNET_BUFFERSW));
ptr = ptr->Next;
ptrW = ptrW->Next;
}
rc = HttpSendRequestExW(hRequest, lpBuffersInW, NULL, dwFlags, dwContext);
if (lpBuffersInW)
{
ptrW = lpBuffersInW;
while (ptrW)
{
LPINTERNET_BUFFERSW ptrW2;
HeapFree(GetProcessHeap(),0,(LPVOID)ptrW->lpcszHeader);
ptrW2 = ptrW->Next;
HeapFree(GetProcessHeap(),0,ptrW);
ptrW = ptrW2;
}
}
return rc;
}
/***********************************************************************
@ -1211,9 +1580,105 @@ BOOL WINAPI HttpSendRequestExW(HINTERNET hRequest,
LPINTERNET_BUFFERSW lpBuffersOut,
DWORD dwFlags, DWORD dwContext)
{
FIXME("(%p, %p, %p, %08lx, %08lx): stub\n", hRequest, lpBuffersIn,
lpBuffersOut, dwFlags, dwContext);
return FALSE;
LPINTERNET_BUFFERSW buf_ptr;
DWORD bufferlen = 0;
BOOL rc;
LPWININETHTTPREQW lpwhr;
LPWSTR requestString = NULL;
DWORD len;
char *ascii_req;
INT cnt;
TRACE("(%p, %p, %p, %08lx, %08lx): stub\n", hRequest, lpBuffersIn,
lpBuffersOut, dwFlags, dwContext);
lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
if (NULL == lpwhr || lpwhr->hdr.htype != WH_HHTTPREQ)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
return FALSE;
}
HTTP_FixVerb(lpwhr);
/* add headers */
buf_ptr = lpBuffersIn;
while(buf_ptr)
{
if (buf_ptr->lpcszHeader)
{
HTTP_HttpAddRequestHeadersW(lpwhr, buf_ptr->lpcszHeader,
buf_ptr->dwHeadersLength, HTTP_ADDREQ_FLAG_ADD |
HTTP_ADDHDR_FLAG_REPLACE);
}
bufferlen += buf_ptr->dwBufferTotal;
buf_ptr = buf_ptr->Next;
}
lpwhr->hdr.dwFlags |= dwFlags;
lpwhr->hdr.dwContext = dwContext;
if (bufferlen > 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 \n\r */ +
20 /* int */ ];
sprintfW(contentLengthStr, szContentLength, bufferlen);
HTTP_HttpAddRequestHeadersW(lpwhr, contentLengthStr, -1L,
HTTP_ADDREQ_FLAG_ADD);
}
HTTP_FixURL(lpwhr);
/* Do Send Request logic */
TRACE("Going to url %s %s\n",
debugstr_w(lpwhr->StdHeaders[HTTP_QUERY_HOST].lpszValue),
debugstr_w(lpwhr->lpszPath));
HTTP_AddProxyInfo(lpwhr);
requestString = HTTP_BuildHeaderRequestString(lpwhr);
TRACE("Request header -> %s\n", debugstr_w(requestString) );
if (!(rc = HTTP_OpenConnection(lpwhr)))
goto end;
SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_CONNECTED_TO_SERVER, NULL, 0);
/* send the request as ASCII */
len = WideCharToMultiByte( CP_ACP, 0, requestString, -1, NULL, 0, NULL,
NULL);
/* we do not want the null because optional data will be sent with following
* InternetWriteFile calls
*/
len --;
ascii_req = HeapAlloc( GetProcessHeap(), 0, len);
WideCharToMultiByte( CP_ACP, 0, requestString, -1, ascii_req, len, NULL,
NULL );
TRACE("full request -> %s\n", debugstr_an(ascii_req,len) );
SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_SENDING_REQUEST, NULL, 0);
rc = NETCON_send(&lpwhr->netConnection, ascii_req, len, 0, &cnt);
HeapFree( GetProcessHeap(), 0, ascii_req );
/* This may not be sent here. It may come laster */
SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
INTERNET_STATUS_REQUEST_SENT, &len,sizeof(DWORD));
end:
HeapFree(GetProcessHeap(), 0, requestString);
WININET_Release(&lpwhr->hdr);
TRACE("<---\n");
return rc;
}
/***********************************************************************
@ -1470,45 +1935,21 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
DWORD dwHeaderLength, LPVOID lpOptional ,DWORD dwOptionalLength)
{
INT cnt;
DWORD i;
BOOL bSuccess = FALSE;
LPWSTR requestString = NULL;
INT responseLen;
LPWININETHTTPSESSIONW lpwhs = NULL;
LPWININETAPPINFOW hIC = NULL;
BOOL loop_next = FALSE;
int CustHeaderIndex;
INTERNET_ASYNC_RESULT iar;
TRACE("--> %p\n", lpwhr);
assert(lpwhr->hdr.htype == WH_HHTTPREQ);
lpwhs = (LPWININETHTTPSESSIONW) lpwhr->hdr.lpwhparent;
if (NULL == lpwhs || lpwhs->hdr.htype != WH_HHTTPSESSION)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
return FALSE;
}
hIC = (LPWININETAPPINFOW) lpwhs->hdr.lpwhparent;
if (NULL == hIC || hIC->hdr.htype != WH_HINIT)
{
INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
return FALSE;
}
/* Clear any error information */
INTERNET_SetLastError(0);
/* if the verb is NULL default to GET */
if (NULL == lpwhr->lpszVerb)
{
static const WCHAR szGET[] = { 'G','E','T', 0 };
lpwhr->lpszVerb = WININET_strdupW(szGET);
}
HTTP_FixVerb(lpwhr);
/* if we are using optional stuff, we must add the fixed header of that option length */
if (lpOptional && dwOptionalLength)
{
@ -1521,50 +1962,13 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
do
{
static const WCHAR szSlash[] = { '/',0 };
static const WCHAR szSpace[] = { ' ',0 };
static const WCHAR szHttp[] = { 'h','t','t','p',':','/','/', 0 };
static const WCHAR szcrlf[] = {'\r','\n', 0};
static const WCHAR sztwocrlf[] = {'\r','\n','\r','\n', 0};
static const WCHAR szSetCookie[] = {'S','e','t','-','C','o','o','k','i','e',0 };
static const WCHAR szColon[] = { ':',' ',0 };
LPCWSTR *req;
LPWSTR p;
DWORD len, n;
DWORD len;
char *ascii_req;
TRACE("Going to url %s %s\n", debugstr_w(lpwhr->StdHeaders[HTTP_QUERY_HOST].lpszValue), debugstr_w(lpwhr->lpszPath));
loop_next = FALSE;
/* If we don't have a path we set it to root */
if (NULL == lpwhr->lpszPath)
lpwhr->lpszPath = WININET_strdupW(szSlash);
else /* remove \r and \n*/
{
int nLen = strlenW(lpwhr->lpszPath);
while ((nLen >0 ) && ((lpwhr->lpszPath[nLen-1] == '\r')||(lpwhr->lpszPath[nLen-1] == '\n')))
{
nLen--;
lpwhr->lpszPath[nLen]='\0';
}
/* Replace '\' with '/' */
while (nLen>0) {
nLen--;
if (lpwhr->lpszPath[nLen] == '\\') lpwhr->lpszPath[nLen]='/';
}
}
if(CSTR_EQUAL != CompareStringW( LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
lpwhr->lpszPath, strlenW(szHttp), szHttp, strlenW(szHttp) )
&& lpwhr->lpszPath[0] != '/') /* not an absolute path ?? --> fix it !! */
{
WCHAR *fixurl = HeapAlloc(GetProcessHeap(), 0,
(strlenW(lpwhr->lpszPath) + 2)*sizeof(WCHAR));
*fixurl = '/';
strcpyW(fixurl + 1, lpwhr->lpszPath);
HeapFree( GetProcessHeap(), 0, lpwhr->lpszPath );
lpwhr->lpszPath = fixurl;
}
HTTP_FixURL(lpwhr);
/* add the headers the caller supplied */
if( lpszHeaders && dwHeaderLength )
@ -1573,68 +1977,10 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
HTTP_ADDREQ_FLAG_ADD | HTTP_ADDHDR_FLAG_REPLACE);
}
/* if there's a proxy username and password, add it to the headers */
if (hIC && (hIC->lpszProxyUsername || hIC->lpszProxyPassword ))
HTTP_InsertProxyAuthorization(lpwhr, hIC->lpszProxyUsername, hIC->lpszProxyPassword);
/* if there's a proxy username and password, add it to the headers */
HTTP_AddProxyInfo(lpwhr);
/* allocate space for an array of all the string pointers to be added */
len = (HTTP_QUERY_MAX + lpwhr->nCustHeaders)*4 + 9;
req = HeapAlloc( GetProcessHeap(), 0, len*sizeof(LPCWSTR) );
/* add the verb, path and HTTP/1.0 */
n = 0;
req[n++] = lpwhr->lpszVerb;
req[n++] = szSpace;
req[n++] = lpwhr->lpszPath;
req[n++] = HTTPHEADER;
/* Append standard request headers */
for (i = 0; i <= HTTP_QUERY_MAX; i++)
{
if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST)
{
req[n++] = szcrlf;
req[n++] = lpwhr->StdHeaders[i].lpszField;
req[n++] = szColon;
req[n++] = lpwhr->StdHeaders[i].lpszValue;
TRACE("Adding header %s (%s)\n",
debugstr_w(lpwhr->StdHeaders[i].lpszField),
debugstr_w(lpwhr->StdHeaders[i].lpszValue));
}
}
/* Append custom request heades */
for (i = 0; i < lpwhr->nCustHeaders; i++)
{
if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
{
req[n++] = szcrlf;
req[n++] = lpwhr->pCustHeaders[i].lpszField;
req[n++] = szColon;
req[n++] = lpwhr->pCustHeaders[i].lpszValue;
TRACE("Adding custom header %s (%s)\n",
debugstr_w(lpwhr->pCustHeaders[i].lpszField),
debugstr_w(lpwhr->pCustHeaders[i].lpszValue));
}
}
if( n >= len )
ERR("oops. buffer overrun\n");
req[n] = NULL;
requestString = HTTP_build_req( req, 4 );
HeapFree( GetProcessHeap(), 0, req );
/*
* Set (header) termination string for request
* Make sure there's exactly two new lines at the end of the request
*/
p = &requestString[strlenW(requestString)-1];
while ( (*p == '\n') || (*p == '\r') )
p--;
strcpyW( p+1, sztwocrlf );
requestString = HTTP_BuildHeaderRequestString(lpwhr);
TRACE("Request header -> %s\n", debugstr_w(requestString) );
@ -1681,78 +2027,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(LPWININETHTTPREQW lpwhr, LPCWSTR lpszHeaders,
sizeof(DWORD));
/* process headers here. Is this right? */
CustHeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSetCookie);
if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES) && (CustHeaderIndex >= 0))
{
LPHTTPHEADERW setCookieHeader;
int nPosStart = 0, nPosEnd = 0, len;
static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','/',0};
setCookieHeader = &lpwhr->pCustHeaders[CustHeaderIndex];
while (setCookieHeader->lpszValue[nPosEnd] != '\0')
{
LPWSTR buf_cookie, cookie_name, cookie_data;
LPWSTR buf_url;
LPWSTR domain = NULL;
int nEqualPos = 0;
while (setCookieHeader->lpszValue[nPosEnd] != ';' && setCookieHeader->lpszValue[nPosEnd] != ',' &&
setCookieHeader->lpszValue[nPosEnd] != '\0')
{
nPosEnd++;
}
if (setCookieHeader->lpszValue[nPosEnd] == ';')
{
/* fixme: not case sensitive, strcasestr is gnu only */
int nDomainPosEnd = 0;
int nDomainPosStart = 0, nDomainLength = 0;
static const WCHAR szDomain[] = {'d','o','m','a','i','n','=',0};
LPWSTR lpszDomain = strstrW(&setCookieHeader->lpszValue[nPosEnd], szDomain);
if (lpszDomain)
{ /* they have specified their own domain, lets use it */
while (lpszDomain[nDomainPosEnd] != ';' && lpszDomain[nDomainPosEnd] != ',' &&
lpszDomain[nDomainPosEnd] != '\0')
{
nDomainPosEnd++;
}
nDomainPosStart = strlenW(szDomain);
nDomainLength = (nDomainPosEnd - nDomainPosStart) + 1;
domain = HeapAlloc(GetProcessHeap(), 0, (nDomainLength + 1)*sizeof(WCHAR));
lstrcpynW(domain, &lpszDomain[nDomainPosStart], nDomainLength + 1);
}
}
if (setCookieHeader->lpszValue[nPosEnd] == '\0') break;
buf_cookie = HeapAlloc(GetProcessHeap(), 0, ((nPosEnd - nPosStart) + 1)*sizeof(WCHAR));
lstrcpynW(buf_cookie, &setCookieHeader->lpszValue[nPosStart], (nPosEnd - nPosStart) + 1);
TRACE("%s\n", debugstr_w(buf_cookie));
while (buf_cookie[nEqualPos] != '=' && buf_cookie[nEqualPos] != '\0')
{
nEqualPos++;
}
if (buf_cookie[nEqualPos] == '\0' || buf_cookie[nEqualPos + 1] == '\0')
{
HeapFree(GetProcessHeap(), 0, buf_cookie);
break;
}
cookie_name = HeapAlloc(GetProcessHeap(), 0, (nEqualPos + 1)*sizeof(WCHAR));
lstrcpynW(cookie_name, buf_cookie, nEqualPos + 1);
cookie_data = &buf_cookie[nEqualPos + 1];
len = strlenW((domain ? domain : lpwhr->StdHeaders[HTTP_QUERY_HOST].lpszValue)) +
strlenW(lpwhr->lpszPath) + 9;
buf_url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
sprintfW(buf_url, szFmt, (domain ? domain : lpwhr->StdHeaders[HTTP_QUERY_HOST].lpszValue)); /* FIXME PATH!!! */
InternetSetCookieW(buf_url, cookie_name, cookie_data);
HeapFree(GetProcessHeap(), 0, buf_url);
HeapFree(GetProcessHeap(), 0, buf_cookie);
HeapFree(GetProcessHeap(), 0, cookie_name);
HeapFree(GetProcessHeap(), 0, domain);
nPosStart = nPosEnd;
}
}
HTTP_ProcessHeaders(lpwhr);
}
while (loop_next);

View File

@ -1040,6 +1040,65 @@ static void InternetCreateUrlA_test()
HeapFree(GetProcessHeap(), 0, szUrl);
}
static void HttpSendRequestEx_test(void)
{
HINTERNET hSession;
HINTERNET hConnect;
HINTERNET hRequest;
INTERNET_BUFFERS BufferIn;
DWORD dwBytesWritten;
DWORD dwBytesRead;
CHAR szBuffer[256];
int i;
static const char szPostData[] = "mode=Test";
static const char szContentType[] = "Content-Type: application/x-www-form-urlencoded";
hSession = InternetOpen("Wine Regression Test",
INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
ok( hSession != NULL ,"Unable to open Internet session\n");
hConnect = InternetConnect(hSession, "crossover.codeweavers.com",
INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0,
0);
ok( hConnect != NULL, "Unable to connect to http://crossover.codeweavers.com\n");
hRequest = HttpOpenRequest(hConnect, "POST", "/posttest.php",
NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
ok( hRequest != NULL, "Failed to open request handle\n");
BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS);
BufferIn.Next = NULL;
BufferIn.lpcszHeader = szContentType;
BufferIn.dwHeadersLength = sizeof(szContentType);
BufferIn.dwHeadersTotal = sizeof(szContentType);
BufferIn.lpvBuffer = NULL;
BufferIn.dwBufferLength = 0;
BufferIn.dwBufferTotal = sizeof(szPostData)-1;
BufferIn.dwOffsetLow = 0;
BufferIn.dwOffsetHigh = 0;
ok(HttpSendRequestEx(hRequest, &BufferIn, NULL, 0 ,0),
"SendRequestEx Failed\n");
for (i = 0; szPostData[i]; i++)
ok(InternetWriteFile(hRequest, &szPostData[i], 1, &dwBytesWritten),
"InternetWriteFile failed\n");
ok(HttpEndRequest(hRequest, NULL, 0, 0), "HttpEndRequest Failed\n");
ok(InternetReadFile(hRequest, szBuffer, 255, &dwBytesRead),
"Unable to read responce\n");
szBuffer[dwBytesRead] = 0;
ok(dwBytesRead == 13,"Read %lu bytes instead of 13\n",dwBytesRead);
ok(strncmp(szBuffer,"mode => Test\n",dwBytesRead)==0,"Got string %s\n",szBuffer);
ok(InternetCloseHandle(hRequest), "Close request handle failed\n");
ok(InternetCloseHandle(hConnect), "Close connect handle failed\n");
ok(InternetCloseHandle(hSession), "Close session handle failed\n");
}
START_TEST(http)
{
InternetReadFile_test(INTERNET_FLAG_ASYNC);
@ -1053,4 +1112,5 @@ START_TEST(http)
InternetTimeToSystemTimeA_test();
InternetTimeToSystemTimeW_test();
InternetCreateUrlA_test();
HttpSendRequestEx_test();
}