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:
parent
d07a7bbba5
commit
74e71b6643
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
/* ########################### */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue