From: Thomas Csovscity thc.fr13nd@gmail.com
--- dlls/kernelbase/path.c | 76 +++++++++++++++++++++++++++++++++++++++- dlls/shlwapi/tests/url.c | 62 ++++++++++++++++---------------- 2 files changed, 106 insertions(+), 32 deletions(-)
diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index 86b15944102..17bcd4f8d31 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,81 @@ 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 154c0b47bef..660f80a4a27 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}, @@ -1837,11 +1837,11 @@ static const struct parse_urlfixupw_test_t {
/* 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"http:someone@example.com", L"http://someone@example.com", S_OK}, {L"abc:def", NULL, S_FALSE, TRUE}, {L"someone@example.com", NULL, S_FALSE, TRUE},
@@ -1871,10 +1871,10 @@ static const struct parse_urlfixupw_test_t { {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},