fix for HTTP_HttpSendRequestA, lpszHeaders, and POST data

Jeremy Shaw jeremy.shaw at lindows.com
Tue Dec 9 20:23:05 CST 2003


Hello,

If you call HTTP_HttpSendRequestA, and pass in lpszHeaders that are
not terminate with '\r\n', AND you are attempting to send POST data,
it won't work, because there will not be an empty line between the
HTTP headers and the POST data. (The remote server will simply wait a
few minutes thinking you have not sent the POST data yet, eventually
timing out).

I believe it is a mistake for wine to assume the lpszHeaders will be
terminated with '\r\n'. The Xten sipphone client does not terminate
lpszHeaders with '\r\n', and it works fine under numerous versions of
Microsoft Windows. MSDN also makes no mention of any need to terminate
the lpszHeaders with '\r\n'.

Below is a rather simple (and safe) patch that adds a '\r\n' to
lpszHeaders if it is not already terminated by '\r\n'.

Note, the variable name 'lpszHeaders_r_n' is kind of lame, please feel
free to pick a better name if you have an idea.

Jeremy Shaw.


--- orig/dlls/wininet/http.c
+++ mod/dlls/wininet/http.c
@@ -1160,6 +1160,7 @@
     INT i;
     BOOL bSuccess = FALSE;
     LPSTR requestString = NULL;
+    LPSTR lpszHeaders_r_n = NULL; /* lpszHeaders with atleast one pair of \r\n at the end */
     INT requestStringLen;
     INT responseLen;
     INT headerLength = 0;
@@ -1236,10 +1237,34 @@
             strlen(HTTPHEADER) +
             5; /* " \r\n\r\n" */
 
+	/* add "\r\n" to end of lpszHeaders if needed */
+	if (lpszHeaders)
+	{
+	    int len = strlen(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), "\r\n", 2) == 0))
+	    {
+		lpszHeaders_r_n = HTTP_strdup(lpszHeaders);
+	    }
+	    else
+	    {
+		TRACE("Adding \r\n to lpszHeaders.\n");
+		lpszHeaders_r_n =  HeapAlloc( GetProcessHeap(), 0, strlen(lpszHeaders) + 3 );
+		strcpy( lpszHeaders_r_n, lpszHeaders );
+		strcpy( lpszHeaders_r_n + strlen(lpszHeaders), "\r\n" );
+	    }
+	}
+
         /* Add length of passed headers */
         if (lpszHeaders)
         {
-            headerLength = -1 == dwHeaderLength ?  strlen(lpszHeaders) : dwHeaderLength;
+            headerLength = -1 == dwHeaderLength ?  strlen(lpszHeaders_r_n) : dwHeaderLength;
             requestStringLen += headerLength +  2; /* \r\n */
         }
 
@@ -1319,12 +1344,18 @@
             cnt += sprintf(requestString + cnt, "%s%s", HTTPHOSTHEADER, lpwhr->lpszHostName);
 
         /* Append passed request headers */
-        if (lpszHeaders)
+        if (lpszHeaders_r_n)
         {
             strcpy(requestString + cnt, "\r\n");
             cnt += 2;
-            strcpy(requestString + cnt, lpszHeaders);
+            strcpy(requestString + cnt, lpszHeaders_r_n);
             cnt += headerLength;
+	    /* only add \r\n if not already present */
+	    if (memcmp((requestString + cnt) - 2, "\r\n", 2) != 0)
+	    {
+                strcpy(requestString + cnt, "\r\n");
+                cnt += 2;
+	    }
         }
 
         /* Set (header) termination string for request */
@@ -1345,7 +1376,7 @@
             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;
+	    requestStringLen -= 2;
         }
         else
         { /* if there is no optional data, add on another \r\n just to be safe */
@@ -1463,6 +1494,9 @@
 
     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