From a4969063366608a4fd18fc586e9c452fca41d119 Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Sun, 4 Jul 2004 00:24:47 +0000 Subject: [PATCH] Build http requests in a more consistent way. Fix the size of the request buffer. Don't try converting the optional information from W to A. --- dlls/wininet/http.c | 235 +++++++++++++++----------------------------- 1 file changed, 78 insertions(+), 157 deletions(-) diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c index f5425774623..fc266c0bbb7 100644 --- a/dlls/wininet/http.c +++ b/dlls/wininet/http.c @@ -1372,6 +1372,29 @@ static BOOL HTTP_HandleRedirect(LPWININETHTTPREQW lpwhr, LPCWSTR lpszUrl, LPCWST return HttpSendRequestW(handle, lpszHeaders, dwHeaderLength, lpOptional, dwOptionalLength); } +/*********************************************************************** + * HTTP_build_req (internal) + * + * concatenate all the strings in the request together + */ +static LPWSTR HTTP_build_req( LPCWSTR *list, int len ) +{ + LPCWSTR *t; + LPWSTR str; + + for( t = list; *t ; t++ ) + len += strlenW( *t ); + len++; + + str = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + *str = 0; + + for( t = list; *t ; t++ ) + strcatW( str, *t ); + + return str; +} + /*********************************************************************** * HTTP_HttpSendRequestW (internal) * @@ -1389,10 +1412,7 @@ BOOL WINAPI HTTP_HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders, INT i; BOOL bSuccess = FALSE; LPWSTR requestString = NULL; - LPWSTR lpszHeaders_r_n = NULL; /* lpszHeaders with atleast one pair of \r\n at the end */ - INT requestStringLen; INT responseLen; - INT headerLength = 0; LPWININETHTTPREQW lpwhr; LPWININETHTTPSESSIONW lpwhs = NULL; LPWININETAPPINFOW hIC = NULL; @@ -1451,6 +1471,12 @@ BOOL WINAPI HTTP_HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders, 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; + int len, n; + char *ascii_req; + TRACE("Going to url %s %s\n", debugstr_w(lpwhr->lpszHostName), debugstr_w(lpwhr->lpszPath)); loop_next = FALSE; @@ -1471,104 +1497,27 @@ BOOL WINAPI HTTP_HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders, lpwhr->lpszPath = fixurl; } - /* Calculate length of request string */ - requestStringLen = - strlenW(lpwhr->lpszVerb) + - strlenW(lpwhr->lpszPath) + - strlenW(HTTPHEADER) + - 5; /* " \r\n\r\n" */ + /* allocate space for an array of all the string pointers to be added */ + len = (1 + HTTP_QUERY_MAX + lpwhr->nCustHeaders)*4 + 3; + req = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len*sizeof(LPCWSTR) ); - /* add "\r\n" to end of lpszHeaders if needed */ - if (lpszHeaders) - { - int len = strlenW(lpszHeaders); - - /* Check if the string is terminated with \r\n, but not if - * the string is less that 2 characters long, because then - * we would be looking at memory before the beginning of - * the string. Besides, if it is less than 2 characters - * long, then clearly, its not terminated with \r\n. - */ - if ((len > 2) && (memcmp(lpszHeaders + (len - 2), szcrlf, sizeof szcrlf) == 0)) - { - lpszHeaders_r_n = WININET_strdupW(lpszHeaders); - } - else - { - TRACE("Adding \r\n to lpszHeaders.\n"); - lpszHeaders_r_n = HeapAlloc( GetProcessHeap(), 0, - (len + 3)*sizeof(WCHAR) ); - strcpyW( lpszHeaders_r_n, lpszHeaders ); - strcatW( lpszHeaders_r_n, szcrlf ); - } - } - - /* Add length of passed headers */ - if (lpszHeaders) - { - headerLength = -1 == dwHeaderLength ? strlenW(lpszHeaders_r_n) : dwHeaderLength; - 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++) - { - if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST) - { - requestStringLen += strlenW(lpwhr->pCustHeaders[i].lpszField) + - strlenW(lpwhr->pCustHeaders[i].lpszValue) + 4; /*: \r\n */ - } - } - - /* Calculate the length of standard request headers */ - for (i = 0; i <= HTTP_QUERY_MAX; i++) - { - if (lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST) - { - requestStringLen += strlenW(lpwhr->StdHeaders[i].lpszField) + - strlenW(lpwhr->StdHeaders[i].lpszValue) + 4; /*: \r\n */ - } - } - - if (lpwhr->lpszHostName) - requestStringLen += (strlenW(HTTPHOSTHEADER) + strlenW(lpwhr->lpszHostName)); - - /* if there is optional data to send, add the length */ - if (lpOptional) - { - requestStringLen += dwOptionalLength; - } - - /* Allocate string to hold entire request */ - requestString = HeapAlloc(GetProcessHeap(), 0, (requestStringLen + 1)*sizeof(WCHAR)); - if (NULL == requestString) - { - INTERNET_SetLastError(ERROR_OUTOFMEMORY); - goto lend; - } - - /* Build request string */ - strcpyW(requestString, lpwhr->lpszVerb); - strcatW(requestString, szSpace); - strcatW(requestString, lpwhr->lpszPath); - strcatW(requestString, HTTPHEADER ); - cnt = strlenW(requestString); + /* 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) { - static const WCHAR szFmt[] = { '\r','\n','%','s',':',' ','%','s', 0}; - cnt += sprintfW(requestString + cnt, szFmt, - lpwhr->StdHeaders[i].lpszField, lpwhr->StdHeaders[i].lpszValue); + 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)); @@ -1580,9 +1529,11 @@ BOOL WINAPI HTTP_HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders, { if (lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST) { - static const WCHAR szFmt[] = { '\r','\n','%','s',':',' ','%','s', 0}; - cnt += sprintfW(requestString + cnt, szFmt, - lpwhr->pCustHeaders[i].lpszField, lpwhr->pCustHeaders[i].lpszValue); + 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)); @@ -1591,53 +1542,27 @@ BOOL WINAPI HTTP_HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders, if (lpwhr->lpszHostName) { - static const WCHAR szFmt[] = { '%','s','%','s',0 }; - cnt += sprintfW(requestString + cnt, szFmt, HTTPHOSTHEADER, lpwhr->lpszHostName); + req[n++] = HTTPHOSTHEADER; + req[n++] = lpwhr->lpszHostName; } - /* Append passed request headers */ - if (lpszHeaders_r_n) - { - strcpyW(requestString + cnt, szcrlf); - cnt += 2; - strcpyW(requestString + cnt, lpszHeaders_r_n); - cnt += headerLength; - /* only add \r\n if not already present */ - if (memcmp((requestString + cnt) - 2, szcrlf, sizeof szcrlf) != 0) - { - strcpyW(requestString + cnt, szcrlf); - cnt += 2; - } - } + if( n > len ) + ERR("oops. buffer overrun\n"); - /* Set (header) termination string for request */ - if (memcmp((requestString + cnt) - 4, sztwocrlf, sizeof sztwocrlf) != 0) - { /* only add it if the request string doesn't already - have the thing.. (could happen if the custom header - added it */ - strcpyW(requestString + cnt, szcrlf); - cnt += 2; - } - else - requestStringLen -= 2; + requestString = HTTP_build_req( req, 4 ); + HeapFree( GetProcessHeap(), 0, req ); - /* if optional data, append it */ - if (lpOptional) - { - memcpy(requestString + cnt, lpOptional, dwOptionalLength*sizeof(WCHAR)); - cnt += dwOptionalLength; - /* we also have to decrease the expected string length by two, - * since we won't be adding on those following \r\n's */ - requestStringLen -= 2; - } - else - { /* if there is no optional data, add on another \r\n just to be safe */ - /* termination for request */ - strcpyW(requestString + cnt, szcrlf); - cnt += 2; - } + /* + * 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 ); + + TRACE("Request header -> %s\n", debugstr_w(requestString) ); - TRACE("(%s) len(%d)\n", debugstr_w(requestString), requestStringLen); /* Send the request and store the results */ if (!HTTP_OpenConnection(lpwhr)) goto lend; @@ -1645,24 +1570,23 @@ BOOL WINAPI HTTP_HttpSendRequestW(HINTERNET hHttpRequest, LPCWSTR lpszHeaders, SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext, INTERNET_STATUS_SENDING_REQUEST, NULL, 0); - /* send the request as ASCII */ - { - int ascii_len; - char *ascii_req; - - ascii_len = WideCharToMultiByte( CP_ACP, 0, requestString, - requestStringLen, NULL, 0, NULL, NULL ); - ascii_req = HeapAlloc( GetProcessHeap(), 0, ascii_len ); - WideCharToMultiByte( CP_ACP, 0, requestString, requestStringLen, - ascii_req, ascii_len, NULL, NULL ); - NETCON_send(&lpwhr->netConnection, ascii_req, ascii_len, 0, &cnt); - HeapFree( GetProcessHeap(), 0, ascii_req ); - } - + /* send the request as ASCII, tack on the optional data */ + if( !lpOptional ) + 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], lpOptional, dwOptionalLength ); + len += dwOptionalLength; + NETCON_send(&lpwhr->netConnection, ascii_req, len, 0, &cnt); + HeapFree( GetProcessHeap(), 0, ascii_req ); SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext, INTERNET_STATUS_REQUEST_SENT, - &requestStringLen,sizeof(DWORD)); + &len,sizeof(DWORD)); SendAsyncCallback(hIC, hHttpRequest, lpwhr->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); @@ -1761,9 +1685,6 @@ lend: if (requestString) HeapFree(GetProcessHeap(), 0, requestString); - if (lpszHeaders) - HeapFree(GetProcessHeap(), 0, lpszHeaders_r_n); - /* TODO: send notification for P3P header */ if(!(hIC->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && bSuccess)