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

📄 webnsurlextras.mm

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 MM
📖 第 1 页 / 共 3 页
字号:
    static int URLComponentTypeBufferLength = 2048;        UInt8 staticAllBytesBuffer[URLComponentTypeBufferLength];    UInt8 *allBytesBuffer = staticAllBytesBuffer;        CFIndex bytesFilled = CFURLGetBytes((CFURLRef)self, allBytesBuffer, URLComponentTypeBufferLength);    if (bytesFilled == -1) {        CFIndex bytesToAllocate = CFURLGetBytes((CFURLRef)self, NULL, 0);        allBytesBuffer = static_cast<UInt8 *>(malloc(bytesToAllocate));        bytesFilled = CFURLGetBytes((CFURLRef)self, allBytesBuffer, bytesToAllocate);    }        CFRange range;    if (componentType != completeURL) {        range = CFURLGetByteRangeForComponent((CFURLRef)self, componentType, NULL);        if (range.location == kCFNotFound) {            return nil;        }    }    else {        range.location = 0;        range.length = bytesFilled;    }        NSData *componentData = [NSData dataWithBytes:allBytesBuffer + range.location length:range.length];         const unsigned char *bytes = static_cast<const unsigned char *>([componentData bytes]);    NSMutableData *resultData = [NSMutableData data];    // NOTE: add leading '?' to query strings non-zero length query strings.    // NOTE: retain question-mark only query strings.    if (componentType == kCFURLComponentQuery) {        if (range.length > 0 || [self _web_hasQuestionMarkOnlyQueryString]) {            [resultData appendBytes:"?" length:1];            }    }    int i;    for (i = 0; i < range.length; i++) {        unsigned char c = bytes[i];        if (c <= 0x20 || c >= 0x7f) {            char escaped[3];            escaped[0] = '%';            escaped[1] = hexDigit(c >> 4);            escaped[2] = hexDigit(c & 0xf);            [resultData appendBytes:escaped length:3];            }        else {            char b[1];            b[0] = c;            [resultData appendBytes:b length:1];            }                   }        if (staticAllBytesBuffer != allBytesBuffer) {        free(allBytesBuffer);    }        return resultData;}-(NSData *)_web_schemeData{    return [self _web_dataForURLComponentType:kCFURLComponentScheme];}-(NSData *)_web_hostData{    NSData *result = [self _web_dataForURLComponentType:kCFURLComponentHost];    NSData *scheme = [self _web_schemeData];    // Take off localhost for file    if ([scheme _web_isCaseInsensitiveEqualToCString:"file"]) {        return ([result _web_isCaseInsensitiveEqualToCString:"localhost"]) ? nil : result;    }    return result;}- (NSString *)_web_hostString{    NSData *data = [self _web_hostData];    if (!data) {        data = [NSData data];    }    return [[[NSString alloc] initWithData:[self _web_hostData] encoding:NSUTF8StringEncoding] autorelease];}- (NSString *)_webkit_suggestedFilenameWithMIMEType:(NSString *)MIMEType{    return suggestedFilenameWithMIMEType(self, MIMEType);}@end@implementation NSString (WebNSURLExtras)- (BOOL)_web_isUserVisibleURL{    BOOL valid = YES;    // get buffer    char static_buffer[1024];    const char *p;    BOOL success = CFStringGetCString((CFStringRef)self, static_buffer, 1023, kCFStringEncodingUTF8);    if (success) {        p = static_buffer;    } else {        p = [self UTF8String];    }    int length = strlen(p);    // check for characters <= 0x20 or >=0x7f, %-escape sequences of %7f, and xn--, these    // are the things that will lead _web_userVisibleString to actually change things.    int i;    for (i = 0; i < length; i++) {        unsigned char c = p[i];        // escape control characters, space, and delete        if (c <= 0x20 || c == 0x7f) {            valid = NO;            break;        } else if (c == '%' && (i + 1 < length && isHexDigit(p[i + 1])) && i + 2 < length && isHexDigit(p[i + 2])) {            unsigned char u = (hexDigitValue(p[i + 1]) << 4) | hexDigitValue(p[i + 2]);            if (u > 0x7f) {                valid = NO;                break;            }            i += 2;        } else {            // Check for "xn--" in an efficient, non-case-sensitive, way.            if (c == '-' && i >= 3 && (p[i - 3] | 0x20) == 'x' && (p[i - 2] | 0x20) == 'n' && p[i - 1] == '-') {                valid = NO;                break;            }        }    }    return valid;}- (BOOL)_webkit_isJavaScriptURL{    return [self _webkit_hasCaseInsensitivePrefix:@"javascript:"];}- (BOOL)_webkit_isFileURL{    return [self rangeOfString:@"file:" options:(NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound;}- (NSString *)_webkit_stringByReplacingValidPercentEscapes{    return decodeURLEscapeSequences(self);}- (NSString *)_webkit_scriptIfJavaScriptURL{    if (![self _webkit_isJavaScriptURL]) {        return nil;    }    return [[self substringFromIndex:11] _webkit_stringByReplacingValidPercentEscapes];}- (BOOL)_webkit_isFTPDirectoryURL{    int length = [self length];    if (length < 5) {  // 5 is length of "ftp:/"        return NO;    }    unichar lastChar = [self characterAtIndex:length - 1];    return lastChar == '/' && [self _webkit_hasCaseInsensitivePrefix:@"ftp:"];}static BOOL readIDNScriptWhiteListFile(NSString *filename){    if (!filename) {        return NO;    }    FILE *file = fopen([filename fileSystemRepresentation], "r");    if (file == NULL) {        return NO;    }    // Read a word at a time.    // Allow comments, starting with # character to the end of the line.    while (1) {        // Skip a comment if present.        int result = fscanf(file, " #%*[^\n\r]%*[\n\r]");        if (result == EOF) {            break;        }        // Read a script name if present.        char word[33];        result = fscanf(file, " %32[^# \t\n\r]%*[^# \t\n\r] ", word);        if (result == EOF) {            break;        }        if (result == 1) {            // Got a word, map to script code and put it into the array.            int32_t script = u_getPropertyValueEnum(UCHAR_SCRIPT, word);            if (script >= 0 && script < USCRIPT_CODE_LIMIT) {                size_t index = script / 32;                uint32_t mask = 1 << (script % 32);                IDNScriptWhiteList[index] |= mask;            }        }    }    fclose(file);    return YES;}static void readIDNScriptWhiteList(void){    // Read white list from library.    NSArray *dirs = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSAllDomainsMask, YES);    int i, numDirs = [dirs count];    for (i = 0; i < numDirs; i++) {        NSString *dir = [dirs objectAtIndex:i];        if (readIDNScriptWhiteListFile([dir stringByAppendingPathComponent:@"IDNScriptWhiteList.txt"])) {            return;        }    }    // Fall back on white list inside bundle.    NSBundle *bundle = [NSBundle bundleWithIdentifier:@"com.apple.WebKit"];    readIDNScriptWhiteListFile([bundle pathForResource:@"IDNScriptWhiteList" ofType:@"txt"]);}static BOOL allCharactersInIDNScriptWhiteList(const UChar *buffer, int32_t length){    pthread_once(&IDNScriptWhiteListFileRead, readIDNScriptWhiteList);    int32_t i = 0;    while (i < length) {        UChar32 c;        U16_NEXT(buffer, i, length, c)        UErrorCode error = U_ZERO_ERROR;        UScriptCode script = uscript_getScript(c, &error);        if (error != U_ZERO_ERROR) {            LOG_ERROR("got ICU error while trying to look at scripts: %d", error);            return NO;        }        if (script < 0) {            LOG_ERROR("got negative number for script code from ICU: %d", script);            return NO;        }        if (script >= USCRIPT_CODE_LIMIT) {            return NO;        }        size_t index = script / 32;        uint32_t mask = 1 << (script % 32);        if (!(IDNScriptWhiteList[index] & mask)) {            return NO;        }        if (isLookalikeCharacter(c))            return NO;    }    return YES;}// Return value of nil means no mapping is necessary.// If makeString is NO, then return value is either nil or self to indicate mapping is necessary.// If makeString is YES, then return value is either nil or the mapped string.- (NSString *)_web_mapHostNameWithRange:(NSRange)range encode:(BOOL)encode makeString:(BOOL)makeString{    if (range.length > HOST_NAME_BUFFER_LENGTH) {        return nil;    }    if ([self length] == 0)        return nil;        UChar sourceBuffer[HOST_NAME_BUFFER_LENGTH];    UChar destinationBuffer[HOST_NAME_BUFFER_LENGTH];        NSString *string = self;    if (encode && [self rangeOfString:@"%" options:NSLiteralSearch range:range].location != NSNotFound) {        NSString *substring = [self substringWithRange:range];        substring = WebCFAutorelease(CFURLCreateStringByReplacingPercentEscapes(NULL, (CFStringRef)substring, CFSTR("")));        if (substring != nil) {            string = substring;            range = NSMakeRange(0, [string length]);        }    }        int length = range.length;    [string getCharacters:sourceBuffer range:range];    UErrorCode error = U_ZERO_ERROR;    int32_t numCharactersConverted = (encode ? uidna_IDNToASCII : uidna_IDNToUnicode)        (sourceBuffer, length, destinationBuffer, HOST_NAME_BUFFER_LENGTH, UIDNA_ALLOW_UNASSIGNED, NULL, &error);    if (error != U_ZERO_ERROR) {        return nil;    }    if (numCharactersConverted == length && memcmp(sourceBuffer, destinationBuffer, length * sizeof(UChar)) == 0) {        return nil;    }    if (!encode && !allCharactersInIDNScriptWhiteList(destinationBuffer, numCharactersConverted)) {        return nil;    }    return makeString ? (NSString *)[NSString stringWithCharacters:destinationBuffer length:numCharactersConverted] : (NSString *)self;}- (BOOL)_web_hostNameNeedsDecodingWithRange:(NSRange)range{    return [self _web_mapHostNameWithRange:range encode:NO makeString:NO] != nil;}- (BOOL)_web_hostNameNeedsEncodingWithRange:(NSRange)range{    return [self _web_mapHostNameWithRange:range encode:YES makeString:NO] != nil;}- (NSString *)_web_decodeHostNameWithRange:(NSRange)range{    return [self _web_mapHostNameWithRange:range encode:NO makeString:YES];}- (NSString *)_web_encodeHostNameWithRange:(NSRange)range{    return [self _web_mapHostNameWithRange:range encode:YES makeString:YES];}- (NSString *)_web_decodeHostName{    NSString *name = [self _web_mapHostNameWithRange:NSMakeRange(0, [self length]) encode:NO makeString:YES];    return name == nil ? self : name;}- (NSString *)_web_encodeHostName{    NSString *name = [self _web_mapHostNameWithRange:NSMakeRange(0, [self length]) encode:YES makeString:YES];    return name == nil ? self : name;}-(NSRange)_webkit_rangeOfURLScheme{    NSRange colon = [self rangeOfString:@":"];    if (colon.location != NSNotFound && colon.location > 0) {        NSRange scheme = {0, colon.location};        static NSCharacterSet *InverseSchemeCharacterSet = nil;        if (!InverseSchemeCharacterSet) {            /*             This stuff is very expensive.  10-15 msec on a 2x1.2GHz.  If not cached it swamps             everything else when adding items to the autocomplete DB.  Makes me wonder if we             even need to enforce the character set here.            */            NSString *acceptableCharacters = @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+.-";            InverseSchemeCharacterSet = [[[NSCharacterSet characterSetWithCharactersInString:acceptableCharacters] invertedSet] retain];        }        NSRange illegals = [self rangeOfCharacterFromSet:InverseSchemeCharacterSet options:0 range:scheme];        if (illegals.location == NSNotFound)            return scheme;    }    return NSMakeRange(NSNotFound, 0);}-(BOOL)_webkit_looksLikeAbsoluteURL{    // Trim whitespace because _web_URLWithString allows whitespace.    return [[self _webkit_stringByTrimmingWhitespace] _webkit_rangeOfURLScheme].location != NSNotFound;}- (NSString *)_webkit_URLFragment{    NSRange fragmentRange;        fragmentRange = [self rangeOfString:@"#" options:NSLiteralSearch];    if (fragmentRange.location == NSNotFound)        return nil;    return [self substringFromIndex:fragmentRange.location + 1];}@end

⌨️ 快捷键说明

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