From 91c7ab52a873c9c6443443937bad998f5dc40bbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sat, 16 May 2015 03:16:15 +0200
Subject: wininet: Replacing header fields should fail if they do not exist
 yet.

A lot of details are not properly covered by tests yet and were
marked with FIXME comments. The implementation was written in such
a way that it behaves identical to the old code in such situations.
---
 dlls/wininet/http.c       | 185 +++++++++++++++++++++++-----------------------
 dlls/wininet/tests/http.c |   6 +-
 2 files changed, 96 insertions(+), 95 deletions(-)

diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index f7c8f76..85bc392 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -6115,127 +6115,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;
diff --git a/dlls/wininet/tests/http.c b/dlls/wininet/tests/http.c
index ff76e9f..8b5cdb7 100644
--- a/dlls/wininet/tests/http.c
+++ b/dlls/wininet/tests/http.c
@@ -3116,13 +3116,13 @@ static void test_header_override(int port)
 
     ret = HttpAddRequestHeadersA(req, host_header_override, ~0u, HTTP_ADDREQ_FLAG_REPLACE);
     err = GetLastError();
-    todo_wine ok(!ret, "HttpAddRequestHeaders succeeded\n");
-    todo_wine ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "Expected error ERROR_HTTP_HEADER_NOT_FOUND, got %d\n", err);
+    ok(!ret, "HttpAddRequestHeaders succeeded\n");
+    ok(err == ERROR_HTTP_HEADER_NOT_FOUND, "Expected error ERROR_HTTP_HEADER_NOT_FOUND, got %d\n", err);
 
     ret = HttpSendRequestA(req, NULL, 0, NULL, 0);
     ok(ret, "HttpSendRequest failed\n");
 
-    test_status_code_todo(req, 400);
+    test_status_code(req, 400);
 
     InternetCloseHandle(req);
     InternetSetCookieA("http://localhost", "cookie", "biscuit");
-- 
2.4.3