[WININET] Sync with Wine Staging 3.9. CORE-14656
[reactos.git] / dll / win32 / wininet / http.c
index f9694ca..35ea56b 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "internet.h"
+#include "config.h"
+
+#include <stdlib.h>
 
 #ifdef HAVE_ZLIB
 #  include <zlib.h>
 #endif
 
-#include <winternl.h>
+#include "winsock2.h"
+#include "ws2ipdef.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <time.h>
+#include <assert.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wininet.h"
+#include "winerror.h"
+#include "winternl.h"
+#define NO_SHLWAPI_STREAM
+#define NO_SHLWAPI_REG
+#define NO_SHLWAPI_STRFCNS
+#define NO_SHLWAPI_GDI
+#include "shlwapi.h"
+#include "sspi.h"
+#include "wincrypt.h"
+#include "winuser.h"
+
+#include "internet.h"
+#include "wine/debug.h"
+#include "wine/exception.h"
+#include "wine/unicode.h"
 
-#include <wine/exception.h>
+WINE_DEFAULT_DEBUG_CHANNEL(wininet);
 
 static const WCHAR g_szHttp1_0[] = {'H','T','T','P','/','1','.','0',0};
 static const WCHAR g_szHttp1_1[] = {'H','T','T','P','/','1','.','1',0};
@@ -742,10 +769,18 @@ static void HTTP_ProcessCookies( http_request_t *request )
     int HeaderIndex;
     int numCookies = 0;
     LPHTTPHEADERW setCookieHeader;
+    WCHAR *path, *tmp;
 
     if(request->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES)
         return;
 
+    path = heap_strdupW(request->path);
+    if (!path)
+        return;
+
+    tmp = strrchrW(path, '/');
+    if (tmp && tmp[1]) tmp[1] = 0;
+
     EnterCriticalSection( &request->headers_section );
 
     while((HeaderIndex = HTTP_GetCustomHeaderIndex(request, szSet_Cookie, numCookies++, FALSE)) != -1)
@@ -764,10 +799,11 @@ static void HTTP_ProcessCookies( http_request_t *request )
 
         name = substr(setCookieHeader->lpszValue, data - setCookieHeader->lpszValue);
         data++;
-        set_cookie(substrz(request->server->name), substrz(request->path), name, substrz(data), INTERNET_COOKIE_HTTPONLY);
+        set_cookie(substrz(request->server->name), substrz(path), name, substrz(data), INTERNET_COOKIE_HTTPONLY);
     }
 
     LeaveCriticalSection( &request->headers_section );
+    heap_free(path);
 }
 
 static void strip_spaces(LPWSTR start)
@@ -2326,11 +2362,6 @@ static DWORD HTTPREQ_SetOption(object_header_t *hdr, DWORD option, void *buffer,
         if (!(req->session->appInfo->proxyPassword = heap_strdupW(buffer))) return ERROR_OUTOFMEMORY;
         return ERROR_SUCCESS;
 
-    case INTERNET_OPTION_HTTP_DECODING:
-        if(size != sizeof(BOOL))
-            return ERROR_INVALID_PARAMETER;
-        req->decoding = *(BOOL*)buffer;
-        return ERROR_SUCCESS;
     }
 
     return INET_SetOption(hdr, option, buffer, size);
@@ -2900,7 +2931,7 @@ static DWORD set_content_length(http_request_t *request)
         request->contentLength = ~0u;
     }
 
-    if(request->decoding) {
+    if(request->hdr.decoding) {
         int encoding_idx;
 
         static const WCHAR deflateW[] = {'d','e','f','l','a','t','e',0};
@@ -3286,6 +3317,7 @@ static DWORD HTTP_HttpOpenRequestW(http_session_t *session,
     request->hdr.htype = WH_HHTTPREQ;
     request->hdr.dwFlags = dwFlags;
     request->hdr.dwContext = dwContext;
+    request->hdr.decoding = session->hdr.decoding;
     request->contentLength = ~0u;
 
     request->netconn_stream.data_stream.vtbl = &netconn_stream_vtbl;
@@ -5032,7 +5064,7 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
             res = set_content_length(request);
             if(res != ERROR_SUCCESS)
                 goto lend;
-            if(!request->contentLength)
+            if(!request->contentLength && !secure_proxy_connect)
                 http_release_netconn(request, TRUE);
 
             if (!(request->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && responseLen)
@@ -5080,7 +5112,8 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
                                                  request->session->password, host))
                         {
                             heap_free(requestString);
-                            if(!drain_content(request, TRUE) == ERROR_SUCCESS) {
+                            if (drain_content(request, TRUE) != ERROR_SUCCESS)
+                            {
                                 FIXME("Could not drain content\n");
                                 http_release_netconn(request, FALSE);
                             }
@@ -5108,7 +5141,8 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
                                                  NULL))
                         {
                             heap_free(requestString);
-                            if(!drain_content(request, TRUE) == ERROR_SUCCESS) {
+                            if (drain_content(request, TRUE) != ERROR_SUCCESS)
+                            {
                                 FIXME("Could not drain content\n");
                                 http_release_netconn(request, FALSE);
                             }
@@ -5136,6 +5170,8 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders,
                 remove_header(request, szProxy_Authorization, TRUE);
                 destroy_authinfo(request->proxyAuthInfo);
                 request->proxyAuthInfo = NULL;
+                request->contentLength = 0;
+                request->netconn_stream.content_length = 0;
 
                 secure_proxy_connect = FALSE;
                 loop_next = TRUE;
@@ -5793,6 +5829,7 @@ DWORD HTTP_Connect(appinfo_t *hIC, LPCWSTR lpszServerName,
     session->hdr.dwFlags = dwFlags;
     session->hdr.dwContext = dwContext;
     session->hdr.dwInternalFlags |= dwInternalFlags;
+    session->hdr.decoding = hIC->hdr.decoding;
 
     WININET_AddRef( &hIC->hdr );
     session->appInfo = hIC;
@@ -6050,127 +6087,128 @@ static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer)
 
 static DWORD HTTP_ProcessHeader(http_request_t *request, LPCWSTR field, LPCWSTR value, DWORD dwModifier)
 {
-    LPHTTPHEADERW lphttpHdr = NULL;
+    LPHTTPHEADERW lphttpHdr;
     INT index;
     BOOL request_only = !!(dwModifier & HTTP_ADDHDR_FLAG_REQ);
-    DWORD res = ERROR_HTTP_INVALID_HEADER;
+    DWORD res = ERROR_SUCCESS;
 
     TRACE("--> %s: %s - 0x%08x\n", debugstr_w(field), debugstr_w(value), dwModifier);
 
     EnterCriticalSection( &request->headers_section );
 
-    /* REPLACE wins out over ADD */
-    if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
-        dwModifier &= ~HTTP_ADDHDR_FLAG_ADD;
-    
-    if (dwModifier & HTTP_ADDHDR_FLAG_ADD)
-        index = -1;
-    else
-        index = HTTP_GetCustomHeaderIndex(request, field, 0, request_only);
-
+    index = HTTP_GetCustomHeaderIndex(request, field, 0, request_only);
     if (index >= 0)
     {
-        if (dwModifier & HTTP_ADDHDR_FLAG_ADD_IF_NEW)
-        {
-            LeaveCriticalSection( &request->headers_section );
-            return ERROR_HTTP_INVALID_HEADER;
-        }
         lphttpHdr = &request->custHeaders[index];
-    }
-    else if (value)
-    {
-        HTTPHEADERW hdr;
 
-        hdr.lpszField = (LPWSTR)field;
-        hdr.lpszValue = (LPWSTR)value;
-        hdr.wFlags = hdr.wCount = 0;
+        /* replace existing header if FLAG_REPLACE is given */
+        if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
+        {
+            HTTP_DeleteCustomHeader( request, index );
 
-        if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
-            hdr.wFlags |= HDR_ISREQUEST;
+            if (value && value[0])
+            {
+                HTTPHEADERW hdr;
 
-        res = HTTP_InsertCustomHeader(request, &hdr);
-        LeaveCriticalSection( &request->headers_section );
-        return res;
-    }
-    /* no value to delete */
-    else
-    {
-        LeaveCriticalSection( &request->headers_section );
-        return ERROR_SUCCESS;
-    }
+                hdr.lpszField = (LPWSTR)field;
+                hdr.lpszValue = (LPWSTR)value;
+                hdr.wFlags = hdr.wCount = 0;
 
-    if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
-           lphttpHdr->wFlags |= HDR_ISREQUEST;
-    else
-        lphttpHdr->wFlags &= ~HDR_ISREQUEST;
+                if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
+                    hdr.wFlags |= HDR_ISREQUEST;
 
-    if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
-    {
-        HTTP_DeleteCustomHeader( request, index );
+                res = HTTP_InsertCustomHeader( request, &hdr );
+            }
 
-        if (value && value[0])
+            goto out;
+        }
+
+        /* do not add new header if FLAG_ADD_IF_NEW is set */
+        if (dwModifier & HTTP_ADDHDR_FLAG_ADD_IF_NEW)
         {
-            HTTPHEADERW hdr;
+            res = ERROR_HTTP_INVALID_HEADER; /* FIXME */
+            goto out;
+        }
 
-            hdr.lpszField = (LPWSTR)field;
-            hdr.lpszValue = (LPWSTR)value;
-            hdr.wFlags = hdr.wCount = 0;
+        /* handle appending to existing header */
+        if (dwModifier & COALESCEFLAGS)
+        {
+            LPWSTR lpsztmp;
+            WCHAR ch = 0;
+            INT len = 0;
+            INT origlen = strlenW(lphttpHdr->lpszValue);
+            INT valuelen = strlenW(value);
 
+            /* FIXME: Should it really clear HDR_ISREQUEST? */
             if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
-                hdr.wFlags |= HDR_ISREQUEST;
-
-            res = HTTP_InsertCustomHeader(request, &hdr);
-            LeaveCriticalSection( &request->headers_section );
-            return res;
-        }
+                lphttpHdr->wFlags |= HDR_ISREQUEST;
+            else
+                lphttpHdr->wFlags &= ~HDR_ISREQUEST;
 
-        LeaveCriticalSection( &request->headers_section );
-        return ERROR_SUCCESS;
-    }
-    else if (dwModifier & COALESCEFLAGS)
-    {
-        LPWSTR lpsztmp;
-        WCHAR ch = 0;
-        INT len = 0;
-        INT origlen = strlenW(lphttpHdr->lpszValue);
-        INT valuelen = strlenW(value);
+            if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA)
+            {
+                ch = ',';
+                lphttpHdr->wFlags |= HDR_COMMADELIMITED;
+            }
+            else if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
+            {
+                ch = ';';
+                lphttpHdr->wFlags |= HDR_COMMADELIMITED;
+            }
 
-        if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA)
-        {
-            ch = ',';
-            lphttpHdr->wFlags |= HDR_COMMADELIMITED;
-        }
-        else if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
-        {
-            ch = ';';
-            lphttpHdr->wFlags |= HDR_COMMADELIMITED;
-        }
+            len = origlen + valuelen + ((ch > 0) ? 2 : 0);
 
-        len = origlen + valuelen + ((ch > 0) ? 2 : 0);
+            lpsztmp = heap_realloc(lphttpHdr->lpszValue, (len+1)*sizeof(WCHAR));
+            if (lpsztmp)
+            {
+                lphttpHdr->lpszValue = lpsztmp;
+                /* FIXME: Increment lphttpHdr->wCount. Perhaps lpszValue should be an array */
+                if (ch > 0)
+                {
+                    lphttpHdr->lpszValue[origlen] = ch;
+                    origlen++;
+                    lphttpHdr->lpszValue[origlen] = ' ';
+                    origlen++;
+                }
 
-        lpsztmp = heap_realloc(lphttpHdr->lpszValue, (len+1)*sizeof(WCHAR));
-        if (lpsztmp)
-        {
-            lphttpHdr->lpszValue = lpsztmp;
-    /* FIXME: Increment lphttpHdr->wCount. Perhaps lpszValue should be an array */
-            if (ch > 0)
+                memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen*sizeof(WCHAR));
+                lphttpHdr->lpszValue[len] = '\0';
+            }
+            else
             {
-                lphttpHdr->lpszValue[origlen] = ch;
-                origlen++;
-                lphttpHdr->lpszValue[origlen] = ' ';
-                origlen++;
+                WARN("heap_realloc (%d bytes) failed\n",len+1);
+                res = ERROR_OUTOFMEMORY;
             }
 
-            memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen*sizeof(WCHAR));
-            lphttpHdr->lpszValue[len] = '\0';
-            res = ERROR_SUCCESS;
-        }
-        else
-        {
-            WARN("heap_realloc (%d bytes) failed\n",len+1);
-            res = ERROR_OUTOFMEMORY;
+            goto out;
         }
     }
+
+    /* FIXME: What about other combinations? */
+    if ((dwModifier & ~HTTP_ADDHDR_FLAG_REQ) == HTTP_ADDHDR_FLAG_REPLACE)
+    {
+        res = ERROR_HTTP_HEADER_NOT_FOUND;
+        goto out;
+    }
+
+    /* FIXME: What if value == ""? */
+    if (value)
+    {
+        HTTPHEADERW hdr;
+
+        hdr.lpszField = (LPWSTR)field;
+        hdr.lpszValue = (LPWSTR)value;
+        hdr.wFlags = hdr.wCount = 0;
+
+        if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
+            hdr.wFlags |= HDR_ISREQUEST;
+
+        res = HTTP_InsertCustomHeader( request, &hdr );
+        goto out;
+    }
+
+    /* FIXME: What if value == NULL? */
+out:
     TRACE("<-- %d\n", res);
     LeaveCriticalSection( &request->headers_section );
     return res;