From: Thomas Csovscity thc.fr13nd@gmail.com
--- dlls/kernelbase/path.c | 75 +++++++++++++++- dlls/shlwapi/tests/url.c | 184 +++++++++++++++++++-------------------- 2 files changed, 166 insertions(+), 93 deletions(-)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 86b15944102..498294a89d1 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -4091,7 +4091,7 @@ INT WINAPI UrlCompareW(const WCHAR *url1, const WCHAR *url2, BOOL ignore_slash) HRESULT WINAPI UrlFixupW(const WCHAR *url, WCHAR *translatedUrl, DWORD maxChars) { DWORD src_len, dst_len, len; - DWORD pos = 0; + DWORD colon_pos = 0, pos = 0; WCHAR *helper_str = NULL; WCHAR *save_str = translatedUrl;
@@ -4133,7 +4133,80 @@ HRESULT WINAPI UrlFixupW(const WCHAR *url, WCHAR *translatedUrl, DWORD maxChars) if (!helper_str) return S_FALSE;
+ /* + * Colon should not be at the beginning + */ + colon_pos = helper_str-url; + if (helper_str && (1 >= colon_pos)) + return S_FALSE; + /* + * Check if string fits into maxChars + */ + // TODO: Use own buffer for adjustments, output buffer may not fit before fix + if (colon_pos >= maxChars && maxChars < 3) + return S_FALSE; + + /* + * Set potential scheme + */ + lstrcpynW(save_str, url, pos+2); + url = url + colon_pos + 1; + + /* + * Find schemes with trailing or leading typos + */ + for (pos=1; pos<ARRAY_SIZE(url_scheme); pos++) + { + /* http is always prefered before https, if string has typos */ + len = wcslen(url_scheme[pos]); + if (!_wcsnicmp(url_scheme[pos], L"https", len+1)) + { + continue; + } + if ( (len <= wcslen(save_str)) && (StrStrIW(save_str, url_scheme[pos])) ) + { + /* + * check if string fits into maxChars + */ + if (len+1 >= maxChars) + return S_FALSE; + + lstrcpynW(save_str, url_scheme[pos], len+1); + lstrcatW(save_str, L":"); + goto scheme_done; + } + } + + /* Return false in most remaining cases should be safe */ + return S_FALSE; + + /* Concat scheme + rest */ scheme_done: + /* + * Concat L"://"" for ftp, http, https scheme * else ":" + */ + if ( 0 == lstrcmpW(save_str, L"ftp:") || + 0 == lstrcmpW(save_str, L"http:") || + 0 == lstrcmpW(save_str, L"https:") ) + { + if ( url[0] == L'\' || url[0] == L'/' ) + { + url++; + if ( url[0] == L'\' || url[0] == L'/' ) + url++; + } + lstrcatW(save_str, L"//"); + } + /* + * Remove leading "/", "" and ":" from url. + * Output already have them if needed + */ + while ( url[0] == L'\' || url[0] == L'/' ) + { + lstrcatW(save_str, L"/"); + url++; + } + /* Add the URL path */ src_len = lstrlenW(url) + 1; dst_len = maxChars - lstrlenW(save_str); diff --git a/dlls/shlwapi/tests/url.c b/dlls/shlwapi/tests/url.c index d9f2f5cde0d..6ecd5aa6ffa 100644 --- a/dlls/shlwapi/tests/url.c +++ b/dlls/shlwapi/tests/url.c @@ -1618,8 +1618,8 @@ static const struct parse_urlfixupw_test_t { HRESULT res; BOOL todo; } parse_urlfixupw_tests[] = { - {L"ftp:", L"ftp://", S_OK, TRUE}, - {L"http:", L"http://", S_OK, TRUE}, + {L"ftp:", L"ftp://", S_OK}, + {L"http:", L"http://", S_OK}, {L"gopher:", L"gopher:", S_OK}, {L"mailto:", L"mailto:", S_OK}, {L"news:", L"news:", S_OK}, @@ -1628,7 +1628,7 @@ static const struct parse_urlfixupw_test_t { {L"wais:", L"wais:", S_OK}, {L"file:", L"file:", S_OK}, {L"mk:", L"mk:", S_OK}, - {L"https:", L"https://", S_OK, TRUE}, + {L"https:", L"https://", S_OK}, {L"shell:", L"shell:", S_OK}, {L"snews:", L"snews:", S_OK}, {L"local:", L"local:", S_OK}, @@ -1650,27 +1650,27 @@ static const struct parse_urlfixupw_test_t { {L"ftp://", L"ftp://", S_OK},
/* typos in front one letter */ - {L"aftp://", L"ftp://", S_OK, TRUE}, - {L"ahttp://", L"http://", S_OK, TRUE}, - {L"agopher://", L"gopher://", S_OK, TRUE}, - {L"amailto://", L"mailto://", S_OK, TRUE}, + {L"aftp://", L"ftp://", S_OK}, + {L"ahttp://", L"http://", S_OK}, + {L"agopher://", L"gopher://", S_OK}, + {L"amailto://", L"mailto://", S_OK}, {L"anews://", L"snews://", S_OK, TRUE}, - {L"anntp://", L"nntp://", S_OK, TRUE}, - {L"atelnet://", L"telnet://", S_OK, TRUE}, - {L"awais://", L"wais://", S_OK, TRUE}, - {L"afile://", L"file://", S_OK, TRUE}, - {L"amk://", L"mk://", S_OK, TRUE}, - {L"ahttps://", L"http://", S_OK, TRUE}, - {L"ashell://", L"shell://", S_OK, TRUE}, + {L"anntp://", L"nntp://", S_OK}, + {L"atelnet://", L"telnet://", S_OK}, + {L"awais://", L"wais://", S_OK}, + {L"afile://", L"file://", S_OK}, + {L"amk://", L"mk://", S_OK}, + {L"ahttps://", L"http://", S_OK}, + {L"ashell://", L"shell://", S_OK}, {L"asnews://", L"snews://", S_OK, TRUE}, - {L"alocal://", L"local://", S_OK, TRUE}, - {L"ajavascript://", L"javascript://", S_OK, TRUE}, - {L"avbscript://", L"vbscript://", S_OK, TRUE}, - {L"aabout://", L"about://", S_OK, TRUE}, - {L"ares://", L"res://", S_OK, TRUE}, + {L"alocal://", L"local://", S_OK}, + {L"ajavascript://", L"javascript://", S_OK}, + {L"avbscript://", L"vbscript://", S_OK}, + {L"aabout://", L"about://", S_OK}, + {L"ares://", L"res://", S_OK}, {L"ams-shell-rooted://", L"ms-shell-rooted://", S_OK, TRUE}, {L"ams-shell-idlist://", L"ms-shell-idlist://", S_OK, TRUE}, - {L"ahcp://", L"hcp://", S_OK, TRUE}, + {L"ahcp://", L"hcp://", S_OK},
/* typos in front two letters */ {L"bahttp://", L"about://", S_OK, TRUE}, @@ -1712,11 +1712,11 @@ static const struct parse_urlfixupw_test_t { {L"newsssss://", L"snews://", S_OK, TRUE},
/* typos letters behind*/ - {L"mks://", L"mk://", S_OK, TRUE}, - {L"mkss://", L"mk://", S_OK, TRUE}, - {L"mailtooo://", L"mailto://", S_OK, TRUE}, - {L"mailtoooo://", L"mailto://", S_OK, TRUE}, - {L"mailtooooo://", L"mailto://", S_OK, TRUE}, + {L"mks://", L"mk://", S_OK}, + {L"mkss://", L"mk://", S_OK}, + {L"mailtooo://", L"mailto://", S_OK}, + {L"mailtoooo://", L"mailto://", S_OK}, + {L"mailtooooo://", L"mailto://", S_OK},
/* typos fixing two letters */ {L"cc:", L"hcp:", S_OK, TRUE}, @@ -1776,37 +1776,37 @@ static const struct parse_urlfixupw_test_t { {L"ftp", NULL, S_FALSE},
/* one letter never matched in winxp */ - {L"a:", NULL, S_FALSE, TRUE}, - {L"b:", NULL, S_FALSE, TRUE}, - {L"c:", NULL, S_FALSE, TRUE}, - {L"d:", NULL, S_FALSE, TRUE}, - {L"e:", NULL, S_FALSE, TRUE}, - {L"f:", NULL, S_FALSE, TRUE}, - {L"g:", NULL, S_FALSE, TRUE}, - {L"h:", NULL, S_FALSE, TRUE}, - {L"i:", NULL, S_FALSE, TRUE}, - {L"j:", NULL, S_FALSE, TRUE}, - {L"k:", NULL, S_FALSE, TRUE}, - {L"l:", NULL, S_FALSE, TRUE}, - {L"m:", NULL, S_FALSE, TRUE}, - {L"n:", NULL, S_FALSE, TRUE}, - {L"o:", NULL, S_FALSE, TRUE}, - {L"p:", NULL, S_FALSE, TRUE}, - {L"q:", NULL, S_FALSE, TRUE}, - {L"r:", NULL, S_FALSE, TRUE}, - {L"s:", NULL, S_FALSE, TRUE}, - {L"t:", NULL, S_FALSE, TRUE}, - {L"u:", NULL, S_FALSE, TRUE}, - {L"v:", NULL, S_FALSE, TRUE}, - {L"w:", NULL, S_FALSE, TRUE}, - {L"x:", NULL, S_FALSE, TRUE}, - {L"y:", NULL, S_FALSE, TRUE}, - {L"z:", NULL, S_FALSE, TRUE}, - - {L"gophssss://", NULL, S_FALSE, TRUE}, - {L"gop://", NULL, S_FALSE, TRUE}, - {L"go://", NULL, S_FALSE, TRUE}, - {L"mai://", NULL, S_FALSE, TRUE}, + {L"a:", NULL, S_FALSE}, + {L"b:", NULL, S_FALSE}, + {L"c:", NULL, S_FALSE}, + {L"d:", NULL, S_FALSE}, + {L"e:", NULL, S_FALSE}, + {L"f:", NULL, S_FALSE}, + {L"g:", NULL, S_FALSE}, + {L"h:", NULL, S_FALSE}, + {L"i:", NULL, S_FALSE}, + {L"j:", NULL, S_FALSE}, + {L"k:", NULL, S_FALSE}, + {L"l:", NULL, S_FALSE}, + {L"m:", NULL, S_FALSE}, + {L"n:", NULL, S_FALSE}, + {L"o:", NULL, S_FALSE}, + {L"p:", NULL, S_FALSE}, + {L"q:", NULL, S_FALSE}, + {L"r:", NULL, S_FALSE}, + {L"s:", NULL, S_FALSE}, + {L"t:", NULL, S_FALSE}, + {L"u:", NULL, S_FALSE}, + {L"v:", NULL, S_FALSE}, + {L"w:", NULL, S_FALSE}, + {L"x:", NULL, S_FALSE}, + {L"y:", NULL, S_FALSE}, + {L"z:", NULL, S_FALSE}, + + {L"gophssss://", NULL, S_FALSE}, + {L"gop://", NULL, S_FALSE}, + {L"go://", NULL, S_FALSE}, + {L"mai://", NULL, S_FALSE},
{L"mkkkto://", NULL, S_FALSE, TRUE}, {L"mailtoooooo://", NULL, S_FALSE, TRUE}, @@ -1817,64 +1817,64 @@ static const struct parse_urlfixupw_test_t { {L"ft", NULL, S_FALSE},
/* mixed tests */ - {L"aa:", NULL, S_FALSE, TRUE}, - {L"bb:", NULL, S_FALSE, TRUE}, - {L"dd:", NULL, S_FALSE, TRUE}, - {L"gg:", NULL, S_FALSE, TRUE}, - {L"ii:", NULL, S_FALSE, TRUE}, - {L"jj:", NULL, S_FALSE, TRUE}, - {L"ll:", NULL, S_FALSE, TRUE}, - {L"oo:", NULL, S_FALSE, TRUE}, - {L"pp:", NULL, S_FALSE, TRUE}, - {L"qq:", NULL, S_FALSE, TRUE}, - {L"ss:", NULL, S_FALSE, TRUE}, - {L"uu:", NULL, S_FALSE, TRUE}, - {L"vv:", NULL, S_FALSE, TRUE}, - {L"ww:", NULL, S_FALSE, TRUE}, - {L"xx:", NULL, S_FALSE, TRUE}, - {L"yy:", NULL, S_FALSE, TRUE}, - {L"zz:", NULL, S_FALSE, TRUE}, + {L"aa:", NULL, S_FALSE}, + {L"bb:", NULL, S_FALSE}, + {L"dd:", NULL, S_FALSE}, + {L"gg:", NULL, S_FALSE}, + {L"ii:", NULL, S_FALSE}, + {L"jj:", NULL, S_FALSE}, + {L"ll:", NULL, S_FALSE}, + {L"oo:", NULL, S_FALSE}, + {L"pp:", NULL, S_FALSE}, + {L"qq:", NULL, S_FALSE}, + {L"ss:", NULL, S_FALSE}, + {L"uu:", NULL, S_FALSE}, + {L"vv:", NULL, S_FALSE}, + {L"ww:", NULL, S_FALSE}, + {L"xx:", NULL, S_FALSE}, + {L"yy:", NULL, S_FALSE}, + {L"zz:", NULL, S_FALSE},
/* taken from example in documentation */ {L"http://www.microsoft.com", L"http://www.microsoft.com", S_OK}, - {L"http:www.microsoft.com", L"http://www.microsoft.com", S_OK, TRUE}, + {L"http:www.microsoft.com", L"http://www.microsoft.com", S_OK}, {L"mail:someone@example.com", L"mailto:someone@example.com", S_OK, TRUE}, {L"htpp:wwwmicrosoft.com", L"http://wwwmicrosoft.com", S_OK, TRUE}, {L"htps:\www.microsoft.com", L"http://www.microsoft.com", S_OK, TRUE}, - {L"http:someone@example.com", L"http://someone@example.com", S_OK, TRUE}, - {L"abc:def", NULL, S_FALSE, TRUE}, + {L"http:someone@example.com", L"http://someone@example.com", S_OK}, + {L"abc:def", NULL, S_FALSE}, {L"someone@example.com", NULL, S_FALSE},
- {L"fztzp:", NULL, S_FALSE, TRUE}, - {L"zfztzp:", NULL, S_FALSE, TRUE}, - {L"zfztp:", NULL, S_FALSE, TRUE}, - {L"zftzp:", NULL, S_FALSE, TRUE}, + {L"fztzp:", NULL, S_FALSE}, + {L"zfztzp:", NULL, S_FALSE}, + {L"zfztp:", NULL, S_FALSE}, + {L"zftzp:", NULL, S_FALSE}, {L"zftpz:", NULL, S_FALSE, TRUE},
{L"htztps:", L"http://", S_OK, TRUE}, {L"hzttps:", L"http://", S_OK, TRUE}, - {L"htzztps:", NULL, S_FALSE, TRUE}, - {L"hzzzzzzzzzzzzzztp:", NULL, S_FALSE, TRUE}, - {L"hzzzzzzzzzzzzzztpz:", NULL, S_FALSE, TRUE}, - {L"zhzzzzzzzzzzzzzztp:", NULL, S_FALSE, TRUE}, - {L"zhzzzzzzzzzzzzzztpz:", NULL, S_FALSE, TRUE}, - {L"zzzzzzhzzzzzzzzzzzzzztzzzzzzpzzzzzz:", NULL, S_FALSE, TRUE}, + {L"htzztps:", NULL, S_FALSE}, + {L"hzzzzzzzzzzzzzztp:", NULL, S_FALSE}, + {L"hzzzzzzzzzzzzzztpz:", NULL, S_FALSE}, + {L"zhzzzzzzzzzzzzzztp:", NULL, S_FALSE}, + {L"zhzzzzzzzzzzzzzztpz:", NULL, S_FALSE}, + {L"zzzzzzhzzzzzzzzzzzzzztzzzzzzpzzzzzz:", NULL, S_FALSE},
{L"hfttp:", L"http://", S_OK, TRUE}, {L"hfttpz:", L"http://", S_OK, TRUE}, {L"zhftp:", NULL, S_FALSE, TRUE}, {L"hftftpz:", NULL, S_FALSE, TRUE}, - {L"hftddtpz:", NULL, S_FALSE, TRUE}, - {L"hftddtddpz:", NULL, S_FALSE, TRUE}, + {L"hftddtpz:", NULL, S_FALSE}, + {L"hftddtddpz:", NULL, S_FALSE},
{L"hfftp:", L"http://", S_OK, TRUE}, {L"hftpz:", L"http://", S_OK, TRUE}, {L"hztpz:", L"http://", S_OK, TRUE},
- {L"httpz:", L"http://", S_OK, TRUE}, - {L"httpsz:", L"http://", S_OK, TRUE}, - {L"httpzz:", L"http://", S_OK, TRUE}, - {L"httpzzz:", L"http://", S_OK, TRUE}, + {L"httpz:", L"http://", S_OK}, + {L"httpsz:", L"http://", S_OK}, + {L"httpzz:", L"http://", S_OK}, + {L"httpzzz:", L"http://", S_OK}, {L"httpzzzz:", NULL, S_FALSE, TRUE}, {L"httpzzzzz:", NULL, S_FALSE, TRUE},