📄 url.c
字号:
}
/*************************************************************************
* UrlIsW [SHLWAPI.@]
*
* See UrlIsA.
*/
BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis)
{
static const WCHAR stemp[] = { 'f','i','l','e',':',0 };
PARSEDURLW base;
DWORD res1;
LPCWSTR last;
TRACE("(%s %d)\n", debugstr_w(pszUrl), Urlis);
switch (Urlis) {
case URLIS_OPAQUE:
base.cbSize = sizeof(base);
res1 = ParseURLW(pszUrl, &base);
if (res1) return FALSE; /* invalid scheme */
switch (base.nScheme)
{
case URL_SCHEME_MAILTO:
case URL_SCHEME_SHELL:
case URL_SCHEME_JAVASCRIPT:
case URL_SCHEME_VBSCRIPT:
case URL_SCHEME_ABOUT:
return TRUE;
}
return FALSE;
case URLIS_FILEURL:
return !strncmpW(stemp, pszUrl, 5);
case URLIS_DIRECTORY:
last = pszUrl + strlenW(pszUrl) - 1;
return (last >= pszUrl && (*last == '/' || *last == '\\'));
case URLIS_URL:
return PathIsURLW(pszUrl);
case URLIS_NOHISTORY:
case URLIS_APPLIABLE:
case URLIS_HASQUERY:
default:
FIXME("(%s %d): stub\n", debugstr_w(pszUrl), Urlis);
}
return FALSE;
}
/*************************************************************************
* UrlIsNoHistoryA [SHLWAPI.@]
*
* Determine if a Url should not be stored in the users history list.
*
* PARAMS
* pszUrl [I] Url to check
*
* RETURNS
* TRUE, if pszUrl should be excluded from the history list,
* FALSE otherwise.
*/
BOOL WINAPI UrlIsNoHistoryA(LPCSTR pszUrl)
{
return UrlIsA(pszUrl, URLIS_NOHISTORY);
}
/*************************************************************************
* UrlIsNoHistoryW [SHLWAPI.@]
*
* See UrlIsNoHistoryA.
*/
BOOL WINAPI UrlIsNoHistoryW(LPCWSTR pszUrl)
{
return UrlIsW(pszUrl, URLIS_NOHISTORY);
}
/*************************************************************************
* UrlIsOpaqueA [SHLWAPI.@]
*
* Determine if a Url is opaque.
*
* PARAMS
* pszUrl [I] Url to check
*
* RETURNS
* TRUE if pszUrl is opaque,
* FALSE Otherwise.
*
* NOTES
* An opaque Url is one that does not start with "<protocol>://".
*/
BOOL WINAPI UrlIsOpaqueA(LPCSTR pszUrl)
{
return UrlIsA(pszUrl, URLIS_OPAQUE);
}
/*************************************************************************
* UrlIsOpaqueW [SHLWAPI.@]
*
* See UrlIsOpaqueA.
*/
BOOL WINAPI UrlIsOpaqueW(LPCWSTR pszUrl)
{
return UrlIsW(pszUrl, URLIS_OPAQUE);
}
/*************************************************************************
* Scans for characters of type "type" and when not matching found,
* returns pointer to it and length in size.
*
* Characters tested based on RFC 1738
*/
static LPCWSTR URL_ScanID(LPCWSTR start, LPDWORD size, WINE_URL_SCAN_TYPE type)
{
static DWORD alwayszero = 0;
BOOL cont = TRUE;
*size = 0;
switch(type){
case SCHEME:
while (cont) {
if ( (islowerW(*start) && isalphaW(*start)) ||
isdigitW(*start) ||
(*start == '+') ||
(*start == '-') ||
(*start == '.')) {
start++;
(*size)++;
}
else
cont = FALSE;
}
break;
case USERPASS:
while (cont) {
if ( isalphaW(*start) ||
isdigitW(*start) ||
/* user/password only characters */
(*start == ';') ||
(*start == '?') ||
(*start == '&') ||
(*start == '=') ||
/* *extra* characters */
(*start == '!') ||
(*start == '*') ||
(*start == '\'') ||
(*start == '(') ||
(*start == ')') ||
(*start == ',') ||
/* *safe* characters */
(*start == '$') ||
(*start == '_') ||
(*start == '+') ||
(*start == '-') ||
(*start == '.')) {
start++;
(*size)++;
} else if (*start == '%') {
if (isxdigitW(*(start+1)) &&
isxdigitW(*(start+2))) {
start += 3;
*size += 3;
} else
cont = FALSE;
} else
cont = FALSE;
}
break;
case PORT:
while (cont) {
if (isdigitW(*start)) {
start++;
(*size)++;
}
else
cont = FALSE;
}
break;
case HOST:
while (cont) {
if (isalnumW(*start) ||
(*start == '-') ||
(*start == '.') ) {
start++;
(*size)++;
}
else
cont = FALSE;
}
break;
default:
FIXME("unknown type %d\n", type);
return (LPWSTR)&alwayszero;
}
/* TRACE("scanned %d characters next char %p<%c>\n",
*size, start, *start); */
return start;
}
/*************************************************************************
* Attempt to parse URL into pieces.
*/
static LONG URL_ParseUrl(LPCWSTR pszUrl, WINE_PARSE_URL *pl)
{
LPCWSTR work;
memset(pl, 0, sizeof(WINE_PARSE_URL));
pl->pScheme = pszUrl;
work = URL_ScanID(pl->pScheme, &pl->szScheme, SCHEME);
if (!*work || (*work != ':')) goto ErrorExit;
work++;
if ((*work != '/') || (*(work+1) != '/')) goto ErrorExit;
pl->pUserName = work + 2;
work = URL_ScanID(pl->pUserName, &pl->szUserName, USERPASS);
if (*work == ':' ) {
/* parse password */
work++;
pl->pPassword = work;
work = URL_ScanID(pl->pPassword, &pl->szPassword, USERPASS);
if (*work != '@') {
/* what we just parsed must be the hostname and port
* so reset pointers and clear then let it parse */
pl->szUserName = pl->szPassword = 0;
work = pl->pUserName - 1;
pl->pUserName = pl->pPassword = 0;
}
} else if (*work == '@') {
/* no password */
pl->szPassword = 0;
pl->pPassword = 0;
} else if (!*work || (*work == '/') || (*work == '.')) {
/* what was parsed was hostname, so reset pointers and let it parse */
pl->szUserName = pl->szPassword = 0;
work = pl->pUserName - 1;
pl->pUserName = pl->pPassword = 0;
} else goto ErrorExit;
/* now start parsing hostname or hostnumber */
work++;
pl->pHostName = work;
work = URL_ScanID(pl->pHostName, &pl->szHostName, HOST);
if (*work == ':') {
/* parse port */
work++;
pl->pPort = work;
work = URL_ScanID(pl->pPort, &pl->szPort, PORT);
}
if (*work == '/') {
/* see if query string */
pl->pQuery = strchrW(work, '?');
if (pl->pQuery) pl->szQuery = strlenW(pl->pQuery);
}
TRACE("parse successful: scheme=%p(%d), user=%p(%d), pass=%p(%d), host=%p(%d), port=%p(%d), query=%p(%d)\n",
pl->pScheme, pl->szScheme,
pl->pUserName, pl->szUserName,
pl->pPassword, pl->szPassword,
pl->pHostName, pl->szHostName,
pl->pPort, pl->szPort,
pl->pQuery, pl->szQuery);
return S_OK;
ErrorExit:
FIXME("failed to parse %s\n", debugstr_w(pszUrl));
return E_INVALIDARG;
}
/*************************************************************************
* UrlGetPartA [SHLWAPI.@]
*
* Retrieve part of a Url.
*
* PARAMS
* pszIn [I] Url to parse
* pszOut [O] Destination for part of pszIn requested
* pcchOut [I] Size of pszOut
* [O] length of pszOut string EXLUDING '\0' if S_OK, otherwise
* needed size of pszOut INCLUDING '\0'.
* dwPart [I] URL_PART_ enum from "shlwapi.h"
* dwFlags [I] URL_ flags from "shlwapi.h"
*
* RETURNS
* Success: S_OK. pszOut contains the part requested, pcchOut contains its length.
* Failure: An HRESULT error code describing the error.
*/
HRESULT WINAPI UrlGetPartA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut,
DWORD dwPart, DWORD dwFlags)
{
LPWSTR in, out;
DWORD ret, len, len2;
in = HeapAlloc(GetProcessHeap(), 0,
(2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
out = in + INTERNET_MAX_URL_LENGTH;
MultiByteToWideChar(0, 0, pszIn, -1, in, INTERNET_MAX_URL_LENGTH);
len = INTERNET_MAX_URL_LENGTH;
ret = UrlGetPartW(in, out, &len, dwPart, dwFlags);
if (ret != S_OK) {
HeapFree(GetProcessHeap(), 0, in);
return ret;
}
len2 = WideCharToMultiByte(0, 0, out, len, 0, 0, 0, 0);
if (len2 > *pcchOut) {
*pcchOut = len2;
HeapFree(GetProcessHeap(), 0, in);
return E_POINTER;
}
WideCharToMultiByte(0, 0, out, len+1, pszOut, *pcchOut, 0, 0);
*pcchOut = len2;
HeapFree(GetProcessHeap(), 0, in);
return S_OK;
}
/*************************************************************************
* UrlGetPartW [SHLWAPI.@]
*
* See UrlGetPartA.
*/
HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut,
DWORD dwPart, DWORD dwFlags)
{
WINE_PARSE_URL pl;
HRESULT ret;
DWORD size, schsize;
LPCWSTR addr, schaddr;
TRACE("(%s %p %p(%d) %08x %08x)\n",
debugstr_w(pszIn), pszOut, pcchOut, *pcchOut, dwPart, dwFlags);
ret = URL_ParseUrl(pszIn, &pl);
if (!ret) {
schaddr = pl.pScheme;
schsize = pl.szScheme;
switch (dwPart) {
case URL_PART_SCHEME:
if (!pl.szScheme) return E_INVALIDARG;
addr = pl.pScheme;
size = pl.szScheme;
break;
case URL_PART_HOSTNAME:
if (!pl.szHostName) return E_INVALIDARG;
addr = pl.pHostName;
size = pl.szHostName;
break;
case URL_PART_USERNAME:
if (!pl.szUserName) return E_INVALIDARG;
addr = pl.pUserName;
size = pl.szUserName;
break;
case URL_PART_PASSWORD:
if (!pl.szPassword) return E_INVALIDARG;
addr = pl.pPassword;
size = pl.szPassword;
break;
case URL_PART_PORT:
if (!pl.szPort) return E_INVALIDARG;
addr = pl.pPort;
size = pl.szPort;
break;
case URL_PART_QUERY:
if (!pl.szQuery) return E_INVALIDARG;
addr = pl.pQuery;
size = pl.szQuery;
break;
default:
return E_INVALIDARG;
}
if (dwFlags == URL_PARTFLAG_KEEPSCHEME) {
if (*pcchOut < schsize + size + 2) {
*pcchOut = schsize + size + 2;
return E_POINTER;
}
memcpy(pszOut, schaddr, schsize*sizeof(WCHAR));
pszOut[schsize] = ':';
memcpy(pszOut+schsize+1, addr, size*sizeof(WCHAR));
pszOut[schsize+1+size] = 0;
*pcchOut = schsize + 1 + size;
}
else {
if (*pcchOut < size + 1) {*pcchOut = size+1; return E_POINTER;}
memcpy(pszOut, addr, size*sizeof(WCHAR));
pszOut[size] = 0;
*pcchOut = size;
}
TRACE("len=%d %s\n", *pcchOut, debugstr_w(pszOut));
}
return ret;
}
/*************************************************************************
* PathIsURLA [SHLWAPI.@]
*
* Check if the given path is a Url.
*
* PARAMS
* lpszPath [I] Path to check.
*
* RETURNS
* TRUE if lpszPath is a Url.
* FALSE if lpszPath is NULL or not a Url.
*/
BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
{
PARSEDURLA base;
DWORD res1;
if (!lpstrPath || !*lpstrPath) return FALSE;
/* get protocol */
base.cbSize = sizeof(base);
res1 = ParseURLA(lpstrPath, &base);
return
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -