Hans Leidekker : winhttp: Don' t try to read data when the server response is HTTP_STATUS_NO_CONTENT or HTTP_STATUS_NOT_MODIFIED.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Dec 9 15:35:50 CST 2014


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue Dec  9 12:50:07 2014 +0100

winhttp: Don't try to read data when the server response is HTTP_STATUS_NO_CONTENT or HTTP_STATUS_NOT_MODIFIED.

Tests based on a patch by Bruno Jesus.

---

 dlls/winhttp/request.c       | 15 ++++++-----
 dlls/winhttp/tests/winhttp.c | 62 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 62ecfee..61f5439 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -1802,14 +1802,15 @@ static BOOL handle_authorization( request_t *request, DWORD status )
 }
 
 /* set the request content length based on the headers */
-static DWORD set_content_length( request_t *request )
+static DWORD set_content_length( request_t *request, DWORD status )
 {
     WCHAR encoding[20];
-    DWORD buflen;
+    DWORD buflen = sizeof(request->content_length);
 
-    buflen = sizeof(request->content_length);
-    if (!query_headers( request, WINHTTP_QUERY_CONTENT_LENGTH|WINHTTP_QUERY_FLAG_NUMBER,
-                        NULL, &request->content_length, &buflen, NULL ))
+    if (status == HTTP_STATUS_NO_CONTENT || status == HTTP_STATUS_NOT_MODIFIED)
+        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);
@@ -2302,7 +2303,7 @@ static BOOL receive_response( request_t *request, BOOL async )
         query = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER;
         if (!(ret = query_headers( request, query, NULL, &status, &size, NULL ))) break;
 
-        set_content_length( request );
+        set_content_length( request, status );
 
         if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request );
 
@@ -2329,7 +2330,7 @@ static BOOL receive_response( request_t *request, BOOL async )
         break;
     }
 
-    if (ret) refill_buffer( request, FALSE );
+    if (request->content_length) refill_buffer( request, FALSE );
 
     if (async)
     {
diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c
index 8a863cb..7d0167b 100644
--- a/dlls/winhttp/tests/winhttp.c
+++ b/dlls/winhttp/tests/winhttp.c
@@ -1801,6 +1801,10 @@ static const char nocontentmsg[] =
 "Server: winetest\r\n"
 "\r\n";
 
+static const char notmodified[] =
+"HTTP/1.1 304 Not Modified\r\n"
+"\r\n";
+
 static const char noauthmsg[] =
 "HTTP/1.1 401 Unauthorized\r\n"
 "Server: winetest\r\n"
@@ -1888,6 +1892,11 @@ static DWORD CALLBACK server_thread(LPVOID param)
         {
             send(c, nocontentmsg, sizeof nocontentmsg - 1, 0);
         }
+        if (strstr(buffer, "GET /not_modified"))
+        {
+            send(c, notmodified, sizeof notmodified - 1, 0);
+            Sleep(6000);
+        }
         if (strstr(buffer, "GET /quit"))
         {
             send(c, okmsg, sizeof okmsg - 1, 0);
@@ -2129,7 +2138,7 @@ static void test_no_content(int port)
 {
     static const WCHAR no_contentW[] = {'/','n','o','_','c','o','n','t','e','n','t',0};
     HINTERNET ses, con, req;
-    WCHAR buf[128];
+    char buf[128];
     DWORD size, len = sizeof(buf), bytes_read, status;
     BOOL ret;
 
@@ -2181,6 +2190,7 @@ static void test_no_content(int port)
     ok(size == 0, "expected 0, got %d\n", size);
 
     ret = WinHttpReadData(req, buf, len, &bytes_read);
+    ok(ret, "expected success\n");
     ok( bytes_read == 0, "expected 0, got %u available\n", bytes_read );
 
     size = 12345;
@@ -2202,6 +2212,55 @@ static void test_no_content(int port)
     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};
+    static const WCHAR ifmodifiedW[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',':',' '};
+    BOOL ret;
+    HINTERNET session, request, connection;
+    DWORD status, size, start = GetTickCount();
+    SYSTEMTIME st;
+    WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3];
+
+    memcpy(today, ifmodifiedW, sizeof(ifmodifiedW));
+    GetSystemTime(&st);
+    WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]);
+
+    session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
+        WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
+    ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError());
+
+    connection = WinHttpConnect(session, localhostW, port, 0);
+    ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError());
+
+    request = WinHttpOpenRequest(connection, NULL, pathW, NULL, WINHTTP_NO_REFERER,
+        WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE);
+    ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError());
+
+    ret = WinHttpSendRequest(request, today, ~0u, NULL, 0, 0, 0);
+    ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError());
+
+    ret = WinHttpReceiveResponse(request, NULL);
+    ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError());
+
+    size = sizeof(status);
+    ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER,
+                              NULL, &status, &size, NULL);
+    ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
+    ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status);
+
+    size = 0xdeadbeef;
+    ret = WinHttpQueryDataAvailable(request, &size);
+    ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError());
+    ok(!size, "got %u\n", size);
+
+    WinHttpCloseHandle(request);
+    WinHttpCloseHandle(connection);
+    WinHttpCloseHandle(session);
+    start = GetTickCount() - start;
+    ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start);
+}
+
 static void test_bad_header( int port )
 {
     static const WCHAR bad_headerW[] =
@@ -3211,6 +3270,7 @@ START_TEST (winhttp)
     test_basic_request(si.port, NULL, basicW);
     test_no_headers(si.port);
     test_no_content(si.port);
+    test_not_modified(si.port);
     test_basic_authentication(si.port);
     test_bad_header(si.port);
     test_multiple_reads(si.port);




More information about the wine-cvs mailing list