Reviewed by John
authorkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Nov 2003 23:29:57 +0000 (23:29 +0000)
committerkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 14 Nov 2003 23:29:57 +0000 (23:29 +0000)
        Fix for this bug:

        <rdar://problem/3481701>: Crashes before loading page/no error msg
        (forums.pelicanparts.com) Works in IE and Netscape

        This fix is really a workaround for this bug:

        <rdar://problem/3484937>: Horribly malformed URL crashes when call
        is made to CFURLCopyHostName

        The fix is to avoid all usages of [NSURL host] by replacing all
        such calls with a private URL method added to WebNSURLExtras.

I copied a number of URL methods from the private NSURL
extras file in Foundation to the WebKit URL extras file.

        * Misc.subproj/WebNSDataExtras.h: Added. Helper for new URL extras.
        * Misc.subproj/WebNSDataExtras.m: Ditto.
        (-[NSData _web_isCaseInsensitiveEqualToCString:]): New helper.
        * Misc.subproj/WebNSURLExtras.h:
        * Misc.subproj/WebNSURLExtras.m:
        (-[NSURL _web_hasQuestionMarkOnlyQueryString]): Added.
        (-[NSURL _web_schemeSeparatorWithoutColon]): Added.
        (-[NSURL _web_dataForURLComponentType:]): Added.
        (-[NSURL _web_schemeData]): Added.
        (-[NSURL _web_hostData]): Added.
        (-[NSURL _web_hostString]): Added.
        * WebKit.pbproj/project.pbxproj:
        * WebView.subproj/WebView.m:
        (-[WebView userAgentForURL:]): Replace call to [NSURL host] with new
extras _web_hostString method.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@5502 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKit/ChangeLog
WebKit/Misc.subproj/WebNSDataExtras.h [new file with mode: 0644]
WebKit/Misc.subproj/WebNSDataExtras.m [new file with mode: 0644]
WebKit/Misc.subproj/WebNSURLExtras.h
WebKit/Misc.subproj/WebNSURLExtras.m
WebKit/WebKit.pbproj/project.pbxproj
WebKit/WebView.subproj/WebView.m

index b01dcdc59c40824683d37219523f6a7e08b99483..cf04bf9d9123a173a6bea18d6a801168ce900e77 100644 (file)
@@ -1,3 +1,39 @@
+2003-11-14  Ken Kocienda  <kocienda@apple.com>
+
+        Reviewed by John
+
+        Fix for this bug:
+
+        <rdar://problem/3481701>: Crashes before loading page/no error msg
+        (forums.pelicanparts.com) Works in IE and Netscape
+
+        This fix is really a workaround for this bug:
+
+        <rdar://problem/3484937>: Horribly malformed URL crashes when call
+        is made to CFURLCopyHostName
+
+        The fix is to avoid all usages of [NSURL host] by replacing all
+        such calls with a private URL method added to WebNSURLExtras.
+
+       I copied a number of URL methods from the private NSURL
+       extras file in Foundation to the WebKit URL extras file.
+
+        * Misc.subproj/WebNSDataExtras.h: Added. Helper for new URL extras.
+        * Misc.subproj/WebNSDataExtras.m: Ditto.
+        (-[NSData _web_isCaseInsensitiveEqualToCString:]): New helper.
+        * Misc.subproj/WebNSURLExtras.h:
+        * Misc.subproj/WebNSURLExtras.m:
+        (-[NSURL _web_hasQuestionMarkOnlyQueryString]): Added.
+        (-[NSURL _web_schemeSeparatorWithoutColon]): Added.
+        (-[NSURL _web_dataForURLComponentType:]): Added.
+        (-[NSURL _web_schemeData]): Added.
+        (-[NSURL _web_hostData]): Added.
+        (-[NSURL _web_hostString]): Added.
+        * WebKit.pbproj/project.pbxproj:
+        * WebView.subproj/WebView.m:
+        (-[WebView userAgentForURL:]): Replace call to [NSURL host] with new
+       extras _web_hostString method.
+
 === Safari-114 ===
 
 2003-11-14  Vicki Murley <vicki@apple.com>
diff --git a/WebKit/Misc.subproj/WebNSDataExtras.h b/WebKit/Misc.subproj/WebNSDataExtras.h
new file mode 100644 (file)
index 0000000..4a738b5
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+    WebNSURLExtras.h
+    Private (SPI) header
+    Copyright 2003, Apple, Inc. All rights reserved.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface NSData (WebNSURLExtras)
+
+-(BOOL)_web_isCaseInsensitiveEqualToCString:(const char *)string;
+
+@end
diff --git a/WebKit/Misc.subproj/WebNSDataExtras.m b/WebKit/Misc.subproj/WebNSDataExtras.m
new file mode 100644 (file)
index 0000000..3b5f482
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+    WebNSDataExtras.m
+    Private (SPI) header
+    Copyright 2003, Apple, Inc. All rights reserved.
+ */
+
+#import <WebKit/WebNSDataExtras.h>
+
+#import <WebKit/WebAssertions.h>
+
+@implementation NSData (WebNSDataExtras)
+
+-(BOOL)_web_isCaseInsensitiveEqualToCString:(const char *)string
+{
+    ASSERT(string);
+    
+    const char *bytes = [self bytes];
+    return strncasecmp(bytes, string, [self length]) == 0;
+}
+
+@end
index 033cc1f841fecc4f14ad29b2b44d686f641d7291..9fbfbe582daf5c3aab6d334120131a897d03de70 100644 (file)
@@ -20,6 +20,9 @@
 - (NSString *)_web_originalDataAsString;
 - (const char *)_web_URLCString;
 
+- (NSData *)_web_hostData;
+- (NSString *)_web_hostString;
+
 - (NSString *)_web_userVisibleString;
 
 - (BOOL)_web_isEmpty;
index 35fd836fc8558a6a0de74abc8d41a898c1989657..9f5ad82d4ce3177c16299f58f350fc45b094698f 100644 (file)
@@ -7,6 +7,7 @@
 #import <WebKit/WebNSURLExtras.h>
 
 #import <WebKit/WebAssertions.h>
+#import <WebKit/WebNSDataExtras.h>
 
 #import <Foundation/NSString_NSURLExtras.h>
 #import <Foundation/NSURLProtocolPrivate.h>
@@ -525,6 +526,120 @@ static NSString *mapHostNames(NSString *string, BOOL encode)
     return [[self _web_originalDataAsString] _web_hasCaseInsensitivePrefix:@"about:"] || [self _web_isEmpty];
 }
 
+-(BOOL)_web_hasQuestionMarkOnlyQueryString
+{
+    CFRange rangeWithSeparators;
+    CFURLGetByteRangeForComponent((CFURLRef)self, kCFURLComponentQuery, &rangeWithSeparators);
+    if (rangeWithSeparators.location != kCFNotFound && rangeWithSeparators.length == 1) {
+        return YES;
+    }
+    return NO;
+}
+
+-(NSData *)_web_schemeSeparatorWithoutColon
+{
+    NSData *result = nil;
+    CFRange rangeWithSeparators;
+    CFRange range = CFURLGetByteRangeForComponent((CFURLRef)self, kCFURLComponentScheme, &rangeWithSeparators);
+    if (rangeWithSeparators.location != kCFNotFound) {
+        NSString *absoluteString = [self absoluteString];
+        NSRange separatorsRange = NSMakeRange(range.location + range.length + 1, rangeWithSeparators.length - range.length - 1);
+        if (separatorsRange.location + separatorsRange.length <= [absoluteString length]) {
+            NSString *slashes = [absoluteString substringWithRange:separatorsRange];
+            result = [slashes dataUsingEncoding:NSISOLatin1StringEncoding];
+        }
+    }
+    return result;
+}
+
+#define completeURL (CFURLComponentType)-1
+
+-(NSData *)_web_dataForURLComponentType:(CFURLComponentType)componentType
+{
+    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 = 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 = [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];
+}
+
 @end
 
 @implementation NSString (WebNSURLExtras)
index 164c0674f4ff9e94dbb0629876a5b8c9fcc3da6c..2b55ef61446d547d6192485df4d4f87b5df2b36d 100644 (file)
                                ED21B9820528F7AA003299AC,
                                833987820543012D00EE146E,
                                BE26F18F05517E0800BFA0C3,
+                               BECD142B0565830A005BB09C,
                        );
                        isa = PBXHeadersBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                                BE6DC39C04C62C4E004D0EF6,
                                65DA2609052CC18700A97B31,
                                BE26F19005517E0800BFA0C3,
+                               BECD142C0565830A005BB09C,
                        );
                        isa = PBXSourcesBuildPhase;
                        runOnlyForDeploymentPostprocessing = 0;
                                BEE18F9A0472B73200CA289C,
                                9345DDB20365FFD0008635CE,
                                9345DDB30365FFD0008635CE,
+                               BECD14290565830A005BB09C,
+                               BECD142A0565830A005BB09C,
                                8398847A03426FB000BC5F5E,
                                8398847B03426FB000BC5F5E,
                                ED2B2474033A2DA800C1A526,
                        settings = {
                        };
                };
+               BECD14290565830A005BB09C = {
+                       expectedFileType = sourcecode.c.h;
+                       fileEncoding = 4;
+                       isa = PBXFileReference;
+                       path = WebNSDataExtras.h;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               BECD142A0565830A005BB09C = {
+                       expectedFileType = sourcecode.c.objc;
+                       fileEncoding = 4;
+                       isa = PBXFileReference;
+                       path = WebNSDataExtras.m;
+                       refType = 4;
+                       sourceTree = "<group>";
+               };
+               BECD142B0565830A005BB09C = {
+                       fileRef = BECD14290565830A005BB09C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
+               BECD142C0565830A005BB09C = {
+                       fileRef = BECD142A0565830A005BB09C;
+                       isa = PBXBuildFile;
+                       settings = {
+                       };
+               };
                BEE18F920472A0CF00CA289C = {
                        expectedFileType = sourcecode.c.h;
                        fileEncoding = 30;
index 64cad60006e86b66a8450723f731883d78457cef..0e91fd2faa221e5013b791d4b82d379d7c2baf24 100644 (file)
@@ -1517,7 +1517,7 @@ NS_ENDHANDLER
     // Look to see if we need to spoof.
     // First step is to get the host as a C-format string.
     UserAgentStringType type = Safari;
-    NSString *host = [URL host];
+    NSString *host = [URL _web_hostString];
     char hostBuffer[256];
     if (host && CFStringGetCString((CFStringRef)host, hostBuffer, sizeof(hostBuffer), kCFStringEncodingASCII)) {
         // Next step is to find the last part of the name.