📄 url.c
字号:
/*
* Url functions
*
* Copyright 2000 Huw D M Davies for CodeWeavers.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winerror.h"
#include "wine/unicode.h"
#include "wininet.h"
#include "winreg.h"
#include "winternl.h"
#define NO_SHLWAPI_STREAM
#include "shlwapi.h"
#include "wine/debug.h"
HMODULE WINAPI MLLoadLibraryW(LPCWSTR,HMODULE,DWORD);
BOOL WINAPI MLFreeLibrary(HMODULE);
HRESULT WINAPI MLBuildResURLW(LPCWSTR,HMODULE,DWORD,LPCWSTR,LPWSTR,DWORD);
WINE_DEFAULT_DEBUG_CHANNEL(shell);
/* The following schemes were identified in the native version of
* SHLWAPI.DLL version 5.50
*/
static const struct {
URL_SCHEME scheme_number;
WCHAR scheme_name[12];
} shlwapi_schemes[] = {
{URL_SCHEME_FTP, {'f','t','p',0}},
{URL_SCHEME_HTTP, {'h','t','t','p',0}},
{URL_SCHEME_GOPHER, {'g','o','p','h','e','r',0}},
{URL_SCHEME_MAILTO, {'m','a','i','l','t','o',0}},
{URL_SCHEME_NEWS, {'n','e','w','s',0}},
{URL_SCHEME_NNTP, {'n','n','t','p',0}},
{URL_SCHEME_TELNET, {'t','e','l','n','e','t',0}},
{URL_SCHEME_WAIS, {'w','a','i','s',0}},
{URL_SCHEME_FILE, {'f','i','l','e',0}},
{URL_SCHEME_MK, {'m','k',0}},
{URL_SCHEME_HTTPS, {'h','t','t','p','s',0}},
{URL_SCHEME_SHELL, {'s','h','e','l','l',0}},
{URL_SCHEME_SNEWS, {'s','n','e','w','s',0}},
{URL_SCHEME_LOCAL, {'l','o','c','a','l',0}},
{URL_SCHEME_JAVASCRIPT, {'j','a','v','a','s','c','r','i','p','t',0}},
{URL_SCHEME_VBSCRIPT, {'v','b','s','c','r','i','p','t',0}},
{URL_SCHEME_ABOUT, {'a','b','o','u','t',0}},
{URL_SCHEME_RES, {'r','e','s',0}},
};
typedef struct {
LPCWSTR pScheme; /* [out] start of scheme */
DWORD szScheme; /* [out] size of scheme (until colon) */
LPCWSTR pUserName; /* [out] start of Username */
DWORD szUserName; /* [out] size of Username (until ":" or "@") */
LPCWSTR pPassword; /* [out] start of Password */
DWORD szPassword; /* [out] size of Password (until "@") */
LPCWSTR pHostName; /* [out] start of Hostname */
DWORD szHostName; /* [out] size of Hostname (until ":" or "/") */
LPCWSTR pPort; /* [out] start of Port */
DWORD szPort; /* [out] size of Port (until "/" or eos) */
LPCWSTR pQuery; /* [out] start of Query */
DWORD szQuery; /* [out] size of Query (until eos) */
} WINE_PARSE_URL;
typedef enum {
SCHEME,
HOST,
PORT,
USERPASS,
} WINE_URL_SCAN_TYPE;
static const CHAR hexDigits[] = "0123456789ABCDEF";
static const WCHAR fileW[] = {'f','i','l','e','\0'};
static const unsigned char HashDataLookup[256] = {
0x01, 0x0E, 0x6E, 0x19, 0x61, 0xAE, 0x84, 0x77, 0x8A, 0xAA, 0x7D, 0x76, 0x1B,
0xE9, 0x8C, 0x33, 0x57, 0xC5, 0xB1, 0x6B, 0xEA, 0xA9, 0x38, 0x44, 0x1E, 0x07,
0xAD, 0x49, 0xBC, 0x28, 0x24, 0x41, 0x31, 0xD5, 0x68, 0xBE, 0x39, 0xD3, 0x94,
0xDF, 0x30, 0x73, 0x0F, 0x02, 0x43, 0xBA, 0xD2, 0x1C, 0x0C, 0xB5, 0x67, 0x46,
0x16, 0x3A, 0x4B, 0x4E, 0xB7, 0xA7, 0xEE, 0x9D, 0x7C, 0x93, 0xAC, 0x90, 0xB0,
0xA1, 0x8D, 0x56, 0x3C, 0x42, 0x80, 0x53, 0x9C, 0xF1, 0x4F, 0x2E, 0xA8, 0xC6,
0x29, 0xFE, 0xB2, 0x55, 0xFD, 0xED, 0xFA, 0x9A, 0x85, 0x58, 0x23, 0xCE, 0x5F,
0x74, 0xFC, 0xC0, 0x36, 0xDD, 0x66, 0xDA, 0xFF, 0xF0, 0x52, 0x6A, 0x9E, 0xC9,
0x3D, 0x03, 0x59, 0x09, 0x2A, 0x9B, 0x9F, 0x5D, 0xA6, 0x50, 0x32, 0x22, 0xAF,
0xC3, 0x64, 0x63, 0x1A, 0x96, 0x10, 0x91, 0x04, 0x21, 0x08, 0xBD, 0x79, 0x40,
0x4D, 0x48, 0xD0, 0xF5, 0x82, 0x7A, 0x8F, 0x37, 0x69, 0x86, 0x1D, 0xA4, 0xB9,
0xC2, 0xC1, 0xEF, 0x65, 0xF2, 0x05, 0xAB, 0x7E, 0x0B, 0x4A, 0x3B, 0x89, 0xE4,
0x6C, 0xBF, 0xE8, 0x8B, 0x06, 0x18, 0x51, 0x14, 0x7F, 0x11, 0x5B, 0x5C, 0xFB,
0x97, 0xE1, 0xCF, 0x15, 0x62, 0x71, 0x70, 0x54, 0xE2, 0x12, 0xD6, 0xC7, 0xBB,
0x0D, 0x20, 0x5E, 0xDC, 0xE0, 0xD4, 0xF7, 0xCC, 0xC4, 0x2B, 0xF9, 0xEC, 0x2D,
0xF4, 0x6F, 0xB6, 0x99, 0x88, 0x81, 0x5A, 0xD9, 0xCA, 0x13, 0xA5, 0xE7, 0x47,
0xE6, 0x8E, 0x60, 0xE3, 0x3E, 0xB3, 0xF6, 0x72, 0xA2, 0x35, 0xA0, 0xD7, 0xCD,
0xB4, 0x2F, 0x6D, 0x2C, 0x26, 0x1F, 0x95, 0x87, 0x00, 0xD8, 0x34, 0x3F, 0x17,
0x25, 0x45, 0x27, 0x75, 0x92, 0xB8, 0xA3, 0xC8, 0xDE, 0xEB, 0xF8, 0xF3, 0xDB,
0x0A, 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1 };
static DWORD get_scheme_code(LPCWSTR scheme, DWORD scheme_len)
{
int i;
for(i=0; i < sizeof(shlwapi_schemes)/sizeof(shlwapi_schemes[0]); i++) {
if(scheme_len == strlenW(shlwapi_schemes[i].scheme_name)
&& !memcmp(scheme, shlwapi_schemes[i].scheme_name, scheme_len*sizeof(WCHAR)))
return shlwapi_schemes[i].scheme_number;
}
return URL_SCHEME_UNKNOWN;
}
static BOOL URL_JustLocation(LPCWSTR str)
{
while(*str && (*str == '/')) str++;
if (*str) {
while (*str && ((*str == '-') ||
(*str == '.') ||
isalnumW(*str))) str++;
if (*str == '/') return FALSE;
}
return TRUE;
}
/*************************************************************************
* @ [SHLWAPI.1]
*
* Parse a Url into its constituent parts.
*
* PARAMS
* x [I] Url to parse
* y [O] Undocumented structure holding the parsed information
*
* RETURNS
* Success: S_OK. y contains the parsed Url details.
* Failure: An HRESULT error code.
*/
HRESULT WINAPI ParseURLA(LPCSTR x, PARSEDURLA *y)
{
WCHAR scheme[INTERNET_MAX_SCHEME_LENGTH];
DWORD cnt, len;
y->nScheme = URL_SCHEME_INVALID;
if (y->cbSize != sizeof(*y)) return E_INVALIDARG;
/* FIXME: leading white space generates error of 0x80041001 which
* is undefined
*/
if (*x <= ' ') return 0x80041001;
cnt = 0;
y->cchProtocol = 0;
y->pszProtocol = x;
while (*x) {
if (*x == ':') {
y->cchProtocol = cnt;
cnt = -1;
y->pszSuffix = x+1;
break;
}
x++;
cnt++;
}
/* check for no scheme in string start */
/* (apparently schemes *must* be larger than a single character) */
if ((*x == '\0') || (y->cchProtocol <= 1)) {
y->pszProtocol = NULL;
return 0x80041001;
}
/* found scheme, set length of remainder */
y->cchSuffix = lstrlenA(y->pszSuffix);
len = MultiByteToWideChar(CP_ACP, 0, y->pszProtocol, y->cchProtocol,
scheme, sizeof(scheme)/sizeof(WCHAR));
y->nScheme = get_scheme_code(scheme, len);
return S_OK;
}
/*************************************************************************
* @ [SHLWAPI.2]
*
* Unicode version of ParseURLA.
*/
HRESULT WINAPI ParseURLW(LPCWSTR x, PARSEDURLW *y)
{
DWORD cnt;
y->nScheme = URL_SCHEME_INVALID;
if (y->cbSize != sizeof(*y)) return E_INVALIDARG;
/* FIXME: leading white space generates error of 0x80041001 which
* is undefined
*/
if (*x <= ' ') return 0x80041001;
cnt = 0;
y->cchProtocol = 0;
y->pszProtocol = x;
while (*x) {
if (*x == ':') {
y->cchProtocol = cnt;
cnt = -1;
y->pszSuffix = x+1;
break;
}
x++;
cnt++;
}
/* check for no scheme in string start */
/* (apparently schemes *must* be larger than a single character) */
if ((*x == '\0') || (y->cchProtocol <= 1)) {
y->pszProtocol = NULL;
return 0x80041001;
}
/* found scheme, set length of remainder */
y->cchSuffix = lstrlenW(y->pszSuffix);
y->nScheme = get_scheme_code(y->pszProtocol, y->cchProtocol);
return S_OK;
}
/*************************************************************************
* UrlCanonicalizeA [SHLWAPI.@]
*
* Canonicalize a Url.
*
* PARAMS
* pszUrl [I] Url to cCanonicalize
* pszCanonicalized [O] Destination for converted Url.
* pcchCanonicalized [I/O] Length of pszUrl, destination for length of pszCanonicalized
* dwFlags [I] Flags controlling the conversion.
*
* RETURNS
* Success: S_OK. The pszCanonicalized contains the converted Url.
* Failure: E_POINTER, if *pcchCanonicalized is too small.
*
* MSDN incorrectly describes the flags for this function. They should be:
*| URL_DONT_ESCAPE_EXTRA_INFO 0x02000000
*| URL_ESCAPE_SPACES_ONLY 0x04000000
*| URL_ESCAPE_PERCENT 0x00001000
*| URL_ESCAPE_UNSAFE 0x10000000
*| URL_UNESCAPE 0x10000000
*| URL_DONT_SIMPLIFY 0x08000000
*| URL_ESCAPE_SEGMENT_ONLY 0x00002000
*/
HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized,
LPDWORD pcchCanonicalized, DWORD dwFlags)
{
LPWSTR base, canonical;
DWORD ret, len, len2;
TRACE("(%s %p %p 0x%08x) using W version\n",
debugstr_a(pszUrl), pszCanonicalized,
pcchCanonicalized, dwFlags);
if(!pszUrl || !pszCanonicalized || !pcchCanonicalized)
return E_INVALIDARG;
base = HeapAlloc(GetProcessHeap(), 0,
(2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
canonical = base + INTERNET_MAX_URL_LENGTH;
MultiByteToWideChar(0, 0, pszUrl, -1, base, INTERNET_MAX_URL_LENGTH);
len = INTERNET_MAX_URL_LENGTH;
ret = UrlCanonicalizeW(base, canonical, &len, dwFlags);
if (ret != S_OK) {
HeapFree(GetProcessHeap(), 0, base);
return ret;
}
len2 = WideCharToMultiByte(0, 0, canonical, len, 0, 0, 0, 0);
if (len2 > *pcchCanonicalized) {
*pcchCanonicalized = len;
HeapFree(GetProcessHeap(), 0, base);
return E_POINTER;
}
WideCharToMultiByte(0, 0, canonical, len+1, pszCanonicalized,
*pcchCanonicalized, 0, 0);
*pcchCanonicalized = len2;
HeapFree(GetProcessHeap(), 0, base);
return S_OK;
}
/*************************************************************************
* UrlCanonicalizeW [SHLWAPI.@]
*
* See UrlCanonicalizeA.
*/
HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,
LPDWORD pcchCanonicalized, DWORD dwFlags)
{
HRESULT hr = S_OK;
DWORD EscapeFlags;
LPWSTR lpszUrlCpy, wk1, wk2, mp, mp2, root;
INT nByteLen, state;
DWORD nLen, nWkLen;
WCHAR slash = '/';
static const WCHAR wszFile[] = {'f','i','l','e',':'};
TRACE("(%s %p %p 0x%08x)\n", debugstr_w(pszUrl), pszCanonicalized,
pcchCanonicalized, dwFlags);
if(!pszUrl || !pszCanonicalized || !pcchCanonicalized)
return E_INVALIDARG;
if(!*pszUrl) {
*pszCanonicalized = 0;
return S_OK;
}
nByteLen = (lstrlenW(pszUrl) + 1) * sizeof(WCHAR); /* length in bytes */
lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, INTERNET_MAX_URL_LENGTH);
if((dwFlags & URL_FILE_USE_PATHURL) && nByteLen >= sizeof(wszFile)
&& !memcmp(wszFile, pszUrl, sizeof(wszFile)))
slash = '\\';
/*
* state =
* 0 initial 1,3
* 1 have 2[+] alnum 2,3
* 2 have scheme (found :) 4,6,3
* 3 failed (no location)
* 4 have // 5,3
* 5 have 1[+] alnum 6,3
* 6 have location (found /) save root location
*/
wk1 = (LPWSTR)pszUrl;
wk2 = lpszUrlCpy;
state = 0;
if(pszUrl[1] == ':') { /* Assume path */
static const WCHAR wszFilePrefix[] = {'f','i','l','e',':','/','/','/'};
memcpy(wk2, wszFilePrefix, sizeof(wszFilePrefix));
wk2 += sizeof(wszFilePrefix)/sizeof(WCHAR);
if (dwFlags & URL_FILE_USE_PATHURL)
{
slash = '\\';
--wk2;
}
else
dwFlags |= URL_ESCAPE_UNSAFE;
state = 5;
}
while (*wk1) {
switch (state) {
case 0:
if (!isalnumW(*wk1)) {state = 3; break;}
*wk2++ = *wk1++;
if (!isalnumW(*wk1)) {state = 3; break;}
*wk2++ = *wk1++;
state = 1;
break;
case 1:
*wk2++ = *wk1;
if (*wk1++ == ':') state = 2;
break;
case 2:
if (*wk1 != '/') {state = 3; break;}
*wk2++ = *wk1++;
if (*wk1 != '/') {state = 6; break;}
*wk2++ = *wk1++;
if(*wk1 == '/' && (dwFlags & URL_FILE_USE_PATHURL))
wk1++;
state = 4;
break;
case 3:
nWkLen = strlenW(wk1);
memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR));
mp = wk2;
wk1 += nWkLen;
wk2 += nWkLen;
while(mp < wk2) {
if(*mp == '/' || *mp == '\\')
*mp = slash;
mp++;
}
break;
case 4:
if (!isalnumW(*wk1) && (*wk1 != '-') && (*wk1 != '.') && (*wk1 != ':'))
{state = 3; break;}
while(isalnumW(*wk1) || (*wk1 == '-') || (*wk1 == '.') || (*wk1 == ':'))
*wk2++ = *wk1++;
state = 5;
if (!*wk1)
*wk2++ = slash;
break;
case 5:
if (*wk1 != '/' && *wk1 != '\\') {state = 3; break;}
while(*wk1 == '/' || *wk1 == '\\') {
*wk2++ = slash;
wk1++;
}
state = 6;
break;
case 6:
if(dwFlags & URL_DONT_SIMPLIFY) {
state = 3;
break;
}
/* Now at root location, cannot back up any more. */
/* "root" will point at the '/' */
root = wk2-1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -