📄 url.c
字号:
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 == L'+') ||
(*start == L'-') ||
(*start == L'.')) {
start++;
(*size)++;
}
else
cont = FALSE;
}
break;
case USERPASS:
while (cont) {
if ( isalphaW(*start) ||
isdigitW(*start) ||
/* user/password only characters */
(*start == L';') ||
(*start == L'?') ||
(*start == L'&') ||
(*start == L'=') ||
/* *extra* characters */
(*start == L'!') ||
(*start == L'*') ||
(*start == L'\'') ||
(*start == L'(') ||
(*start == L')') ||
(*start == L',') ||
/* *safe* characters */
(*start == L'$') ||
(*start == L'_') ||
(*start == L'+') ||
(*start == L'-') ||
(*start == L'.')) {
start++;
(*size)++;
} else if (*start == L'%') {
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 == L'-') ||
(*start == L'.') ) {
start++;
(*size)++;
}
else
cont = FALSE;
}
break;
default:
FIXME("unknown type %d\n", type);
return (LPWSTR)&alwayszero;
}
/* TRACE("scanned %ld 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 != L':')) goto ErrorExit;
work++;
if ((*work != L'/') || (*(work+1) != L'/')) goto ErrorExit;
pl->pUserName = work + 2;
work = URL_ScanID(pl->pUserName, &pl->szUserName, USERPASS);
if (*work == L':' ) {
/* parse password */
work++;
pl->pPassword = work;
work = URL_ScanID(pl->pPassword, &pl->szPassword, USERPASS);
if (*work != L'@') {
/* 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 == L'@') {
/* no password */
pl->szPassword = 0;
pl->pPassword = 0;
} else if (!*work || (*work == L'/') || (*work == L'.')) {
/* 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 == L':') {
/* parse port */
work++;
pl->pPort = work;
work = URL_ScanID(pl->pPort, &pl->szPort, PORT);
}
if (*work == L'/') {
/* see if query string */
pl->pQuery = strchrW(work, L'?');
if (pl->pQuery) pl->szQuery = strlenW(pl->pQuery);
}
TRACE("parse successful: scheme=%p(%ld), user=%p(%ld), pass=%p(%ld), host=%p(%ld), port=%p(%ld), query=%p(%ld)\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(%ld) %08lx %08lx)\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=%ld %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 (base.nScheme != URL_SCHEME_INVALID);
}
/*************************************************************************
* PathIsURLW [SHLWAPI.@]
*
* See PathIsURLA.
*/
BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
{
PARSEDURLW base;
DWORD res1;
if (!lpstrPath || !*lpstrPath) return FALSE;
/* get protocol */
base.cbSize = sizeof(base);
res1 = ParseURLW(lpstrPath, &base);
return (base.nScheme != URL_SCHEME_INVALID);
}
/*************************************************************************
* UrlCreateFromPathA [SHLWAPI.@]
*
* See UrlCreateFromPathW
*/
HRESULT WINAPI UrlCreateFromPathA(LPCSTR pszPath, LPSTR pszUrl, LPDWORD pcchUrl, DWORD dwReserved)
{
WCHAR bufW[INTERNET_MAX_URL_LENGTH];
WCHAR *urlW = bufW;
UNICODE_STRING pathW;
HRESULT ret;
DWORD lenW = sizeof(bufW)/sizeof(WCHAR), lenA;
if(!RtlCreateUnicodeStringFromAsciiz(&pathW, pszPath))
return E_INVALIDARG;
if((ret = UrlCreateFromPathW(pathW.Buffer, urlW, &lenW, dwReserved)) == E_POINTER) {
urlW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
ret = UrlCreateFromPathW(pathW.Buffer, urlW, &lenW, dwReserved);
}
if(ret == S_OK || ret == S_FALSE) {
RtlUnicodeToMultiByteSize(&lenA, urlW, lenW * sizeof(WCHAR));
if(*pcchUrl > lenA) {
RtlUnicodeToMultiByteN(pszUrl, *pcchUrl - 1, &lenA, urlW, lenW * sizeof(WCHAR));
pszUrl[lenA] = 0;
*pcchUrl = lenA;
} else {
*pcchUrl = lenA + 1;
ret = E_POINTER;
}
}
if(urlW != bufW) HeapFree(GetProcessHeap(), 0, urlW);
RtlFreeUnicodeString(&pathW);
return ret;
}
/*************************************************************************
* UrlCreateFromPathW [SHLWAPI.@]
*
* Create a Url from a file path.
*
* PARAMS
* pszPath [I] Path to convert
* pszUrl [O] Destination for the converted Url
* pcchUrl [I/O] Length of pszUrl
* dwReserved [I] Reserved, must be 0
*
* RETURNS
* Success: S_OK pszUrl contains the converted path, S_FALSE if the path is already a Url
* Failure: An HRESULT error code.
*/
HRESULT WINAPI UrlCreateFromPathW(LPCWSTR pszPath, LPWSTR pszUrl, LPDWORD pcchUrl, DWORD dwReserved)
{
DWORD needed;
HRESULT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -