⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 url.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.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"

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
 */
typedef struct {
    URL_SCHEME  scheme_number;
    LPCSTR scheme_name;
} SHL_2_inet_scheme;

static const SHL_2_inet_scheme shlwapi_schemes[] = {
  {URL_SCHEME_FTP,        "ftp"},
  {URL_SCHEME_HTTP,       "http"},
  {URL_SCHEME_GOPHER,     "gopher"},
  {URL_SCHEME_MAILTO,     "mailto"},
  {URL_SCHEME_NEWS,       "news"},
  {URL_SCHEME_NNTP,       "nntp"},
  {URL_SCHEME_TELNET,     "telnet"},
  {URL_SCHEME_WAIS,       "wais"},
  {URL_SCHEME_FILE,       "file"},
  {URL_SCHEME_MK,         "mk"},
  {URL_SCHEME_HTTPS,      "https"},
  {URL_SCHEME_SHELL,      "shell"},
  {URL_SCHEME_SNEWS,      "snews"},
  {URL_SCHEME_LOCAL,      "local"},
  {URL_SCHEME_JAVASCRIPT, "javascript"},
  {URL_SCHEME_VBSCRIPT,   "vbscript"},
  {URL_SCHEME_ABOUT,      "about"},
  {URL_SCHEME_RES,        "res"},
  {0, 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 BOOL URL_JustLocation(LPCWSTR str)
{
    while(*str && (*str == L'/')) str++;
    if (*str) {
	while (*str && ((*str == L'-') ||
			(*str == L'.') ||
			isalnumW(*str))) str++;
	if (*str == L'/') 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)
{
    DWORD cnt;
    const SHL_2_inet_scheme *inet_pro;

    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);

    /* see if known scheme and return indicator number */
    y->nScheme = URL_SCHEME_UNKNOWN;
    inet_pro = shlwapi_schemes;
    while (inet_pro->scheme_name) {
	if (!strncasecmp(inet_pro->scheme_name, y->pszProtocol,
		    min(y->cchProtocol, lstrlenA(inet_pro->scheme_name)))) {
	    y->nScheme = inet_pro->scheme_number;
	    break;
	}
	inet_pro++;
    }
    return S_OK;
}

/*************************************************************************
 *      @	[SHLWAPI.2]
 *
 * Unicode version of ParseURLA.
 */
HRESULT WINAPI ParseURLW(LPCWSTR x, PARSEDURLW *y)
{
    DWORD cnt;
    const SHL_2_inet_scheme *inet_pro;
    LPSTR cmpstr;
    INT 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 <= L' ') return 0x80041001;
    cnt = 0;
    y->cchProtocol = 0;
    y->pszProtocol = x;
    while (*x) {
	if (*x == L':') {
	    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 == L'\0') || (y->cchProtocol <= 1)) {
	y->pszProtocol = NULL;
	return 0x80041001;
    }

    /* found scheme, set length of remainder */
    y->cchSuffix = lstrlenW(y->pszSuffix);

    /* see if known scheme and return indicator number */
    len = WideCharToMultiByte(0, 0, y->pszProtocol, y->cchProtocol, 0, 0, 0, 0);
    cmpstr = HeapAlloc(GetProcessHeap(), 0, len);
    WideCharToMultiByte(0, 0, y->pszProtocol, y->cchProtocol, cmpstr, len, 0, 0);
    y->nScheme = URL_SCHEME_UNKNOWN;
    inet_pro = shlwapi_schemes;
    while (inet_pro->scheme_name) {
	if (!strncasecmp(inet_pro->scheme_name, cmpstr,
		    min(len, lstrlenA(inet_pro->scheme_name)))) {
	    y->nScheme = inet_pro->scheme_number;
	    break;
	}
	inet_pro++;
    }
    HeapFree(GetProcessHeap(), 0, cmpstr);
    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%08lx) 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 = dwFlags & URL_FILE_USE_PATHURL ? '\\' : '/';

    TRACE("(%s %p %p 0x%08lx)\n", debugstr_w(pszUrl), pszCanonicalized,
	  pcchCanonicalized, dwFlags);

    if(!pszUrl || !pszCanonicalized || !pcchCanonicalized)
	return E_INVALIDARG;

    nByteLen = (lstrlenW(pszUrl) + 1) * sizeof(WCHAR); /* length in bytes */
    lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nByteLen);

    if (dwFlags & URL_DONT_SIMPLIFY)
        memcpy(lpszUrlCpy, pszUrl, nByteLen);
    else {

	/*
	 * 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;
	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++ == L':') state = 2;
		break;
	    case 2:
		if (*wk1 != L'/') {state = 3; break;}
		*wk2++ = *wk1++;
		if (*wk1 != L'/') {state = 6; break;}
		*wk2++ = *wk1++;
                if((dwFlags & URL_FILE_USE_PATHURL) && *wk1 == '/')
                    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 != L'-') && (*wk1 != L'.') && (*wk1 != ':'))
                    {state = 3; break;}
                while(isalnumW(*wk1) || (*wk1 == L'-') || (*wk1 == L'.') || (*wk1 == ':'))
                    *wk2++ = *wk1++;
                state = 5;
                break;
            case 5:
                if (*wk1 != '/' && *wk1 != '\\') {state = 3; break;}
                while(*wk1 == '/') {
                    *wk2++ = slash;
                    wk1++;
                }
                state = 6;
		break;
	    case 6:
		/* Now at root location, cannot back up any more. */
		/* "root" will point at the '/' */
		root = wk2-1;
		while (*wk1) {
		    TRACE("wk1=%c\n", (CHAR)*wk1);

                    mp = strchrW(wk1, '/');
                    mp2 = strchrW(wk1, '\\');
                    if(mp2 && 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 == L'.') {
			TRACE("found '/.'\n");
                        if (wk1[1] == '/' || wk1[1] == '\\') {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -