shlwapi: UrlCanonicalize: fix URL_DONT_SIMPLIFY.
- URL_DONT_SIMPLIFY should change '/' <-> '\' - Better '/' / '\' handling
This commit is contained in:
parent
50c64c04df
commit
11a0c8cd39
|
@ -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 {
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Reference in New Issue