Commit 2516fb78 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

winhttp: Fix a couple of corner cases in header processing.

parent 49b6b60e
...@@ -327,12 +327,8 @@ static header_t *parse_header( LPCWSTR string ) ...@@ -327,12 +327,8 @@ static header_t *parse_header( LPCWSTR string )
q++; /* skip past colon */ q++; /* skip past colon */
while (*q == ' ') q++; while (*q == ' ') q++;
if (!*q)
{
WARN("no value in line %s\n", debugstr_w(string));
return header;
}
len = strlenW( q ); len = strlenW( q );
if (!(header->value = heap_alloc( (len + 1) * sizeof(WCHAR) ))) if (!(header->value = heap_alloc( (len + 1) * sizeof(WCHAR) )))
{ {
free_header( header ); free_header( header );
...@@ -404,76 +400,65 @@ static BOOL delete_header( request_t *request, DWORD index ) ...@@ -404,76 +400,65 @@ static BOOL delete_header( request_t *request, DWORD index )
static BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only ) static BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only )
{ {
int index; int index;
header_t *header; header_t hdr;
TRACE("%s: %s 0x%08x\n", debugstr_w(field), debugstr_w(value), flags); TRACE("%s: %s 0x%08x\n", debugstr_w(field), debugstr_w(value), flags);
/* replace wins out over add */ if ((index = get_header_index( request, field, 0, request_only )) >= 0)
if (flags & WINHTTP_ADDREQ_FLAG_REPLACE) flags &= ~WINHTTP_ADDREQ_FLAG_ADD;
if (flags & WINHTTP_ADDREQ_FLAG_ADD) index = -1;
else
index = get_header_index( request, field, 0, request_only );
if (index >= 0)
{ {
if (flags & WINHTTP_ADDREQ_FLAG_ADD_IF_NEW) return FALSE; if (flags & WINHTTP_ADDREQ_FLAG_ADD_IF_NEW) return FALSE;
header = &request->headers[index];
}
else if (value)
{
header_t hdr;
hdr.field = (LPWSTR)field;
hdr.value = (LPWSTR)value;
hdr.is_request = request_only;
return insert_header( request, &hdr );
} }
/* no value to delete */
else return TRUE;
if (flags & WINHTTP_ADDREQ_FLAG_REPLACE) if (flags & WINHTTP_ADDREQ_FLAG_REPLACE)
{ {
if (index >= 0)
{
delete_header( request, index ); delete_header( request, index );
if (value) if (!value || !value[0]) return TRUE;
}
else if (!(flags & WINHTTP_ADDREQ_FLAG_ADD))
{ {
header_t hdr; set_last_error( ERROR_WINHTTP_HEADER_NOT_FOUND );
return FALSE;
}
hdr.field = (LPWSTR)field; hdr.field = (LPWSTR)field;
hdr.value = (LPWSTR)value; hdr.value = (LPWSTR)value;
hdr.is_request = request_only; hdr.is_request = request_only;
return insert_header( request, &hdr ); return insert_header( request, &hdr );
} }
return TRUE; else if (value)
}
else if (flags & (WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON))
{ {
WCHAR sep, *tmp;
int len, orig_len, value_len;
orig_len = strlenW( header->value ); if ((flags & (WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON)) &&
value_len = strlenW( value ); index >= 0)
{
WCHAR *tmp;
int len, len_orig, len_value;
header_t *header = &request->headers[index];
if (flags & WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA) sep = ','; len_orig = strlenW( header->value );
else sep = ';'; len_value = strlenW( value );
len = orig_len + value_len + 2; len = len_orig + len_value + 2;
if ((tmp = heap_realloc( header->value, (len + 1) * sizeof(WCHAR) ))) if (!(tmp = heap_realloc( header->value, (len + 1) * sizeof(WCHAR) ))) return FALSE;
{
header->value = tmp; header->value = tmp;
header->value[len_orig++] = (flags & WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA) ? ',' : ';';
header->value[len_orig++] = ' ';
header->value[orig_len] = sep; memcpy( &header->value[len_orig], value, len_value * sizeof(WCHAR) );
orig_len++;
header->value[orig_len] = ' ';
orig_len++;
memcpy( &header->value[orig_len], value, value_len * sizeof(WCHAR) );
header->value[len] = 0; header->value[len] = 0;
return TRUE; return TRUE;
} }
else
{
hdr.field = (LPWSTR)field;
hdr.value = (LPWSTR)value;
hdr.is_request = request_only;
return insert_header( request, &hdr );
}
} }
return TRUE; return TRUE;
} }
...@@ -2128,7 +2113,9 @@ static BOOL read_reply( request_t *request ) ...@@ -2128,7 +2113,9 @@ static BOOL read_reply( request_t *request )
/* we rely on the fact that the protocol is ascii */ /* we rely on the fact that the protocol is ascii */
MultiByteToWideChar( CP_ACP, 0, status_code, len, status_codeW, len ); MultiByteToWideChar( CP_ACP, 0, status_code, len, status_codeW, len );
status_codeW[len] = 0; status_codeW[len] = 0;
if (!(process_header( request, attr_status, status_codeW, WINHTTP_ADDREQ_FLAG_REPLACE, FALSE ))) return FALSE; if (!(process_header( request, attr_status, status_codeW,
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE, FALSE )))
return FALSE;
len = status_code - buffer; len = status_code - buffer;
if (!(versionW = heap_alloc( len * sizeof(WCHAR) ))) return FALSE; if (!(versionW = heap_alloc( len * sizeof(WCHAR) ))) return FALSE;
...@@ -2358,7 +2345,7 @@ static BOOL handle_redirect( request_t *request, DWORD status ) ...@@ -2358,7 +2345,7 @@ static BOOL handle_redirect( request_t *request, DWORD status )
} }
else heap_free( hostname ); else heap_free( hostname );
if (!(ret = add_host_header( request, WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end; if (!(ret = add_host_header( request, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end;
if (!(ret = open_connection( request ))) goto end; if (!(ret = open_connection( request ))) goto end;
heap_free( request->path ); heap_free( request->path );
...@@ -3227,7 +3214,8 @@ static HRESULT WINAPI winhttp_request_SetRequestHeader( ...@@ -3227,7 +3214,8 @@ static HRESULT WINAPI winhttp_request_SetRequestHeader(
goto done; goto done;
} }
sprintfW( str, fmtW, header, value ? value : emptyW ); sprintfW( str, fmtW, header, value ? value : emptyW );
if (!WinHttpAddRequestHeaders( request->hrequest, str, len, WINHTTP_ADDREQ_FLAG_REPLACE )) if (!WinHttpAddRequestHeaders( request->hrequest, str, len,
WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE ))
{ {
err = get_last_error(); err = get_last_error();
} }
......
...@@ -420,6 +420,8 @@ static void test_WinHttpAddHeaders(void) ...@@ -420,6 +420,8 @@ static void test_WinHttpAddHeaders(void)
{'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0','/','p','o','s','t','.','p','h','p',' ','H','T','T','P','/','1'}; {'P','O','S','T',' ','h','t','t','p',':','/','/','t','e','s','t','.','w','i','n','e','h','q','.','o','r','g',':','8','0','/','p','o','s','t','.','p','h','p',' ','H','T','T','P','/','1'};
static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0}; static const WCHAR test_header_end[] = {'\r','\n','\r','\n',0};
static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0}; static const WCHAR test_header_name[] = {'W','a','r','n','i','n','g',0};
static const WCHAR test_header_name2[] = {'n','a','m','e',0};
static const WCHAR test_header_name3[] = {'a',0};
static const WCHAR test_header_range[] = {'R','a','n','g','e',0}; static const WCHAR test_header_range[] = {'R','a','n','g','e',0};
static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0}; static const WCHAR test_header_range_bytes[] = {'R','a','n','g','e',':',' ','b','y','t','e','s','=','0','-','7','7','3','\r','\n',0};
static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0}; static const WCHAR test_header_bytes[] = {'b','y','t','e','s','=','0','-','7','7','3',0};
...@@ -438,6 +440,7 @@ static void test_WinHttpAddHeaders(void) ...@@ -438,6 +440,7 @@ static void test_WinHttpAddHeaders(void)
static const WCHAR field[] = {'f','i','e','l','d',0}; static const WCHAR field[] = {'f','i','e','l','d',0};
static const WCHAR value[] = {'v','a','l','u','e',' ',0}; static const WCHAR value[] = {'v','a','l','u','e',' ',0};
static const WCHAR value_nospace[] = {'v','a','l','u','e',0}; static const WCHAR value_nospace[] = {'v','a','l','u','e',0};
static const WCHAR empty[] = {0};
static const WCHAR test_headers[][14] = static const WCHAR test_headers[][14] =
{ {
...@@ -454,7 +457,9 @@ static void test_WinHttpAddHeaders(void) ...@@ -454,7 +457,9 @@ static void test_WinHttpAddHeaders(void)
{':','b',0}, {':','b',0},
{'c','d',0}, {'c','d',0},
{' ','e',' ',':','f',0}, {' ','e',' ',':','f',0},
{'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0} {'f','i','e','l','d',':',' ','v','a','l','u','e',' ',0},
{'n','a','m','e',':',' ','v','a','l','u','e',0},
{'n','a','m','e',':',0}
}; };
static const WCHAR test_indices[][6] = static const WCHAR test_indices[][6] =
{ {
...@@ -763,6 +768,14 @@ static void test_WinHttpAddHeaders(void) ...@@ -763,6 +768,14 @@ static void test_WinHttpAddHeaders(void)
ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD); ret = WinHttpAddRequestHeaders(request, test_headers[9], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
ok(ret, "WinHttpAddRequestHeaders failed\n"); ok(ret, "WinHttpAddRequestHeaders failed\n");
index = 0;
memset(buffer, 0xff, sizeof(buffer));
len = sizeof(buffer);
ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
test_header_name3, buffer, &len, &index);
ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError());
ok(!memcmp(buffer, empty, sizeof(empty)), "unexpected result\n");
ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD); ret = WinHttpAddRequestHeaders(request, test_headers[10], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
ok(!ret, "WinHttpAddRequestHeaders failed\n"); ok(!ret, "WinHttpAddRequestHeaders failed\n");
...@@ -803,6 +816,52 @@ static void test_WinHttpAddHeaders(void) ...@@ -803,6 +816,52 @@ static void test_WinHttpAddHeaders(void)
ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len); ok(len == lstrlenW(test_header_bytes) * sizeof(WCHAR), "wrong length %u\n", len);
ok(index == 1, "wrong index %u\n", index); ok(index == 1, "wrong index %u\n", index);
index = 0;
len = sizeof(buffer);
ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
test_header_name2, buffer, &len, &index);
ok(!ret, "unexpected success\n");
SetLastError(0xdeadbeef);
ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
err = GetLastError();
ok(!ret, "unexpected success\n");
ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
ret = WinHttpAddRequestHeaders(request, test_headers[14], ~0u, WINHTTP_ADDREQ_FLAG_ADD);
ok(ret, "got %u\n", GetLastError());
index = 0;
len = sizeof(buffer);
ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
test_header_name2, buffer, &len, &index);
ok(ret, "got %u\n", GetLastError());
ok(index == 1, "wrong index %u\n", index);
ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
ret = WinHttpAddRequestHeaders(request, test_headers[15], ~0u, WINHTTP_ADDREQ_FLAG_REPLACE);
ok(ret, "got %u\n", GetLastError());
index = 0;
len = sizeof(buffer);
SetLastError(0xdeadbeef);
ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
test_header_name2, buffer, &len, &index);
err = GetLastError();
ok(!ret, "unexpected success\n");
ok(err == ERROR_WINHTTP_HEADER_NOT_FOUND, "got %u\n", err);
ret = WinHttpAddRequestHeaders(request, test_headers[14], -1L, 0);
ok(ret, "got %u\n", GetLastError());
index = 0;
len = sizeof(buffer);
ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_CUSTOM | WINHTTP_QUERY_FLAG_REQUEST_HEADERS,
test_header_name2, buffer, &len, &index);
ok(ret, "got %u\n", GetLastError());
ok(index == 1, "wrong index %u\n", index);
ok(!memcmp(buffer, value_nospace, sizeof(value_nospace)), "incorrect string\n");
ret = WinHttpCloseHandle(request); ret = WinHttpCloseHandle(request);
ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret); ok(ret == TRUE, "WinHttpCloseHandle failed on closing request, got %d.\n", ret);
done: done:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment