From 11a0c8cd39a33b1b1f2ccccca58d9428021acc1a Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 11 Jan 2006 21:15:31 +0100 Subject: [PATCH] shlwapi: UrlCanonicalize: fix URL_DONT_SIMPLIFY. - URL_DONT_SIMPLIFY should change '/' <-> '\' - Better '/' / '\' handling --- dlls/shlwapi/tests/path.c | 7 +- dlls/shlwapi/url.c | 255 +++++++++++++++++++------------------- 2 files changed, 133 insertions(+), 129 deletions(-) diff --git a/dlls/shlwapi/tests/path.c b/dlls/shlwapi/tests/path.c index 1efbe0f1005..6800da2d54c 100644 --- a/dlls/shlwapi/tests/path.c +++ b/dlls/shlwapi/tests/path.c @@ -72,7 +72,9 @@ const TEST_URL_CANONICALIZE TEST_CANONICALIZE[] = { {"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"} + {"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, S_OK, "file://c:\\\\tests\\foo bar"}, + {"file:///c:\\tests\\foo bar", 0, S_OK, "file:///c:/tests/foo bar"}, + {"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, S_OK, "file:///c:/tests/foo bar"}, }; typedef struct _TEST_URL_ESCAPE { @@ -174,8 +176,10 @@ typedef struct _TEST_URL_COMBINE { const TEST_URL_COMBINE TEST_COMBINE[] = { {"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"}, + {"http://www.%77inehq.org/tests", "tests1", 0, S_OK, "http://www.%77inehq.org/tests1"}, /*FIXME {"http://www.winehq.org/tests", "../tests2", 0, S_OK, "http://www.winehq.org/tests2"},*/ {"http://www.winehq.org/tests/", "../tests3", 0, S_OK, "http://www.winehq.org/tests3"}, + {"http://www.winehq.org/tests/test1", "test2", 0, S_OK, "http://www.winehq.org/tests/test2"}, {"http://www.winehq.org/tests/../tests", "tests4", 0, S_OK, "http://www.winehq.org/tests4"}, {"http://www.winehq.org/tests/../tests/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"}, {"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"}, @@ -184,6 +188,7 @@ const TEST_URL_COMBINE TEST_COMBINE[] = { {"http://www.winehq.org/tests/#example", "tests9", 0, S_OK, "http://www.winehq.org/tests/tests9"}, {"http://www.winehq.org/tests/../tests/", "/tests10/..", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests10/.."}, {"http://www.winehq.org/tests/../", "tests11", URL_DONT_SIMPLIFY, S_OK, "http://www.winehq.org/tests/../tests11"}, + {"file:///C:\\dir\\file.txt", "test.txt", 0, S_OK, "file:///C:/dir/test.txt"} }; struct { diff --git a/dlls/shlwapi/url.c b/dlls/shlwapi/url.c index 4e5c691bd87..721142063c2 100644 --- a/dlls/shlwapi/url.c +++ b/dlls/shlwapi/url.c @@ -341,140 +341,139 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, nByteLen = (lstrlenW(pszUrl) + 1) * sizeof(WCHAR); /* length in bytes */ lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nByteLen); - if (dwFlags & URL_DONT_SIMPLIFY) - memcpy(lpszUrlCpy, pszUrl, nByteLen); - else { + /* + * state = + * 0 initial 1,3 + * 1 have 2[+] alnum 2,3 + * 2 have scheme (found :) 4,6,3 + * 3 failed (no location) + * 4 have // 5,3 + * 5 have 1[+] alnum 6,3 + * 6 have location (found /) save root location + */ - /* - * state = - * 0 initial 1,3 - * 1 have 2[+] alnum 2,3 - * 2 have scheme (found :) 4,6,3 - * 3 failed (no location) - * 4 have // 5,3 - * 5 have 1[+] alnum 6,3 - * 6 have location (found /) save root location - */ + wk1 = (LPWSTR)pszUrl; + wk2 = lpszUrlCpy; + state = 0; + while (*wk1) { + switch (state) { + case 0: + if (!isalnumW(*wk1)) {state = 3; break;} + *wk2++ = *wk1++; + if (!isalnumW(*wk1)) {state = 3; break;} + *wk2++ = *wk1++; + state = 1; + break; + case 1: + *wk2++ = *wk1; + if (*wk1++ == L':') state = 2; + break; + case 2: + if (*wk1 != L'/') {state = 3; break;} + *wk2++ = *wk1++; + if (*wk1 != L'/') {state = 6; break;} + *wk2++ = *wk1++; + if(*wk1 == '/' && (dwFlags & URL_FILE_USE_PATHURL)) + wk1++; + state = 4; + break; + case 3: + nWkLen = strlenW(wk1); + memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR)); + mp = wk2; + wk1 += nWkLen; + wk2 += nWkLen; - wk1 = (LPWSTR)pszUrl; - wk2 = lpszUrlCpy; - state = 0; - while (*wk1) { - switch (state) { - case 0: - if (!isalnumW(*wk1)) {state = 3; break;} - *wk2++ = *wk1++; - if (!isalnumW(*wk1)) {state = 3; break;} - *wk2++ = *wk1++; - state = 1; - break; - case 1: - *wk2++ = *wk1; - if (*wk1++ == L':') state = 2; - break; - case 2: - if (*wk1 != L'/') {state = 3; break;} - *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'.') && (*wk1 != ':')) - {state = 3; break;} - while(isalnumW(*wk1) || (*wk1 == L'-') || (*wk1 == L'.') || (*wk1 == ':')) - *wk2++ = *wk1++; - state = 5; + while(mp < wk2) { + if(*mp == '/' || *mp == '\\') + *mp = slash; + mp++; + } + break; + case 4: + 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 == '/' || *wk1 == '\\') { + *wk2++ = slash; + wk1++; + } + state = 6; + break; + case 6: + if(dwFlags & URL_DONT_SIMPLIFY) { + state = 3; break; - case 5: - if (*wk1 != '/' && *wk1 != '\\') {state = 3; break;} - while(*wk1 == '/') { - *wk2++ = slash; - wk1++; + } + + /* Now at root location, cannot back up any more. */ + /* "root" will point at the '/' */ + + root = wk2-1; + while (*wk1) { + mp = strchrW(wk1, '/'); + mp2 = strchrW(wk1, '\\'); + if(mp2 && (!mp || mp2 < mp)) + mp = mp2; + if (!mp) { + nWkLen = strlenW(wk1); + memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR)); + wk1 += nWkLen; + wk2 += nWkLen; + continue; } - state = 6; - break; - case 6: - /* Now at root location, cannot back up any more. */ - /* "root" will point at the '/' */ - root = wk2-1; - while (*wk1) { - TRACE("wk1=%c\n", (CHAR)*wk1); + nLen = mp - wk1; + if(nLen) { + memcpy(wk2, wk1, nLen * sizeof(WCHAR)); + wk2 += nLen; + wk1 += nLen; + } + *wk2++ = slash; + wk1++; - mp = strchrW(wk1, '/'); - mp2 = strchrW(wk1, '\\'); - if(mp2 && mp2 < mp) - mp = mp2; - if (!mp) { - nWkLen = strlenW(wk1); - memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR)); - wk1 += nWkLen; - wk2 += nWkLen; - continue; - } - nLen = mp - wk1; - if(nLen) { - memcpy(wk2, wk1, nLen * sizeof(WCHAR)); - wk2 += nLen; - wk1 += nLen; + if (*wk1 == L'.') { + TRACE("found '/.'\n"); + if (wk1[1] == '/' || wk1[1] == '\\') { + /* case of /./ -> skip the ./ */ + wk1 += 2; } - *wk2++ = slash; - wk1++; - - if (*wk1 == L'.') { - TRACE("found '/.'\n"); - if (wk1[1] == '/' || wk1[1] == '\\') { - /* case of /./ -> skip the ./ */ - wk1 += 2; - } - else if (wk1[1] == '.') { - /* found /.. look for next / */ - TRACE("found '/..'\n"); - 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, slash); - if (mp && (mp >= root)) { - /* found valid backup point */ - wk2 = mp + 1; - if(wk1[2] != '/' && wk1[2] != '\\') - wk1 += 2; - else - wk1 += 3; - } - else { - /* did not find point, restore '/' */ - *(wk2-1) = slash; - } - } - } - } - } - *wk2 = L'\0'; - break; - default: - FIXME("how did we get here - state=%d\n", state); - HeapFree(GetProcessHeap(), 0, lpszUrlCpy); - return E_INVALIDARG; - } - } + else if (wk1[1] == '.') { + /* found /.. look for next / */ + TRACE("found '/..'\n"); + 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, slash); + if (mp && (mp >= root)) { + /* found valid backup point */ + wk2 = mp + 1; + if(wk1[2] != '/' && wk1[2] != '\\') + wk1 += 2; + else + wk1 += 3; + } + else { + /* did not find point, restore '/' */ + *(wk2-1) = slash; + } + } + } + } + } + *wk2 = L'\0'; + break; + default: + FIXME("how did we get here - state=%d\n", state); + HeapFree(GetProcessHeap(), 0, lpszUrlCpy); + return E_INVALIDARG; + } *wk2 = L'\0'; TRACE("Simplified, orig <%s>, simple <%s>\n", debugstr_w(pszUrl), debugstr_w(lpszUrlCpy));