Module: wine Branch: master Commit: 3f644cb0bfdba11432f730c9cd1fb95cdb63c4b7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=3f644cb0bfdba11432f730c9cd...
Author: Jacek Caban jacek@codeweavers.com Date: Wed Feb 1 11:22:39 2017 +0100
inetcomm: Added IInternetProtocolInfo::CombineUrl implementation.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/inetcomm/protocol.c | 74 ++++++++++++++++++++++++++++++++++++-- dlls/inetcomm/tests/mimeole.c | 83 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 154 insertions(+), 3 deletions(-)
diff --git a/dlls/inetcomm/protocol.c b/dlls/inetcomm/protocol.c index f6600b9..300c139 100644 --- a/dlls/inetcomm/protocol.c +++ b/dlls/inetcomm/protocol.c @@ -24,6 +24,7 @@ #include "inetcomm_private.h"
#include "wine/debug.h" +#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(inetcomm);
@@ -36,6 +37,39 @@ typedef struct { IUnknown *outer_unk; } MimeHtmlProtocol;
+typedef struct { + const WCHAR *mhtml; + size_t mhtml_len; + const WCHAR *location; +} mhtml_url_t; + +static const WCHAR mhtml_prefixW[] = {'m','h','t','m','l',':'}; +static const WCHAR mhtml_separatorW[] = {'!','x','-','u','s','c',':'}; + +static HRESULT parse_mhtml_url(const WCHAR *url, mhtml_url_t *r) +{ + const WCHAR *p; + + if(strncmpiW(url, mhtml_prefixW, sizeof(mhtml_prefixW)/sizeof(WCHAR))) + return E_FAIL; + + r->mhtml = url + sizeof(mhtml_prefixW)/sizeof(WCHAR); + p = strchrW(r->mhtml, '!'); + if(p) { + r->mhtml_len = p - r->mhtml; + /* FIXME: We handle '!' and '!x-usc:' in URLs as the same thing. Those should not be the same. */ + if(!strncmpW(p, mhtml_separatorW, sizeof(mhtml_separatorW)/sizeof(WCHAR))) + p += sizeof(mhtml_separatorW)/sizeof(WCHAR); + else + p++; + }else { + r->mhtml_len = strlenW(r->mhtml); + } + + r->location = p; + return S_OK; +} + static inline MimeHtmlProtocol *impl_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, MimeHtmlProtocol, IUnknown_inner); @@ -247,10 +281,46 @@ static HRESULT WINAPI MimeHtmlProtocolInfo_CombineUrl(IInternetProtocolInfo *ifa DWORD cchResult, DWORD* pcchResult, DWORD dwReserved) { MimeHtmlProtocol *This = impl_from_IInternetProtocolInfo(iface); - FIXME("(%p)->(%s %s %08x %p %d %p %d)\n", This, debugstr_w(pwzBaseUrl), + size_t len = sizeof(mhtml_prefixW)/sizeof(WCHAR); + mhtml_url_t url; + WCHAR *p; + HRESULT hres; + + TRACE("(%p)->(%s %s %08x %p %d %p %d)\n", This, debugstr_w(pwzBaseUrl), debugstr_w(pwzRelativeUrl), dwCombineFlags, pwzResult, cchResult, pcchResult, dwReserved); - return E_NOTIMPL; + + hres = parse_mhtml_url(pwzBaseUrl, &url); + if(FAILED(hres)) + return hres; + + if(!strncmpiW(pwzRelativeUrl, mhtml_prefixW, sizeof(mhtml_prefixW)/sizeof(WCHAR))) { + FIXME("Relative URL is mhtml protocol\n"); + return INET_E_USE_DEFAULT_PROTOCOLHANDLER; + } + + len += url.mhtml_len; + if(*pwzRelativeUrl) + len += strlenW(pwzRelativeUrl) + sizeof(mhtml_separatorW)/sizeof(WCHAR); + if(len >= cchResult) { + *pcchResult = 0; + return E_FAIL; + } + + memcpy(pwzResult, mhtml_prefixW, sizeof(mhtml_prefixW)); + p = pwzResult + sizeof(mhtml_prefixW)/sizeof(WCHAR); + memcpy(p, url.mhtml, url.mhtml_len*sizeof(WCHAR)); + p += url.mhtml_len; + if(*pwzRelativeUrl) { + memcpy(p, mhtml_separatorW, sizeof(mhtml_separatorW)); + p += sizeof(mhtml_separatorW)/sizeof(WCHAR); + strcpyW(p, pwzRelativeUrl); + }else { + *p = 0; + } + + *pcchResult = len; + return S_OK; }
static HRESULT WINAPI MimeHtmlProtocolInfo_CompareUrl(IInternetProtocolInfo *iface, LPCWSTR pwzUrl1, diff --git a/dlls/inetcomm/tests/mimeole.c b/dlls/inetcomm/tests/mimeole.c index fe19893..3f07adc 100644 --- a/dlls/inetcomm/tests/mimeole.c +++ b/dlls/inetcomm/tests/mimeole.c @@ -27,6 +27,7 @@ #include "ocidl.h"
#include "mimeole.h" +#include "wininet.h"
#include <stdio.h>
@@ -1161,15 +1162,91 @@ static void test_MimeOleGetPropertySchema(void) IMimePropertySchema_Release(schema); }
+static const struct { + const char *base_url; + const char *relative_url; + const char *expected_result; + BOOL todo; +} combine_tests[] = { + { + "mhtml:file:///c:/dir/test.mht", "http://test.org", + "mhtml:file:///c:/dir/test.mht!x-usc:http://test.org" + }, { + "mhtml:file:///c:/dir/test.mht", "3D"http://test.org%5C"", + "mhtml:file:///c:/dir/test.mht!x-usc:3D"http://test.org%5C"" + }, { + "mhtml:file:///c:/dir/test.mht", "123abc", + "mhtml:file:///c:/dir/test.mht!x-usc:123abc" + }, { + "mhtml:file:///c:/dir/test.mht!x-usc:http://test.org", "123abc", + "mhtml:file:///c:/dir/test.mht!x-usc:123abc" + }, { + "MhtMl:file:///c:/dir/test.mht!x-usc:http://test.org/dir/dir2/file.html", "../..", + "mhtml:file:///c:/dir/test.mht!x-usc:../.." + }, {"mhtml:file:///c:/dir/test.mht!x-usc:file:///c:/dir/dir2/file.html", "../..", + "mhtml:file:///c:/dir/test.mht!x-usc:../.." + }, { + "mhtml:file:///c:/dir/test.mht!x-usc:http://test.org", "", + "mhtml:file:///c:/dir/test.mht" + }, { + "mhtml:file:///c:/dir/test.mht!x-usc:http://test.org", "mhtml:file:///d:/file.html", + "file:///d:/file.html", TRUE + }, { + "mhtml:file:///c:/dir/test.mht!x-usc:http://test.org", "mhtml:file:///c:/dir2/test.mht!x-usc:http://test.org", + "mhtml:file:///c:/dir2/test.mht!x-usc:http://test.org", TRUE + }, { + "mhtml:file:///c:/dir/test.mht!http://test.org", "123abc", + "mhtml:file:///c:/dir/test.mht!x-usc:123abc" + }, { + "mhtml:file:///c:/dir/test.mht!http://test.org", "", + "mhtml:file:///c:/dir/test.mht" + } +}; + static void test_mhtml_protocol_info(void) { + WCHAR *base_url, *relative_url, combined_url[INTERNET_MAX_URL_LENGTH]; IInternetProtocolInfo *protocol_info; + DWORD combined_len; + unsigned i, exlen; HRESULT hres;
+ static const WCHAR http_url[] = {'h','t','t','p',':','/','/','t','e','s','t','.','o','r','g',0}; + hres = CoCreateInstance(&CLSID_IMimeHtmlProtocol, NULL, CLSCTX_INPROC_SERVER, &IID_IInternetProtocolInfo, (void**)&protocol_info); ok(hres == S_OK, "Could not create protocol info: %08x\n", hres);
+ for(i = 0; i < sizeof(combine_tests)/sizeof(*combine_tests); i++) { + base_url = a2w(combine_tests[i].base_url); + relative_url = a2w(combine_tests[i].relative_url); + + combined_len = 0xdeadbeef; + hres = IInternetProtocolInfo_CombineUrl(protocol_info, base_url, relative_url, ICU_BROWSER_MODE, + combined_url, sizeof(combined_url)/sizeof(WCHAR), &combined_len, 0); + todo_wine_if(combine_tests[i].todo) + ok(hres == S_OK, "[%u] CombineUrl failed: %08x\n", i, hres); + if(SUCCEEDED(hres)) { + exlen = strlen(combine_tests[i].expected_result); + ok(combined_len == exlen, "[%u] combined len is %u, expected %u\n", i, combined_len, exlen); + ok(!strcmp_wa(combined_url, combine_tests[i].expected_result), "[%u] combined URL is %s, expected %s\n", + i, wine_dbgstr_w(combined_url), combine_tests[i].expected_result); + + combined_len = 0xdeadbeef; + hres = IInternetProtocolInfo_CombineUrl(protocol_info, base_url, relative_url, ICU_BROWSER_MODE, + combined_url, exlen, &combined_len, 0); + ok(hres == E_FAIL, "[%u] CombineUrl returned: %08x\n", i, hres); + ok(!combined_len, "[%u] combined_len = %u\n", i, combined_len); + } + + HeapFree(GetProcessHeap(), 0, base_url); + HeapFree(GetProcessHeap(), 0, relative_url); + } + + hres = IInternetProtocolInfo_CombineUrl(protocol_info, http_url, http_url, ICU_BROWSER_MODE, + combined_url, sizeof(combined_url)/sizeof(WCHAR), &combined_len, 0); + ok(hres == E_FAIL, "CombineUrl failed: %08x\n", hres); + IInternetProtocolInfo_Release(protocol_info); }
@@ -1195,6 +1272,8 @@ static const IUnknownVtbl outer_vtbl = { outer_Release };
+static BOOL broken_mhtml_resolver; + static void test_mhtml_protocol(void) { IUnknown outer = { &outer_vtbl }; @@ -1225,7 +1304,8 @@ static void test_mhtml_protocol(void)
IClassFactory_Release(class_factory);
- test_mhtml_protocol_info(); + if(!broken_mhtml_resolver) + test_mhtml_protocol_info(); }
static void test_MimeOleObjectFromMoniker(void) @@ -1261,6 +1341,7 @@ static void test_MimeOleObjectFromMoniker(void) IBindCtx_Release(bind_ctx); if(hres == INET_E_RESOURCE_NOT_FOUND) { /* winxp */ win_skip("Broken MHTML behaviour found. Skipping some tests.\n"); + broken_mhtml_resolver = TRUE; return; }