Module: wine Branch: master Commit: 74e71b664350f5ec89ff6b1ec9d15b80f2bd2baf URL: http://source.winehq.org/git/wine.git/?a=commit;h=74e71b664350f5ec89ff6b1ec9...
Author: Daniel Lehman dlehman@esri.com Date: Mon Nov 23 17:34:24 2015 -0800
shlwapi: Implement URL_ESCAPE_AS_UTF8.
Signed-off-by: Daniel Lehman dlehman@esri.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/shlwapi/tests/url.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ dlls/shlwapi/url.c | 50 ++++++++++++++++++++++++++++++++------ include/shlwapi.h | 1 + 3 files changed, 107 insertions(+), 7 deletions(-)
diff --git a/dlls/shlwapi/tests/url.c b/dlls/shlwapi/tests/url.c index 857ed15..85da922 100644 --- a/dlls/shlwapi/tests/url.c +++ b/dlls/shlwapi/tests/url.c @@ -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)); + } }
/* ########################### */ diff --git a/dlls/shlwapi/url.c b/dlls/shlwapi/url.c index 1a53252..0680a55 100644 --- a/dlls/shlwapi/url.c +++ b/dlls/shlwapi/url.c @@ -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; diff --git a/include/shlwapi.h b/include/shlwapi.h index 205d5e6..e3b14b3 100644 --- a/include/shlwapi.h +++ b/include/shlwapi.h @@ -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