Thomas Mullaly : urlmon: Added a canonicalization function for the scheme of a URI.

Alexandre Julliard julliard at winehq.org
Wed Jul 21 10:54:51 CDT 2010


Module: wine
Branch: master
Commit: 4de04ce8c7695b789aee407d7204458eb12e53ea
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=4de04ce8c7695b789aee407d7204458eb12e53ea

Author: Thomas Mullaly <thomas.mullaly at 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;
 }




More information about the wine-cvs mailing list