Module: wine Branch: refs/heads/master Commit: bb8a7478bc2b945bd082a9db8f987a1609c71f59 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=bb8a7478bc2b945bd082a9db...
Author: Jacek Caban jacek@codeweavers.com Date: Mon Dec 26 12:58:28 2005 +0100
shlwapi: Fix UrlCanonicalize. - Added support for URL_FILE_USE_PATHURL. - Fix handling of '/' and ''.
---
dlls/shlwapi/tests/path.c | 9 ++++++ dlls/shlwapi/url.c | 69 +++++++++++++++++++++++++++++++-------------- 2 files changed, 56 insertions(+), 22 deletions(-)
diff --git a/dlls/shlwapi/tests/path.c b/dlls/shlwapi/tests/path.c index eca68b9..1efbe0f 100644 --- a/dlls/shlwapi/tests/path.c +++ b/dlls/shlwapi/tests/path.c @@ -60,10 +60,19 @@ const TEST_URL_CANONICALIZE TEST_CANONIC {"http://www.winehq.org/tests/../?query=x&return=y", 0, S_OK, "http://www.winehq.org/?query=x&return=y%22%7D, {"http://www.winehq.org/tests/..#example", 0, S_OK, "http://www.winehq.org/#example%22%7D, {"http://www.winehq.org/tests/../#example", 0, S_OK, "http://www.winehq.org/#example%22%7D, + {"http://www.winehq.org/tests%5C%5C../#example", 0, S_OK, "http://www.winehq.org/#example%22%7D, + {"http://www.winehq.org/tests/..%5C%5C#example", 0, S_OK, "http://www.winehq.org/#example%22%7D, + {"http://www.winehq.org%5C%5Ctests/../#example", 0, S_OK, "http://www.winehq.org/#example%22%7D, {"http://www.winehq.org/tests/../#example", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../#example%22%7D, {"http://www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY| URL_DONT_ESCAPE_EXTRA_INFO , S_OK, "http://www.winehq.org/tests/foo%20bar%22%7D, {"http://www.winehq.org/tests/foo%20bar", URL_UNESCAPE , S_OK, "http://www.winehq.org/tests/foo bar"}, {"file:///c:/tests/foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"}, + {"file:///c:/tests\foo%20bar", URL_UNESCAPE , S_OK, "file:///c:/tests/foo bar"}, + {"file:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\tests\foo bar"}, + {"file://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\tests\foo bar"}, + {"file://c:/tests\../tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\tests\foo bar"}, + {"file://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\tests\foo bar"}, + {"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\tests\foo bar"} };
typedef struct _TEST_URL_ESCAPE { diff --git a/dlls/shlwapi/url.c b/dlls/shlwapi/url.c index d25628e..4e5c691 100644 --- a/dlls/shlwapi/url.c +++ b/dlls/shlwapi/url.c @@ -327,9 +327,10 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR { HRESULT hr = S_OK; DWORD EscapeFlags; - LPWSTR lpszUrlCpy, wk1, wk2, mp, root; + LPWSTR lpszUrlCpy, wk1, wk2, mp, mp2, root; INT nByteLen, state; DWORD nLen, nWkLen; + WCHAR slash = dwFlags & URL_FILE_USE_PATHURL ? '\' : '/';
TRACE("(%s %p %p 0x%08lx)\n", debugstr_w(pszUrl), pszCanonicalized, pcchCanonicalized, dwFlags); @@ -376,23 +377,37 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR *wk2++ = *wk1++; if (*wk1 != L'/') {state = 6; break;} *wk2++ = *wk1++; + if((dwFlags & URL_FILE_USE_PATHURL) && *wk1 == '/') + wk1++; state = 4; break; case 3: nWkLen = strlenW(wk1); memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR)); + mp = wk2; wk1 += nWkLen; wk2 += nWkLen; + + while(mp < wk2) { + if(*mp == '/' || *mp == '\') + *mp = slash; + mp++; + } break; case 4: - if (!isalnumW(*wk1) && (*wk1 != L'-') && (*wk1 != L'.')) {state = 3; break;} - while(isalnumW(*wk1) || (*wk1 == L'-') || (*wk1 == L'.')) *wk2++ = *wk1++; - state = 5; - break; - case 5: - if (*wk1 != L'/') {state = 3; break;} - *wk2++ = *wk1++; - state = 6; + if (!isalnumW(*wk1) && (*wk1 != L'-') && (*wk1 != L'.') && (*wk1 != ':')) + {state = 3; break;} + while(isalnumW(*wk1) || (*wk1 == L'-') || (*wk1 == L'.') || (*wk1 == ':')) + *wk2++ = *wk1++; + state = 5; + break; + case 5: + if (*wk1 != '/' && *wk1 != '\') {state = 3; break;} + while(*wk1 == '/') { + *wk2++ = slash; + wk1++; + } + state = 6; break; case 6: /* Now at root location, cannot back up any more. */ @@ -400,7 +415,11 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR root = wk2-1; while (*wk1) { TRACE("wk1=%c\n", (CHAR)*wk1); - mp = strchrW(wk1, L'/'); + + mp = strchrW(wk1, '/'); + mp2 = strchrW(wk1, '\'); + if(mp2 && mp2 < mp) + mp = mp2; if (!mp) { nWkLen = strlenW(wk1); memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR)); @@ -408,35 +427,41 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR wk2 += nWkLen; continue; } - nLen = mp - wk1 + 1; - memcpy(wk2, wk1, nLen * sizeof(WCHAR)); - wk2 += nLen; - wk1 += nLen; + nLen = mp - wk1; + if(nLen) { + memcpy(wk2, wk1, nLen * sizeof(WCHAR)); + wk2 += nLen; + wk1 += nLen; + } + *wk2++ = slash; + wk1++; + if (*wk1 == L'.') { TRACE("found '/.'\n"); - if (*(wk1+1) == L'/') { + if (wk1[1] == '/' || wk1[1] == '\') { /* case of /./ -> skip the ./ */ wk1 += 2; } - else if (*(wk1+1) == L'.') { + else if (wk1[1] == '.') { /* found /.. look for next / */ TRACE("found '/..'\n"); - if (*(wk1+2) == L'/' || *(wk1+2) == L'?' || *(wk1+2) == L'#' || *(wk1+2) == 0) { + if (wk1[2] == '/' || wk1[2] == '\' ||wk1[2] == '?' + || wk1[2] == '#' || !wk1[2]) { /* case /../ -> need to backup wk2 */ TRACE("found '/../'\n"); *(wk2-1) = L'\0'; /* set end of string */ - mp = strrchrW(root, L'/'); + mp = strrchrW(root, slash); if (mp && (mp >= root)) { /* found valid backup point */ wk2 = mp + 1; - if(*(wk1+2) != L'/') + if(wk1[2] != '/' && wk1[2] != '\') wk1 += 2; else wk1 += 3; } else { - /* did not find point, restore '/' */ - *(wk2-1) = L'/'; + /* did not find point, restore '/' */ + *(wk2-1) = slash; } } } @@ -458,7 +483,7 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR while ((nLen > 0) && ((lpszUrlCpy[nLen-1] == '\r')||(lpszUrlCpy[nLen-1] == '\n'))) lpszUrlCpy[--nLen]=0;
- if(dwFlags & URL_UNESCAPE) + if(dwFlags & (URL_UNESCAPE | URL_FILE_USE_PATHURL)) UrlUnescapeW(lpszUrlCpy, NULL, &nLen, URL_UNESCAPE_INPLACE);
if((EscapeFlags = dwFlags & (URL_ESCAPE_UNSAFE |