Hans Leidekker : winhttp: Don't try to read data after a HEAD request.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Jan 21 15:16:21 CST 2015


Module: wine
Branch: master
Commit: 27ba8c834326bb526fc57148feb6d83883c7a7c6
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=27ba8c834326bb526fc57148feb6d83883c7a7c6

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Wed Jan 21 13:25:18 2015 +0100

winhttp: Don't try to read data after a HEAD request.

---

 dlls/winhttp/request.c       | 34 +++++++++++++--------
 dlls/winhttp/tests/winhttp.c | 70 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 13 deletions(-)

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index de5eae4..dc13fd0 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -1807,20 +1807,23 @@ static DWORD set_content_length( request_t *request, DWORD status )
     WCHAR encoding[20];
     DWORD buflen = sizeof(request->content_length);
 
-    if (status == HTTP_STATUS_NO_CONTENT || status == HTTP_STATUS_NOT_MODIFIED)
+    if (status == HTTP_STATUS_NO_CONTENT || status == HTTP_STATUS_NOT_MODIFIED || !strcmpW( request->verb, headW ))
         request->content_length = 0;
-    else if (!query_headers( request, WINHTTP_QUERY_CONTENT_LENGTH|WINHTTP_QUERY_FLAG_NUMBER,
-                             NULL, &request->content_length, &buflen, NULL ))
-        request->content_length = ~0u;
-
-    buflen = sizeof(encoding);
-    if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) &&
-        !strcmpiW( encoding, chunkedW ))
+    else
     {
-        request->content_length = ~0u;
-        request->read_chunked = TRUE;
-        request->read_chunked_size = ~0u;
-        request->read_chunked_eof = FALSE;
+        if (!query_headers( request, WINHTTP_QUERY_CONTENT_LENGTH|WINHTTP_QUERY_FLAG_NUMBER,
+                            NULL, &request->content_length, &buflen, NULL ))
+            request->content_length = ~0u;
+
+        buflen = sizeof(encoding);
+        if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) &&
+            !strcmpiW( encoding, chunkedW ))
+        {
+            request->content_length = ~0u;
+            request->read_chunked = TRUE;
+            request->read_chunked_size = ~0u;
+            request->read_chunked_eof = FALSE;
+        }
     }
     request->content_read = 0;
     return request->content_length;
@@ -1969,6 +1972,7 @@ static DWORD get_available_data( request_t *request )
 /* check if we have reached the end of the data to read */
 static BOOL end_of_read_data( request_t *request )
 {
+    if (!request->content_length) return TRUE;
     if (request->read_chunked) return request->read_chunked_eof;
     if (request->content_length == ~0u) return FALSE;
     return (request->content_length == request->content_read);
@@ -2394,8 +2398,11 @@ BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved )
 
 static BOOL query_data_available( request_t *request, DWORD *available, BOOL async )
 {
-    DWORD count = get_available_data( request );
+    DWORD count = 0;
+
+    if (end_of_read_data( request )) goto done;
 
+    count = get_available_data( request );
     if (!request->read_chunked)
         count += netconn_query_data_available( &request->netconn );
     if (!count)
@@ -2406,6 +2413,7 @@ static BOOL query_data_available( request_t *request, DWORD *available, BOOL asy
             count += netconn_query_data_available( &request->netconn );
     }
 
+done:
     if (async) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &count, sizeof(count) );
     TRACE("%u bytes available\n", count);
     if (available) *available = count;
diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c
index 384df23..2cad807 100644
--- a/dlls/winhttp/tests/winhttp.c
+++ b/dlls/winhttp/tests/winhttp.c
@@ -1818,6 +1818,11 @@ static const char okauthmsg[] =
 "Connection: close\r\n"
 "\r\n";
 
+static const char headmsg[] =
+"HTTP/1.1 200 OK\r\n"
+"Content-Length: 100\r\n"
+"\r\n";
+
 struct server_info
 {
     HANDLE event;
@@ -1904,6 +1909,11 @@ static DWORD CALLBACK server_thread(LPVOID param)
             send(c, notmodified, sizeof notmodified - 1, 0);
             continue;
         }
+        if (strstr(buffer, "HEAD /head"))
+        {
+            send(c, headmsg, sizeof headmsg - 1, 0);
+            continue;
+        }
         if (strstr(buffer, "GET /quit"))
         {
             send(c, okmsg, sizeof okmsg - 1, 0);
@@ -2220,6 +2230,65 @@ static void test_no_content(int port)
     WinHttpCloseHandle(ses);
 }
 
+static void test_head_request(int port)
+{
+    static const WCHAR verbW[] = {'H','E','A','D',0};
+    static const WCHAR headW[] = {'/','h','e','a','d',0};
+    HINTERNET ses, con, req;
+    char buf[128];
+    DWORD size, len, count, status;
+    BOOL ret;
+
+    ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0);
+    ok(ses != NULL, "failed to open session %u\n", GetLastError());
+
+    con = WinHttpConnect(ses, localhostW, port, 0);
+    ok(con != NULL, "failed to open a connection %u\n", GetLastError());
+
+    req = WinHttpOpenRequest(con, verbW, headW, NULL, NULL, NULL, 0);
+    ok(req != NULL, "failed to open a request %u\n", GetLastError());
+
+    ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0);
+    ok(ret, "failed to send request %u\n", GetLastError());
+
+    ret = WinHttpReceiveResponse(req, NULL);
+    ok(ret, "failed to receive response %u\n", GetLastError());
+
+    status = 0xdeadbeef;
+    size = sizeof(status);
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
+                              NULL, &status, &size, NULL);
+    ok(ret, "failed to get status code %u\n", GetLastError());
+    ok(status == 200, "got %u\n", status);
+
+    len = 0xdeadbeef;
+    size = sizeof(len);
+    ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER,
+                              NULL, &len, &size, 0);
+    ok(ret, "failed to get content-length header %u\n", GetLastError());
+    ok(len == 100, "got %u\n", len);
+
+    count = 0xdeadbeef;
+    ret = WinHttpQueryDataAvailable(req, &count);
+    ok(ret, "failed to query data available %u\n", GetLastError());
+    ok(!count, "got %u\n", count);
+
+    len = sizeof(buf);
+    count = 0xdeadbeef;
+    ret = WinHttpReadData(req, buf, len, &count);
+    ok(ret, "failed to read data %u\n", GetLastError());
+    ok(!count, "got %u\n", count);
+
+    count = 0xdeadbeef;
+    ret = WinHttpQueryDataAvailable(req, &count);
+    ok(ret, "failed to query data available %u\n", GetLastError());
+    ok(!count, "got %u\n", count);
+
+    WinHttpCloseHandle(req);
+    WinHttpCloseHandle(con);
+    WinHttpCloseHandle(ses);
+}
+
 static void test_not_modified(int port)
 {
     static const WCHAR pathW[] = {'/','n','o','t','_','m','o','d','i','f','i','e','d',0};
@@ -3278,6 +3347,7 @@ START_TEST (winhttp)
     test_basic_request(si.port, NULL, basicW);
     test_no_headers(si.port);
     test_no_content(si.port);
+    test_head_request(si.port);
     test_not_modified(si.port);
     test_basic_authentication(si.port);
     test_bad_header(si.port);




More information about the wine-cvs mailing list