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

📄 webnsurlextras.mm

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 MM
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1.  Redistributions of source code must retain the above copyright *     notice, this list of conditions and the following disclaimer.  * 2.  Redistributions in binary form must reproduce the above copyright *     notice, this list of conditions and the following disclaimer in the *     documentation and/or other materials provided with the distribution.  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of *     its contributors may be used to endorse or promote products derived *     from this software without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#import "WebNSURLExtras.h"#import "WebKitNSStringExtras.h"#import "WebLocalizableStrings.h"#import "WebNSDataExtras.h"#import "WebNSObjectExtras.h"#import "WebSystemInterface.h"#import <Foundation/NSURLRequest.h>#import <WebCore/KURL.h>#import <WebCore/LoaderNSURLExtras.h>#import <WebKitSystemInterface.h>#import <wtf/Assertions.h>#import <unicode/uchar.h>#import <unicode/uidna.h>#import <unicode/uscript.h>using namespace WebCore;using namespace WTF;typedef void (* StringRangeApplierFunction)(NSString *string, NSRange range, void *context);// Needs to be big enough to hold an IDN-encoded name.// For host names bigger than this, we won't do IDN encoding, which is almost certainly OK.#define HOST_NAME_BUFFER_LENGTH 2048#define URL_BYTES_BUFFER_LENGTH 2048static pthread_once_t IDNScriptWhiteListFileRead = PTHREAD_ONCE_INIT;static uint32_t IDNScriptWhiteList[(USCRIPT_CODE_LIMIT + 31) / 32];static inline BOOL isLookalikeCharacter(int charCode){// FIXME: Move this code down into WebCore so it can be shared with other platforms.// This function treats the following as unsafe, lookalike characters:// any non-printable character, any character considered as whitespace that isn't already converted to a space by ICU, // and any ignorable character.// We also considered the characters in Mozilla's blacklist (http://kb.mozillazine.org/Network.IDN.blacklist_chars), // and included all of these characters that ICU can encode.    if (!u_isprint(charCode) || u_isUWhiteSpace(charCode) || u_hasBinaryProperty(charCode, UCHAR_DEFAULT_IGNORABLE_CODE_POINT))        return YES;    switch (charCode) {        case 0x01C3: /* LATIN LETTER RETROFLEX CLICK */        case 0x0337: /* COMBINING SHORT SOLIDUS OVERLAY */        case 0x0338: /* COMBINING LONG SOLIDUS OVERLAY */        case 0x05B4: /* HEBREW POINT HIRIQ */        case 0x05BC: /* HEBREW POINT DAGESH OR MAPIQ */        case 0x05C3: /* HEBREW PUNCTUATION SOF PASUQ */        case 0x05F4: /* HEBREW PUNCTUATION GERSHAYIM */        case 0x0660: /* ARABIC INDIC DIGIT ZERO */        case 0x06D4: /* ARABIC FULL STOP */        case 0x06F0: /* EXTENDED ARABIC INDIC DIGIT ZERO */        case 0x2027: /* HYPHENATION POINT */        case 0x2039: /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */        case 0x203A: /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */        case 0x2044: /* FRACTION SLASH */        case 0x2215: /* DIVISION SLASH */        case 0x23ae: /* INTEGRAL EXTENSION */        case 0x2571: /* BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT */        case 0x29F8: /* BIG SOLIDUS */        case 0x29f6: /* SOLIDUS WITH OVERBAR */        case 0x2AFB: /* TRIPLE SOLIDUS BINARY RELATION */        case 0x2AFD: /* DOUBLE SOLIDUS OPERATOR */        case 0x3008: /* LEFT ANGLE BRACKET */        case 0x3014: /* LEFT TORTOISE SHELL BRACKET */        case 0x3015: /* RIGHT TORTOISE SHELL BRACKET */        case 0x3033: /* VERTICAL KANA REPEAT MARK UPPER HALF */        case 0x321D: /* PARENTHESIZED KOREAN CHARACTER OJEON */        case 0x321E: /* PARENTHESIZED KOREAN CHARACTER O HU */        case 0x33DF: /* SQUARE A OVER M */        case 0xFE14: /* PRESENTATION FORM FOR VERTICAL SEMICOLON */        case 0xFE15: /* PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK */        case 0xFE3F: /* PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET */        case 0xFE5D: /* SMALL LEFT TORTOISE SHELL BRACKET */        case 0xFE5E: /* SMALL RIGHT TORTOISE SHELL BRACKET */            return YES;        default:            return NO;    }}static char hexDigit(int i){    if (i < 0 || i > 16) {        LOG_ERROR("illegal hex digit");        return '0';    }    int h = i;    if (h >= 10) {        h = h - 10 + 'A';     }    else {        h += '0';    }    return h;}static BOOL isHexDigit(char c){    return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');}static int hexDigitValue(char c){    if (c >= '0' && c <= '9') {        return c - '0';    }    if (c >= 'A' && c <= 'F') {        return c - 'A' + 10;    }    if (c >= 'a' && c <= 'f') {        return c - 'a' + 10;    }    LOG_ERROR("illegal hex digit");    return 0;}static void applyHostNameFunctionToMailToURLString(NSString *string, StringRangeApplierFunction f, void *context){    // In a mailto: URL, host names come after a '@' character and end with a '>' or ',' or '?' character.    // Skip quoted strings so that characters in them don't confuse us.    // When we find a '?' character, we are past the part of the URL that contains host names.    static NSCharacterSet *hostNameOrStringStartCharacters;    if (hostNameOrStringStartCharacters == nil) {        hostNameOrStringStartCharacters = [NSCharacterSet characterSetWithCharactersInString:@"\"@?"];        CFRetain(hostNameOrStringStartCharacters);    }    static NSCharacterSet *hostNameEndCharacters;    if (hostNameEndCharacters == nil) {        hostNameEndCharacters = [NSCharacterSet characterSetWithCharactersInString:@">,?"];        CFRetain(hostNameEndCharacters);    }    static NSCharacterSet *quotedStringCharacters;    if (quotedStringCharacters == nil) {        quotedStringCharacters = [NSCharacterSet characterSetWithCharactersInString:@"\"\\"];        CFRetain(quotedStringCharacters);    }    unsigned stringLength = [string length];    NSRange remaining = NSMakeRange(0, stringLength);        while (1) {        // Find start of host name or of quoted string.        NSRange hostNameOrStringStart = [string rangeOfCharacterFromSet:hostNameOrStringStartCharacters options:0 range:remaining];        if (hostNameOrStringStart.location == NSNotFound) {            return;        }        unichar c = [string characterAtIndex:hostNameOrStringStart.location];        remaining.location = NSMaxRange(hostNameOrStringStart);        remaining.length = stringLength - remaining.location;        if (c == '?') {            return;        }                if (c == '@') {            // Find end of host name.            unsigned hostNameStart = remaining.location;            NSRange hostNameEnd = [string rangeOfCharacterFromSet:hostNameEndCharacters options:0 range:remaining];            BOOL done;            if (hostNameEnd.location == NSNotFound) {                hostNameEnd.location = stringLength;                done = YES;            } else {                remaining.location = hostNameEnd.location;                remaining.length = stringLength - remaining.location;                done = NO;            }            // Process host name range.            f(string, NSMakeRange(hostNameStart, hostNameEnd.location - hostNameStart), context);            if (done) {                return;            }        } else {            // Skip quoted string.            ASSERT(c == '"');            while (1) {                NSRange escapedCharacterOrStringEnd = [string rangeOfCharacterFromSet:quotedStringCharacters options:0 range:remaining];                if (escapedCharacterOrStringEnd.location == NSNotFound) {                    return;                }                c = [string characterAtIndex:escapedCharacterOrStringEnd.location];                remaining.location = NSMaxRange(escapedCharacterOrStringEnd);                remaining.length = stringLength - remaining.location;                                // If we are the end of the string, then break from the string loop back to the host name loop.                if (c == '"') {                    break;                }                                // Skip escaped character.                ASSERT(c == '\\');                if (remaining.length == 0) {                    return;                }                                remaining.location += 1;                remaining.length -= 1;            }        }    }}static void applyHostNameFunctionToURLString(NSString *string, StringRangeApplierFunction f, void *context){    // Find hostnames. Too bad we can't use any real URL-parsing code to do this,    // but we have to do it before doing all the %-escaping, and this is the only    // code we have that parses mailto URLs anyway.    // Maybe we should implement this using a character buffer instead?    if ([string _webkit_hasCaseInsensitivePrefix:@"mailto:"]) {        applyHostNameFunctionToMailToURLString(string, f, context);        return;    }    // Find the host name in a hierarchical URL.    // It comes after a "://" sequence, with scheme characters preceding.    // If ends with the end of the string or a ":", "/", or a "?".    // If there is a "@" character, the host part is just the part after the "@".    NSRange separatorRange = [string rangeOfString:@"://"];    if (separatorRange.location == NSNotFound) {        return;    }    // Check that all characters before the :// are valid scheme characters.    static NSCharacterSet *nonSchemeCharacters;    if (nonSchemeCharacters == nil) {        nonSchemeCharacters = [[NSCharacterSet characterSetWithCharactersInString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-."] invertedSet];        CFRetain(nonSchemeCharacters);    }    if ([string rangeOfCharacterFromSet:nonSchemeCharacters options:0 range:NSMakeRange(0, separatorRange.location)].location != NSNotFound) {        return;    }    unsigned stringLength = [string length];    static NSCharacterSet *hostTerminators;    if (hostTerminators == nil) {        hostTerminators = [NSCharacterSet characterSetWithCharactersInString:@":/?#"];        CFRetain(hostTerminators);    }    // Start after the separator.    unsigned authorityStart = NSMaxRange(separatorRange);    // Find terminating character.    NSRange hostNameTerminator = [string rangeOfCharacterFromSet:hostTerminators options:0 range:NSMakeRange(authorityStart, stringLength - authorityStart)];    unsigned hostNameEnd = hostNameTerminator.location == NSNotFound ? stringLength : hostNameTerminator.location;    // Find "@" for the start of the host name.    NSRange userInfoTerminator = [string rangeOfString:@"@" options:0 range:NSMakeRange(authorityStart, hostNameEnd - authorityStart)];    unsigned hostNameStart = userInfoTerminator.location == NSNotFound ? authorityStart : NSMaxRange(userInfoTerminator);    f(string, NSMakeRange(hostNameStart, hostNameEnd - hostNameStart), context);}@implementation NSURL (WebNSURLExtras)static void collectRangesThatNeedMapping(NSString *string, NSRange range, void *context, BOOL encode){    BOOL needsMapping = encode        ? [string _web_hostNameNeedsEncodingWithRange:range]        : [string _web_hostNameNeedsDecodingWithRange:range];    if (!needsMapping) {        return;    }    NSMutableArray **array = (NSMutableArray **)context;    if (*array == nil) {        *array = [[NSMutableArray alloc] init];    }    [*array addObject:[NSValue valueWithRange:range]];}static void collectRangesThatNeedEncoding(NSString *string, NSRange range, void *context){    return collectRangesThatNeedMapping(string, range, context, YES);}static void collectRangesThatNeedDecoding(NSString *string, NSRange range, void *context){    return collectRangesThatNeedMapping(string, range, context, NO);}static NSString *mapHostNames(NSString *string, BOOL encode){    // Generally, we want to optimize for the case where there is one host name that does not need mapping.        if (encode && [string canBeConvertedToEncoding:NSASCIIStringEncoding])        return string;    // Make a list of ranges that actually need mapping.    NSMutableArray *hostNameRanges = nil;    StringRangeApplierFunction f = encode        ? collectRangesThatNeedEncoding        : collectRangesThatNeedDecoding;    applyHostNameFunctionToURLString(string, f, &hostNameRanges);    if (hostNameRanges == nil)        return string;    // Do the mapping.    NSMutableString *mutableCopy = [string mutableCopy];    unsigned i = [hostNameRanges count];    while (i-- != 0) {        NSRange hostNameRange = [[hostNameRanges objectAtIndex:i] rangeValue];        NSString *mappedHostName = encode            ? [string _web_encodeHostNameWithRange:hostNameRange]            : [string _web_decodeHostNameWithRange:hostNameRange];        [mutableCopy replaceCharactersInRange:hostNameRange withString:mappedHostName];    }    [hostNameRanges release];    return [mutableCopy autorelease];}+ (NSURL *)_web_URLWithUserTypedString:(NSString *)string relativeToURL:(NSURL *)URL{    if (string == nil) {        return nil;    }    string = mapHostNames([string _webkit_stringByTrimmingWhitespace], YES);    NSData *userTypedData = [string dataUsingEncoding:NSUTF8StringEncoding];    ASSERT(userTypedData);    const UInt8 *inBytes = static_cast<const UInt8 *>([userTypedData bytes]);    int inLength = [userTypedData length];    if (inLength == 0) {        return [NSURL URLWithString:@""];    }        char *outBytes = static_cast<char *>(malloc(inLength * 3)); // large enough to %-escape every character    char *p = outBytes;    int outLength = 0;    int i;    for (i = 0; i < inLength; i++) {        UInt8 c = inBytes[i];        if (c <= 0x20 || c >= 0x7f) {            *p++ = '%';            *p++ = hexDigit(c >> 4);            *p++ = hexDigit(c & 0xf);            outLength += 3;

⌨️ 快捷键说明

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