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

📄 url.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:

#define WINE_URL_BASH_AS_SLASH    0x01
#define WINE_URL_COLLAPSE_SLASHES 0x02
#define WINE_URL_ESCAPE_SLASH     0x04
#define WINE_URL_ESCAPE_HASH      0x08
#define WINE_URL_ESCAPE_QUESTION  0x10
#define WINE_URL_STOP_ON_HASH     0x20
#define WINE_URL_STOP_ON_QUESTION 0x40

static inline BOOL URL_NeedEscapeW(WCHAR ch, DWORD dwFlags, DWORD int_flags)
{

    if (isalnumW(ch))
        return FALSE;

    if(dwFlags & URL_ESCAPE_SPACES_ONLY) {
        if(ch == ' ')
	    return TRUE;
	else
	    return FALSE;
    }

    if ((dwFlags & URL_ESCAPE_PERCENT) && (ch == '%'))
	return TRUE;

    if (ch <= 31 || ch >= 127)
	return TRUE;

    else {
        switch (ch) {
	case ' ':
	case '<':
	case '>':
	case '\"':
	case '{':
	case '}':
	case '|':
	case '\\':
	case '^':
	case ']':
	case '[':
	case '`':
	case '&':
	    return TRUE;

	case '/':
            if (int_flags & WINE_URL_ESCAPE_SLASH) return TRUE;
            return FALSE;

	case '?':
	    if (int_flags & WINE_URL_ESCAPE_QUESTION) return TRUE;
            return FALSE;

        case '#':
            if (int_flags & WINE_URL_ESCAPE_HASH) return TRUE;
            return FALSE;

	default:
	    return FALSE;
	}
    }
}


/*************************************************************************
 *      UrlEscapeW	[SHLWAPI.@]
 *
 * Converts unsafe characters in a Url into escape sequences.
 *
 * PARAMS
 *  pszUrl      [I]   Url to modify
 *  pszEscaped  [O]   Destination for modified Url
 *  pcchEscaped [I/O] Length of pszUrl, destination for length of pszEscaped
 *  dwFlags     [I]   URL_ flags from "shlwapi.h"
 *
 * RETURNS
 *  Success: S_OK. pszEscaped contains the escaped Url, pcchEscaped
 *           contains its length.
 *  Failure: E_POINTER, if pszEscaped is not large enough. In this case
 *           pcchEscaped is set to the required length.
 *
 * Converts unsafe characters into their escape sequences.
 *
 * NOTES
 * - By default this function stops converting at the first '?' or
 *  '#' character.
 * - If dwFlags contains URL_ESCAPE_SPACES_ONLY then only spaces are
 *   converted, but the conversion continues past a '?' or '#'.
 * - Note that this function did not work well (or at all) in shlwapi version 4.
 *
 * BUGS
 *  Only the following flags are implemented:
 *|     URL_ESCAPE_SPACES_ONLY
 *|     URL_DONT_ESCAPE_EXTRA_INFO
 *|     URL_ESCAPE_SEGMENT_ONLY
 *|     URL_ESCAPE_PERCENT
 */
HRESULT WINAPI UrlEscapeW(
	LPCWSTR pszUrl,
	LPWSTR pszEscaped,
	LPDWORD pcchEscaped,
	DWORD dwFlags)
{
    LPCWSTR src;
    DWORD needed = 0, ret;
    BOOL stop_escaping = FALSE;
    WCHAR next[5], *dst = pszEscaped;
    INT len;
    PARSEDURLW parsed_url;
    DWORD int_flags;
    DWORD slashes = 0;
    static const WCHAR localhost[] = {'l','o','c','a','l','h','o','s','t',0};

    TRACE("(%s %p %p 0x%08x)\n", debugstr_w(pszUrl), pszEscaped,
	  pcchEscaped, dwFlags);

    if(!pszUrl || !pcchEscaped)
        return E_INVALIDARG;

    if(dwFlags & ~(URL_ESCAPE_SPACES_ONLY |
		   URL_ESCAPE_SEGMENT_ONLY |
		   URL_DONT_ESCAPE_EXTRA_INFO |
		   URL_ESCAPE_PERCENT))
        FIXME("Unimplemented flags: %08x\n", dwFlags);

    /* fix up flags */
    if (dwFlags & URL_ESCAPE_SPACES_ONLY)
	/* if SPACES_ONLY specified, reset the other controls */
	dwFlags &= ~(URL_DONT_ESCAPE_EXTRA_INFO |
		     URL_ESCAPE_PERCENT |
		     URL_ESCAPE_SEGMENT_ONLY);

    else
	/* if SPACES_ONLY *not* specified the assume DONT_ESCAPE_EXTRA_INFO */
	dwFlags |= URL_DONT_ESCAPE_EXTRA_INFO;


    int_flags = 0;
    if(dwFlags & URL_ESCAPE_SEGMENT_ONLY) {
        int_flags = WINE_URL_ESCAPE_QUESTION | WINE_URL_ESCAPE_HASH | WINE_URL_ESCAPE_SLASH;
    } else {
        parsed_url.cbSize = sizeof(parsed_url);
        if(ParseURLW(pszUrl, &parsed_url) != S_OK)
            parsed_url.nScheme = URL_SCHEME_INVALID;

        TRACE("scheme = %d (%s)\n", parsed_url.nScheme, debugstr_wn(parsed_url.pszProtocol, parsed_url.cchProtocol));

        if(dwFlags & URL_DONT_ESCAPE_EXTRA_INFO)
            int_flags = WINE_URL_STOP_ON_HASH | WINE_URL_STOP_ON_QUESTION;

        switch(parsed_url.nScheme) {
        case URL_SCHEME_FILE:
            int_flags |= WINE_URL_BASH_AS_SLASH | WINE_URL_COLLAPSE_SLASHES | WINE_URL_ESCAPE_HASH;
            int_flags &= ~WINE_URL_STOP_ON_HASH;
            break;

        case URL_SCHEME_HTTP:
        case URL_SCHEME_HTTPS:
            int_flags |= WINE_URL_BASH_AS_SLASH;
            if(parsed_url.pszSuffix[0] != '/' && parsed_url.pszSuffix[0] != '\\')
                int_flags |= WINE_URL_ESCAPE_SLASH;
            break;

        case URL_SCHEME_MAILTO:
            int_flags |= WINE_URL_ESCAPE_SLASH | WINE_URL_ESCAPE_QUESTION | WINE_URL_ESCAPE_HASH;
            int_flags &= ~(WINE_URL_STOP_ON_QUESTION | WINE_URL_STOP_ON_HASH);
            break;

        case URL_SCHEME_INVALID:
            break;

        case URL_SCHEME_FTP:
        default:
            if(parsed_url.pszSuffix[0] != '/')
                int_flags |= WINE_URL_ESCAPE_SLASH;
            break;
        }
    }

    for(src = pszUrl; *src; ) {
        WCHAR cur = *src;
        len = 0;
        
        if((int_flags & WINE_URL_COLLAPSE_SLASHES) && src == pszUrl + parsed_url.cchProtocol + 1) {
            int localhost_len = sizeof(localhost)/sizeof(WCHAR) - 1;
            while(cur == '/' || cur == '\\') {
                slashes++;
                cur = *++src;
            }
            if(slashes == 2 && !strncmpiW(src, localhost, localhost_len)) { /* file://localhost/ -> file:/// */
                if(*(src + localhost_len) == '/' || *(src + localhost_len) == '\\')
                src += localhost_len + 1;
                slashes = 3;
            }

            switch(slashes) {
            case 1:
            case 3:
                next[0] = next[1] = next[2] = '/';
                len = 3;
                break;
            case 0:
                len = 0;
                break;
            default:
                next[0] = next[1] = '/';
                len = 2;
                break;
            }
        }
        if(len == 0) {

            if(cur == '#' && (int_flags & WINE_URL_STOP_ON_HASH))
                stop_escaping = TRUE;

            if(cur == '?' && (int_flags & WINE_URL_STOP_ON_QUESTION))
                stop_escaping = TRUE;

            if(cur == '\\' && (int_flags & WINE_URL_BASH_AS_SLASH) && !stop_escaping) cur = '/';

            if(URL_NeedEscapeW(cur, dwFlags, int_flags) && stop_escaping == FALSE) {
                next[0] = '%';
                next[1] = hexDigits[(cur >> 4) & 0xf];
                next[2] = hexDigits[cur & 0xf];
                len = 3;
            } else {
                next[0] = cur;
                len = 1;
            }
            src++;
        }

	if(needed + len <= *pcchEscaped) {
	    memcpy(dst, next, len*sizeof(WCHAR));
	    dst += len;
	}
	needed += len;
    }

    if(needed < *pcchEscaped) {
        *dst = '\0';
	ret = S_OK;
    } else {
        needed++; /* add one for the '\0' */
	ret = E_POINTER;
    }
    *pcchEscaped = needed;
    return ret;
}


/*************************************************************************
 *      UrlUnescapeA	[SHLWAPI.@]
 *
 * Converts Url escape sequences back to ordinary characters.
 *
 * PARAMS
 *  pszUrl        [I/O]  Url to convert
 *  pszUnescaped  [O]    Destination for converted Url
 *  pcchUnescaped [I/O]  Size of output string
 *  dwFlags       [I]    URL_ESCAPE_ Flags from "shlwapi.h"
 *
 * RETURNS
 *  Success: S_OK. The converted value is in pszUnescaped, or in pszUrl if
 *           dwFlags includes URL_ESCAPE_INPLACE.
 *  Failure: E_POINTER if the converted Url is bigger than pcchUnescaped. In
 *           this case pcchUnescaped is set to the size required.
 * NOTES
 *  If dwFlags includes URL_DONT_ESCAPE_EXTRA_INFO, the conversion stops at
 *  the first occurrence of either a '?' or '#' character.
 */
HRESULT WINAPI UrlUnescapeA(
	LPSTR pszUrl,
	LPSTR pszUnescaped,
	LPDWORD pcchUnescaped,
	DWORD dwFlags)
{
    char *dst, next;
    LPCSTR src;
    HRESULT ret;
    DWORD needed;
    BOOL stop_unescaping = FALSE;

    TRACE("(%s, %p, %p, 0x%08x)\n", debugstr_a(pszUrl), pszUnescaped,
	  pcchUnescaped, dwFlags);

    if(!pszUrl || (!pszUnescaped && !(dwFlags & URL_UNESCAPE_INPLACE)) || !pcchUnescaped)
	return E_INVALIDARG;

    if(dwFlags & URL_UNESCAPE_INPLACE)
        dst = pszUrl;
    else
        dst = pszUnescaped;

    for(src = pszUrl, needed = 0; *src; src++, needed++) {
        if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO &&
	   (*src == '#' || *src == '?')) {
	    stop_unescaping = TRUE;
	    next = *src;
	} else if(*src == '%' && isxdigit(*(src + 1)) && isxdigit(*(src + 2))
		  && stop_unescaping == FALSE) {
	    INT ih;
	    char buf[3];
	    memcpy(buf, src + 1, 2);
	    buf[2] = '\0';
	    ih = strtol(buf, NULL, 16);
	    next = (CHAR) ih;
	    src += 2; /* Advance to end of escape */
	} else
	    next = *src;

	if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped)
	    *dst++ = next;
    }

    if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) {
        *dst = '\0';
	ret = S_OK;
    } else {
        needed++; /* add one for the '\0' */
	ret = E_POINTER;
    }
    if(!(dwFlags & URL_UNESCAPE_INPLACE))
        *pcchUnescaped = needed;

    if (ret == S_OK) {
	TRACE("result %s\n", (dwFlags & URL_UNESCAPE_INPLACE) ?
	      debugstr_a(pszUrl) : debugstr_a(pszUnescaped));
    }

    return ret;
}

/*************************************************************************
 *      UrlUnescapeW	[SHLWAPI.@]
 *
 * See UrlUnescapeA.
 */
HRESULT WINAPI UrlUnescapeW(
	LPWSTR pszUrl,
	LPWSTR pszUnescaped,
	LPDWORD pcchUnescaped,
	DWORD dwFlags)
{
    WCHAR *dst, next;
    LPCWSTR src;
    HRESULT ret;
    DWORD needed;
    BOOL stop_unescaping = FALSE;

    TRACE("(%s, %p, %p, 0x%08x)\n", debugstr_w(pszUrl), pszUnescaped,
	  pcchUnescaped, dwFlags);

    if(!pszUrl || (!pszUnescaped && !(dwFlags & URL_UNESCAPE_INPLACE))|| !pcchUnescaped)
	return E_INVALIDARG;

    if(dwFlags & URL_UNESCAPE_INPLACE)
        dst = pszUrl;
    else
        dst = pszUnescaped;

    for(src = pszUrl, needed = 0; *src; src++, needed++) {
        if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO &&
           (*src == '#' || *src == '?')) {
	    stop_unescaping = TRUE;
	    next = *src;
        } else if(*src == '%' && isxdigitW(*(src + 1)) && isxdigitW(*(src + 2))
		  && stop_unescaping == FALSE) {
	    INT ih;
	    WCHAR buf[5] = {'0','x',0};
	    memcpy(buf + 2, src + 1, 2*sizeof(WCHAR));
	    buf[4] = 0;
	    StrToIntExW(buf, STIF_SUPPORT_HEX, &ih);
	    next = (WCHAR) ih;
	    src += 2; /* Advance to end of escape */
	} else
	    next = *src;

	if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped)
	    *dst++ = next;
    }

    if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) {
        *dst = '\0';
	ret = S_OK;
    } else {
        needed++; /* add one for the '\0' */
	ret = E_POINTER;
    }
    if(!(dwFlags & URL_UNESCAPE_INPLACE))
        *pcchUnescaped = needed;

    if (ret == S_OK) {
	TRACE("result %s\n", (dwFlags & URL_UNESCAPE_INPLACE) ?
	      debugstr_w(pszUrl) : debugstr_w(pszUnescaped));
    }

    return ret;
}

/*************************************************************************
 *      UrlGetLocationA 	[SHLWAPI.@]
 *
 * Get the location from a Url.
 *
 * PARAMS
 *  pszUrl [I] Url to get the location from
 *
 * RETURNS
 *  A pointer to the start of the location in pszUrl, or NULL if there is
 *  no location.
 *
 * NOTES
 *  - MSDN erroneously states that "The location is the segment of the Url
 *    starting with a '?' or '#' character". Neither V4 nor V5 of shlwapi.dll
 *    stop at '?' and always return a NULL in this case.
 *  - MSDN also erroneously states that "If a file URL has a query string,
 *    the returned string is the query string". In all tested cases, if the
 *    Url starts with "fi" then a NULL is returned. V5 gives the following results:
 *|       Result   Url
 *|       ------   ---
 *|       NULL     file://aa/b/cd#hohoh
 *|       #hohoh   http://aa/b/cd#hohoh
 *|       NULL     fi://aa/b/cd#hohoh
 *|       #hohoh   ff://aa/b/cd#hohoh
 */
LPCSTR WINAPI UrlGetLocationA(
	LPCSTR pszUrl)
{
    PARSEDURLA base;
    DWORD res1;

⌨️ 快捷键说明

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