diff --git a/dlls/urlmon/tests/uri.c b/dlls/urlmon/tests/uri.c index 11a464e9d10..54f5ef4352c 100644 --- a/dlls/urlmon/tests/uri.c +++ b/dlls/urlmon/tests/uri.c @@ -3771,6 +3771,122 @@ static const uri_properties uri_tests[] = { {URL_SCHEME_FILE,S_OK,FALSE}, {URLZONE_INVALID,E_NOTIMPL,FALSE} } + }, + /* The backslashes after the scheme name are converted to forward slashes. */ + { "file:\\\\c:\\dir\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE, + Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH + |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE + |Uri_HAS_SCHEME, FALSE, + { + {"file://c:\\dir\\index.html",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"file://c:\\dir\\index.html",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {".html",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE}, + {"c:\\dir\\index.html",S_OK,FALSE}, + {"c:\\dir\\index.html",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"file:\\\\c:\\dir\\index.html",S_OK,FALSE}, + {"file",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE} + }, + { + {0,S_OK,FALSE}, + {0,S_FALSE,FALSE}, + {URL_SCHEME_FILE,S_OK,FALSE}, + {URLZONE_INVALID,E_NOTIMPL,FALSE} + } + }, + { "file:\\\\c:/dir/index.html", 0, S_OK, FALSE, + Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH + |Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE + |Uri_HAS_SCHEME, FALSE, + { + {"file:///c:/dir/index.html",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"file:///c:/dir/index.html",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {".html",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE}, + {"/c:/dir/index.html",S_OK,FALSE}, + {"/c:/dir/index.html",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"file:\\\\c:/dir/index.html",S_OK,FALSE}, + {"file",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE} + }, + { + {0,S_OK,FALSE}, + {0,S_FALSE,FALSE}, + {URL_SCHEME_FILE,S_OK,FALSE}, + {URLZONE_INVALID,E_NOTIMPL,FALSE} + } + }, + { "http:\\\\google.com", 0, S_OK, FALSE, + Uri_HAS_ABSOLUTE_URI|Uri_HAS_AUTHORITY|Uri_HAS_DISPLAY_URI|Uri_HAS_DOMAIN| + Uri_HAS_HOST|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME| + Uri_HAS_HOST_TYPE|Uri_HAS_PORT|Uri_HAS_SCHEME, + FALSE, + { + {"http://google.com/",S_OK,FALSE}, + {"google.com",S_OK,FALSE}, + {"http://google.com/",S_OK,FALSE}, + {"google.com",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE}, + {"google.com",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"/",S_OK,FALSE}, + {"/",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"http:\\\\google.com",S_OK,FALSE}, + {"http",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE} + }, + { + {Uri_HOST_DNS,S_OK,FALSE}, + {80,S_OK,FALSE}, + {URL_SCHEME_HTTP,S_OK,FALSE}, + {URLZONE_INVALID,E_NOTIMPL,FALSE} + } + }, + /* the "\\\\" aren't converted to "//" for unknown scheme types and it's considered opaque. */ + { "zip:\\\\google.com", 0, S_OK, FALSE, + Uri_HAS_ABSOLUTE_URI|Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH| + Uri_HAS_PATH_AND_QUERY|Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_SCHEME| + Uri_HAS_HOST_TYPE, + FALSE, + { + {"zip:\\\\google.com",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"zip:\\\\google.com",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {".com",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE}, + {"\\\\google.com",S_OK,FALSE}, + {"\\\\google.com",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"zip:\\\\google.com",S_OK,FALSE}, + {"zip",S_OK,FALSE}, + {"",S_FALSE,FALSE}, + {"",S_FALSE,FALSE} + }, + { + {Uri_HOST_UNKNOWN,S_OK,FALSE}, + {0,S_FALSE,FALSE}, + {URL_SCHEME_UNKNOWN,S_OK,FALSE}, + {URLZONE_INVALID,E_NOTIMPL,FALSE} + } } }; diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c index 530b1ad1a76..f184aab7416 100644 --- a/dlls/urlmon/uri.c +++ b/dlls/urlmon/uri.c @@ -306,6 +306,33 @@ static inline BOOL is_hierarchical_scheme(URL_SCHEME type) { type == URL_SCHEME_RES); } +/* Determines if the URI is hierarchical using the information already parsed into + * data and using the current location of parsing in the URI string. + * + * Windows considers a URI hierarchical if on of the following is true: + * A.) It's a wildcard scheme. + * B.) It's an implicit file scheme. + * C.) It's a known hierarchical scheme and it has two '\\' after the scheme name. + * (the '\\' will be converted into "//" during canonicalization). + * D.) It's not a relative URI and "//" appears after the scheme name. + */ +static inline BOOL is_hierarchical_uri(const WCHAR **ptr, const parse_data *data) { + const WCHAR *start = *ptr; + + if(data->scheme_type == URL_SCHEME_WILDCARD) + return TRUE; + else if(data->scheme_type == URL_SCHEME_FILE && data->has_implicit_scheme) + return TRUE; + else if(is_hierarchical_scheme(data->scheme_type) && (*ptr)[0] == '\\' && (*ptr)[1] == '\\') { + *ptr += 2; + return TRUE; + } else if(!data->is_relative && check_hierarchical(ptr)) + return TRUE; + + *ptr = start; + return FALSE; +} + /* Checks if the two Uri's are logically equivalent. It's a simple * comparison, since they are both of type Uri, and it can access * the properties of each Uri directly without the need to go @@ -1866,17 +1893,8 @@ static BOOL parse_path_opaque(const WCHAR **ptr, parse_data *data, DWORD flags) static BOOL parse_hierpart(const WCHAR **ptr, parse_data *data, DWORD flags) { const WCHAR *start = *ptr; - /* Checks if the authority information needs to be parsed. - * - * Relative URI's aren't hierarchical URI's, but, they could trick - * "check_hierarchical" into thinking it is, so we need to explicitly - * make sure it's not relative. Also, if the URI is an implicit file - * scheme it might not contain a "//", but, it's considered hierarchical - * anyways. Wildcard Schemes are always considered hierarchical - */ - if(data->scheme_type == URL_SCHEME_WILDCARD || - (data->scheme_type == URL_SCHEME_FILE && is_implicit_file_path(*ptr)) || - (!data->is_relative && check_hierarchical(ptr))) { + /* Checks if the authority information needs to be parsed. */ + if(is_hierarchical_uri(ptr, data)) { /* Only treat it as a hierarchical URI if the scheme_type is known or * the Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES flag is not set. */ @@ -1885,10 +1903,6 @@ static BOOL parse_hierpart(const WCHAR **ptr, parse_data *data, DWORD flags) { TRACE("(%p %p %x): Treating URI as an hierarchical URI.\n", ptr, data, flags); data->is_opaque = FALSE; - if(data->scheme_type == URL_SCHEME_FILE) - /* Skip past the "//" after the scheme (if any). */ - check_hierarchical(ptr); - /* TODO: Handle hierarchical URI's, parse authority then parse the path. */ if(!parse_authority(ptr, data, flags)) return FALSE;