[1/3] winebrowser: Manually percent-encode file: paths for unix filenames.

Vincent Povirk madewokherd at gmail.com
Tue Jul 1 15:42:41 CDT 2014


For bug 32651.

We really need to percent-encode each extended byte individually in
the Unix filename. Urlmon has no knowledge of the Unix filesystem
encoding, so it can't possibly do this correctly given a WCHAR string.

Another possibility would be to pad the 8-bit characters with 0's to
create the WCHAR string to pass to urlmon. This would probably work in
Wine for now, but in my testing I couldn't get native urlmon to encode
non-ascii characters in file uri's at all.

I couldn't find any definitive information on which reserved
characters needed to be encoded in file: uri's, so to build the
safe_chars list I made a file with a name containing all the legal
windows filename characters that are also reserved characters in
uri's. Anything firefox didn't encode when opening the file went in
the list.
-------------- next part --------------
From 401f2af9a7d40b5c54b103264d70ae08dec0f7cd Mon Sep 17 00:00:00 2001
From: Vincent Povirk <vincent at codeweavers.com>
Date: Fri, 27 Jun 2014 15:44:32 -0500
Subject: [PATCH 1/3] winebrowser: Manually percent-encode file: paths for unix
 filenames.

---
 programs/winebrowser/main.c | 60 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 54 insertions(+), 6 deletions(-)

diff --git a/programs/winebrowser/main.c b/programs/winebrowser/main.c
index 22f3a93..f7a59fc 100644
--- a/programs/winebrowser/main.c
+++ b/programs/winebrowser/main.c
@@ -309,6 +309,59 @@ done:
     return ret;
 }
 
+static WCHAR *encode_unix_path(const char *src)
+{
+    int len = 1;
+    const char *tmp_src;
+    WCHAR *dst, *tmp_dst;
+    const char safe_chars[] = "/-_.~@&=+$,:";
+    const char hex_digits[] = "0123456789ABCDEF";
+
+    tmp_src = src;
+
+    while (*tmp_src != 0)
+    {
+        if ((*tmp_src >= 'a' && *tmp_src <= 'z') ||
+            (*tmp_src >= 'A' && *tmp_src <= 'Z') ||
+            (*tmp_src >= '0' && *tmp_src <= '9') ||
+            strchr(safe_chars, *tmp_src))
+            len += 1;
+        else
+            len += 3;
+        tmp_src++;
+    }
+
+    dst = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
+
+    if (!dst)
+        return NULL;
+
+    tmp_src = src;
+    tmp_dst = dst;
+
+    while (*tmp_src != 0)
+    {
+        if ((*tmp_src >= 'a' && *tmp_src <= 'z') ||
+            (*tmp_src >= 'A' && *tmp_src <= 'Z') ||
+            (*tmp_src >= '0' && *tmp_src <= '9') ||
+            strchr(safe_chars, *tmp_src))
+        {
+            *tmp_dst++ = *tmp_src;
+        }
+        else
+        {
+            *tmp_dst++ = '%';
+            *tmp_dst++ = hex_digits[*(unsigned char*)(tmp_src) / 16];
+            *tmp_dst++ = hex_digits[*tmp_src & 0xf];
+        }
+        tmp_src++;
+    }
+
+    *tmp_dst = 0;
+    
+    return dst;
+}
+
 static IUri *convert_file_uri(IUri *uri)
 {
     wine_get_unix_file_name_t wine_get_unix_file_name_ptr;
@@ -333,12 +386,7 @@ static IUri *convert_file_uri(IUri *uri)
     unixpath = wine_get_unix_file_name_ptr(filename);
     SysFreeString(filename);
     if(unixpath && stat(unixpath, &dummy) >= 0) {
-        int len;
-
-        len = MultiByteToWideChar(CP_UNIXCP, 0, unixpath, -1, NULL, 0);
-        new_path = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
-        if(new_path)
-            MultiByteToWideChar(CP_UNIXCP, 0, unixpath, -1, new_path, len);
+        new_path = encode_unix_path(unixpath);
         HeapFree(GetProcessHeap(), 0, unixpath);
     }else {
         WINE_WARN("File %s does not exist\n", wine_dbgstr_a(unixpath));
-- 
1.8.3.2



More information about the wine-patches mailing list