webservices: Add support for encoded UTF-8 characters in WsDecodeUrl.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
947fbfee68
commit
20686f47af
@ -54,8 +54,10 @@ static void test_WsDecodeUrl(void)
|
|||||||
'%','2','0','2',0};
|
'%','2','0','2',0};
|
||||||
static WCHAR url26[] = {'h','t','t','p',':','/','/','h','o','s','t','#','f','r','a','g',
|
static WCHAR url26[] = {'h','t','t','p',':','/','/','h','o','s','t','#','f','r','a','g',
|
||||||
'%','2','0','2',0};
|
'%','2','0','2',0};
|
||||||
|
static WCHAR url27[] = {'h','t','t','p',':','/','/','h','o','s','t','/','%','c','3','%','a','b','/',0};
|
||||||
static WCHAR host2[] = {'h','o','s','t',' ','2'};
|
static WCHAR host2[] = {'h','o','s','t',' ','2'};
|
||||||
static WCHAR path2[] = {'/','p','a','t','h',' ','2'};
|
static WCHAR path2[] = {'/','p','a','t','h',' ','2'};
|
||||||
|
static WCHAR path3[] = {'/',0xeb,'/'};
|
||||||
static WCHAR query2[] = {'q','u','e','r','y',' ','2'};
|
static WCHAR query2[] = {'q','u','e','r','y',' ','2'};
|
||||||
static WCHAR frag2[] = {'f','r','a','g',' ','2'};
|
static WCHAR frag2[] = {'f','r','a','g',' ','2'};
|
||||||
static const struct
|
static const struct
|
||||||
@ -103,8 +105,9 @@ static void test_WsDecodeUrl(void)
|
|||||||
url22 + 12, 4 },
|
url22 + 12, 4 },
|
||||||
{ url23, S_OK, WS_URL_HTTP_SCHEME_TYPE, host2, 6, 80 },
|
{ url23, S_OK, WS_URL_HTTP_SCHEME_TYPE, host2, 6, 80 },
|
||||||
{ url24, S_OK, WS_URL_HTTP_SCHEME_TYPE, url24 + 7, 4, 80, NULL, 0, path2, 7 },
|
{ url24, S_OK, WS_URL_HTTP_SCHEME_TYPE, url24 + 7, 4, 80, NULL, 0, path2, 7 },
|
||||||
{ url25, S_OK, WS_URL_HTTP_SCHEME_TYPE, url24 + 7, 4, 80, NULL, 0, NULL, 0, query2, 7 },
|
{ url25, S_OK, WS_URL_HTTP_SCHEME_TYPE, url25 + 7, 4, 80, NULL, 0, NULL, 0, query2, 7 },
|
||||||
{ url26, S_OK, WS_URL_HTTP_SCHEME_TYPE, url24 + 7, 4, 80, NULL, 0, NULL, 0, NULL, 0, frag2, 6 },
|
{ url26, S_OK, WS_URL_HTTP_SCHEME_TYPE, url26 + 7, 4, 80, NULL, 0, NULL, 0, NULL, 0, frag2, 6 },
|
||||||
|
{ url27, S_OK, WS_URL_HTTP_SCHEME_TYPE, url27 + 7, 4, 80, NULL, 0, path3, 3 },
|
||||||
};
|
};
|
||||||
WS_HEAP *heap;
|
WS_HEAP *heap;
|
||||||
WS_STRING str;
|
WS_STRING str;
|
||||||
|
@ -71,11 +71,36 @@ static USHORT default_port( WS_URL_SCHEME_TYPE scheme )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned char *strdup_utf8( const WCHAR *str, ULONG len, ULONG *ret_len )
|
||||||
|
{
|
||||||
|
unsigned char *ret;
|
||||||
|
*ret_len = WideCharToMultiByte( CP_UTF8, 0, str, len, NULL, 0, NULL, NULL );
|
||||||
|
if ((ret = heap_alloc( *ret_len )))
|
||||||
|
WideCharToMultiByte( CP_UTF8, 0, str, len, (char *)ret, *ret_len, NULL, NULL );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int url_decode_byte( char c1, char c2 )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (c1 >= '0' && c1 <= '9') ret = (c1 - '0') * 16;
|
||||||
|
else if (c1 >= 'a' && c1 <= 'f') ret = (c1 - 'a' + 10) * 16;
|
||||||
|
else ret = (c1 - 'A' + 10) * 16;
|
||||||
|
|
||||||
|
if (c2 >= '0' && c2 <= '9') ret += c2 - '0';
|
||||||
|
else if (c2 >= 'a' && c2 <= 'f') ret += c2 - 'a' + 10;
|
||||||
|
else ret += c2 - 'A' + 10;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static WCHAR *url_decode( WCHAR *str, ULONG len, WS_HEAP *heap, ULONG *ret_len )
|
static WCHAR *url_decode( WCHAR *str, ULONG len, WS_HEAP *heap, ULONG *ret_len )
|
||||||
{
|
{
|
||||||
WCHAR *p = str, *q, *ret;
|
WCHAR *p = str, *q, *ret;
|
||||||
BOOL decode = FALSE;
|
BOOL decode = FALSE, convert = FALSE;
|
||||||
ULONG i, val;
|
ULONG i, len_utf8, len_left;
|
||||||
|
unsigned char *utf8, *r;
|
||||||
|
|
||||||
*ret_len = len;
|
*ret_len = len;
|
||||||
for (i = 0; i < len; i++, p++)
|
for (i = 0; i < len; i++, p++)
|
||||||
@ -84,26 +109,24 @@ static WCHAR *url_decode( WCHAR *str, ULONG len, WS_HEAP *heap, ULONG *ret_len )
|
|||||||
if (p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] ))
|
if (p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] ))
|
||||||
{
|
{
|
||||||
decode = TRUE;
|
decode = TRUE;
|
||||||
|
if (url_decode_byte( p[1], p[2] ) > 159)
|
||||||
|
{
|
||||||
|
convert = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
*ret_len -= 2;
|
*ret_len -= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!decode) return str;
|
if (!decode) return str;
|
||||||
|
if (!convert)
|
||||||
|
{
|
||||||
if (!(q = ret = ws_alloc( heap, *ret_len * sizeof(WCHAR) ))) return NULL;
|
if (!(q = ret = ws_alloc( heap, *ret_len * sizeof(WCHAR) ))) return NULL;
|
||||||
p = str;
|
p = str;
|
||||||
while (len)
|
while (len)
|
||||||
{
|
{
|
||||||
if (len >= 3 && p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] ))
|
if (len >= 3 && p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] ))
|
||||||
{
|
{
|
||||||
if (p[1] >= '0' && p[1] <= '9') val = (p[1] - '0') * 16;
|
*q++ = url_decode_byte( p[1], p[2] );
|
||||||
else if (p[1] >= 'a' && p[1] <= 'f') val = (p[1] - 'a') * 16;
|
|
||||||
else val = (p[1] - 'A') * 16;
|
|
||||||
|
|
||||||
if (p[2] >= '0' && p[2] <= '9') val += p[2] - '0';
|
|
||||||
else if (p[1] >= 'a' && p[1] <= 'f') val += p[2] - 'a';
|
|
||||||
else val += p[1] - 'A';
|
|
||||||
|
|
||||||
*q++ = val;
|
|
||||||
p += 3;
|
p += 3;
|
||||||
len -= 3;
|
len -= 3;
|
||||||
}
|
}
|
||||||
@ -113,7 +136,35 @@ static WCHAR *url_decode( WCHAR *str, ULONG len, WS_HEAP *heap, ULONG *ret_len )
|
|||||||
len -= 1;
|
len -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(r = utf8 = strdup_utf8( str, len, &len_utf8 ))) return NULL;
|
||||||
|
len_left = len_utf8;
|
||||||
|
while (len_left)
|
||||||
|
{
|
||||||
|
if (len_left >= 3 && r[0] == '%' && isxdigit( r[1] ) && isxdigit( r[2] ))
|
||||||
|
{
|
||||||
|
r[0] = url_decode_byte( r[1], r[2] );
|
||||||
|
len_left -= 3;
|
||||||
|
memmove( r + 1, r + 3, len_left );
|
||||||
|
len_utf8 -= 2;
|
||||||
|
}
|
||||||
|
else len_left -= 1;
|
||||||
|
r++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(*ret_len = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, (char *)utf8,
|
||||||
|
len_utf8, NULL, 0 )))
|
||||||
|
{
|
||||||
|
WARN( "invalid UTF-8 sequence\n" );
|
||||||
|
heap_free( utf8 );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if ((ret = ws_alloc( heap, *ret_len * sizeof(WCHAR) )))
|
||||||
|
MultiByteToWideChar( CP_UTF8, 0, (char *)utf8, len_utf8, ret, *ret_len );
|
||||||
|
|
||||||
|
heap_free( utf8 );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,20 +327,11 @@ static inline ULONG escape_size( unsigned char ch, const char *except )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *strdup_utf8( const WCHAR *str, ULONG len, ULONG *ret_len )
|
|
||||||
{
|
|
||||||
char *ret;
|
|
||||||
*ret_len = WideCharToMultiByte( CP_UTF8, 0, str, len, NULL, 0, NULL, NULL );
|
|
||||||
if ((ret = heap_alloc( *ret_len )))
|
|
||||||
WideCharToMultiByte( CP_UTF8, 0, str, len, ret, *ret_len, NULL, NULL );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT url_encode_size( const WCHAR *str, ULONG len, const char *except, ULONG *ret_len )
|
static HRESULT url_encode_size( const WCHAR *str, ULONG len, const char *except, ULONG *ret_len )
|
||||||
{
|
{
|
||||||
ULONG i, len_utf8;
|
ULONG i, len_utf8;
|
||||||
BOOL convert = FALSE;
|
BOOL convert = FALSE;
|
||||||
char *utf8;
|
unsigned char *utf8;
|
||||||
|
|
||||||
*ret_len = 0;
|
*ret_len = 0;
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
@ -339,7 +381,7 @@ static HRESULT url_encode( const WCHAR *str, ULONG len, WCHAR *buf, const char *
|
|||||||
ULONG i, len_utf8, len_enc;
|
ULONG i, len_utf8, len_enc;
|
||||||
BOOL convert = FALSE;
|
BOOL convert = FALSE;
|
||||||
WCHAR *p = buf;
|
WCHAR *p = buf;
|
||||||
char *utf8;
|
unsigned char *utf8;
|
||||||
|
|
||||||
*ret_len = 0;
|
*ret_len = 0;
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user