shlwapi: UrlCanonicalize: fix URL_DONT_SIMPLIFY.

- URL_DONT_SIMPLIFY should change '/' <-> '\'
- Better '/' / '\' handling
This commit is contained in:
Jacek Caban 2006-01-11 21:15:31 +01:00 committed by Alexandre Julliard
parent 50c64c04df
commit 11a0c8cd39
2 changed files with 133 additions and 129 deletions

View File

@ -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\\../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%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 { typedef struct _TEST_URL_ESCAPE {
@ -174,8 +176,10 @@ typedef struct _TEST_URL_COMBINE {
const TEST_URL_COMBINE TEST_COMBINE[] = { const TEST_URL_COMBINE TEST_COMBINE[] = {
{"http://www.winehq.org/tests", "tests1", 0, S_OK, "http://www.winehq.org/tests1"}, {"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"},*/ /*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/", "../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", "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/", "tests5", 0, S_OK, "http://www.winehq.org/tests/tests5"},
{"http://www.winehq.org/tests/../tests/", "/tests6/..", 0, S_OK, "http://www.winehq.org/"}, {"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/#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/../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"}, {"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 { struct {

View File

@ -341,140 +341,139 @@ HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,
nByteLen = (lstrlenW(pszUrl) + 1) * sizeof(WCHAR); /* length in bytes */ nByteLen = (lstrlenW(pszUrl) + 1) * sizeof(WCHAR); /* length in bytes */
lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nByteLen); lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nByteLen);
if (dwFlags & URL_DONT_SIMPLIFY) /*
memcpy(lpszUrlCpy, pszUrl, nByteLen); * state =
else { * 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;
* state = wk2 = lpszUrlCpy;
* 0 initial 1,3 state = 0;
* 1 have 2[+] alnum 2,3 while (*wk1) {
* 2 have scheme (found :) 4,6,3 switch (state) {
* 3 failed (no location) case 0:
* 4 have // 5,3 if (!isalnumW(*wk1)) {state = 3; break;}
* 5 have 1[+] alnum 6,3 *wk2++ = *wk1++;
* 6 have location (found /) save root location 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; while(mp < wk2) {
wk2 = lpszUrlCpy; if(*mp == '/' || *mp == '\\')
state = 0; *mp = slash;
while (*wk1) { mp++;
switch (state) { }
case 0: break;
if (!isalnumW(*wk1)) {state = 3; break;} case 4:
*wk2++ = *wk1++; if (!isalnumW(*wk1) && (*wk1 != L'-') && (*wk1 != L'.') && (*wk1 != ':'))
if (!isalnumW(*wk1)) {state = 3; break;} {state = 3; break;}
*wk2++ = *wk1++; while(isalnumW(*wk1) || (*wk1 == L'-') || (*wk1 == L'.') || (*wk1 == ':'))
state = 1; *wk2++ = *wk1++;
break; state = 5;
case 1: break;
*wk2++ = *wk1; case 5:
if (*wk1++ == L':') state = 2; if (*wk1 != '/' && *wk1 != '\\') {state = 3; break;}
break; while(*wk1 == '/' || *wk1 == '\\') {
case 2: *wk2++ = slash;
if (*wk1 != L'/') {state = 3; break;} wk1++;
*wk2++ = *wk1++; }
if (*wk1 != L'/') {state = 6; break;} state = 6;
*wk2++ = *wk1++; break;
if((dwFlags & URL_FILE_USE_PATHURL) && *wk1 == '/') case 6:
wk1++; if(dwFlags & URL_DONT_SIMPLIFY) {
state = 4; state = 3;
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;
break; break;
case 5: }
if (*wk1 != '/' && *wk1 != '\\') {state = 3; break;}
while(*wk1 == '/') { /* Now at root location, cannot back up any more. */
*wk2++ = slash; /* "root" will point at the '/' */
wk1++;
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; nLen = mp - wk1;
break; if(nLen) {
case 6: memcpy(wk2, wk1, nLen * sizeof(WCHAR));
/* Now at root location, cannot back up any more. */ wk2 += nLen;
/* "root" will point at the '/' */ wk1 += nLen;
root = wk2-1; }
while (*wk1) { *wk2++ = slash;
TRACE("wk1=%c\n", (CHAR)*wk1); wk1++;
mp = strchrW(wk1, '/'); if (*wk1 == L'.') {
mp2 = strchrW(wk1, '\\'); TRACE("found '/.'\n");
if(mp2 && mp2 < mp) if (wk1[1] == '/' || wk1[1] == '\\') {
mp = mp2; /* case of /./ -> skip the ./ */
if (!mp) { wk1 += 2;
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;
} }
*wk2++ = slash; else if (wk1[1] == '.') {
wk1++; /* found /.. look for next / */
TRACE("found '/..'\n");
if (*wk1 == L'.') { if (wk1[2] == '/' || wk1[2] == '\\' ||wk1[2] == '?'
TRACE("found '/.'\n"); || wk1[2] == '#' || !wk1[2]) {
if (wk1[1] == '/' || wk1[1] == '\\') { /* case /../ -> need to backup wk2 */
/* case of /./ -> skip the ./ */ TRACE("found '/../'\n");
wk1 += 2; *(wk2-1) = L'\0'; /* set end of string */
} mp = strrchrW(root, slash);
else if (wk1[1] == '.') { if (mp && (mp >= root)) {
/* found /.. look for next / */ /* found valid backup point */
TRACE("found '/..'\n"); wk2 = mp + 1;
if (wk1[2] == '/' || wk1[2] == '\\' ||wk1[2] == '?' if(wk1[2] != '/' && wk1[2] != '\\')
|| wk1[2] == '#' || !wk1[2]) { wk1 += 2;
/* case /../ -> need to backup wk2 */ else
TRACE("found '/../'\n"); wk1 += 3;
*(wk2-1) = L'\0'; /* set end of string */ }
mp = strrchrW(root, slash); else {
if (mp && (mp >= root)) { /* did not find point, restore '/' */
/* found valid backup point */ *(wk2-1) = slash;
wk2 = mp + 1; }
if(wk1[2] != '/' && wk1[2] != '\\') }
wk1 += 2; }
else }
wk1 += 3; }
} *wk2 = L'\0';
else { break;
/* did not find point, restore '/' */ default:
*(wk2-1) = slash; FIXME("how did we get here - state=%d\n", state);
} HeapFree(GetProcessHeap(), 0, lpszUrlCpy);
} return E_INVALIDARG;
} }
}
}
*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'; *wk2 = L'\0';
TRACE("Simplified, orig <%s>, simple <%s>\n", TRACE("Simplified, orig <%s>, simple <%s>\n",
debugstr_w(pszUrl), debugstr_w(lpszUrlCpy)); debugstr_w(pszUrl), debugstr_w(lpszUrlCpy));