WININET: build http requests in a better way
Mike McCormack
mike at codeweavers.com
Thu Jul 1 08:41:49 CDT 2004
ChangeLog:
* 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.
-------------- next part --------------
Index: dlls/wininet/http.c
===================================================================
RCS file: /home/wine/wine/dlls/wininet/http.c,v
retrieving revision 1.64
diff -u -r1.64 http.c
--- dlls/wininet/http.c 28 Jun 2004 20:28:38 -0000 1.64
+++ dlls/wininet/http.c 1 Jul 2004 14:38:26 -0000
@@ -1373,6 +1373,29 @@
}
/***********************************************************************
+ * 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)
*
* Sends the specified request to the HTTP server
@@ -1389,10 +1412,7 @@
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 @@
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 @@
lpwhr->lpszPath = fixurl;
}
- /* Calculate length of request string */
- requestStringLen =
- strlenW(lpwhr->lpszVerb) +
- strlenW(lpwhr->lpszPath) +
- strlenW(HTTPHEADER) +
- 5; /* " \r\n\r\n" */
-
- /* 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);
+ /* 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 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 @@
{
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 @@
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 @@
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);
@@ -1760,9 +1684,6 @@
if (requestString)
HeapFree(GetProcessHeap(), 0, requestString);
-
- if (lpszHeaders)
- HeapFree(GetProcessHeap(), 0, lpszHeaders_r_n);
/* TODO: send notification for P3P header */
More information about the wine-patches
mailing list