Jacek Caban : itss: Canonicalize relative paths before resolving object.

Alexandre Julliard julliard at winehq.org
Fri Sep 21 14:22:40 CDT 2012


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

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Sep 21 12:28:18 2012 +0200

itss: Canonicalize relative paths before resolving object.

---

 dlls/itss/protocol.c       |   51 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/itss/tests/protocol.c |    3 ++
 2 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/dlls/itss/protocol.c b/dlls/itss/protocol.c
index fa2ad8b..6b188c6 100644
--- a/dlls/itss/protocol.c
+++ b/dlls/itss/protocol.c
@@ -134,6 +134,55 @@ static LPCWSTR skip_schema(LPCWSTR url)
     return NULL;
 }
 
+/* Adopted from urlmon */
+static void remove_dot_segments(WCHAR *path) {
+    const WCHAR *in = path;
+    WCHAR *out = path;
+
+    while(1) {
+        /* Move the first path segment in the input buffer to the end of
+         * the output buffer, and any subsequent characters up to, including
+         * the next "/" character (if any) or the end of the input buffer.
+         */
+        while(*in != '/') {
+            if(!(*out++ = *in++))
+                return;
+        }
+
+        *out++ = *in++;
+
+        while(*in) {
+            if(*in != '.')
+                break;
+
+            /* Handle ending "/." */
+            if(!in[1]) {
+                ++in;
+                break;
+            }
+
+            /* Handle "/./" */
+            if(in[1] == '/') {
+                in += 2;
+                continue;
+            }
+
+            /* If we don't have "/../" or ending "/.." */
+            if(in[1] != '.' || (in[2] && in[2] != '/'))
+                break;
+
+            in += *in ? 3 : 2;
+
+            /* Find the slash preceding out pointer and move out pointer to it */
+            if(out > path+1 && *--out == '/')
+                --out;
+            while(out > path && *(--out) != '/');
+            if(*out == '/')
+                ++out;
+        }
+    }
+}
+
 static HRESULT report_result(IInternetProtocolSink *sink, HRESULT hres)
 {
     IInternetProtocolSink_ReportResult(sink, hres, 0, NULL);
@@ -215,6 +264,8 @@ static HRESULT WINAPI ITSProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
             *p = '/';
     }
 
+    remove_dot_segments(object_name);
+
     TRACE("Resolving %s\n", debugstr_w(object_name));
 
     memset(&chm_object, 0, sizeof(chm_object));
diff --git a/dlls/itss/tests/protocol.c b/dlls/itss/tests/protocol.c
index b718502..7467d37 100644
--- a/dlls/itss/tests/protocol.c
+++ b/dlls/itss/tests/protocol.c
@@ -87,6 +87,8 @@ static const WCHAR blank_url7[] = {'m','k',':','@','M','S','I','T','S','t','o','
     't','e','s','t','.','c','h','m',':',':','\\','b','l','a','n','k','.','h','t','m','l',0};
 static const WCHAR blank_url8[] = {'m','k',':','@','M','S','I','T','S','t','o','r','e',':',
     't','e','s','t','.','c','h','m',':',':','/','b','l','a','n','k','.','h','t','m','l','/',0};
+static const WCHAR blank_url9[] = {'i','t','s',':',
+    't','e','s','t','.','c','h','m',':',':','/','d','i','r','/','.','.','/','b','l','a','n','k','.','h','t','m','l',0};
 
 static enum {
     ITS_PROTOCOL,
@@ -612,6 +614,7 @@ static void test_its_protocol(void)
             test_protocol_url(factory, blank_url5, TRUE);
             test_protocol_url(factory, blank_url6, TRUE);
             test_protocol_url(factory, blank_url8, TRUE);
+            test_protocol_url(factory, blank_url9, TRUE);
             bindf = BINDF_FROMURLMON | BINDF_NEEDFILE;
             test_protocol_url(factory, blank_url1, TRUE);
         }




More information about the wine-cvs mailing list