http.c: HttpSendRequestEx

Aric Stewart aric at codeweavers.com
Fri Nov 18 15:56:05 CST 2005


Implement HttpSendRequestEx and HttpEndRequest. Restructure, breaking 
some things out of HTTP_SendRequestW to avoid duplicate code.

Fixes Picasa (Hello) mail for Picasa and works toward improving Gmail 
access.
-------------- next part --------------
Index: dlls/wininet/http.c
===================================================================
RCS file: /home/wine/wine/dlls/wininet/http.c,v
retrieving revision 1.110
diff -u -r1.110 http.c
--- dlls/wininet/http.c	15 Nov 2005 18:16:55 -0000	1.110
+++ dlls/wininet/http.c	18 Nov 2005 21:53:41 -0000
@@ -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 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 @@
     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 @@
  *    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 @@
  *    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 @@
 			       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 @@
                    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 @@
 	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 @@
 
     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 @@
                         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);
-
-        /* 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));
-            }
-        }
+        /* if there's a proxy username and password, add it to the headers */
+        HTTP_AddProxyInfo(lpwhr);
 
-        /* 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 @@
                           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);
 


More information about the wine-patches mailing list