Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42677 Signed-off-by: Hans Leidekker hans@codeweavers.com --- dlls/winhttp/request.c | 12 ++-- dlls/winhttp/session.c | 67 +++++++++++++++------- dlls/winhttp/tests/url.c | 29 +++++++++- dlls/winhttp/tests/winhttp.c | 60 +++++++++++++++----- dlls/winhttp/url.c | 122 +++++++++++++++++------------------------ dlls/winhttp/winhttp_private.h | 10 +++- 6 files changed, 188 insertions(+), 112 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index a365cdba48..960c755f8a 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -2535,18 +2535,18 @@ static BOOL handle_redirect( request_t *request, DWORD status )
if (location[0] == '/') { - len = escape_string( NULL, location, len_loc ); + len = escape_string( NULL, location, len_loc, 0 ); if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; - escape_string( path, location, len_loc ); + escape_string( path, location, len_loc, 0 ); } else { if ((p = strrchrW( request->path, '/' ))) *p = 0; - len = strlenW( request->path ) + 1 + escape_string( NULL, location, len_loc ); + len = strlenW( request->path ) + 1 + escape_string( NULL, location, len_loc, 0 ); if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; strcpyW( path, request->path ); strcatW( path, slashW ); - escape_string( path + strlenW(path), location, len_loc ); + escape_string( path + strlenW(path), location, len_loc, 0 ); } heap_free( request->path ); request->path = path; @@ -2597,9 +2597,9 @@ static BOOL handle_redirect( request_t *request, DWORD status ) request->path = NULL; if (uc.dwUrlPathLength) { - len = escape_string( NULL, uc.lpszUrlPath, uc.dwUrlPathLength + uc.dwExtraInfoLength ); + len = escape_string( NULL, uc.lpszUrlPath, uc.dwUrlPathLength + uc.dwExtraInfoLength, 0 ); if (!(request->path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; - escape_string( request->path, uc.lpszUrlPath, uc.dwUrlPathLength + uc.dwExtraInfoLength ); + escape_string( request->path, uc.lpszUrlPath, uc.dwUrlPathLength + uc.dwExtraInfoLength, 0 ); } else request->path = strdupW( slashW ); } diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c index 959cafa209..061091547a 100644 --- a/dlls/winhttp/session.c +++ b/dlls/winhttp/session.c @@ -1090,6 +1090,50 @@ static BOOL store_accept_types( request_t *request, const WCHAR **accept_types ) return TRUE; }
+static WCHAR *get_request_path( const WCHAR *object, DWORD flags ) +{ + DWORD len, path_len = 0, query_len = 0; + const WCHAR *p = object, *q = NULL; + enum escape_flags path_flags, query_flags; + WCHAR *ret; + + if (flags & WINHTTP_FLAG_ESCAPE_DISABLE) path_flags = ESCAPE_FLAG_SPACE_ONLY|ESCAPE_FLAG_REMOVE_CRLF; + else if (flags & WINHTTP_FLAG_ESCAPE_PERCENT) path_flags = ESCAPE_FLAG_PERCENT; + else path_flags = 0; + + if (flags & WINHTTP_FLAG_ESCAPE_DISABLE_QUERY) query_flags = ESCAPE_FLAG_SPACE_ONLY|ESCAPE_FLAG_REMOVE_CRLF; + else query_flags = path_flags; + + if (object) + { + path_len = strlenW( object ); + if (object[0] == '/') + { + path_len--; + p++; + } + if ((q = strchrW( p, '?' ))) + { + q++; + query_len = path_len - (q - p); + path_len -= query_len + 1; + } + } + + len = escape_string( NULL, p, path_len, path_flags ); + len += escape_string( NULL, q, query_len, query_flags ); + if (!(ret = heap_alloc( (len + 3) * sizeof(WCHAR) ))) return NULL; + + ret[0] = '/'; + len = escape_string( ret + 1, p, path_len, path_flags ) + 1; + if (q) + { + ret[len] = '?'; + escape_string( ret + 1 + len, q, query_len, query_flags ); + } + return ret; +} + /*********************************************************************** * WinHttpOpenRequest (winhttp.@) */ @@ -1103,12 +1147,11 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR o TRACE("%p, %s, %s, %s, %s, %p, 0x%08x\n", hconnect, debugstr_w(verb), debugstr_w(object), debugstr_w(version), debugstr_w(referrer), types, flags);
- if(types && TRACE_ON(winhttp)) { + if (types && TRACE_ON(winhttp)) + { const WCHAR **iter; - TRACE("accept types:\n"); - for(iter = types; *iter; iter++) - TRACE(" %s\n", debugstr_w(*iter)); + for (iter = types; *iter; iter++) TRACE(" %s\n", debugstr_w(*iter)); }
if (!(connect = (connect_t *)grab_object( hconnect ))) @@ -1150,21 +1193,7 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR o
if (!verb || !verb[0]) verb = getW; if (!(request->verb = strdupW( verb ))) goto end; - - if (object) - { - WCHAR *path, *p; - unsigned int len, len_object = strlenW(object); - - len = escape_string( NULL, object, len_object ); - if (object[0] != '/') len++; - if (!(p = path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; - - if (object[0] != '/') *p++ = '/'; - escape_string( p, object, len_object ); - request->path = path; - } - else if (!(request->path = strdupW( slashW ))) goto end; + if (!(request->path = get_request_path( object, flags ))) goto end;
if (!version || !version[0]) version = http1_1; if (!(request->version = strdupW( version ))) goto end; diff --git a/dlls/winhttp/tests/url.c b/dlls/winhttp/tests/url.c index 214b7f34cf..1980ad4da2 100644 --- a/dlls/winhttp/tests/url.c +++ b/dlls/winhttp/tests/url.c @@ -34,6 +34,7 @@ static WCHAR password[] = {'p','a','s','s','w','o','r','d',0}; static WCHAR about[] = {'/','s','i','t','e','/','a','b','o','u','t',0}; static WCHAR query[] = {'?','q','u','e','r','y',0}; static WCHAR escape[] = {' ','!','"','#','$','%','&',''','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\',']','^','_','`','{','|','}','~',0}; +static WCHAR escape2[] = {'\r',0x1f,' ','\n',0x7f,'\r','\n',0};
static const WCHAR url1[] = {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d', @@ -72,6 +73,8 @@ static const WCHAR url14[] = {'h','t','t','p',':','/','/','w','w','w','.','w','i static const WCHAR url15[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':','6','5','5','3','6',0}; static const WCHAR url16[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':','0',0}; static const WCHAR url17[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',':',0}; +static const WCHAR url18[] = + {'h','t','t','p',':','/','/','%','0','D','%','1','F','%','2','0','%','0','A','%','7','F','%','0','D','%','0','A',0};
static const WCHAR url_k1[] = {'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d', @@ -301,7 +304,31 @@ static void WinHttpCreateUrl_test( void ) ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len ); ok( ret, "expected success\n" ); ok( len == 113, "expected len 113 got %u\n", len ); - ok( !lstrcmpW( url, url7 ), "url doesn't match\n" ); + ok( !lstrcmpW( url, url7 ), "url doesn't match %s\n", wine_dbgstr_w(url) ); + + /* escape extra info */ + memset( &uc, 0, sizeof(uc) ); + uc.dwStructSize = sizeof(uc); + uc.lpszExtraInfo = escape2; + uc.dwExtraInfoLength = lstrlenW( uc.lpszExtraInfo ); + url[0] = 0; + len = 256; + ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len ); + ok( ret, "expected success\n" ); + ok( len == lstrlenW(url18), "expected len %u got %u\n", lstrlenW(url18), len ); + ok( !lstrcmpW( url, url18 ), "url doesn't match\n" ); + + /* escape path */ + memset( &uc, 0, sizeof(uc) ); + uc.dwStructSize = sizeof(uc); + uc.lpszUrlPath = escape2; + uc.dwUrlPathLength = lstrlenW( uc.lpszUrlPath ); + url[0] = 0; + len = 256; + ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len ); + ok( ret, "expected success\n" ); + ok( len == lstrlenW(url18), "expected len %u got %u\n", lstrlenW(url18), len ); + ok( !lstrcmpW( url, url18 ), "url doesn't match\n" );
/* NULL lpszScheme, 0 nScheme and nPort */ fill_url_components( &uc ); diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index 9138d6ad98..e13f95057b 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -2362,7 +2362,15 @@ static DWORD CALLBACK server_thread(LPVOID param) } else if (strstr(buffer, "GET /escape")) { - if (strstr(buffer, "GET /escape?one%20two%0D%0A HTTP/1.1")) send(c, okmsg, sizeof(okmsg) - 1, 0); + static const char res[] = "%0D%0A%1F%7F%3C%20%one?%1F%7F%20!%22%23$%&'()*+,-./:;%3C=%3E?@%5B%5C%5D" + "%5E_%60%7B%7C%7D~%0D%0A "; + static const char res2[] = "%0D%0A%1F%7F%3C%20%25two?%1F%7F%20!%22%23$%25&'()*+,-./:;%3C=%3E?@%5B%5C%5D" + "%5E_%60%7B%7C%7D~%0D%0A "; + static const char res3[] = "\x1f\x7f<%20%three?\x1f\x7f%20!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ "; + static const char res4[] = "%0D%0A%1F%7F%3C%20%four?\x1f\x7f%20!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ "; + + if (strstr(buffer + 11, res) || strstr(buffer + 11, res2) || strstr(buffer + 11, res3) || + strstr(buffer + 11, res4 )) send(c, okmsg, sizeof(okmsg) - 1, 0); else send(c, notokmsg, sizeof(notokmsg) - 1, 0); } if (strstr(buffer, "GET /quit")) @@ -3340,21 +3348,13 @@ static void test_cookies( int port ) WinHttpCloseHandle( ses ); }
-static void test_request_path_escapes( int port ) +static void do_request( HINTERNET con, const WCHAR *obj, DWORD flags ) { - static const WCHAR objW[] = - {'/','e','s','c','a','p','e','?','o','n','e',' ','t','w','o','\r','\n',0}; - HINTERNET ses, con, req; + HINTERNET req; DWORD status, size; BOOL ret;
- ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, 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, objW, NULL, NULL, NULL, 0 ); + req = WinHttpOpenRequest( con, NULL, obj, NULL, NULL, NULL, flags ); ok( req != NULL, "failed to open a request %u\n", GetLastError() );
ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 ); @@ -3367,9 +3367,41 @@ static void test_request_path_escapes( int port ) 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 == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status ); - + ok( status == HTTP_STATUS_OK, "request %s with flags %08x failed %u\n", wine_dbgstr_w(obj), flags, status ); WinHttpCloseHandle( req ); +} + +static void test_request_path_escapes( int port ) +{ + static const WCHAR objW[] = + {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','o','n','e','?',0x1f,0x7f,' ','!','"','#', + '$','%','&',''','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\',']','^','_','`', + '{','|','}','~','\r','\n',0}; + static const WCHAR obj2W[] = + {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','w','o','?',0x1f,0x7f,' ','!','"','#', + '$','%','&',''','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\',']','^','_','`', + '{','|','}','~','\r','\n',0}; + static const WCHAR obj3W[] = + {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','t','h','r','e','e','?',0x1f,0x7f,' ','!', + '"','#','$','%','&',''','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\',']','^', + '_','`','{','|','}','~','\r','\n',0}; + static const WCHAR obj4W[] = + {'/','e','s','c','a','p','e','\r','\n',0x1f,0x7f,'<',' ','%','f','o','u','r','?',0x1f,0x7f,' ','!','"', + '#','$','%','&',''','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\',']','^','_', + '`','{','|','}','~','\r','\n',0}; + HINTERNET ses, con; + + ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, 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() ); + + do_request( con, objW, 0 ); + do_request( con, obj2W, WINHTTP_FLAG_ESCAPE_PERCENT ); + do_request( con, obj3W, WINHTTP_FLAG_ESCAPE_DISABLE ); + do_request( con, obj4W, WINHTTP_FLAG_ESCAPE_DISABLE_QUERY ); + WinHttpCloseHandle( con ); WinHttpCloseHandle( ses ); } diff --git a/dlls/winhttp/url.c b/dlls/winhttp/url.c index 1e481d7dec..2019305ab3 100644 --- a/dlls/winhttp/url.c +++ b/dlls/winhttp/url.c @@ -87,59 +87,52 @@ static WCHAR *decode_url( LPCWSTR url, DWORD *len ) return ret; }
-static BOOL need_escape( WCHAR c ) + +static BOOL need_escape( WCHAR ch, enum escape_flags flags ) { - if (isalnumW( c )) return FALSE; + static const WCHAR escapes[] = {' ','"','#','<','>','[','\',']','^','`','{','|','}',0}; + const WCHAR *p = escapes;
- if (c <= 31 || c >= 127) return TRUE; - else + if (ch != ' ' && (flags & ESCAPE_FLAG_SPACE_ONLY)) return FALSE; + if (ch == '%' && (flags & ESCAPE_FLAG_PERCENT)) return TRUE; + if (ch == '~' && (flags & ESCAPE_FLAG_TILDE)) return TRUE; + + if (ch <= 31 || ch >= 127) return TRUE; + while (*p) { - switch (c) - { - case ' ': - case '"': - case '#': - case '%': - case '<': - case '>': - case ']': - case '\': - case '[': - case '^': - case '`': - case '{': - case '|': - case '}': - case '~': - return TRUE; - default: - return FALSE; - } + if (ch == *p++) return TRUE; } + return FALSE; }
-DWORD escape_string( WCHAR *dst, const WCHAR *src, DWORD len ) +DWORD escape_string( WCHAR *dst, const WCHAR *src, DWORD len, enum escape_flags flags ) { static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; DWORD ret = len; unsigned int i; WCHAR *p = dst;
- for (i = 0; i < len; i++, p++) + for (i = 0; i < len; i++) { - if (need_escape( src[i] )) + if ((flags & ESCAPE_FLAG_REMOVE_CRLF) && (src[i] == '\r' || src[i] == '\n')) + { + ret--; + continue; + } + if (need_escape( src[i], flags )) { if (dst) { p[0] = '%'; p[1] = hex[(src[i] >> 4) & 0xf]; p[2] = hex[src[i] & 0xf]; - p += 2; + p += 3; } ret += 2; } - else if (dst) *p = src[i]; + else if (dst) *p++ = src[i]; } + if (dst) dst[ret] = 0; return ret; } @@ -153,7 +146,7 @@ static WCHAR *escape_url( const WCHAR *url, DWORD *len ) if ((p = strrchrW( url, '/' ))) { len_base = p - url; - len_path = escape_string( NULL, p, *len - len_base ); + len_path = escape_string( NULL, p, *len - len_base, ESCAPE_FLAG_PERCENT|ESCAPE_FLAG_TILDE ); } else { @@ -164,7 +157,7 @@ static WCHAR *escape_url( const WCHAR *url, DWORD *len ) if (!(ret = heap_alloc( (len_base + len_path + 1) * sizeof(WCHAR) ))) return NULL; memcpy( ret, url, len_base * sizeof(WCHAR) );
- if (p) escape_string( ret + len_base, p, *len - (p - url) ); + if (p) escape_string( ret + len_base, p, *len - (p - url), ESCAPE_FLAG_PERCENT|ESCAPE_FLAG_TILDE ); ret[len_base + len_path] = 0;
*len = len_base + len_path; @@ -349,18 +342,18 @@ static BOOL uses_default_port( INTERNET_SCHEME scheme, INTERNET_PORT port ) return FALSE; }
-static DWORD comp_length( DWORD len, DWORD flags, WCHAR *comp ) +static DWORD get_comp_length( DWORD len, DWORD flags, WCHAR *comp ) { DWORD ret; unsigned int i;
ret = len ? len : strlenW( comp ); if (!(flags & ICU_ESCAPE)) return ret; - for (i = 0; i < len; i++) if (need_escape( comp[i] )) ret += 2; + for (i = 0; i < len; i++) if (need_escape( comp[i], ESCAPE_FLAG_PERCENT|ESCAPE_FLAG_TILDE )) ret += 2; return ret; }
-static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) +static BOOL get_url_length( URL_COMPONENTS *uc, DWORD flags, DWORD *len ) { static const WCHAR formatW[] = {'%','u',0}; INTERNET_SCHEME scheme; @@ -368,7 +361,7 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) *len = 0; if (uc->lpszScheme) { - DWORD scheme_len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme ); + DWORD scheme_len = get_comp_length( uc->dwSchemeLength, 0, uc->lpszScheme ); *len += scheme_len; scheme = get_scheme( uc->lpszScheme, scheme_len ); } @@ -378,12 +371,11 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) if (!scheme) scheme = INTERNET_SCHEME_HTTP; *len += strlenW( get_scheme_string( scheme ) ); } - *len += 1; /* ':' */ - if (uc->lpszHostName) *len += 2; /* "//" */ + *len += 3; /* "://" */
if (uc->lpszUserName) { - *len += comp_length( uc->dwUserNameLength, 0, uc->lpszUserName ); + *len += get_comp_length( uc->dwUserNameLength, 0, uc->lpszUserName ); *len += 1; /* "@" */ } else @@ -397,11 +389,11 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) if (uc->lpszPassword) { *len += 1; /* ":" */ - *len += comp_length( uc->dwPasswordLength, 0, uc->lpszPassword ); + *len += get_comp_length( uc->dwPasswordLength, 0, uc->lpszPassword ); } if (uc->lpszHostName) { - *len += comp_length( uc->dwHostNameLength, 0, uc->lpszHostName ); + *len += get_comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
if (!uses_default_port( scheme, uc->nPort )) { @@ -412,8 +404,8 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) } if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') *len += 1; /* '/' */ } - if (uc->lpszUrlPath) *len += comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath ); - if (uc->lpszExtraInfo) *len += comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo ); + if (uc->lpszUrlPath) *len += get_comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath ); + if (uc->lpszExtraInfo) *len += get_comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo ); return TRUE; }
@@ -423,7 +415,6 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDWORD required ) { static const WCHAR formatW[] = {'%','u',0}; - static const WCHAR twoslashW[] = {'/','/'}; DWORD len; INTERNET_SCHEME scheme;
@@ -435,7 +426,7 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW return FALSE; }
- if (!calc_length( uc, flags, &len )) return FALSE; + if (!get_url_length( uc, flags, &len )) return FALSE;
if (*required < len) { @@ -453,7 +444,7 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW *required = len; if (uc->lpszScheme) { - len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme ); + len = get_comp_length( uc->dwSchemeLength, 0, uc->lpszScheme ); memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) ); url += len;
@@ -472,58 +463,47 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW url += len; }
- /* all schemes are followed by at least a colon */ - *url = ':'; - url++; + *url++ = ':'; + *url++ = '/'; + *url++ = '/';
- if (uc->lpszHostName) - { - memcpy( url, twoslashW, sizeof(twoslashW) ); - url += ARRAY_SIZE( twoslashW ); - } if (uc->lpszUserName) { - len = comp_length( uc->dwUserNameLength, 0, uc->lpszUserName ); + len = get_comp_length( uc->dwUserNameLength, 0, uc->lpszUserName ); memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) ); url += len;
if (uc->lpszPassword) { - *url = ':'; - url++; - - len = comp_length( uc->dwPasswordLength, 0, uc->lpszPassword ); + *url++ = ':'; + len = get_comp_length( uc->dwPasswordLength, 0, uc->lpszPassword ); memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) ); url += len; } - *url = '@'; - url++; + *url++ = '@'; } if (uc->lpszHostName) { - len = comp_length( uc->dwHostNameLength, 0, uc->lpszHostName ); + len = get_comp_length( uc->dwHostNameLength, 0, uc->lpszHostName ); memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) ); url += len;
if (!uses_default_port( scheme, uc->nPort )) { - *url = ':'; - url++; - + *url++ = ':'; url += sprintfW( url, formatW, uc->nPort ); }
/* add slash between hostname and path if necessary */ if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') { - *url = '/'; - url++; + *url++ = '/'; } } if (uc->lpszUrlPath) { - len = comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath ); - if (flags & ICU_ESCAPE) url += escape_string( url, uc->lpszUrlPath, len ); + len = get_comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath ); + if (flags & ICU_ESCAPE) url += escape_string( url, uc->lpszUrlPath, len, ESCAPE_FLAG_PERCENT|ESCAPE_FLAG_TILDE ); else { memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) ); @@ -532,8 +512,8 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW } if (uc->lpszExtraInfo) { - len = comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo ); - if (flags & ICU_ESCAPE) url += escape_string( url, uc->lpszExtraInfo, len ); + len = get_comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo ); + if (flags & ICU_ESCAPE) url += escape_string( url, uc->lpszExtraInfo, len, ESCAPE_FLAG_PERCENT|ESCAPE_FLAG_TILDE ); else { memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) ); diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 6b4e3b0405..53b3c163df 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -307,7 +307,15 @@ BOOL set_server_for_hostname( connect_t *, LPCWSTR, INTERNET_PORT ) DECLSPEC_HID void destroy_authinfo( struct authinfo * ) DECLSPEC_HIDDEN;
void release_host( hostdata_t *host ) DECLSPEC_HIDDEN; -DWORD escape_string( WCHAR *, const WCHAR *, DWORD ) DECLSPEC_HIDDEN; + +enum escape_flags +{ + ESCAPE_FLAG_REMOVE_CRLF = 0x01, + ESCAPE_FLAG_SPACE_ONLY = 0x02, + ESCAPE_FLAG_PERCENT = 0x04, + ESCAPE_FLAG_TILDE = 0x08, +}; +DWORD escape_string( WCHAR *, const WCHAR *, DWORD, enum escape_flags ) DECLSPEC_HIDDEN;
extern HRESULT WinHttpRequest_create( void ** ) DECLSPEC_HIDDEN; void release_typelib( void ) DECLSPEC_HIDDEN;