Module: wine Branch: master Commit: 4de04ce8c7695b789aee407d7204458eb12e53ea URL: http://source.winehq.org/git/wine.git/?a=commit;h=4de04ce8c7695b789aee407d72...
Author: Thomas Mullaly thomas.mullaly@gmail.com Date: Mon Jun 7 17:46:43 2010 -0400
urlmon: Added a canonicalization function for the scheme of a URI.
---
dlls/urlmon/uri.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 124 insertions(+), 2 deletions(-)
diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c index b0c6351..fc46def 100644 --- a/dlls/urlmon/uri.c +++ b/dlls/urlmon/uri.c @@ -28,8 +28,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); typedef struct { const IUriVtbl *lpIUriVtbl; LONG ref; + BSTR raw_uri;
- BSTR raw_uri; + /* Information about the canonicalized URI's buffer. */ + WCHAR *canon_uri; + DWORD canon_size; + DWORD canon_len; + + INT scheme_start; + DWORD scheme_len; + URL_SCHEME scheme_type; } Uri;
typedef struct { @@ -40,7 +48,6 @@ typedef struct { typedef struct { BSTR uri;
- BOOL is_relative;
const WCHAR *scheme; @@ -243,6 +250,109 @@ static BOOL parse_uri(parse_data *data, DWORD flags) { return TRUE; }
+/* Canonicalizes the scheme information specified in the parse_data using the specified flags. */ +static BOOL canonicalize_scheme(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) { + uri->scheme_start = -1; + uri->scheme_len = 0; + + if(!data->scheme) { + /* The only type of URI that doesn't have to have a scheme is a relative + * URI. + */ + if(!data->is_relative) { + FIXME("(%p %p %x): Unable to determine the scheme type of %s.\n", data, + uri, flags, debugstr_w(data->uri)); + return FALSE; + } + } else { + if(!computeOnly) { + DWORD i; + INT pos = uri->canon_len; + + for(i = 0; i < data->scheme_len; ++i) { + /* Scheme name must be lower case after canonicalization. */ + uri->canon_uri[i + pos] = tolowerW(data->scheme[i]); + } + + uri->canon_uri[i + pos] = ':'; + uri->scheme_start = pos; + + TRACE("(%p %p %x): Canonicalized scheme=%s, len=%d.\n", data, uri, flags, + debugstr_wn(uri->canon_uri, uri->scheme_len), data->scheme_len); + } + + /* This happens in both compute only and non-compute only. */ + uri->canon_len += data->scheme_len + 1; + uri->scheme_len = data->scheme_len; + } + return TRUE; +} + +/* Compute's what the length of the URI specified by the parse_data will be + * after canonicalization occurs using the specified flags. + * + * This function will return a non-zero value indicating the length of the canonicalized + * URI, or -1 on error. + */ +static int compute_canonicalized_length(const parse_data *data, DWORD flags) { + Uri uri; + + memset(&uri, 0, sizeof(Uri)); + + TRACE("(%p %x): Beginning to compute canonicalized length for URI %s\n", data, flags, + debugstr_w(data->uri)); + + if(!canonicalize_scheme(data, &uri, flags, TRUE)) { + ERR("(%p %x): Failed to compute URI scheme length.\n", data, flags); + return -1; + } + + TRACE("(%p %x): Finished computing canonicalized URI length. length=%d\n", data, flags, uri.canon_len); + + return uri.canon_len; +} + +/* Canonicalizes the URI data specified in the parse_data, using the given flags. If the + * canonicalization succeededs it will store all the canonicalization information + * in the pointer to the Uri. + * + * To canonicalize a URI this function first computes what the length of the URI + * specified by the parse_data will be. Once this is done it will then perfom the actual + * canonicalization of the URI. + */ +static HRESULT canonicalize_uri(const parse_data *data, Uri *uri, DWORD flags) { + INT len; + + uri->canon_uri = NULL; + len = uri->canon_size = uri->canon_len = 0; + + TRACE("(%p %p %x): beginning to canonicalize URI %s.\n", data, uri, flags, debugstr_w(data->uri)); + + /* First try to compute the length of the URI. */ + len = compute_canonicalized_length(data, flags); + if(len == -1) { + ERR("(%p %p %x): Could not compute the canonicalized length of %s.\n", data, uri, flags, + debugstr_w(data->uri)); + return E_INVALIDARG; + } + + uri->canon_uri = heap_alloc((len+1)*sizeof(WCHAR)); + if(!uri->canon_uri) + return E_OUTOFMEMORY; + + if(!canonicalize_scheme(data, uri, flags, FALSE)) { + ERR("(%p %p %x): Unable to canonicalize the scheme of the URI.\n", data, uri, flags); + heap_free(uri->canon_uri); + return E_INVALIDARG; + } + uri->scheme_type = data->scheme_type; + + uri->canon_uri[uri->canon_len] = '\0'; + TRACE("(%p %p %x): finished canonicalizing the URI.\n", data, uri, flags); + + return S_OK; +} + #define URI(x) ((IUri*) &(x)->lpIUriVtbl) #define URIBUILDER(x) ((IUriBuilder*) &(x)->lpIUriBuilderVtbl)
@@ -287,6 +397,7 @@ static ULONG WINAPI Uri_Release(IUri *iface)
if(!ref) { SysFreeString(This->raw_uri); + heap_free(This->canon_uri); heap_free(This); }
@@ -684,6 +795,7 @@ static const IUriVtbl UriVtbl = { HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IUri **ppURI) { Uri *ret; + HRESULT hr; parse_data data;
TRACE("(%s %x %x %p)\n", debugstr_w(pwzURI), dwFlags, (DWORD)dwReserved, ppURI); @@ -713,6 +825,7 @@ HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IU memset(&data, 0, sizeof(parse_data)); data.uri = ret->raw_uri;
+ /* Validate and parse the URI into it's components. */ if(!parse_uri(&data, dwFlags)) { /* Encountered an unsupported or invalid URI */ SysFreeString(ret->raw_uri); @@ -721,6 +834,15 @@ HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IU return E_INVALIDARG; }
+ /* Canonicalize the URI. */ + hr = canonicalize_uri(&data, ret, dwFlags); + if(FAILED(hr)) { + SysFreeString(ret->raw_uri); + heap_free(ret); + *ppURI = NULL; + return hr; + } + *ppURI = URI(ret); return S_OK; }