/// Merge `base` and `path` in-place static void merge(SerdChunk* base, SerdChunk* path) { size_t up; const uint8_t* begin = remove_dot_segments(path->buf, path->len, &up); const uint8_t* end = path->buf + path->len; if (base->len) { // Find the up'th last slash const uint8_t* base_last = (base->buf + base->len - 1); ++up; do { if (*base_last == '/') { --up; } } while (up > 0 && (--base_last > base->buf)); // Set path prefix base->len = base_last - base->buf + 1; } // Set path suffix path->buf = begin; path->len = end - begin; }
/* This function directly implements the "Transform References" * algorithm described in RFC 3986 section 5.2.2. */ ne_uri *ne_uri_resolve(const ne_uri *base, const ne_uri *relative, ne_uri *target) { memset(target, 0, sizeof *target); if (relative->scheme) { target->scheme = ne_strdup(relative->scheme); copy_authority(target, relative); target->path = remove_dot_segments(relative->path); if (relative->query) target->query = ne_strdup(relative->query); } else { if (relative->host) { copy_authority(target, relative); target->path = remove_dot_segments(relative->path); if (relative->query) target->query = ne_strdup(relative->query); } else { if (relative->path[0] == '\0') { target->path = ne_strdup(base->path); if (relative->query) { target->query = ne_strdup(relative->query); } else if (base->query) { target->query = ne_strdup(base->query); } } else { if (relative->path[0] == '/') { target->path = remove_dot_segments(relative->path); } else { char *merged = merge_paths(base, relative->path); target->path = remove_dot_segments(merged); ne_free(merged); } if (relative->query) target->query = ne_strdup(relative->query); } copy_authority(target, base); } if (base->scheme) target->scheme = ne_strdup(base->scheme); } if (relative->fragment) target->fragment = ne_strdup(relative->fragment); return target; }
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); }