From 6aa90a2dceb388d1b46bfc7700d219afd7bd42f5 Mon Sep 17 00:00:00 2001 From: Thomas Mullaly Date: Sun, 29 Aug 2010 17:10:10 -0400 Subject: [PATCH] urlmon: Implemented IUriBuilder_{Get/Set}Fragment. --- dlls/urlmon/tests/uri.c | 22 +++++++- dlls/urlmon/uri.c | 122 +++++++++++++++++++++++++++++++++------- 2 files changed, 121 insertions(+), 23 deletions(-) diff --git a/dlls/urlmon/tests/uri.c b/dlls/urlmon/tests/uri.c index 9206ce0c9d5..1ce6dfaf5ca 100644 --- a/dlls/urlmon/tests/uri.c +++ b/dlls/urlmon/tests/uri.c @@ -4266,7 +4266,7 @@ typedef struct _uri_builder_test { static const uri_builder_test uri_builder_tests[] = { { "http://google.com/",0,S_OK,FALSE, { - {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,TRUE}, + {TRUE,"#fragment",NULL,Uri_PROPERTY_FRAGMENT,S_OK,FALSE}, {TRUE,"password",NULL,Uri_PROPERTY_PASSWORD,S_OK,TRUE}, {TRUE,"?query=x",NULL,Uri_PROPERTY_QUERY,S_OK,TRUE}, {TRUE,"username",NULL,Uri_PROPERTY_USER_NAME,S_OK,TRUE} @@ -4295,6 +4295,24 @@ static const uri_builder_test uri_builder_tests[] = { "http://[::192.2.3.4]/",0,S_OK,TRUE, "http://[::192.2.3.4]/",0,S_OK,TRUE, "http://[::192.2.3.4]/",0,0,0,S_OK,TRUE + }, + { "http://google.com/",0,S_OK,FALSE, + { + {TRUE,"Frag","#Frag",Uri_PROPERTY_FRAGMENT,S_OK,FALSE} + }, + {FALSE}, + "http://google.com/#Frag",0,S_OK,TRUE, + "http://google.com/#Frag",0,S_OK,TRUE, + "http://google.com/#Frag",0,0,0,S_OK,TRUE + }, + { "http://google.com/",0,S_OK,FALSE, + { + {TRUE,"","#",Uri_PROPERTY_FRAGMENT,S_OK,FALSE}, + }, + {FALSE}, + "http://google.com/#",0,S_OK,TRUE, + "http://google.com/#",0,S_OK,TRUE, + "http://google.com/#",0,0,0,S_OK,TRUE } }; @@ -5819,7 +5837,7 @@ static void test_IUriBuilder_CreateInvalidArgs(void) { if(uri) IUri_Release(uri); hr = IUriBuilder_SetFragment(builder, NULL); - todo_wine { ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK); } + ok(hr == S_OK, "Error: IUriBuilder_SetFragment returned 0x%08x, expected 0x%08x.\n", hr, S_OK); /* The IUriBuilder is changed, so it returns E_NOTIMPL again. */ uri = (void*) 0xdeadbeef; diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c index 43775481da6..c6b496ba3ee 100644 --- a/dlls/urlmon/uri.c +++ b/dlls/urlmon/uri.c @@ -77,7 +77,11 @@ typedef struct { const IUriBuilderVtbl *lpIUriBuilderVtbl; LONG ref; - IUri *uri; + Uri *uri; + DWORD modified_props; + + WCHAR *fragment; + DWORD fragment_len; } UriBuilder; typedef struct { @@ -3243,6 +3247,76 @@ static HRESULT canonicalize_uri(const parse_data *data, Uri *uri, DWORD flags) { return S_OK; } +static HRESULT get_builder_component(LPWSTR *component, DWORD *component_len, + LPCWSTR source, DWORD source_len, + LPCWSTR *output, DWORD *output_len) +{ + if(!output_len) { + if(output) + *output = NULL; + return E_POINTER; + } + + if(!output) { + *output_len = 0; + return E_POINTER; + } + + if(!(*component) && source) { + /* Allocate 'component', and copy the contents from 'source' + * into the new allocation. + */ + *component = heap_alloc((source_len+1)*sizeof(WCHAR)); + if(!(*component)) + return E_OUTOFMEMORY; + + memcpy(*component, source, source_len*sizeof(WCHAR)); + (*component)[source_len] = '\0'; + *component_len = source_len; + } + + *output = *component; + *output_len = *component_len; + return *output ? S_OK : S_FALSE; +} + +/* Allocates 'component' and copies the string from 'new_value' into 'component'. + * If 'prefix' is set and 'new_value' isn't NULL, then it checks if 'new_value' + * starts with 'prefix'. If it doesn't then 'prefix' is prepended to 'component'. + */ +static HRESULT set_builder_component(LPWSTR *component, DWORD *component_len, LPCWSTR new_value, + WCHAR prefix) +{ + if(*component) + heap_free(*component); + + if(!new_value) { + *component = NULL; + *component_len = 0; + } else { + BOOL add_prefix = FALSE; + DWORD len = lstrlenW(new_value); + DWORD pos = 0; + + if(prefix && *new_value != prefix) { + add_prefix = TRUE; + *component = heap_alloc((len+2)*sizeof(WCHAR)); + } else + *component = heap_alloc((len+1)*sizeof(WCHAR)); + + if(!(*component)) + return E_OUTOFMEMORY; + + if(add_prefix) + (*component)[pos++] = prefix; + + memcpy(*component+pos, new_value, (len+1)*sizeof(WCHAR)); + *component_len = len+pos; + } + + return S_OK; +} + #define URI(x) ((IUri*) &(x)->lpIUriVtbl) #define URIBUILDER(x) ((IUriBuilder*) &(x)->lpIUriBuilderVtbl) @@ -4234,7 +4308,8 @@ static ULONG WINAPI UriBuilder_Release(IUriBuilder *iface) TRACE("(%p) ref=%d\n", This, ref); if(!ref) { - if(This->uri) IUri_Release(This->uri); + if(This->uri) IUri_Release(URI(This->uri)); + heap_free(This->fragment); heap_free(This); } @@ -4353,19 +4428,11 @@ static HRESULT WINAPI UriBuilder_GetFragment(IUriBuilder *iface, DWORD *pcchFrag UriBuilder *This = URIBUILDER_THIS(iface); TRACE("(%p)->(%p %p)\n", This, pcchFragment, ppwzFragment); - if(!pcchFragment) { - if(ppwzFragment) - *ppwzFragment = NULL; - return E_POINTER; - } - - if(!ppwzFragment) { - *pcchFragment = 0; - return E_POINTER; - } - - FIXME("(%p)->(%p %p)\n", This, pcchFragment, ppwzFragment); - return E_NOTIMPL; + if(!This->uri || This->uri->fragment_start == -1 || This->modified_props & Uri_HAS_FRAGMENT) + return get_builder_component(&This->fragment, &This->fragment_len, NULL, 0, ppwzFragment, pcchFragment); + else + return get_builder_component(&This->fragment, &This->fragment_len, This->uri->canon_uri+This->uri->fragment_start, + This->uri->fragment_len, ppwzFragment, pcchFragment); } static HRESULT WINAPI UriBuilder_GetHost(IUriBuilder *iface, DWORD *pcchHost, LPCWSTR *ppwzHost) @@ -4511,8 +4578,10 @@ static HRESULT WINAPI UriBuilder_GetUserName(IUriBuilder *iface, DWORD *pcchUser static HRESULT WINAPI UriBuilder_SetFragment(IUriBuilder *iface, LPCWSTR pwzNewValue) { UriBuilder *This = URIBUILDER_THIS(iface); - FIXME("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); - return E_NOTIMPL; + TRACE("(%p)->(%s)\n", This, debugstr_w(pwzNewValue)); + + This->modified_props |= Uri_HAS_FRAGMENT; + return set_builder_component(&This->fragment, &This->fragment_len, pwzNewValue, '#'); } static HRESULT WINAPI UriBuilder_SetHost(IUriBuilder *iface, LPCWSTR pwzNewValue) @@ -4626,16 +4695,27 @@ HRESULT WINAPI CreateIUriBuilder(IUri *pIUri, DWORD dwFlags, DWORD_PTR dwReserve if(!ppIUriBuilder) return E_POINTER; - ret = heap_alloc(sizeof(UriBuilder)); + ret = heap_alloc_zero(sizeof(UriBuilder)); if(!ret) return E_OUTOFMEMORY; ret->lpIUriBuilderVtbl = &UriBuilderVtbl; ret->ref = 1; - ret->uri = pIUri; - if(pIUri) - IUri_AddRef(pIUri); + if(pIUri) { + Uri *uri; + + if((uri = get_uri_obj(pIUri))) { + IUri_AddRef(pIUri); + ret->uri = uri; + } else { + heap_free(ret); + *ppIUriBuilder = NULL; + FIXME("(%p %x %x %p): Unknown IUri types not supported yet.\n", pIUri, dwFlags, + (DWORD)dwReserved, ppIUriBuilder); + return E_NOTIMPL; + } + } *ppIUriBuilder = URIBUILDER(ret); return S_OK;