shlwapi: Implement URL_ESCAPE_AS_UTF8.

Signed-off-by: Daniel Lehman <dlehman@esri.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Daniel Lehman 2015-11-23 17:34:24 -08:00 committed by Alexandre Julliard
parent d07a7bbba5
commit 74e71b6643
3 changed files with 107 additions and 7 deletions

View File

@ -302,6 +302,45 @@ static const TEST_URL_ESCAPE TEST_ESCAPE[] = {
{"ftp\x1f\1end/", 0, 0, S_OK, "ftp%1F%01end/"}
};
typedef struct _TEST_URL_ESCAPEW {
const WCHAR url[INTERNET_MAX_URL_LENGTH];
DWORD flags;
HRESULT expectret;
const WCHAR expecturl[INTERNET_MAX_URL_LENGTH];
const WCHAR win7url[INTERNET_MAX_URL_LENGTH]; /* <= Win7 */
const WCHAR vistaurl[INTERNET_MAX_URL_LENGTH]; /* <= Vista/2k8 */
} TEST_URL_ESCAPEW;
static const TEST_URL_ESCAPEW TEST_ESCAPEW[] = {
{{' ','<','>','"',0}, URL_ESCAPE_AS_UTF8, S_OK, {'%','2','0','%','3','C','%','3','E','%','2','2',0}},
{{'{','}','|','\\',0}, URL_ESCAPE_AS_UTF8, S_OK, {'%','7','B','%','7','D','%','7','C','%','5','C',0}},
{{'^',']','[','`',0}, URL_ESCAPE_AS_UTF8, S_OK, {'%','5','E','%','5','D','%','5','B','%','6','0',0}},
{{'&','/','?','#',0}, URL_ESCAPE_AS_UTF8, S_OK, {'%','2','6','/','?','#',0}},
{{'M','a','s','s',0}, URL_ESCAPE_AS_UTF8, S_OK, {'M','a','s','s',0}},
/* broken < Win8/10 */
{{'M','a',0xdf,0}, URL_ESCAPE_AS_UTF8, S_OK, {'M','a','%','C','3','%','9','F',0},
{'M','a','%','D','F',0}},
/* 0x2070E */
{{0xd841,0xdf0e,0}, URL_ESCAPE_AS_UTF8, S_OK, {'%','F','0','%','A','0','%','9','C','%','8','E',0},
{'%','E','F','%','B','F','%','B','D','%','E','F','%','B','F','%','B','D',0},
{0xd841,0xdf0e,0}},
/* 0x27A3E */
{{0xd85e,0xde3e,0}, URL_ESCAPE_AS_UTF8, S_OK, {'%','F','0','%','A','7','%','A','8','%','B','E',0},
{'%','E','F','%','B','F','%','B','D','%','E','F','%','B','F','%','B','D',0},
{0xd85e,0xde3e,0}},
{{0xd85e,0}, URL_ESCAPE_AS_UTF8, S_OK, {'%','E','F','%','B','F','%','B','D',0},
{0xd85e,0}},
{{0xd85e,0x41}, URL_ESCAPE_AS_UTF8, S_OK, {'%','E','F','%','B','F','%','B','D','A',0},
{0xd85e,'A',0}},
{{0xdc00,0}, URL_ESCAPE_AS_UTF8, S_OK, {'%','E','F','%','B','F','%','B','D',0},
{0xdc00,0}},
{{0xffff,0}, URL_ESCAPE_AS_UTF8, S_OK, {'%','E','F','%','B','F','%','B','F',0},
{0xffff,0}},
};
/* ################ */
typedef struct _TEST_URL_COMBINE {
@ -862,6 +901,15 @@ static void test_UrlEscapeA(void)
ok(size == 34, "got %d, expected %d\n", size, 34);
ok(empty_string[0] == 127, "String has changed, empty_string[0] = %d\n", empty_string[0]);
size = 1;
empty_string[0] = 127;
ret = pUrlEscapeA("/woningplan/woonkamer basis.swf", empty_string, &size, URL_ESCAPE_AS_UTF8);
ok(ret == E_NOTIMPL || broken(ret == E_POINTER), /* < Win7/Win2k8 */
"got %x, expected %x\n", ret, E_NOTIMPL);
ok(size == 1 || broken(size == 34), /* < Win7/Win2k8 */
"got %d, expected %d\n", size, 1);
ok(empty_string[0] == 127, "String has changed, empty_string[0] = %d\n", empty_string[0]);
for(i=0; i<sizeof(TEST_ESCAPE)/sizeof(TEST_ESCAPE[0]); i++) {
CHAR ret_url[INTERNET_MAX_URL_LENGTH];
@ -925,6 +973,21 @@ static void test_UrlEscapeW(void)
FreeWideString(urlW);
FreeWideString(expected_urlW);
}
for(i=0; i<sizeof(TEST_ESCAPEW)/sizeof(TEST_ESCAPEW[0]); i++) {
WCHAR ret_url[INTERNET_MAX_URL_LENGTH];
size = INTERNET_MAX_URL_LENGTH;
ret = pUrlEscapeW(TEST_ESCAPEW[i].url, ret_url, &size, TEST_ESCAPEW[i].flags);
ok(ret == TEST_ESCAPEW[i].expectret, "UrlEscapeW returned 0x%08x instead of 0x%08x for \"%s\"\n",
ret, TEST_ESCAPEW[i].expectret, wine_dbgstr_w(TEST_ESCAPEW[i].url));
ok(!lstrcmpW(ret_url, TEST_ESCAPEW[i].expecturl) ||
broken(!lstrcmpW(ret_url, TEST_ESCAPEW[i].vistaurl)) ||
broken(!lstrcmpW(ret_url, TEST_ESCAPEW[i].win7url)),
"Expected \"%s\" or \"%s\" or \"%s\", but got \"%s\" for \"%s\"\n",
wine_dbgstr_w(TEST_ESCAPEW[i].expecturl), wine_dbgstr_w(TEST_ESCAPEW[i].vistaurl),
wine_dbgstr_w(TEST_ESCAPEW[i].win7url), wine_dbgstr_w(ret_url), wine_dbgstr_w(TEST_ESCAPEW[i].url));
}
}
/* ########################### */

View File

@ -958,6 +958,8 @@ HRESULT WINAPI UrlEscapeA(
if(!RtlCreateUnicodeStringFromAsciiz(&urlW, pszUrl))
return E_INVALIDARG;
if(dwFlags & URL_ESCAPE_AS_UTF8)
return E_NOTIMPL;
if((ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags)) == E_POINTER) {
escapedW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags);
@ -994,6 +996,9 @@ static inline BOOL URL_NeedEscapeW(WCHAR ch, DWORD flags, DWORD int_flags)
if ((flags & URL_ESCAPE_PERCENT) && (ch == '%'))
return TRUE;
if ((flags & URL_ESCAPE_AS_UTF8) && (ch >= 0x80))
return TRUE;
if (ch <= 31 || (ch >= 127 && ch <= 255) )
return TRUE;
@ -1069,8 +1074,8 @@ HRESULT WINAPI UrlEscapeW(
LPCWSTR src;
DWORD needed = 0, ret;
BOOL stop_escaping = FALSE;
WCHAR next[5], *dst, *dst_ptr;
INT len;
WCHAR next[12], *dst, *dst_ptr;
INT i, len;
PARSEDURLW parsed_url;
DWORD int_flags;
DWORD slashes = 0;
@ -1085,7 +1090,8 @@ HRESULT WINAPI UrlEscapeW(
if(dwFlags & ~(URL_ESCAPE_SPACES_ONLY |
URL_ESCAPE_SEGMENT_ONLY |
URL_DONT_ESCAPE_EXTRA_INFO |
URL_ESCAPE_PERCENT))
URL_ESCAPE_PERCENT |
URL_ESCAPE_AS_UTF8))
FIXME("Unimplemented flags: %08x\n", dwFlags);
dst_ptr = dst = HeapAlloc(GetProcessHeap(), 0, *pcchEscaped*sizeof(WCHAR));
@ -1188,10 +1194,40 @@ HRESULT WINAPI UrlEscapeW(
if(cur == '\\' && (int_flags & WINE_URL_BASH_AS_SLASH) && !stop_escaping) cur = '/';
if(URL_NeedEscapeW(cur, dwFlags, int_flags) && stop_escaping == FALSE) {
next[0] = '%';
next[1] = hexDigits[(cur >> 4) & 0xf];
next[2] = hexDigits[cur & 0xf];
len = 3;
if(dwFlags & URL_ESCAPE_AS_UTF8) {
char utf[16];
if ((cur >= 0xd800 && cur <= 0xdfff) &&
(src[1] >= 0xdc00 && src[1] <= 0xdfff))
{
WCHAR sur[2];
sur[0] = cur;
sur[1] = *++src;
len = wine_utf8_wcstombs(WC_ERR_INVALID_CHARS, sur, 2, utf, sizeof(utf));
}
else
len = wine_utf8_wcstombs(WC_ERR_INVALID_CHARS, &cur, 1, utf, sizeof(utf));
if(len < 0) {
utf[0] = 0xef;
utf[1] = 0xbf;
utf[2] = 0xbd;
len = 3;
}
for(i = 0; i < len; i++) {
next[i*3+0] = '%';
next[i*3+1] = hexDigits[(utf[i] >> 4) & 0xf];
next[i*3+2] = hexDigits[utf[i] & 0xf];
}
len *= 3;
} else {
next[0] = '%';
next[1] = hexDigits[(cur >> 4) & 0xf];
next[2] = hexDigits[cur & 0xf];
len = 3;
}
} else {
next[0] = cur;
len = 1;

View File

@ -646,6 +646,7 @@ typedef enum {
#define URL_UNESCAPE_INPLACE 0x00100000
#define URL_FILE_USE_PATHURL 0x00010000
#define URL_ESCAPE_AS_UTF8 0x00040000
#define URL_ESCAPE_SEGMENT_ONLY 0x00002000
#define URL_ESCAPE_PERCENT 0x00001000