Thomas Mullaly : urlmon: Added a scheme name parser for the IUri interface.
Alexandre Julliard
julliard at winehq.org
Wed Jul 21 10:54:51 CDT 2010
Module: wine
Branch: master
Commit: 811ed515ab8791c67bc2edc6118f550b01d163e1
URL: http://source.winehq.org/git/wine.git/?a=commit;h=811ed515ab8791c67bc2edc6118f550b01d163e1
Author: Thomas Mullaly <thomas.mullaly at gmail.com>
Date: Sun Jun 6 23:39:46 2010 -0400
urlmon: Added a scheme name parser for the IUri interface.
---
dlls/urlmon/tests/uri.c | 7 ++
dlls/urlmon/uri.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 162 insertions(+), 1 deletions(-)
diff --git a/dlls/urlmon/tests/uri.c b/dlls/urlmon/tests/uri.c
index a89e5c6..ddd35d8 100644
--- a/dlls/urlmon/tests/uri.c
+++ b/dlls/urlmon/tests/uri.c
@@ -522,12 +522,19 @@ static void test_CreateUri_InvalidArgs(void) {
HRESULT hr;
IUri *uri = (void*) 0xdeadbeef;
+ const WCHAR invalidW[] = {'i','n','v','a','l','i','d',0};
+
hr = pCreateUri(http_urlW, 0, 0, NULL);
ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
hr = pCreateUri(NULL, 0, 0, &uri);
ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x\n", hr, E_INVALIDARG);
ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
+
+ uri = (void*) 0xdeadbeef;
+ hr = pCreateUri(invalidW, 0, 0, &uri);
+ ok(hr == E_INVALIDARG, "Error: CreateUri returned 0x%08x, expected 0x%08x.\n", hr, E_INVALIDARG);
+ ok(uri == NULL, "Error: Expected the IUri to be NULL, but it was %p instead\n", uri);
}
static void test_IUri_GetPropertyBSTR(void) {
diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c
index 732ec44..246eacc 100644
--- a/dlls/urlmon/uri.c
+++ b/dlls/urlmon/uri.c
@@ -20,6 +20,9 @@
#include "urlmon_main.h"
#include "wine/debug.h"
+#define NO_SHLWAPI_REG
+#include "shlwapi.h"
+
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
typedef struct {
@@ -34,6 +37,146 @@ typedef struct {
LONG ref;
} UriBuilder;
+typedef struct {
+ BSTR uri;
+
+
+ BOOL is_relative;
+
+ const WCHAR *scheme;
+ DWORD scheme_len;
+} parse_data;
+
+static inline BOOL is_alpha(WCHAR val) {
+ return ((val >= 'a' && val <= 'z') || (val >= 'A' && val <= 'Z'));
+}
+
+static inline BOOL is_num(WCHAR val) {
+ return (val >= '0' && val <= '9');
+}
+
+/* A URI is implicitly a file path if it begins with
+ * a drive letter (eg X:) or starts with "\\" (UNC path).
+ */
+static inline BOOL is_implicit_file_path(const WCHAR *str) {
+ if(is_alpha(str[0]) && str[1] == ':')
+ return TRUE;
+ else if(str[0] == '\\' && str[1] == '\\')
+ return TRUE;
+
+ return FALSE;
+}
+
+/* Tries to parse the scheme name of the URI.
+ *
+ * scheme = ALPHA *(ALPHA | NUM | '+' | '-' | '.') as defined by RFC 3896.
+ * NOTE: Windows accepts a number as the first character of a scheme.
+ */
+static BOOL parse_scheme_name(const WCHAR **ptr, parse_data *data) {
+ const WCHAR *start = *ptr;
+
+ data->scheme = NULL;
+ data->scheme_len = 0;
+
+ while(**ptr) {
+ if(!is_num(**ptr) && !is_alpha(**ptr) && **ptr != '+' &&
+ **ptr != '-' && **ptr != '.')
+ break;
+
+ (*ptr)++;
+ }
+
+ if(*ptr == start)
+ return FALSE;
+
+ /* Schemes must end with a ':' */
+ if(**ptr != ':') {
+ *ptr = start;
+ return FALSE;
+ }
+
+ data->scheme = start;
+ data->scheme_len = *ptr - start;
+
+ ++(*ptr);
+ return TRUE;
+}
+
+/* Tries to parse (or deduce) the scheme_name of a URI. If it can't
+ * parse a scheme from the URI it will try to deduce the scheme_name and scheme_type
+ * using the flags specified in 'flags' (if any). Flags that affect how this function
+ * operates are the Uri_CREATE_ALLOW_* flags.
+ *
+ * All parsed/deduced information will be stored in 'data' when the function returns.
+ *
+ * Returns TRUE if it was able to successfully parse the information.
+ */
+static BOOL parse_scheme(const WCHAR **ptr, parse_data *data, DWORD flags) {
+ static const WCHAR fileW[] = {'f','i','l','e',0};
+ static const WCHAR wildcardW[] = {'*',0};
+
+ /* First check to see if the uri could implicitly be a file path. */
+ if(is_implicit_file_path(*ptr)) {
+ if(flags & Uri_CREATE_ALLOW_IMPLICIT_FILE_SCHEME) {
+ data->scheme = fileW;
+ data->scheme_len = lstrlenW(fileW);
+ TRACE("(%p %p %x): URI is an implicit file path.\n", ptr, data, flags);
+ } else {
+ /* Window's does not consider anything that can implicitly be a file
+ * path to be a valid URI if the ALLOW_IMPLICIT_FILE_SCHEME flag is not set...
+ */
+ TRACE("(%p %p %x): URI is implicitly a file path, but, the ALLOW_IMPLICIT_FILE_SCHEME flag wasn't set.\n",
+ ptr, data, flags);
+ return FALSE;
+ }
+ } else if(!parse_scheme_name(ptr, data)) {
+ /* No Scheme was found, this means it could be:
+ * a) an implicit Wildcard scheme
+ * b) a relative URI
+ * c) a invalid URI.
+ */
+ if(flags & Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME) {
+ data->scheme = wildcardW;
+ data->scheme_len = lstrlenW(wildcardW);
+
+ TRACE("(%p %p %x): URI is an implicit wildcard scheme.\n", ptr, data, flags);
+ } else if (flags & Uri_CREATE_ALLOW_RELATIVE) {
+ data->is_relative = TRUE;
+ TRACE("(%p %p %x): URI is relative.\n", ptr, data, flags);
+ } else {
+ TRACE("(%p %p %x): Malformed URI found. Unable to deduce scheme name.\n", ptr, data, flags);
+ return FALSE;
+ }
+ }
+
+ if(!data->is_relative)
+ TRACE("(%p %p %x): Found scheme=%s scheme_len=%d\n", ptr, data, flags,
+ debugstr_wn(data->scheme, data->scheme_len), data->scheme_len);
+
+ return TRUE;
+}
+
+/* Parses and validates the components of the specified by data->uri
+ * and stores the information it parses into 'data'.
+ *
+ * Returns TRUE if it successfully parsed the URI. False otherwise.
+ */
+static BOOL parse_uri(parse_data *data, DWORD flags) {
+ const WCHAR *ptr;
+ const WCHAR **pptr;
+
+ ptr = data->uri;
+ pptr = &ptr;
+
+ TRACE("(%p %x): BEGINNING TO PARSE URI %s.\n", data, flags, debugstr_w(data->uri));
+
+ if(!parse_scheme(pptr, data, flags))
+ return FALSE;
+
+ TRACE("(%p %x): FINISHED PARSING URI.\n", data, flags);
+ return TRUE;
+}
+
#define URI(x) ((IUri*) &(x)->lpIUriVtbl)
#define URIBUILDER(x) ((IUriBuilder*) &(x)->lpIUriBuilderVtbl)
@@ -475,6 +618,7 @@ static const IUriVtbl UriVtbl = {
HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IUri **ppURI)
{
Uri *ret;
+ parse_data data;
TRACE("(%s %x %x %p)\n", debugstr_w(pwzURI), dwFlags, (DWORD)dwReserved, ppURI);
@@ -495,12 +639,22 @@ HRESULT WINAPI CreateUri(LPCWSTR pwzURI, DWORD dwFlags, DWORD_PTR dwReserved, IU
/* Create a copy of pwzURI and store it as the raw_uri. */
ret->raw_uri = SysAllocString(pwzURI);
-
if(!ret->raw_uri) {
heap_free(ret);
return E_OUTOFMEMORY;
}
+ memset(&data, 0, sizeof(parse_data));
+ data.uri = ret->raw_uri;
+
+ if(!parse_uri(&data, dwFlags)) {
+ /* Encountered an unsupported or invalid URI */
+ SysFreeString(ret->raw_uri);
+ heap_free(ret);
+ *ppURI = NULL;
+ return E_INVALIDARG;
+ }
+
*ppURI = URI(ret);
return S_OK;
}
More information about the wine-cvs
mailing list