From 1a56a73c861f4e137119f1de86c41d0098fa2e40 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 21 Sep 2012 12:28:18 +0200 Subject: [PATCH] itss: Canonicalize relative paths before resolving object. --- dlls/itss/protocol.c | 51 ++++++++++++++++++++++++++++++++++++++ dlls/itss/tests/protocol.c | 3 +++ 2 files changed, 54 insertions(+) diff --git a/dlls/itss/protocol.c b/dlls/itss/protocol.c index fa2ad8bd5af..6b188c6c368 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 b7185025d65..7467d37ed20 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); }