winhttp: Implement the WINHTTP_FLAG_ESCAPE_* flags.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42677 Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
451e4d326e
commit
ace7f05672
|
@ -2535,18 +2535,18 @@ static BOOL handle_redirect( request_t *request, DWORD status )
|
||||||
|
|
||||||
if (location[0] == '/')
|
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;
|
if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
|
||||||
escape_string( path, location, len_loc );
|
escape_string( path, location, len_loc, 0 );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((p = strrchrW( request->path, '/' ))) *p = 0;
|
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;
|
if (!(path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end;
|
||||||
strcpyW( path, request->path );
|
strcpyW( path, request->path );
|
||||||
strcatW( path, slashW );
|
strcatW( path, slashW );
|
||||||
escape_string( path + strlenW(path), location, len_loc );
|
escape_string( path + strlenW(path), location, len_loc, 0 );
|
||||||
}
|
}
|
||||||
heap_free( request->path );
|
heap_free( request->path );
|
||||||
request->path = path;
|
request->path = path;
|
||||||
|
@ -2597,9 +2597,9 @@ static BOOL handle_redirect( request_t *request, DWORD status )
|
||||||
request->path = NULL;
|
request->path = NULL;
|
||||||
if (uc.dwUrlPathLength)
|
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;
|
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 );
|
else request->path = strdupW( slashW );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1090,6 +1090,50 @@ static BOOL store_accept_types( request_t *request, const WCHAR **accept_types )
|
||||||
return TRUE;
|
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.@)
|
* 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),
|
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);
|
debugstr_w(version), debugstr_w(referrer), types, flags);
|
||||||
|
|
||||||
if(types && TRACE_ON(winhttp)) {
|
if (types && TRACE_ON(winhttp))
|
||||||
|
{
|
||||||
const WCHAR **iter;
|
const WCHAR **iter;
|
||||||
|
|
||||||
TRACE("accept types:\n");
|
TRACE("accept types:\n");
|
||||||
for(iter = types; *iter; iter++)
|
for (iter = types; *iter; iter++) TRACE(" %s\n", debugstr_w(*iter));
|
||||||
TRACE(" %s\n", debugstr_w(*iter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(connect = (connect_t *)grab_object( hconnect )))
|
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 (!verb || !verb[0]) verb = getW;
|
||||||
if (!(request->verb = strdupW( verb ))) goto end;
|
if (!(request->verb = strdupW( verb ))) goto end;
|
||||||
|
if (!(request->path = get_request_path( object, flags ))) 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 (!version || !version[0]) version = http1_1;
|
if (!version || !version[0]) version = http1_1;
|
||||||
if (!(request->version = strdupW( version ))) goto end;
|
if (!(request->version = strdupW( version ))) goto end;
|
||||||
|
|
|
@ -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 about[] = {'/','s','i','t','e','/','a','b','o','u','t',0};
|
||||||
static WCHAR query[] = {'?','q','u','e','r','y',0};
|
static WCHAR query[] = {'?','q','u','e','r','y',0};
|
||||||
static WCHAR escape[] = {' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`','{','|','}','~',0};
|
static WCHAR escape[] = {' ','!','"','#','$','%','&','\'','(',')','*','+',',','-','.','/',':',';','<','=','>','?','@','[','\\',']','^','_','`','{','|','}','~',0};
|
||||||
|
static WCHAR escape2[] = {'\r',0x1f,' ','\n',0x7f,'\r','\n',0};
|
||||||
|
|
||||||
static const WCHAR url1[] =
|
static const WCHAR url1[] =
|
||||||
{'h','t','t','p',':','/','/','u','s','e','r','n','a','m','e',':','p','a','s','s','w','o','r','d',
|
{'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 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 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 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[] =
|
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',
|
{'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 );
|
ret = WinHttpCreateUrl( &uc, ICU_ESCAPE, url, &len );
|
||||||
ok( ret, "expected success\n" );
|
ok( ret, "expected success\n" );
|
||||||
ok( len == 113, "expected len 113 got %u\n", len );
|
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 */
|
/* NULL lpszScheme, 0 nScheme and nPort */
|
||||||
fill_url_components( &uc );
|
fill_url_components( &uc );
|
||||||
|
|
|
@ -2362,7 +2362,15 @@ static DWORD CALLBACK server_thread(LPVOID param)
|
||||||
}
|
}
|
||||||
else if (strstr(buffer, "GET /escape"))
|
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);
|
else send(c, notokmsg, sizeof(notokmsg) - 1, 0);
|
||||||
}
|
}
|
||||||
if (strstr(buffer, "GET /quit"))
|
if (strstr(buffer, "GET /quit"))
|
||||||
|
@ -3340,21 +3348,13 @@ static void test_cookies( int port )
|
||||||
WinHttpCloseHandle( ses );
|
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[] =
|
HINTERNET req;
|
||||||
{'/','e','s','c','a','p','e','?','o','n','e',' ','t','w','o','\r','\n',0};
|
|
||||||
HINTERNET ses, con, req;
|
|
||||||
DWORD status, size;
|
DWORD status, size;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
|
||||||
ses = WinHttpOpen( test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0 );
|
req = WinHttpOpenRequest( con, NULL, obj, NULL, NULL, NULL, flags );
|
||||||
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 );
|
|
||||||
ok( req != NULL, "failed to open a request %u\n", GetLastError() );
|
ok( req != NULL, "failed to open a request %u\n", GetLastError() );
|
||||||
|
|
||||||
ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
|
ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
|
||||||
|
@ -3367,9 +3367,41 @@ static void test_request_path_escapes( int port )
|
||||||
size = sizeof(status);
|
size = sizeof(status);
|
||||||
ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
|
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( 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 );
|
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( con );
|
||||||
WinHttpCloseHandle( ses );
|
WinHttpCloseHandle( ses );
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,59 +87,52 @@ static WCHAR *decode_url( LPCWSTR url, DWORD *len )
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL need_escape( WCHAR c )
|
|
||||||
{
|
|
||||||
if (isalnumW( c )) return FALSE;
|
|
||||||
|
|
||||||
if (c <= 31 || c >= 127) return TRUE;
|
static BOOL need_escape( WCHAR ch, enum escape_flags flags )
|
||||||
else
|
{
|
||||||
|
static const WCHAR escapes[] = {' ','"','#','<','>','[','\\',']','^','`','{','|','}',0};
|
||||||
|
const WCHAR *p = escapes;
|
||||||
|
|
||||||
|
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)
|
if (ch == *p++) return TRUE;
|
||||||
{
|
|
||||||
case ' ':
|
|
||||||
case '"':
|
|
||||||
case '#':
|
|
||||||
case '%':
|
|
||||||
case '<':
|
|
||||||
case '>':
|
|
||||||
case ']':
|
|
||||||
case '\\':
|
|
||||||
case '[':
|
|
||||||
case '^':
|
|
||||||
case '`':
|
|
||||||
case '{':
|
|
||||||
case '|':
|
|
||||||
case '}':
|
|
||||||
case '~':
|
|
||||||
return TRUE;
|
|
||||||
default:
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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'};
|
static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
||||||
DWORD ret = len;
|
DWORD ret = len;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
WCHAR *p = dst;
|
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)
|
if (dst)
|
||||||
{
|
{
|
||||||
p[0] = '%';
|
p[0] = '%';
|
||||||
p[1] = hex[(src[i] >> 4) & 0xf];
|
p[1] = hex[(src[i] >> 4) & 0xf];
|
||||||
p[2] = hex[src[i] & 0xf];
|
p[2] = hex[src[i] & 0xf];
|
||||||
p += 2;
|
p += 3;
|
||||||
}
|
}
|
||||||
ret += 2;
|
ret += 2;
|
||||||
}
|
}
|
||||||
else if (dst) *p = src[i];
|
else if (dst) *p++ = src[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst) dst[ret] = 0;
|
if (dst) dst[ret] = 0;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -153,7 +146,7 @@ static WCHAR *escape_url( const WCHAR *url, DWORD *len )
|
||||||
if ((p = strrchrW( url, '/' )))
|
if ((p = strrchrW( url, '/' )))
|
||||||
{
|
{
|
||||||
len_base = p - 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
|
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;
|
if (!(ret = heap_alloc( (len_base + len_path + 1) * sizeof(WCHAR) ))) return NULL;
|
||||||
memcpy( ret, url, len_base * sizeof(WCHAR) );
|
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;
|
ret[len_base + len_path] = 0;
|
||||||
|
|
||||||
*len = len_base + len_path;
|
*len = len_base + len_path;
|
||||||
|
@ -349,18 +342,18 @@ static BOOL uses_default_port( INTERNET_SCHEME scheme, INTERNET_PORT port )
|
||||||
return FALSE;
|
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;
|
DWORD ret;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
ret = len ? len : strlenW( comp );
|
ret = len ? len : strlenW( comp );
|
||||||
if (!(flags & ICU_ESCAPE)) return ret;
|
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;
|
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};
|
static const WCHAR formatW[] = {'%','u',0};
|
||||||
INTERNET_SCHEME scheme;
|
INTERNET_SCHEME scheme;
|
||||||
|
@ -368,7 +361,7 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len )
|
||||||
*len = 0;
|
*len = 0;
|
||||||
if (uc->lpszScheme)
|
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;
|
*len += scheme_len;
|
||||||
scheme = get_scheme( uc->lpszScheme, 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;
|
if (!scheme) scheme = INTERNET_SCHEME_HTTP;
|
||||||
*len += strlenW( get_scheme_string( scheme ) );
|
*len += strlenW( get_scheme_string( scheme ) );
|
||||||
}
|
}
|
||||||
*len += 1; /* ':' */
|
*len += 3; /* "://" */
|
||||||
if (uc->lpszHostName) *len += 2; /* "//" */
|
|
||||||
|
|
||||||
if (uc->lpszUserName)
|
if (uc->lpszUserName)
|
||||||
{
|
{
|
||||||
*len += comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
|
*len += get_comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
|
||||||
*len += 1; /* "@" */
|
*len += 1; /* "@" */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -397,11 +389,11 @@ static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len )
|
||||||
if (uc->lpszPassword)
|
if (uc->lpszPassword)
|
||||||
{
|
{
|
||||||
*len += 1; /* ":" */
|
*len += 1; /* ":" */
|
||||||
*len += comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
|
*len += get_comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
|
||||||
}
|
}
|
||||||
if (uc->lpszHostName)
|
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 ))
|
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 && *uc->lpszUrlPath != '/') *len += 1; /* '/' */
|
||||||
}
|
}
|
||||||
if (uc->lpszUrlPath) *len += comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath );
|
if (uc->lpszUrlPath) *len += get_comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath );
|
||||||
if (uc->lpszExtraInfo) *len += comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo );
|
if (uc->lpszExtraInfo) *len += get_comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo );
|
||||||
return TRUE;
|
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 )
|
BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDWORD required )
|
||||||
{
|
{
|
||||||
static const WCHAR formatW[] = {'%','u',0};
|
static const WCHAR formatW[] = {'%','u',0};
|
||||||
static const WCHAR twoslashW[] = {'/','/'};
|
|
||||||
DWORD len;
|
DWORD len;
|
||||||
INTERNET_SCHEME scheme;
|
INTERNET_SCHEME scheme;
|
||||||
|
|
||||||
|
@ -435,7 +426,7 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!calc_length( uc, flags, &len )) return FALSE;
|
if (!get_url_length( uc, flags, &len )) return FALSE;
|
||||||
|
|
||||||
if (*required < len)
|
if (*required < len)
|
||||||
{
|
{
|
||||||
|
@ -453,7 +444,7 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW
|
||||||
*required = len;
|
*required = len;
|
||||||
if (uc->lpszScheme)
|
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) );
|
memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) );
|
||||||
url += len;
|
url += len;
|
||||||
|
|
||||||
|
@ -472,58 +463,47 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW
|
||||||
url += len;
|
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)
|
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) );
|
memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) );
|
||||||
url += len;
|
url += len;
|
||||||
|
|
||||||
if (uc->lpszPassword)
|
if (uc->lpszPassword)
|
||||||
{
|
{
|
||||||
*url = ':';
|
*url++ = ':';
|
||||||
url++;
|
len = get_comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
|
||||||
|
|
||||||
len = comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
|
|
||||||
memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) );
|
memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) );
|
||||||
url += len;
|
url += len;
|
||||||
}
|
}
|
||||||
*url = '@';
|
*url++ = '@';
|
||||||
url++;
|
|
||||||
}
|
}
|
||||||
if (uc->lpszHostName)
|
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) );
|
memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) );
|
||||||
url += len;
|
url += len;
|
||||||
|
|
||||||
if (!uses_default_port( scheme, uc->nPort ))
|
if (!uses_default_port( scheme, uc->nPort ))
|
||||||
{
|
{
|
||||||
*url = ':';
|
*url++ = ':';
|
||||||
url++;
|
|
||||||
|
|
||||||
url += sprintfW( url, formatW, uc->nPort );
|
url += sprintfW( url, formatW, uc->nPort );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add slash between hostname and path if necessary */
|
/* add slash between hostname and path if necessary */
|
||||||
if (uc->lpszUrlPath && *uc->lpszUrlPath != '/')
|
if (uc->lpszUrlPath && *uc->lpszUrlPath != '/')
|
||||||
{
|
{
|
||||||
*url = '/';
|
*url++ = '/';
|
||||||
url++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (uc->lpszUrlPath)
|
if (uc->lpszUrlPath)
|
||||||
{
|
{
|
||||||
len = comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath );
|
len = get_comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath );
|
||||||
if (flags & ICU_ESCAPE) url += escape_string( url, uc->lpszUrlPath, len );
|
if (flags & ICU_ESCAPE) url += escape_string( url, uc->lpszUrlPath, len, ESCAPE_FLAG_PERCENT|ESCAPE_FLAG_TILDE );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) );
|
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)
|
if (uc->lpszExtraInfo)
|
||||||
{
|
{
|
||||||
len = comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo );
|
len = get_comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo );
|
||||||
if (flags & ICU_ESCAPE) url += escape_string( url, uc->lpszExtraInfo, len );
|
if (flags & ICU_ESCAPE) url += escape_string( url, uc->lpszExtraInfo, len, ESCAPE_FLAG_PERCENT|ESCAPE_FLAG_TILDE );
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) );
|
memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) );
|
||||||
|
|
|
@ -307,7 +307,15 @@ BOOL set_server_for_hostname( connect_t *, LPCWSTR, INTERNET_PORT ) DECLSPEC_HID
|
||||||
void destroy_authinfo( struct authinfo * ) DECLSPEC_HIDDEN;
|
void destroy_authinfo( struct authinfo * ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
void release_host( hostdata_t *host ) 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;
|
extern HRESULT WinHttpRequest_create( void ** ) DECLSPEC_HIDDEN;
|
||||||
void release_typelib( void ) DECLSPEC_HIDDEN;
|
void release_typelib( void ) DECLSPEC_HIDDEN;
|
||||||
|
|
Loading…
Reference in New Issue