Thomas Mullaly : urlmon: Improved support for opaque file URL paths.

Alexandre Julliard julliard at winehq.org
Fri Aug 27 11:11:17 CDT 2010


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

Author: Thomas Mullaly <thomas.mullaly at gmail.com>
Date:   Thu Aug 26 13:28:19 2010 -0400

urlmon: Improved support for opaque file URL paths.

---

 dlls/urlmon/tests/uri.c |   89 ++++++++++++++++++++++++++++++++++++++++++++++-
 dlls/urlmon/uri.c       |   53 ++++++++++++++++++++++++++--
 2 files changed, 137 insertions(+), 5 deletions(-)

diff --git a/dlls/urlmon/tests/uri.c b/dlls/urlmon/tests/uri.c
index 7a7bfb1..d6bff96 100644
--- a/dlls/urlmon/tests/uri.c
+++ b/dlls/urlmon/tests/uri.c
@@ -3945,6 +3945,90 @@ static const uri_properties uri_tests[] = {
             {URL_SCHEME_FILE,S_OK,FALSE},
             {URLZONE_INVALID,E_NOTIMPL,FALSE}
         }
+    },
+    /* The '\' are still converted to '/' even though it's an opaque file URI. */
+    {   "file:c:\\dir\\../..\\index.html", 0, S_OK, FALSE,
+        Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
+        |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
+        {
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE},
+            {"file:c:/dir/../../index.html",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {".html",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE},
+            {"c:/dir/../../index.html",S_OK,FALSE},
+            {"c:/dir/../../index.html",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {"file:c:\\dir\\../..\\index.html",S_OK,FALSE},
+            {"file",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE}
+        },
+        {
+            {0,S_OK,FALSE},
+            {0,S_FALSE,FALSE},
+            {URL_SCHEME_FILE,S_OK,FALSE},
+            {URLZONE_INVALID,E_NOTIMPL,FALSE}
+        }
+    },
+    /* '/' are still converted to '\' even though it's an opaque URI. */
+    {   "file:c:/dir\\../..\\index.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
+        Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
+        |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
+        {
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE},
+            {"file:c:\\dir\\..\\..\\index.html",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {".html",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE},
+            {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
+            {"c:\\dir\\..\\..\\index.html",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {"file:c:/dir\\../..\\index.html",S_OK,FALSE},
+            {"file",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE}
+        },
+        {
+            {0,S_OK,FALSE},
+            {0,S_FALSE,FALSE},
+            {URL_SCHEME_FILE,S_OK,FALSE},
+            {URLZONE_INVALID,E_NOTIMPL,FALSE}
+        }
+    },
+    /* Forbidden characters aren't percent encoded. */
+    {   "file:c:\\in^|dex.html", Uri_CREATE_FILE_USE_DOS_PATH, S_OK, FALSE,
+        Uri_HAS_DISPLAY_URI|Uri_HAS_EXTENSION|Uri_HAS_PATH|Uri_HAS_PATH_AND_QUERY
+        |Uri_HAS_RAW_URI|Uri_HAS_SCHEME_NAME|Uri_HAS_HOST_TYPE|Uri_HAS_SCHEME, FALSE,
+        {
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE},
+            {"file:c:\\in^|dex.html",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {".html",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE},
+            {"c:\\in^|dex.html",S_OK,FALSE},
+            {"c:\\in^|dex.html",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {"file:c:\\in^|dex.html",S_OK,FALSE},
+            {"file",S_OK,FALSE},
+            {"",S_FALSE,FALSE},
+            {"",S_FALSE,FALSE}
+        },
+        {
+            {0,S_OK,FALSE},
+            {0,S_FALSE,FALSE},
+            {URL_SCHEME_FILE,S_OK,FALSE},
+            {URLZONE_INVALID,E_NOTIMPL,FALSE}
+        }
     }
 };
 
@@ -4006,7 +4090,10 @@ static const invalid_uri invalid_uri_tests[] = {
     {"\n\nhttp://google.com/",Uri_CREATE_NO_PRE_PROCESS_HTML_URI,FALSE},
     {"file://c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
     {"file://c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
-    {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE}
+    {"file://c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
+    {"file:c:\\test<test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
+    {"file:c:\\test>test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE},
+    {"file:c:\\test\"test",Uri_CREATE_FILE_USE_DOS_PATH,FALSE}
 };
 
 typedef struct _uri_equality {
diff --git a/dlls/urlmon/uri.c b/dlls/urlmon/uri.c
index 3a728f5..e2bec70 100644
--- a/dlls/urlmon/uri.c
+++ b/dlls/urlmon/uri.c
@@ -224,6 +224,10 @@ static inline BOOL is_unc_path(const WCHAR *str) {
     return (str[0] == '\\' && str[0] == '\\');
 }
 
+static inline BOOL is_forbidden_dos_path_char(WCHAR val) {
+    return (val == '>' || val == '<' || val == '\"');
+}
+
 /* A URI is implicitly a file path if it begins with
  * a drive letter (eg X:) or starts with "\\" (UNC path).
  */
@@ -1798,7 +1802,7 @@ static BOOL parse_path_hierarchical(const WCHAR **ptr, parse_data *data, DWORD f
                     return FALSE;
                 } else
                     continue;
-            } else if((**ptr == '>' || **ptr == '<' || **ptr == '\"') && is_file &&
+            } else if(is_forbidden_dos_path_char(**ptr) && is_file &&
                       (flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
                 /* File schemes with USE_DOS_PATH set aren't allowed to have
                  * a '<' or '>' or '\"' appear in them.
@@ -1849,9 +1853,13 @@ static BOOL parse_path_hierarchical(const WCHAR **ptr, parse_data *data, DWORD f
  * NOTE:
  *  Windows allows invalid % encoded data to appear in opaque URI paths
  *  for unknown scheme types.
+ *
+ *  File schemes with USE_DOS_PATH set aren't allowed to have '<', '>', or '\"'
+ *  appear in them.
  */
 static BOOL parse_path_opaque(const WCHAR **ptr, parse_data *data, DWORD flags) {
     const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
+    const BOOL is_file = data->scheme_type == URL_SCHEME_FILE;
 
     data->path = *ptr;
 
@@ -1863,6 +1871,11 @@ static BOOL parse_path_opaque(const WCHAR **ptr, parse_data *data, DWORD flags)
                 return FALSE;
             } else
                 continue;
+        } else if(is_forbidden_dos_path_char(**ptr) && is_file &&
+                  (flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
+            *ptr = data->path;
+            data->path = NULL;
+            return FALSE;
         }
 
         ++(*ptr);
@@ -2804,10 +2817,17 @@ static BOOL canonicalize_path_hierarchical(const parse_data *data, Uri *uri,
  *
  *  3)  '\\' are changed to '/' for known scheme types
  *      except for mailto schemes.
+ *
+ *  4)  For file schemes, if USE_DOS_PATH is set all '/'
+ *      are converted to backslashes.
+ *
+ *  5)  For file schemes, if USE_DOS_PATH isn't set all '\'
+ *      are converted to forward slashes.
  */
 static BOOL canonicalize_path_opaque(const parse_data *data, Uri *uri, DWORD flags, BOOL computeOnly) {
     const WCHAR *ptr;
     const BOOL known_scheme = data->scheme_type != URL_SCHEME_UNKNOWN;
+    const BOOL is_file = data->scheme_type == URL_SCHEME_FILE;
 
     if(!data->path) {
         uri->path_start = -1;
@@ -2846,11 +2866,36 @@ static BOOL canonicalize_path_opaque(const parse_data *data, Uri *uri, DWORD fla
                     uri->canon_uri[uri->canon_len] = *ptr;
                 ++uri->canon_len;
             }
+        } else if(*ptr == '/' && is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
+            if(!computeOnly)
+                uri->canon_uri[uri->canon_len] = '\\';
+            ++uri->canon_len;
+        } else if(*ptr == '\\' && is_file) {
+            if(!(flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
+                /* Convert to a '/'. */
+                if(!computeOnly)
+                    uri->canon_uri[uri->canon_len] = '/';
+                ++uri->canon_len;
+            } else {
+                /* Just copy it over. */
+                if(!computeOnly)
+                    uri->canon_uri[uri->canon_len] = *ptr;
+                ++uri->canon_len;
+            }
         } else if(known_scheme && !is_unreserved(*ptr) && !is_reserved(*ptr) &&
                   !(flags & Uri_CREATE_NO_ENCODE_FORBIDDEN_CHARACTERS)) {
-            if(!computeOnly)
-                pct_encode_val(*ptr, uri->canon_uri+uri->canon_len);
-            uri->canon_len += 3;
+            if(is_file && (flags & Uri_CREATE_FILE_USE_DOS_PATH)) {
+                /* Forbidden characters aren't percent encoded for file schemes
+                 * with USE_DOS_PATH set.
+                 */
+                if(!computeOnly)
+                    uri->canon_uri[uri->canon_len] = *ptr;
+                ++uri->canon_len;
+            } else {
+                if(!computeOnly)
+                    pct_encode_val(*ptr, uri->canon_uri+uri->canon_len);
+                uri->canon_len += 3;
+            }
         } else {
             if(!computeOnly)
                 uri->canon_uri[uri->canon_len] = *ptr;




More information about the wine-cvs mailing list