static void test_UrlUnescape(void) { CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH]; WCHAR ret_urlW[INTERNET_MAX_URL_LENGTH]; WCHAR *urlW, *expected_urlW; DWORD dwEscaped; size_t i; static char inplace[] = "file:///C:/Program%20Files"; static WCHAR inplaceW[] = {'f','i','l','e',':','/','/','/','C',':','/', 'P','r','o','g','r','a','m','%','2','0','F','i','l','e','s',0}; for(i=0; i<sizeof(TEST_URL_UNESCAPE)/sizeof(TEST_URL_UNESCAPE[0]); i++) { dwEscaped=INTERNET_MAX_URL_LENGTH; ok(UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, &dwEscaped, 0) == S_OK, "UrlUnescapeA didn't return 0x%08x from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url); ok(strcmp(szReturnUrl,TEST_URL_UNESCAPE[i].expect)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url); dwEscaped = INTERNET_MAX_URL_LENGTH; urlW = GetWideString(TEST_URL_UNESCAPE[i].url); expected_urlW = GetWideString(TEST_URL_UNESCAPE[i].expect); ok(UrlUnescapeW(urlW, ret_urlW, &dwEscaped, 0) == S_OK, "UrlUnescapeW didn't return 0x%08x from \"%s\"\n", S_OK, TEST_URL_UNESCAPE[i].url); WideCharToMultiByte(CP_ACP,0,ret_urlW,-1,szReturnUrl,INTERNET_MAX_URL_LENGTH,0,0); ok(lstrcmpW(ret_urlW, expected_urlW)==0, "Expected \"%s\", but got \"%s\" from \"%s\" flags %08lx\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url, 0L); FreeWideString(urlW); FreeWideString(expected_urlW); } dwEscaped = sizeof(inplace); ok(UrlUnescapeA(inplace, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeA failed unexpectedly\n"); dwEscaped = sizeof(inplaceW); ok(UrlUnescapeW(inplaceW, NULL, &dwEscaped, URL_UNESCAPE_INPLACE) == S_OK, "UrlUnescapeW failed unexpectedly\n"); }
static HRESULT parse_encode(LPCWSTR url, DWORD flags, LPWSTR result, DWORD size, DWORD *rsize) { IInternetProtocolInfo *protocol_info; DWORD prsize; HRESULT hres; TRACE("(%s %08x %p %d %p)\n", debugstr_w(url), flags, result, size, rsize); protocol_info = get_protocol_info(url); if(protocol_info) { hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_ENCODE, flags, result, size, rsize, 0); IInternetProtocolInfo_Release(protocol_info); if(SUCCEEDED(hres)) return hres; } prsize = size; hres = UrlUnescapeW((LPWSTR)url, result, &prsize, flags); if(rsize) *rsize = prsize; return hres; }
HRESULT UrlCanonicalizeUnescape(LPCWSTR pszUrl, LPWSTR pszCanonicalized, LPDWORD pcchCanonicalized, DWORD dwFlags) { HRESULT hr = S_OK; DWORD dwSize; WCHAR wzCanonical[MAX_URL_LENGTH]; if (UrlIsW(pszUrl, URLIS_FILEURL) || !PathIsURLW(pszUrl)) { dwSize = MAX_URL_LENGTH; hr = UrlCanonicalizeW(pszUrl, wzCanonical, &dwSize, dwFlags); if (FAILED(hr)) { goto Exit; } hr = UrlUnescapeW(wzCanonical, pszCanonicalized, pcchCanonicalized, 0); if (FAILED(hr)) { goto Exit; } } else { hr = UrlCanonicalizeW(pszUrl, pszCanonicalized, pcchCanonicalized, dwFlags /*| URL_ESCAPE_PERCENT*/); } Exit: return hr; }
HRESULT UrlCombineUnescape(LPCWSTR pszBase, LPCWSTR pszRelative, LPWSTR pszCombined, LPDWORD pcchCombined, DWORD dwFlags) { HRESULT hr = S_OK; DWORD dwSize; LPWSTR pwzCombined = NULL; LPWSTR pwzFileCombined = NULL; pwzCombined = NEW(WCHAR[MAX_URL_LENGTH]); if (!pwzCombined) { hr = E_OUTOFMEMORY; goto Exit; } // If we're just combining an absolute file path to an relative file // path, do this by concatenating the strings, and canonicalizing it. // This avoids UrlCombine randomness where you could end up with // a partially escaped (and partially unescaped) resulting URL! if (!PathIsURLW(pszBase) && PathIsRelativeWrap(pszRelative)) { pwzFileCombined = NEW(WCHAR[MAX_URL_LENGTH]); if (!pwzFileCombined) { hr = E_OUTOFMEMORY; goto Exit; } wnsprintfW(pwzFileCombined, MAX_URL_LENGTH, L"%ws%ws", pszBase, pszRelative); hr = UrlCanonicalizeUnescape(pwzFileCombined, pszCombined, pcchCombined, 0); goto Exit; } else { dwSize = MAX_URL_LENGTH; hr = UrlCombineW(pszBase, pszRelative, pwzCombined, &dwSize, dwFlags); if (FAILED(hr)) { goto Exit; } } // Don't unescape if the relative part was already an URL because // URLs wouldn't have been escaped during the UrlCombined. if (UrlIsW(pwzCombined, URLIS_FILEURL)) { hr = UrlUnescapeW(pwzCombined, pszCombined, pcchCombined, 0); if (FAILED(hr)) { goto Exit; } } else { if (*pcchCombined >= dwSize) { lstrcpyW(pszCombined, pwzCombined); } *pcchCombined = dwSize; } Exit: SAFEDELETEARRAY(pwzCombined); SAFEDELETEARRAY(pwzFileCombined); return hr; }
void UnescapeUrl(std::wstring& url) { try { DWORD result_length = INTERNET_MAX_URL_LENGTH; std::unique_ptr<wchar_t[]> result(new wchar_t[result_length]); HRESULT hr = UrlUnescapeW(const_cast<wchar_t*>(url.c_str()), result.get(), &result_length, 0); if (hr == S_OK) { url = std::wstring(result.get(), result_length); } /* * Do nothing. This masks error return values from UrlUnescape without logging the error. */ } catch(std::bad_alloc e) { /* * When the code has a systematic way of handling bad_alloc, we'll rethrow (probably). * Until then, we mask the exception and make no modification. */ } catch(...) { // no modification if any other exception } }
/* Helper function to add a file to a job. The helper function takes base file name and creates properly formed path and URL strings for creation of the file. */ static HRESULT addFileHelper(IBackgroundCopyJob* job, const WCHAR *localName, const WCHAR *remoteName) { DWORD urlSize; WCHAR localFile[MAX_PATH]; WCHAR remoteUrl[MAX_PATH]; WCHAR remoteFile[MAX_PATH]; GetCurrentDirectoryW(MAX_PATH, localFile); PathAppendW(localFile, localName); GetCurrentDirectoryW(MAX_PATH, remoteFile); PathAppendW(remoteFile, remoteName); urlSize = MAX_PATH; UrlCreateFromPathW(remoteFile, remoteUrl, &urlSize, 0); UrlUnescapeW(remoteUrl, NULL, &urlSize, URL_UNESCAPE_INPLACE); return IBackgroundCopyJob_AddFile(test_job, remoteUrl, localFile); }
static HRESULT WINAPI ITSProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) { ITSProtocol *This = impl_from_IInternetProtocol(iface); BINDINFO bindinfo; DWORD bindf = 0, len; LPWSTR file_name, mime, object_name, p; LPCWSTR ptr; struct chmFile *chm_file; struct chmUnitInfo chm_object; int res; HRESULT hres; static const WCHAR separator[] = {':',':',0}; TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); ptr = skip_schema(szUrl); if(!ptr) return INET_E_USE_DEFAULT_PROTOCOLHANDLER; memset(&bindinfo, 0, sizeof(bindinfo)); bindinfo.cbSize = sizeof(BINDINFO); hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo); if(FAILED(hres)) { WARN("GetBindInfo failed: %08x\n", hres); return hres; } ReleaseBindInfo(&bindinfo); len = strlenW(ptr)+3; file_name = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); memcpy(file_name, ptr, len*sizeof(WCHAR)); hres = UrlUnescapeW(file_name, NULL, &len, URL_UNESCAPE_INPLACE); if(FAILED(hres)) { WARN("UrlUnescape failed: %08x\n", hres); HeapFree(GetProcessHeap(), 0, file_name); return hres; } p = strstrW(file_name, separator); if(!p) { WARN("invalid url\n"); HeapFree(GetProcessHeap(), 0, file_name); return report_result(pOIProtSink, STG_E_FILENOTFOUND); } *p = 0; chm_file = chm_openW(file_name); if(!chm_file) { WARN("Could not open chm file\n"); HeapFree(GetProcessHeap(), 0, file_name); return report_result(pOIProtSink, STG_E_FILENOTFOUND); } object_name = p+2; len = strlenW(object_name); if(*object_name != '/' && *object_name != '\\') { memmove(object_name+1, object_name, (len+1)*sizeof(WCHAR)); *object_name = '/'; len++; } if(object_name[len-1] == '/') object_name[--len] = 0; for(p=object_name; *p; p++) { if(*p == '\\') *p = '/'; } remove_dot_segments(object_name); TRACE("Resolving %s\n", debugstr_w(object_name)); memset(&chm_object, 0, sizeof(chm_object)); res = chm_resolve_object(chm_file, object_name, &chm_object); if(res != CHM_RESOLVE_SUCCESS) { WARN("Could not resolve chm object\n"); HeapFree(GetProcessHeap(), 0, file_name); chm_close(chm_file); return report_result(pOIProtSink, STG_E_FILENOTFOUND); } IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, strrchrW(object_name, '/')+1); /* FIXME: Native doesn't use FindMimeFromData */ hres = FindMimeFromData(NULL, object_name, NULL, 0, NULL, 0, &mime, 0); HeapFree(GetProcessHeap(), 0, file_name); if(SUCCEEDED(hres)) { IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime); CoTaskMemFree(mime); } release_chm(This); /* Native leaks handle here */ This->chm_file = chm_file; This->chm_object = chm_object; hres = IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION|BSCF_DATAFULLYAVAILABLE, chm_object.length, chm_object.length); if(FAILED(hres)) { WARN("ReportData failed: %08x\n", hres); release_chm(This); return report_result(pOIProtSink, hres); } hres = IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_BEGINDOWNLOADDATA, NULL); return report_result(pOIProtSink, hres); }
static HRESULT WINAPI MkProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE *dwReserved) { MkProtocol *This = impl_from_IInternetProtocolEx(iface); LPWSTR mime, progid, display_name, colon_ptr; DWORD bindf=0, eaten=0, scheme=0, len; BSTR url, path = NULL; IParseDisplayName *pdn; BINDINFO bindinfo; STATSTG statstg; IMoniker *mon; HRESULT hres; CLSID clsid; TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved); hres = IUri_GetScheme(pUri, &scheme); if(FAILED(hres)) return hres; if(scheme != URL_SCHEME_MK) return INET_E_INVALID_URL; memset(&bindinfo, 0, sizeof(bindinfo)); bindinfo.cbSize = sizeof(BINDINFO); hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo); if(FAILED(hres)) { WARN("GetBindInfo failed: %08x\n", hres); return hres; } ReleaseBindInfo(&bindinfo); IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, NULL); hres = IUri_GetDisplayUri(pUri, &url); if(FAILED(hres)) return hres; hres = FindMimeFromData(NULL, url, NULL, 0, NULL, 0, &mime, 0); SysFreeString(url); if(SUCCEEDED(hres)) { IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime); CoTaskMemFree(mime); } hres = IUri_GetPath(pUri, &path); if(FAILED(hres)) return hres; len = SysStringLen(path)+1; hres = UrlUnescapeW(path, NULL, &len, URL_UNESCAPE_INPLACE); if (FAILED(hres)) { SysFreeString(path); return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, ERROR_INVALID_PARAMETER); } progid = path+1; /* skip '@' symbol */ colon_ptr = strchrW(path, ':'); if(!colon_ptr) { SysFreeString(path); return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, ERROR_INVALID_PARAMETER); } len = strlenW(path); display_name = heap_alloc((len+1)*sizeof(WCHAR)); memcpy(display_name, path, (len+1)*sizeof(WCHAR)); progid[colon_ptr-progid] = 0; /* overwrite ':' with NULL terminator */ hres = CLSIDFromProgID(progid, &clsid); SysFreeString(path); if(FAILED(hres)) { heap_free(display_name); return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, ERROR_INVALID_PARAMETER); } hres = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, &IID_IParseDisplayName, (void**)&pdn); if(FAILED(hres)) { WARN("Could not create object %s\n", debugstr_guid(&clsid)); heap_free(display_name); return report_result(pOIProtSink, hres, ERROR_INVALID_PARAMETER); } hres = IParseDisplayName_ParseDisplayName(pdn, NULL /* FIXME */, display_name, &eaten, &mon); heap_free(display_name); IParseDisplayName_Release(pdn); if(FAILED(hres)) { WARN("ParseDisplayName failed: %08x\n", hres); return report_result(pOIProtSink, hres, ERROR_INVALID_PARAMETER); } if(This->stream) { IStream_Release(This->stream); This->stream = NULL; } hres = IMoniker_BindToStorage(mon, NULL /* FIXME */, NULL, &IID_IStream, (void**)&This->stream); IMoniker_Release(mon); if(FAILED(hres)) { WARN("BindToStorage failed: %08x\n", hres); return report_result(pOIProtSink, hres, ERROR_INVALID_PARAMETER); } hres = IStream_Stat(This->stream, &statstg, STATFLAG_NONAME); if(FAILED(hres)) { WARN("Stat failed: %08x\n", hres); return report_result(pOIProtSink, hres, ERROR_INVALID_PARAMETER); } IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION, statstg.cbSize.u.LowPart, statstg.cbSize.u.LowPart); return report_result(pOIProtSink, S_OK, ERROR_SUCCESS); }