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

📄 url.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 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., 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 + -