Hans Leidekker : winhttp: Improve parsing of cookie values.
Alexandre Julliard
julliard at wine.codeweavers.com
Tue Jun 16 10:13:13 CDT 2015
Module: wine
Branch: master
Commit: 41cf9a8372e698ecfa81254fd9ed67459607c3d6
URL: http://source.winehq.org/git/wine.git/?a=commit;h=41cf9a8372e698ecfa81254fd9ed67459607c3d6
Author: Hans Leidekker <hans at codeweavers.com>
Date: Mon Jun 15 17:32:25 2015 +0200
winhttp: Improve parsing of cookie values.
---
dlls/winhttp/cookie.c | 53 ++++++++++----------
dlls/winhttp/tests/winhttp.c | 117 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 144 insertions(+), 26 deletions(-)
diff --git a/dlls/winhttp/cookie.c b/dlls/winhttp/cookie.c
index 6e104b2..4bf0808 100644
--- a/dlls/winhttp/cookie.c
+++ b/dlls/winhttp/cookie.c
@@ -134,22 +134,14 @@ static cookie_t *parse_cookie( const WCHAR *string )
const WCHAR *p;
int len;
- if (!(p = strchrW( string, '=' )))
- {
- WARN("no '=' in %s\n", debugstr_w(string));
- return NULL;
- }
- if (p == string)
- {
- WARN("empty cookie name in %s\n", debugstr_w(string));
- return NULL;
- }
+ if (!(p = strchrW( string, '=' ))) p = string + strlenW( string );
+ len = p - string;
+ while (len && string[len - 1] == ' ') len--;
+ if (!len) return NULL;
if (!(cookie = heap_alloc_zero( sizeof(cookie_t) ))) return NULL;
-
list_init( &cookie->entry );
- len = p - string;
if (!(cookie->name = heap_alloc( (len + 1) * sizeof(WCHAR) )))
{
heap_free( cookie );
@@ -158,18 +150,20 @@ static cookie_t *parse_cookie( const WCHAR *string )
memcpy( cookie->name, string, len * sizeof(WCHAR) );
cookie->name[len] = 0;
- p++; /* skip '=' */
- while (*p == ' ') p++;
-
- len = strlenW( p );
- if (!(cookie->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+ if (*p++ == '=')
{
- free_cookie( cookie );
- return NULL;
- }
- memcpy( cookie->value, p, len * sizeof(WCHAR) );
- cookie->value[len] = 0;
+ while (*p && *p == ' ') p++;
+ len = strlenW( p );
+ while (len && p[len - 1] == ' ') len--;
+ if (!(cookie->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
+ {
+ free_cookie( cookie );
+ return NULL;
+ }
+ memcpy( cookie->value, p, len * sizeof(WCHAR) );
+ cookie->value[len] = 0;
+ }
return cookie;
}
@@ -259,14 +253,21 @@ BOOL add_cookie_headers( request_t *request )
if (strstrW( request->path, cookie->path ) == request->path)
{
- const WCHAR format[] = {'C','o','o','k','i','e',':',' ','%','s','=','%','s',0};
- int len;
+ const WCHAR cookieW[] = {'C','o','o','k','i','e',':',' '};
+ int len, len_cookie = sizeof(cookieW) / sizeof(cookieW[0]), len_name = strlenW( cookie->name );
WCHAR *header;
- len = strlenW( cookie->name ) + strlenW( format ) + strlenW( cookie->value );
+ len = len_cookie + len_name;
+ if (cookie->value) len += strlenW( cookie->value ) + 1;
if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE;
- sprintfW( header, format, cookie->name, cookie->value );
+ memcpy( header, cookieW, len_cookie * sizeof(WCHAR) );
+ strcpyW( header + len_cookie, cookie->name );
+ if (cookie->value)
+ {
+ header[len_cookie + len_name] = '=';
+ strcpyW( header + len_cookie + len_name + 1, cookie->value );
+ }
TRACE("%s\n", debugstr_w(header));
add_request_headers( request, header, len, WINHTTP_ADDREQ_FLAG_ADD );
diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c
index 3860461..10a3f06 100644
--- a/dlls/winhttp/tests/winhttp.c
+++ b/dlls/winhttp/tests/winhttp.c
@@ -1799,6 +1799,15 @@ static const char okmsg[] =
"Server: winetest\r\n"
"\r\n";
+static const char notokmsg[] =
+"HTTP/1.1 400 Bad Request\r\n"
+"\r\n";
+
+static const char cookiemsg[] =
+"HTTP/1.1 200 OK\r\n"
+"Set-Cookie: name = value \r\n"
+"\r\n";
+
static const char nocontentmsg[] =
"HTTP/1.1 204 No Content\r\n"
"Server: winetest\r\n"
@@ -1917,6 +1926,16 @@ static DWORD CALLBACK server_thread(LPVOID param)
send(c, headmsg, sizeof headmsg - 1, 0);
continue;
}
+ if (strstr(buffer, "GET /cookie2"))
+ {
+ if (strstr(buffer, "Cookie: name=value\r\n")) send(c, okmsg, sizeof(okmsg) - 1, 0);
+ else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
+ }
+ else if (strstr(buffer, "GET /cookie"))
+ {
+ if (!strstr(buffer, "Cookie: name=value\r\n")) send(c, cookiemsg, sizeof(cookiemsg) - 1, 0);
+ else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
+ }
if (strstr(buffer, "GET /quit"))
{
send(c, okmsg, sizeof okmsg - 1, 0);
@@ -2503,6 +2522,103 @@ static void test_multiple_reads(int port)
WinHttpCloseHandle(ses);
}
+static void test_cookies( int port )
+{
+ static const WCHAR cookieW[] = {'/','c','o','o','k','i','e',0};
+ static const WCHAR cookie2W[] = {'/','c','o','o','k','i','e','2',0};
+ HINTERNET ses, con, req;
+ DWORD status, size;
+ 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, NULL, cookieW, 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 query status code %u\n", GetLastError() );
+ ok( status == 200, "request failed unexpectedly %u\n", status );
+
+ WinHttpCloseHandle( req );
+
+ req = WinHttpOpenRequest( con, NULL, cookie2W, 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 query status code %u\n", GetLastError() );
+ ok( status == 200, "request failed unexpectedly %u\n", status );
+
+ WinHttpCloseHandle( req );
+ WinHttpCloseHandle( con );
+
+ con = WinHttpConnect( ses, localhostW, port, 0 );
+ ok( con != NULL, "failed to open a connection %u\n", GetLastError() );
+
+ req = WinHttpOpenRequest( con, NULL, cookie2W, 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 query status code %u\n", GetLastError() );
+ ok( status == 200, "request failed unexpectedly %u\n", status );
+
+ WinHttpCloseHandle( req );
+ WinHttpCloseHandle( con );
+ WinHttpCloseHandle( ses );
+
+ 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, NULL, cookie2W, 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 query status code %u\n", GetLastError() );
+ ok( status == 400, "request failed unexpectedly %u\n", status );
+
+ WinHttpCloseHandle( req );
+ WinHttpCloseHandle( con );
+ WinHttpCloseHandle( ses );
+}
+
static void test_connection_info( int port )
{
static const WCHAR basicW[] = {'/','b','a','s','i','c',0};
@@ -3478,6 +3594,7 @@ START_TEST (winhttp)
test_basic_authentication(si.port);
test_bad_header(si.port);
test_multiple_reads(si.port);
+ test_cookies(si.port);
/* send the basic request again to shutdown the server thread */
test_basic_request(si.port, NULL, quitW);
More information about the wine-cvs
mailing list