diff --git a/dlls/urlmon/tests/uri.c b/dlls/urlmon/tests/uri.c index 442c38ca9e7..9ef36aafcef 100644 --- a/dlls/urlmon/tests/uri.c +++ b/dlls/urlmon/tests/uri.c @@ -4862,9 +4862,9 @@ static const uri_builder_test uri_builder_tests[] = { {FALSE}, }, {FALSE}, - 0,S_OK,TRUE, - 0,S_OK,TRUE, - 0,0,0,S_OK,TRUE, + 0,S_OK,FALSE, + 0,S_OK,FALSE, + 0,0,0,S_OK,FALSE, { {"http://:password@google.com/",S_OK}, {":password@google.com",S_OK}, @@ -4929,9 +4929,9 @@ static const uri_builder_test uri_builder_tests[] = { {TRUE,NULL,"zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE} }, {FALSE}, - 0,S_OK,TRUE, - 0,S_OK,TRUE, - 0,0,0,S_OK,TRUE, + 0,S_OK,FALSE, + 0,S_OK,FALSE, + 0,0,0,S_OK,FALSE, { {"zip://google.com/",S_OK}, {"google.com",S_OK}, @@ -4962,9 +4962,9 @@ static const uri_builder_test uri_builder_tests[] = { {TRUE,"","zip",Uri_PROPERTY_SCHEME_NAME,E_INVALIDARG,FALSE} }, {FALSE}, - 0,S_OK,TRUE, - 0,S_OK,TRUE, - 0,0,0,S_OK,TRUE, + 0,S_OK,FALSE, + 0,S_OK,FALSE, + 0,0,0,S_OK,FALSE, { {"zip://google.com/",S_OK}, {"google.com",S_OK}, @@ -4988,6 +4988,103 @@ static const uri_builder_test uri_builder_tests[] = { {URL_SCHEME_UNKNOWN,S_OK}, {URLZONE_INVALID,E_NOTIMPL} } + }, + /* -1 to CreateUri makes it use the same flags as the base IUri was created with. + * CreateUriSimple always uses the flags the base IUri was created with (if any). + */ + { "http://google.com/../../",Uri_CREATE_NO_CANONICALIZE,S_OK,FALSE, + {{FALSE}}, + {FALSE}, + -1,S_OK,FALSE, + 0,S_OK,FALSE, + 0,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,FALSE, + { + {"http://google.com/../../",S_OK}, + {"google.com",S_OK}, + {"http://google.com/../../",S_OK}, + {"google.com",S_OK}, + {"",S_FALSE}, + {"",S_FALSE}, + {"google.com",S_OK}, + {"",S_FALSE}, + {"/../../",S_OK}, + {"/../../",S_OK}, + {"",S_FALSE}, + {"http://google.com/../../",S_OK}, + {"http",S_OK}, + {"",S_FALSE}, + {"",S_FALSE} + }, + { + {Uri_HOST_DNS,S_OK}, + {80,S_OK}, + {URL_SCHEME_HTTP,S_OK}, + {URLZONE_INVALID,E_NOTIMPL} + } + }, + { "http://google.com/",0,S_OK,FALSE, + { + {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE} + }, + {FALSE}, + -1,S_OK,TRUE, + 0,S_OK,TRUE, + Uri_CREATE_NO_DECODE_EXTRA_INFO,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,TRUE, + { + {"http://google.com/#Fr%3C%7C%3Eg",S_OK}, + {"google.com",S_OK}, + {"http://google.com/#Fr%3C%7C%3Eg",S_OK}, + {"google.com",S_OK}, + {"",S_FALSE}, + {"#Fr%3C%7C%3Eg",S_OK}, + {"google.com",S_OK}, + {"",S_FALSE}, + {"/",S_OK}, + {"/",S_OK}, + {"",S_FALSE}, + {"http://google.com/#Fr<|>g",S_OK}, + {"http",S_OK}, + {"",S_FALSE}, + {"",S_FALSE} + }, + { + {Uri_HOST_DNS,S_OK}, + {80,S_OK}, + {URL_SCHEME_HTTP,S_OK}, + {URLZONE_INVALID,E_NOTIMPL} + } + }, + { "http://google.com/",0,S_OK,FALSE, + { + {TRUE,"#Fr<|>g",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE} + }, + {FALSE}, + Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,E_INVALIDARG,FALSE, + 0,S_OK,TRUE, + Uri_CREATE_CANONICALIZE|Uri_CREATE_NO_CANONICALIZE,UriBuilder_USE_ORIGINAL_FLAGS,0,S_OK,TRUE, + { + {"http://google.com/#Fr%3C%7C%3Eg",S_OK}, + {"google.com",S_OK}, + {"http://google.com/#Fr%3C%7C%3Eg",S_OK}, + {"google.com",S_OK}, + {"",S_FALSE}, + {"#Fr%3C%7C%3Eg",S_OK}, + {"google.com",S_OK}, + {"",S_FALSE}, + {"/",S_OK}, + {"/",S_OK}, + {"",S_FALSE}, + {"http://google.com/#Fr<|>g",S_OK}, + {"http",S_OK}, + {"",S_FALSE}, + {"",S_FALSE} + }, + { + {Uri_HOST_DNS,S_OK}, + {80,S_OK}, + {URL_SCHEME_HTTP,S_OK}, + {URLZONE_INVALID,E_NOTIMPL} + } } }; @@ -5023,29 +5120,29 @@ static const uri_builder_remove_test uri_builder_remove_tests[] = { /* Doesn't remove the whole userinfo component. */ { "http://username:pass@google.com/",0,S_OK,FALSE, Uri_HAS_USER_INFO,S_OK,FALSE, - "http://username:pass@google.com/",0,S_OK,TRUE + "http://username:pass@google.com/",0,S_OK,FALSE }, /* Doesn't remove the domain. */ { "http://google.com/",0,S_OK,FALSE, Uri_HAS_DOMAIN,S_OK,FALSE, - "http://google.com/",0,S_OK,TRUE + "http://google.com/",0,S_OK,FALSE }, { "http://google.com:120/",0,S_OK,FALSE, Uri_HAS_AUTHORITY,S_OK,FALSE, - "http://google.com:120/",0,S_OK,TRUE + "http://google.com:120/",0,S_OK,FALSE }, { "http://google.com/test.com/",0,S_OK,FALSE, Uri_HAS_EXTENSION,S_OK,FALSE, - "http://google.com/test.com/",0,S_OK,TRUE + "http://google.com/test.com/",0,S_OK,FALSE }, { "http://google.com/?test=x",0,S_OK,FALSE, Uri_HAS_PATH_AND_QUERY,S_OK,FALSE, - "http://google.com/?test=x",0,S_OK,TRUE + "http://google.com/?test=x",0,S_OK,FALSE }, /* Can't remove the scheme name. */ { "http://google.com/?test=x",0,S_OK,FALSE, Uri_HAS_SCHEME_NAME|Uri_HAS_QUERY,E_INVALIDARG,FALSE, - "http://google.com/?test=x",0,S_OK,TRUE + "http://google.com/?test=x",0,S_OK,FALSE } }; @@ -6664,28 +6761,22 @@ static void test_IUriBuilder_CreateInvalidArgs(void) { /* No longer returns E_NOTIMPL, since a IUri has been set and hasn't been modified. */ uri = NULL; hr = IUriBuilder_CreateUri(builder, 0, Uri_HAS_USER_NAME, 0, &uri); - todo_wine { - ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK); - } - todo_wine { ok(uri != NULL, "Error: The uri was NULL.\n"); } + ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK); + ok(uri != NULL, "Error: The uri was NULL.\n"); if(uri) IUri_Release(uri); uri = NULL; hr = IUriBuilder_CreateUriSimple(builder, Uri_HAS_USER_NAME, 0, &uri); - todo_wine { - ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", - hr, S_OK); - } - todo_wine { ok(uri != NULL, "Error: uri was NULL.\n"); } + ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", + hr, S_OK); + ok(uri != NULL, "Error: uri was NULL.\n"); if(uri) IUri_Release(uri); uri = NULL; hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &uri); - todo_wine { - ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", - hr, S_OK); - } - todo_wine { ok(uri != NULL, "Error: uri was NULL.\n"); } + ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", + hr, S_OK); + ok(uri != NULL, "Error: uri was NULL.\n"); if(uri) IUri_Release(uri); hr = IUriBuilder_SetFragment(builder, NULL); @@ -7920,9 +8011,7 @@ static void test_IUriBuilder_IUriProperty(void) { orig_count = get_refcnt(uri); hr = IUriBuilder_CreateUri(builder, 0, 0, 0, &test); - todo_wine { - ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK); - } + ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK); if(SUCCEEDED(hr)) { cur_count = get_refcnt(uri); ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n", @@ -7932,6 +8021,17 @@ static void test_IUriBuilder_IUriProperty(void) { } if(test) IUri_Release(test); + test = NULL; + hr = IUriBuilder_CreateUri(builder, -1, 0, 0, &test); + ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK); + if(SUCCEEDED(hr)) { + cur_count = get_refcnt(uri); + ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n", + orig_count+1, cur_count); + ok(test == uri, "Error: Expected test to be %p, but was %p instead.\n", uri, test); + } + if(test) IUri_Release(test); + /* Doesn't return the same IUri, if the flag combination is different then the one that created * the base IUri. */ @@ -7952,9 +8052,7 @@ static void test_IUriBuilder_IUriProperty(void) { */ test = NULL; hr = IUriBuilder_CreateUri(builder, Uri_CREATE_CANONICALIZE, 0, 0, &test); - todo_wine { - ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK); - } + ok(hr == S_OK, "Error: IUriBuilder_CreateUri returned 0x%08x, expected 0x%08x.\n", hr, S_OK); if(SUCCEEDED(hr)) { cur_count = get_refcnt(uri); ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n", @@ -7965,9 +8063,7 @@ static void test_IUriBuilder_IUriProperty(void) { test = NULL; hr = IUriBuilder_CreateUriSimple(builder, 0, 0, &test); - todo_wine { - ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK); - } + ok(hr == S_OK, "Error: IUriBuilder_CreateUriSimple returned 0x%08x, expected 0x%08x.\n", hr, S_OK); if(SUCCEEDED(hr)) { cur_count = get_refcnt(uri); ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n", @@ -7978,10 +8074,8 @@ static void test_IUriBuilder_IUriProperty(void) { test = NULL; hr = IUriBuilder_CreateUriWithFlags(builder, 0, 0, 0, 0, &test); - todo_wine { - ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", - hr, S_OK); - } + ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", + hr, S_OK); if(SUCCEEDED(hr)) { cur_count = get_refcnt(uri); ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n", @@ -8010,9 +8104,7 @@ static void test_IUriBuilder_IUriProperty(void) { */ test = NULL; hr = IUriBuilder_CreateUriWithFlags(builder, Uri_CREATE_CANONICALIZE, 0, 0, 0, &test); - todo_wine { - ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK); - } + ok(hr == S_OK, "Error: IUriBuilder_CreateUriWithFlags returned 0x%08x, expected 0x%08x.\n", hr, S_OK); if(SUCCEEDED(hr)) { cur_count = get_refcnt(uri); ok(cur_count == orig_count+1, "Error: Expected uri ref count to be %d, but was %d instead.\n", diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c index b1304d819b6..e4a74010869 100644 --- a/dlls/urlmon/uri.c +++ b/dlls/urlmon/uri.c @@ -41,6 +41,7 @@ typedef struct { DWORD canon_size; DWORD canon_len; BOOL display_absolute; + DWORD create_flags; INT scheme_start; DWORD scheme_len; @@ -335,6 +336,31 @@ static inline BOOL is_hierarchical_scheme(URL_SCHEME type) { type == URL_SCHEME_RES); } +/* Checks if 'flags' contains an invalid combination of Uri_CREATE flags. */ +static inline BOOL has_invalid_flag_combination(DWORD flags) { + return((flags & Uri_CREATE_DECODE_EXTRA_INFO && flags & Uri_CREATE_NO_DECODE_EXTRA_INFO) || + (flags & Uri_CREATE_CANONICALIZE && flags & Uri_CREATE_NO_CANONICALIZE) || + (flags & Uri_CREATE_CRACK_UNKNOWN_SCHEMES && flags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES) || + (flags & Uri_CREATE_PRE_PROCESS_HTML_URI && flags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI) || + (flags & Uri_CREATE_IE_SETTINGS && flags & Uri_CREATE_NO_IE_SETTINGS)); +} + +/* Applies each default Uri_CREATE flags to 'flags' if it + * doesn't cause a flag conflict. + */ +static void apply_default_flags(DWORD *flags) { + if(!(*flags & Uri_CREATE_NO_CANONICALIZE)) + *flags |= Uri_CREATE_CANONICALIZE; + if(!(*flags & Uri_CREATE_NO_DECODE_EXTRA_INFO)) + *flags |= Uri_CREATE_DECODE_EXTRA_INFO; + if(!(*flags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES)) + *flags |= Uri_CREATE_CRACK_UNKNOWN_SCHEMES; + if(!(*flags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI)) + *flags |= Uri_CREATE_PRE_PROCESS_HTML_URI; + if(!(*flags & Uri_CREATE_IE_SETTINGS)) + *flags |= Uri_CREATE_NO_IE_SETTINGS; +} + /* Determines if the URI is hierarchical using the information already parsed into * data and using the current location of parsing in the URI string. * @@ -3381,6 +3407,40 @@ static void reset_builder(UriBuilder *builder) { builder->modified_props = 0; } +static HRESULT build_uri(const UriBuilder *builder, IUri **uri, DWORD create_flags, + DWORD use_orig_flags, DWORD encoding_mask) +{ + if(!uri) + return E_POINTER; + + if(encoding_mask && (!builder->uri || builder->modified_props)) { + *uri = NULL; + return E_NOTIMPL; + } + + /* Decide what flags should be used when creating the Uri. */ + if((use_orig_flags & UriBuilder_USE_ORIGINAL_FLAGS) && builder->uri) + create_flags = builder->uri->create_flags; + else { + if(has_invalid_flag_combination(create_flags)) { + *uri = NULL; + return E_INVALIDARG; + } + + /* Set the default flags if they don't cause a conflict. */ + apply_default_flags(&create_flags); + } + + /* Return the base IUri if no changes have been made and the create_flags match. */ + if(builder->uri && !builder->modified_props && builder->uri->create_flags == create_flags) { + *uri = URI(builder->uri); + IUri_AddRef(*uri); + return S_OK; + } + + return E_NOTIMPL; +} + #define URI_THIS(iface) DEFINE_THIS(Uri, IUri, iface) static HRESULT WINAPI Uri_QueryInterface(IUri *iface, REFIID riid, void **ppv) @@ -4246,11 +4306,7 @@ HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IU } /* Check for invalid flags. */ - if((dwFlags & Uri_CREATE_DECODE_EXTRA_INFO && dwFlags & Uri_CREATE_NO_DECODE_EXTRA_INFO) || - (dwFlags & Uri_CREATE_CANONICALIZE && dwFlags & Uri_CREATE_NO_CANONICALIZE) || - (dwFlags & Uri_CREATE_CRACK_UNKNOWN_SCHEMES && dwFlags & Uri_CREATE_NO_CRACK_UNKNOWN_SCHEMES) || - (dwFlags & Uri_CREATE_PRE_PROCESS_HTML_URI && dwFlags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI) || - (dwFlags & Uri_CREATE_IE_SETTINGS && dwFlags & Uri_CREATE_NO_IE_SETTINGS)) { + if(has_invalid_flag_combination(dwFlags)) { *ppURI = NULL; return E_INVALIDARG; } @@ -4266,6 +4322,9 @@ HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IU ret->lpIUriVtbl = &UriVtbl; ret->ref = 1; + /* Explicitly set the default flags if it doesn't cause a flag conflict. */ + apply_default_flags(&dwFlags); + /* Pre process the URI, unless told otherwise. */ if(!(dwFlags & Uri_CREATE_NO_PRE_PROCESS_HTML_URI)) ret->raw_uri = pre_process_uri(pwzURI); @@ -4298,6 +4357,8 @@ HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IU return hr; } + ret->create_flags = dwFlags; + *ppURI = URI(ret); return S_OK; } @@ -4436,19 +4497,13 @@ static HRESULT WINAPI UriBuilder_CreateUriSimple(IUriBuilder *iface, IUri **ppIUri) { UriBuilder *This = URIBUILDER_THIS(iface); + HRESULT hr; TRACE("(%p)->(%d %d %p)\n", This, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); - if(!ppIUri) - return E_POINTER; - - /* Acts the same way as CreateUri. */ - if(dwAllowEncodingPropertyMask && (!This->uri || This->modified_props)) { - *ppIUri = NULL; - return E_NOTIMPL; - } - - FIXME("(%p)->(%d %d %p)\n", This, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); - return E_NOTIMPL; + hr = build_uri(This, ppIUri, 0, UriBuilder_USE_ORIGINAL_FLAGS, dwAllowEncodingPropertyMask); + if(hr == E_NOTIMPL) + FIXME("(%p)->(%d %d %p)\n", This, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); + return hr; } static HRESULT WINAPI UriBuilder_CreateUri(IUriBuilder *iface, @@ -4458,22 +4513,17 @@ static HRESULT WINAPI UriBuilder_CreateUri(IUriBuilder *iface, IUri **ppIUri) { UriBuilder *This = URIBUILDER_THIS(iface); + HRESULT hr; TRACE("(%p)->(0x%08x %d %d %p)\n", This, dwCreateFlags, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); - if(!ppIUri) - return E_POINTER; + if(dwCreateFlags == -1) + hr = build_uri(This, ppIUri, 0, UriBuilder_USE_ORIGINAL_FLAGS, dwAllowEncodingPropertyMask); + else + hr = build_uri(This, ppIUri, dwCreateFlags, 0, dwAllowEncodingPropertyMask); - /* The only time it doesn't return E_NOTIMPL when the dwAllow parameter - * has flags set, is when the IUriBuilder has a IUri set and it hasn't - * been modified (a call to a "Set*" hasn't been performed). - */ - if(dwAllowEncodingPropertyMask && (!This->uri || This->modified_props)) { - *ppIUri = NULL; - return E_NOTIMPL; - } - - FIXME("(%p)->(0x%08x %d %d %p)\n", This, dwCreateFlags, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); - return E_NOTIMPL; + if(hr == E_NOTIMPL) + FIXME("(%p)->(0x%08x %d %d %p)\n", This, dwCreateFlags, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); + return hr; } static HRESULT WINAPI UriBuilder_CreateUriWithFlags(IUriBuilder *iface, @@ -4484,21 +4534,15 @@ static HRESULT WINAPI UriBuilder_CreateUriWithFlags(IUriBuilder *iface, IUri **ppIUri) { UriBuilder *This = URIBUILDER_THIS(iface); + HRESULT hr; TRACE("(%p)->(0x%08x 0x%08x %d %d %p)\n", This, dwCreateFlags, dwUriBuilderFlags, dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); - if(!ppIUri) - return E_POINTER; - - /* Same as CreateUri. */ - if(dwAllowEncodingPropertyMask && (!This->uri || This->modified_props)) { - *ppIUri = NULL; - return E_NOTIMPL; - } - - FIXME("(%p)->(0x%08x 0x%08x %d %d %p)\n", This, dwCreateFlags, dwUriBuilderFlags, - dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); - return E_NOTIMPL; + hr = build_uri(This, ppIUri, dwCreateFlags, dwUriBuilderFlags, dwAllowEncodingPropertyMask); + if(hr == E_NOTIMPL) + FIXME("(%p)->(0x%08x 0x%08x %d %d %p)\n", This, dwCreateFlags, dwUriBuilderFlags, + dwAllowEncodingPropertyMask, (DWORD)dwReserved, ppIUri); + return hr; } static HRESULT WINAPI UriBuilder_GetIUri(IUriBuilder *iface, IUri **ppIUri)