📄 url.c
字号:
while (*wk1) {
mp = strchrW(wk1, '/');
mp2 = strchrW(wk1, '\\');
if(mp2 && (!mp || mp2 < mp))
mp = mp2;
if (!mp) {
nWkLen = strlenW(wk1);
memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR));
wk1 += nWkLen;
wk2 += nWkLen;
continue;
}
nLen = mp - wk1;
if(nLen) {
memcpy(wk2, wk1, nLen * sizeof(WCHAR));
wk2 += nLen;
wk1 += nLen;
}
*wk2++ = slash;
wk1++;
if (*wk1 == '.') {
TRACE("found '/.'\n");
if (wk1[1] == '/' || wk1[1] == '\\') {
/* case of /./ -> skip the ./ */
wk1 += 2;
}
else if (wk1[1] == '.') {
/* found /.. look for next / */
TRACE("found '/..'\n");
if (wk1[2] == '/' || wk1[2] == '\\' ||wk1[2] == '?'
|| wk1[2] == '#' || !wk1[2]) {
/* case /../ -> need to backup wk2 */
TRACE("found '/../'\n");
*(wk2-1) = '\0'; /* set end of string */
mp = strrchrW(root, slash);
if (mp && (mp >= root)) {
/* found valid backup point */
wk2 = mp + 1;
if(wk1[2] != '/' && wk1[2] != '\\')
wk1 += 2;
else
wk1 += 3;
}
else {
/* did not find point, restore '/' */
*(wk2-1) = slash;
}
}
}
}
}
*wk2 = '\0';
break;
default:
FIXME("how did we get here - state=%d\n", state);
HeapFree(GetProcessHeap(), 0, lpszUrlCpy);
return E_INVALIDARG;
}
*wk2 = '\0';
TRACE("Simplified, orig <%s>, simple <%s>\n",
debugstr_w(pszUrl), debugstr_w(lpszUrlCpy));
}
nLen = lstrlenW(lpszUrlCpy);
while ((nLen > 0) && ((lpszUrlCpy[nLen-1] == '\r')||(lpszUrlCpy[nLen-1] == '\n')))
lpszUrlCpy[--nLen]=0;
if(dwFlags & (URL_UNESCAPE | URL_FILE_USE_PATHURL))
UrlUnescapeW(lpszUrlCpy, NULL, &nLen, URL_UNESCAPE_INPLACE);
if((EscapeFlags = dwFlags & (URL_ESCAPE_UNSAFE |
URL_ESCAPE_SPACES_ONLY |
URL_ESCAPE_PERCENT |
URL_DONT_ESCAPE_EXTRA_INFO |
URL_ESCAPE_SEGMENT_ONLY ))) {
EscapeFlags &= ~URL_ESCAPE_UNSAFE;
hr = UrlEscapeW(lpszUrlCpy, pszCanonicalized, pcchCanonicalized,
EscapeFlags);
} else { /* No escaping needed, just copy the string */
nLen = lstrlenW(lpszUrlCpy);
if(nLen < *pcchCanonicalized)
memcpy(pszCanonicalized, lpszUrlCpy, (nLen + 1)*sizeof(WCHAR));
else {
hr = E_POINTER;
nLen++;
}
*pcchCanonicalized = nLen;
}
HeapFree(GetProcessHeap(), 0, lpszUrlCpy);
if (hr == S_OK)
TRACE("result %s\n", debugstr_w(pszCanonicalized));
return hr;
}
/*************************************************************************
* UrlCombineA [SHLWAPI.@]
*
* Combine two Urls.
*
* PARAMS
* pszBase [I] Base Url
* pszRelative [I] Url to combine with pszBase
* pszCombined [O] Destination for combined Url
* pcchCombined [O] Destination for length of pszCombined
* dwFlags [I] URL_ flags from "shlwapi.h"
*
* RETURNS
* Success: S_OK. pszCombined contains the combined Url, pcchCombined
* contains its length.
* Failure: An HRESULT error code indicating the error.
*/
HRESULT WINAPI UrlCombineA(LPCSTR pszBase, LPCSTR pszRelative,
LPSTR pszCombined, LPDWORD pcchCombined,
DWORD dwFlags)
{
LPWSTR base, relative, combined;
DWORD ret, len, len2;
TRACE("(base %s, Relative %s, Combine size %d, flags %08x) using W version\n",
debugstr_a(pszBase),debugstr_a(pszRelative),
pcchCombined?*pcchCombined:0,dwFlags);
if(!pszBase || !pszRelative || !pcchCombined)
return E_INVALIDARG;
base = HeapAlloc(GetProcessHeap(), 0,
(3*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
relative = base + INTERNET_MAX_URL_LENGTH;
combined = relative + INTERNET_MAX_URL_LENGTH;
MultiByteToWideChar(0, 0, pszBase, -1, base, INTERNET_MAX_URL_LENGTH);
MultiByteToWideChar(0, 0, pszRelative, -1, relative, INTERNET_MAX_URL_LENGTH);
len = *pcchCombined;
ret = UrlCombineW(base, relative, pszCombined?combined:NULL, &len, dwFlags);
if (ret != S_OK) {
*pcchCombined = len;
HeapFree(GetProcessHeap(), 0, base);
return ret;
}
len2 = WideCharToMultiByte(0, 0, combined, len, 0, 0, 0, 0);
if (len2 > *pcchCombined) {
*pcchCombined = len2;
HeapFree(GetProcessHeap(), 0, base);
return E_POINTER;
}
WideCharToMultiByte(0, 0, combined, len+1, pszCombined, (*pcchCombined)+1,
0, 0);
*pcchCombined = len2;
HeapFree(GetProcessHeap(), 0, base);
return S_OK;
}
/*************************************************************************
* UrlCombineW [SHLWAPI.@]
*
* See UrlCombineA.
*/
HRESULT WINAPI UrlCombineW(LPCWSTR pszBase, LPCWSTR pszRelative,
LPWSTR pszCombined, LPDWORD pcchCombined,
DWORD dwFlags)
{
PARSEDURLW base, relative;
DWORD myflags, sizeloc = 0;
DWORD len, res1, res2, process_case = 0;
LPWSTR work, preliminary, mbase, mrelative;
static const WCHAR myfilestr[] = {'f','i','l','e',':','/','/','/','\0'};
static const WCHAR single_slash[] = {'/','\0'};
HRESULT ret;
TRACE("(base %s, Relative %s, Combine size %d, flags %08x)\n",
debugstr_w(pszBase),debugstr_w(pszRelative),
pcchCombined?*pcchCombined:0,dwFlags);
if(!pszBase || !pszRelative || !pcchCombined)
return E_INVALIDARG;
base.cbSize = sizeof(base);
relative.cbSize = sizeof(relative);
/* Get space for duplicates of the input and the output */
preliminary = HeapAlloc(GetProcessHeap(), 0, (3*INTERNET_MAX_URL_LENGTH) *
sizeof(WCHAR));
mbase = preliminary + INTERNET_MAX_URL_LENGTH;
mrelative = mbase + INTERNET_MAX_URL_LENGTH;
*preliminary = '\0';
/* Canonicalize the base input prior to looking for the scheme */
myflags = dwFlags & (URL_DONT_SIMPLIFY | URL_UNESCAPE);
len = INTERNET_MAX_URL_LENGTH;
ret = UrlCanonicalizeW(pszBase, mbase, &len, myflags);
/* Canonicalize the relative input prior to looking for the scheme */
len = INTERNET_MAX_URL_LENGTH;
ret = UrlCanonicalizeW(pszRelative, mrelative, &len, myflags);
/* See if the base has a scheme */
res1 = ParseURLW(mbase, &base);
if (res1) {
/* if pszBase has no scheme, then return pszRelative */
TRACE("no scheme detected in Base\n");
process_case = 1;
}
else do {
/* mk is a special case */
if(base.nScheme == URL_SCHEME_MK) {
static const WCHAR wsz[] = {':',':',0};
WCHAR *ptr = strstrW(base.pszSuffix, wsz);
if(ptr) {
int delta;
ptr += 2;
delta = ptr-base.pszSuffix;
base.cchProtocol += delta;
base.pszSuffix += delta;
base.cchSuffix -= delta;
}
}
/* get size of location field (if it exists) */
work = (LPWSTR)base.pszSuffix;
sizeloc = 0;
if (*work++ == '/') {
if (*work++ == '/') {
/* At this point have start of location and
* it ends at next '/' or end of string.
*/
while(*work && (*work != '/')) work++;
sizeloc = (DWORD)(work - base.pszSuffix);
}
}
/* Change .sizep2 to not have the last leaf in it,
* Note: we need to start after the location (if it exists)
*/
work = strrchrW((base.pszSuffix+sizeloc), '/');
if (work) {
len = (DWORD)(work - base.pszSuffix + 1);
base.cchSuffix = len;
}
/*
* At this point:
* .pszSuffix points to location (starting with '//')
* .cchSuffix length of location (above) and rest less the last
* leaf (if any)
* sizeloc length of location (above) up to but not including
* the last '/'
*/
res2 = ParseURLW(mrelative, &relative);
if (res2) {
/* no scheme in pszRelative */
TRACE("no scheme detected in Relative\n");
relative.pszSuffix = mrelative; /* case 3,4,5 depends on this */
relative.cchSuffix = strlenW(mrelative);
if (*pszRelative == ':') {
/* case that is either left alone or uses pszBase */
if (dwFlags & URL_PLUGGABLE_PROTOCOL) {
process_case = 5;
break;
}
process_case = 1;
break;
}
if (isalnum(*mrelative) && (*(mrelative + 1) == ':')) {
/* case that becomes "file:///" */
strcpyW(preliminary, myfilestr);
process_case = 1;
break;
}
if ((*mrelative == '/') && (*(mrelative+1) == '/')) {
/* pszRelative has location and rest */
process_case = 3;
break;
}
if (*mrelative == '/') {
/* case where pszRelative is root to location */
process_case = 4;
break;
}
process_case = (*base.pszSuffix == '/') ? 5 : 3;
break;
}
/* handle cases where pszRelative has scheme */
if ((base.cchProtocol == relative.cchProtocol) &&
(strncmpW(base.pszProtocol, relative.pszProtocol, base.cchProtocol) == 0)) {
/* since the schemes are the same */
if ((*relative.pszSuffix == '/') && (*(relative.pszSuffix+1) == '/')) {
/* case where pszRelative replaces location and following */
process_case = 3;
break;
}
if (*relative.pszSuffix == '/') {
/* case where pszRelative is root to location */
process_case = 4;
break;
}
/* case where scheme is followed by document path */
process_case = 5;
break;
}
if ((*relative.pszSuffix == '/') && (*(relative.pszSuffix+1) == '/')) {
/* case where pszRelative replaces scheme, location,
* and following and handles PLUGGABLE
*/
process_case = 2;
break;
}
process_case = 1;
break;
} while(FALSE); /* a litte trick to allow easy exit from nested if's */
ret = S_OK;
switch (process_case) {
case 1: /*
* Return pszRelative appended to what ever is in pszCombined,
* (which may the string "file:///"
*/
strcatW(preliminary, mrelative);
break;
case 2: /*
* Same as case 1, but if URL_PLUGGABLE_PROTOCOL was specified
* and pszRelative starts with "//", then append a "/"
*/
strcpyW(preliminary, mrelative);
if (!(dwFlags & URL_PLUGGABLE_PROTOCOL) &&
URL_JustLocation(relative.pszSuffix))
strcatW(preliminary, single_slash);
break;
case 3: /*
* Return the pszBase scheme with pszRelative. Basically
* keeps the scheme and replaces the domain and following.
*/
memcpy(preliminary, base.pszProtocol, (base.cchProtocol + 1)*sizeof(WCHAR));
work = preliminary + base.cchProtocol + 1;
strcpyW(work, relative.pszSuffix);
if (!(dwFlags & URL_PLUGGABLE_PROTOCOL) &&
URL_JustLocation(relative.pszSuffix))
strcatW(work, single_slash);
break;
case 4: /*
* Return the pszBase scheme and location but everything
* after the location is pszRelative. (Replace document
* from root on.)
*/
memcpy(preliminary, base.pszProtocol, (base.cchProtocol+1+sizeloc)*sizeof(WCHAR));
work = preliminary + base.cchProtocol + 1 + sizeloc;
if (dwFlags & URL_PLUGGABLE_PROTOCOL)
*(work++) = '/';
strcpyW(work, relative.pszSuffix);
break;
case 5: /*
* Return the pszBase without its document (if any) and
* append pszRelative after its scheme.
*/
memcpy(preliminary, base.pszProtocol,
(base.cchProtocol+1+base.cchSuffix)*sizeof(WCHAR));
work = preliminary + base.cchProtocol+1+base.cchSuffix - 1;
if (*work++ != '/')
*(work++) = '/';
strcpyW(work, relative.pszSuffix);
break;
default:
FIXME("How did we get here????? process_case=%d\n", process_case);
ret = E_INVALIDARG;
}
if (ret == S_OK) {
/* Reuse mrelative as temp storage as its already allocated and not needed anymore */
ret = UrlCanonicalizeW(preliminary, mrelative, pcchCombined, (dwFlags & ~URL_FILE_USE_PATHURL));
if(SUCCEEDED(ret) && pszCombined) {
lstrcpyW(pszCombined, mrelative);
}
TRACE("return-%d len=%d, %s\n",
process_case, *pcchCombined, debugstr_w(pszCombined));
}
HeapFree(GetProcessHeap(), 0, preliminary);
return ret;
}
/*************************************************************************
* UrlEscapeA [SHLWAPI.@]
*/
HRESULT WINAPI UrlEscapeA(
LPCSTR pszUrl,
LPSTR pszEscaped,
LPDWORD pcchEscaped,
DWORD dwFlags)
{
WCHAR bufW[INTERNET_MAX_URL_LENGTH];
WCHAR *escapedW = bufW;
UNICODE_STRING urlW;
HRESULT ret;
DWORD lenW = sizeof(bufW)/sizeof(WCHAR), lenA;
if(!RtlCreateUnicodeStringFromAsciiz(&urlW, pszUrl))
return E_INVALIDARG;
if((ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags)) == E_POINTER) {
escapedW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags);
}
if(ret == S_OK) {
RtlUnicodeToMultiByteSize(&lenA, escapedW, lenW * sizeof(WCHAR));
if(pszEscaped && *pcchEscaped > lenA) {
RtlUnicodeToMultiByteN(pszEscaped, *pcchEscaped - 1, &lenA, escapedW, lenW * sizeof(WCHAR));
pszEscaped[lenA] = 0;
*pcchEscaped = lenA;
} else {
*pcchEscaped = lenA + 1;
ret = E_INVALIDARG;
}
}
if(escapedW != bufW) HeapFree(GetProcessHeap(), 0, escapedW);
RtlFreeUnicodeString(&urlW);
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -