Thomas Mullaly : urlmon: Implemented functionality for generating raw URI string of a IUriBuilder.

Alexandre Julliard julliard at winehq.org
Mon Oct 4 11:03:58 CDT 2010


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

Author: Thomas Mullaly <thomas.mullaly at gmail.com>
Date:   Wed Sep 29 16:59:30 2010 -0400

urlmon: Implemented functionality for generating raw URI string of a IUriBuilder.

---

 dlls/urlmon/uri.c |  172 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 168 insertions(+), 4 deletions(-)

diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c
index 1707429..c34c418 100644
--- a/dlls/urlmon/uri.c
+++ b/dlls/urlmon/uri.c
@@ -933,6 +933,19 @@ static DWORD ui2ipv4(WCHAR *dest, UINT address) {
     return ret;
 }
 
+static DWORD ui2str(WCHAR *dest, UINT value) {
+    static const WCHAR formatW[] = {'%','u',0};
+    DWORD ret = 0;
+
+    if(!dest) {
+        WCHAR tmp[11];
+        ret = sprintfW(tmp, formatW, value);
+    } else
+        ret = sprintfW(dest, formatW, value);
+
+    return ret;
+}
+
 /* Converts an h16 component (from an IPv6 address) into it's
  * numerical value.
  *
@@ -3847,11 +3860,14 @@ static HRESULT validate_components(const UriBuilder *builder, parse_data *data,
     if(FAILED(hr))
         return hr;
 
-    /* The URI is opaque if it doesn't have an authority component. */
-    data->is_opaque = !data->username && !data->password && !data->host;
-
     setup_port(builder, data, flags);
 
+    /* The URI is opaque if it doesn't have an authority component. */
+    if(!data->is_relative)
+        data->is_opaque = !data->username && !data->password && !data->host && !data->has_port;
+    else
+        data->is_opaque = !data->host && !data->has_port;
+
     hr = validate_path(builder, data, flags);
     if(FAILED(hr))
         return hr;
@@ -3869,11 +3885,144 @@ static HRESULT validate_components(const UriBuilder *builder, parse_data *data,
     return S_OK;
 }
 
+/* Generates a raw uri string using the parse_data. */
+static DWORD generate_raw_uri(const parse_data *data, BSTR uri) {
+    DWORD length = 0;
+
+    if(data->scheme) {
+        if(uri) {
+            memcpy(uri, data->scheme, data->scheme_len*sizeof(WCHAR));
+            uri[data->scheme_len] = ':';
+        }
+        length += data->scheme_len+1;
+    }
+
+    if(!data->is_opaque) {
+        /* For the "//" which appears before the authority component. */
+        if(uri) {
+            uri[length] = '/';
+            uri[length+1] = '/';
+        }
+        length += 2;
+    }
+
+    if(data->username) {
+        if(uri)
+            memcpy(uri+length, data->username, data->username_len*sizeof(WCHAR));
+        length += data->username_len;
+    }
+
+    if(data->password) {
+        if(uri) {
+            uri[length] = ':';
+            memcpy(uri+length+1, data->password, data->password_len*sizeof(WCHAR));
+        }
+        length += data->password_len+1;
+    }
+
+    if(data->password || data->username) {
+        if(uri)
+            uri[length] = '@';
+        ++length;
+    }
+
+    if(data->host) {
+        /* IPv6 addresses get the brackets added around them if they don't already
+         * have them.
+         */
+        const BOOL add_brackets = data->host_type == Uri_HOST_IPV6 && *(data->host) != '[';
+        if(add_brackets) {
+            if(uri)
+                uri[length] = '[';
+            ++length;
+        }
+
+        if(uri)
+            memcpy(uri+length, data->host, data->host_len*sizeof(WCHAR));
+        length += data->host_len;
+
+        if(add_brackets) {
+            if(uri)
+                uri[length] = ']';
+            length++;
+        }
+    }
+
+    if(data->has_port) {
+        /* The port isn't included in the raw uri if it's the default
+         * port for the scheme type.
+         */
+        DWORD i;
+        BOOL is_default = FALSE;
+
+        for(i = 0; i < sizeof(default_ports)/sizeof(default_ports[0]); ++i) {
+            if(data->scheme_type == default_ports[i].scheme &&
+               data->port_value == default_ports[i].port)
+                is_default = TRUE;
+        }
+
+        if(!is_default) {
+            if(uri)
+                uri[length] = ':';
+            ++length;
+
+            if(uri)
+                length += ui2str(uri+length, data->port_value);
+            else
+                length += ui2str(NULL, data->port_value);
+        }
+    }
+
+    /* Check if a '/' should be added before the path for hierarchical URIs. */
+    if(!data->is_opaque && data->path && *(data->path) != '/') {
+        if(uri)
+            uri[length] = '/';
+        ++length;
+    }
+
+    if(data->path) {
+        if(uri)
+            memcpy(uri+length, data->path, data->path_len*sizeof(WCHAR));
+        length += data->path_len;
+    }
+
+    if(data->query) {
+        if(uri)
+            memcpy(uri+length, data->query, data->query_len*sizeof(WCHAR));
+        length += data->query_len;
+    }
+
+    if(data->fragment) {
+        if(uri)
+            memcpy(uri+length, data->fragment, data->fragment_len*sizeof(WCHAR));
+        length += data->fragment_len;
+    }
+
+    if(uri)
+        TRACE("(%p %p): Generated raw uri=%s len=%d\n", data, uri, debugstr_wn(uri, length), length);
+    else
+        TRACE("(%p %p): Computed raw uri len=%d\n", data, uri, length);
+
+    return length;
+}
+
+static HRESULT generate_uri(const UriBuilder *builder, const parse_data *data, Uri *uri, DWORD flags) {
+    DWORD length = generate_raw_uri(data, NULL);
+    uri->raw_uri = SysAllocStringLen(NULL, length);
+    if(!uri->raw_uri)
+        return E_OUTOFMEMORY;
+
+    generate_raw_uri(data, uri->raw_uri);
+
+    return E_NOTIMPL;
+}
+
 static HRESULT build_uri(const UriBuilder *builder, IUri **uri, DWORD create_flags,
                          DWORD use_orig_flags, DWORD encoding_mask)
 {
     HRESULT hr;
     parse_data data;
+    Uri *ret;
 
     if(!uri)
         return E_POINTER;
@@ -3909,7 +4058,22 @@ static HRESULT build_uri(const UriBuilder *builder, IUri **uri, DWORD create_fla
         return hr;
     }
 
-    return E_NOTIMPL;
+    ret = heap_alloc_zero(sizeof(Uri));
+    if(!ret) {
+        *uri = NULL;
+        return E_OUTOFMEMORY;
+    }
+
+    hr = generate_uri(builder, &data, ret, create_flags);
+    if(FAILED(hr)) {
+        SysFreeString(ret->raw_uri);
+        heap_free(ret->canon_uri);
+        heap_free(ret);
+        *uri = NULL;
+        return hr;
+    }
+
+    return S_OK;
 }
 
 #define URI_THIS(iface) DEFINE_THIS(Uri, IUri, iface)




More information about the wine-cvs mailing list