[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677

cblu cblu at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 06:57:21 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit cf54a60415098c1c37bbda534a733f572941c1e1
Author: cblu <cblu at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Nov 6 00:27:06 2002 +0000

    WebKit:
    
    	Fixed: 3074108 - Decode macbinary files during download
    
            * Downloads.subproj/WebDownloadDecoder.h:
            * Downloads.subproj/WebDownloadHandler.h:
            * Downloads.subproj/WebDownloadHandler.m:
            (-[WebDownloadHandler initWithDataSource:]):
            (-[WebDownloadHandler dealloc]):
            (-[WebDownloadHandler decodeHeaderData:dataForkData:resourceForkData:]):
            (-[WebDownloadHandler decodeData:dataForkData:resourceForkData:]):
            (-[WebDownloadHandler closeFile]):
            (-[WebDownloadHandler cleanUpAfterFailure]):
            (-[WebDownloadHandler createFileIfNecessary]):
            (-[WebDownloadHandler writeData:toFork:]):
            (-[WebDownloadHandler writeDataForkData:resourceForkData:]):
            (-[WebDownloadHandler dataIfDoneBufferingData:]):
            (-[WebDownloadHandler receivedData:]):
            (-[WebDownloadHandler finishDecoding]):
            (-[WebDownloadHandler finishedLoading]):
            (-[WebDownloadHandler cancel]):
            * Downloads.subproj/WebMacBinaryDecoder.h:
            * Downloads.subproj/WebMacBinaryDecoder.m:
            (-[WebMacBinaryDecoder decodeData:dataForkData:resourceForkData:]):
            (-[WebMacBinaryDecoder fileAttributes]):
            (-[WebMacBinaryDecoder filename]):
            * Misc.subproj/WebKitErrors.h: added new errors
            * WebView.subproj/WebMainResourceClient.m:
            (-[WebMainResourceClient handle:didReceiveResponse:]): don't send response to download handler
            (-[WebMainResourceClient handle:didReceiveData:]): watch for decoding errors
    
    WebBrowser:
    
    	Fixed: 3074108 - Decode macbinary files during download
    
            * DownloadMonitor.m:
            (-[DownloadMonitor identifierForInitialRequest:fromDataSource:]):
            (-[DownloadMonitor resource:willSendRequest:fromDataSource:]):
            (-[DownloadMonitor resource:didReceiveResponse:fromDataSource:]):
            * DownloadProgressEntry.h:
            * DownloadProgressEntry.m:
            (+[DownloadProgressEntry entryWithDictionary:]): new, convenience
            (+[DownloadProgressEntry entryWithDataSource:]):
            (-[DownloadProgressEntry filename]):
            (-[DownloadProgressEntry path]):
            (-[DownloadProgressEntry setCompleted]):
            * DownloadRow.m:
            (-[DownloadRow _updateStatusFields]):
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2566 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index 05250ba..68c5f6c 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,34 @@
+2002-11-05  Chris Blumenberg  <cblu at apple.com>
+
+	Fixed: 3074108 - Decode macbinary files during download
+
+        * Downloads.subproj/WebDownloadDecoder.h:
+        * Downloads.subproj/WebDownloadHandler.h:
+        * Downloads.subproj/WebDownloadHandler.m:
+        (-[WebDownloadHandler initWithDataSource:]):
+        (-[WebDownloadHandler dealloc]):
+        (-[WebDownloadHandler decodeHeaderData:dataForkData:resourceForkData:]):
+        (-[WebDownloadHandler decodeData:dataForkData:resourceForkData:]):
+        (-[WebDownloadHandler closeFile]):
+        (-[WebDownloadHandler cleanUpAfterFailure]):
+        (-[WebDownloadHandler createFileIfNecessary]):
+        (-[WebDownloadHandler writeData:toFork:]):
+        (-[WebDownloadHandler writeDataForkData:resourceForkData:]):
+        (-[WebDownloadHandler dataIfDoneBufferingData:]):
+        (-[WebDownloadHandler receivedData:]):
+        (-[WebDownloadHandler finishDecoding]):
+        (-[WebDownloadHandler finishedLoading]):
+        (-[WebDownloadHandler cancel]):
+        * Downloads.subproj/WebMacBinaryDecoder.h:
+        * Downloads.subproj/WebMacBinaryDecoder.m:
+        (-[WebMacBinaryDecoder decodeData:dataForkData:resourceForkData:]):
+        (-[WebMacBinaryDecoder fileAttributes]):
+        (-[WebMacBinaryDecoder filename]):
+        * Misc.subproj/WebKitErrors.h: added new errors
+        * WebView.subproj/WebMainResourceClient.m:
+        (-[WebMainResourceClient handle:didReceiveResponse:]): don't send response to download handler
+        (-[WebMainResourceClient handle:didReceiveData:]): watch for decoding errors
+
 2002-11-05  Ken Kocienda  <kocienda at apple.com>
 
 	Fix for this bug:
diff --git a/WebKit/ChangeLog-2002-12-03 b/WebKit/ChangeLog-2002-12-03
index 05250ba..68c5f6c 100644
--- a/WebKit/ChangeLog-2002-12-03
+++ b/WebKit/ChangeLog-2002-12-03
@@ -1,3 +1,34 @@
+2002-11-05  Chris Blumenberg  <cblu at apple.com>
+
+	Fixed: 3074108 - Decode macbinary files during download
+
+        * Downloads.subproj/WebDownloadDecoder.h:
+        * Downloads.subproj/WebDownloadHandler.h:
+        * Downloads.subproj/WebDownloadHandler.m:
+        (-[WebDownloadHandler initWithDataSource:]):
+        (-[WebDownloadHandler dealloc]):
+        (-[WebDownloadHandler decodeHeaderData:dataForkData:resourceForkData:]):
+        (-[WebDownloadHandler decodeData:dataForkData:resourceForkData:]):
+        (-[WebDownloadHandler closeFile]):
+        (-[WebDownloadHandler cleanUpAfterFailure]):
+        (-[WebDownloadHandler createFileIfNecessary]):
+        (-[WebDownloadHandler writeData:toFork:]):
+        (-[WebDownloadHandler writeDataForkData:resourceForkData:]):
+        (-[WebDownloadHandler dataIfDoneBufferingData:]):
+        (-[WebDownloadHandler receivedData:]):
+        (-[WebDownloadHandler finishDecoding]):
+        (-[WebDownloadHandler finishedLoading]):
+        (-[WebDownloadHandler cancel]):
+        * Downloads.subproj/WebMacBinaryDecoder.h:
+        * Downloads.subproj/WebMacBinaryDecoder.m:
+        (-[WebMacBinaryDecoder decodeData:dataForkData:resourceForkData:]):
+        (-[WebMacBinaryDecoder fileAttributes]):
+        (-[WebMacBinaryDecoder filename]):
+        * Misc.subproj/WebKitErrors.h: added new errors
+        * WebView.subproj/WebMainResourceClient.m:
+        (-[WebMainResourceClient handle:didReceiveResponse:]): don't send response to download handler
+        (-[WebMainResourceClient handle:didReceiveData:]): watch for decoding errors
+
 2002-11-05  Ken Kocienda  <kocienda at apple.com>
 
 	Fix for this bug:
diff --git a/WebKit/Downloads.subproj/WebDownload.h b/WebKit/Downloads.subproj/WebDownload.h
index 0596849..634b809 100644
--- a/WebKit/Downloads.subproj/WebDownload.h
+++ b/WebKit/Downloads.subproj/WebDownload.h
@@ -15,12 +15,20 @@
 @interface WebDownloadHandler : NSObject
 {
     WebDataSource *dataSource;
-    NSFileHandle *fileHandle;
+    
+    NSArray *decoderClasses;
+    NSMutableArray *decoderSequence;
+    NSMutableData *bufferedData;
+
+    FSRef fileRef;
+    FSRefPtr fileRefPtr;
+    
+    SInt16 dataForkRefNum;
+    SInt16 resourceForkRefNum;
 }
 
 - initWithDataSource:(WebDataSource *)dSource;
-- (WebError *)receivedResponse:(WebResourceResponse *)response; 
-- (void)receivedData:(NSData *)data;
+- (WebError *)receivedData:(NSData *)data;
 - (WebError *)finishedLoading;
-- (WebError *)cancel;
+- (void)cancel;
 @end
diff --git a/WebKit/Downloads.subproj/WebDownload.m b/WebKit/Downloads.subproj/WebDownload.m
index b879f10..eb110bf 100644
--- a/WebKit/Downloads.subproj/WebDownload.m
+++ b/WebKit/Downloads.subproj/WebDownload.m
@@ -8,13 +8,17 @@
 
 #import <WebKit/WebControllerPolicyDelegatePrivate.h>
 #import <WebKit/WebDataSourcePrivate.h>
+#import <WebKit/WebDownloadDecoder.h>
 #import <WebKit/WebDownloadHandler.h>
 #import <WebKit/WebKitErrors.h>
 #import <WebKit/WebKitLogging.h>
+#import <WebKit/WebMacBinaryDecoder.h>
 
 #import <WebFoundation/WebError.h>
 #import <WebFoundation/WebResourceRequest.h>
 
+#define MinimumHeaderLength 8192
+
 @implementation WebDownloadHandler
 
 - initWithDataSource:(WebDataSource *)dSource
@@ -22,15 +26,20 @@
     [super init];
     
     dataSource = [dSource retain];
+
+    decoderClasses = [[NSArray arrayWithObjects:[WebMacBinaryDecoder class], nil] retain];
+    
     LOG(Download, "Download started for: %s", [[[[dSource request] URL] absoluteString] cString]);
     return self;
 }
 
 - (void)dealloc
 {
-    [fileHandle release];
+    [bufferedData release];
     [dataSource release];
-    
+    [decoderClasses release];
+    [decoderSequence removeAllObjects];
+    [decoderSequence release];
     [super dealloc];
 }
 
@@ -39,53 +48,297 @@
     return [WebError errorWithCode:code inDomain:WebErrorDomainWebKit failingURL:[[dataSource URL] absoluteString]];
 }
 
-- (WebError *)receivedResponse:(WebResourceResponse *)response
+- (void)decodeHeaderData:(NSData *)headerData
+            dataForkData:(NSData **)dataForkData
+        resourceForkData:(NSData **)resourceForkData
+{
+    ASSERT(headerData);
+    ASSERT(dataForkData);
+    ASSERT(resourceForkData);
+    
+    NSObject <WebDownloadDecoder> *decoder;
+    BOOL didDecode;
+    unsigned i;
+
+    for(i=0; i<[decoderClasses count]; i++){
+        Class DecoderClass = [decoderClasses objectAtIndex:i];
+
+        if([DecoderClass canDecodeHeaderData:headerData]){
+            decoder = [[[DecoderClass alloc] init] autorelease];
+            didDecode = [decoder decodeData:headerData dataForkData:dataForkData resourceForkData:resourceForkData];
+
+            if(!didDecode){
+                // Though the decoder said it could decode the header, actual decoding failed. Shouldn't happen.
+                ERROR("Download decoder \"%s\" failed to decode header even though it claimed to handle it.",
+                      [[decoder className] lossyCString]);
+                continue;
+            }
+
+            [decoderSequence addObject:decoder];
+            
+            [self decodeHeaderData:*dataForkData dataForkData:dataForkData resourceForkData:resourceForkData];
+            break;
+        }
+    }
+}
+
+- (BOOL)decodeData:(NSData *)data
+      dataForkData:(NSData **)dataForkData
+  resourceForkData:(NSData **)resourceForkData
+{
+    ASSERT(data);
+    ASSERT([data length]);
+    ASSERT(dataForkData);
+    ASSERT(resourceForkData);
+    
+    if(!decoderSequence){
+        decoderSequence = [[NSMutableArray array] retain];
+        [self decodeHeaderData:data dataForkData:dataForkData resourceForkData:resourceForkData];
+    }
+    else{
+
+        NSObject <WebDownloadDecoder> *decoder;
+        BOOL didDecode;
+        unsigned i;
+        
+        for(i=0; i<[decoderSequence count]; i++){
+            decoder = [decoderSequence objectAtIndex:i];            
+            didDecode = [decoder decodeData:data dataForkData:dataForkData resourceForkData:resourceForkData];
+    
+            if(!didDecode){
+                return NO;
+            }
+            
+            data = *dataForkData;
+        }
+    }
+
+    if([decoderSequence count] == 0){
+        *dataForkData = data;
+        *resourceForkData = nil;
+    }
+    
+    return YES;
+}
+
+- (void)closeFile
+{
+    FSCloseFork(dataForkRefNum);
+    FSCloseFork(resourceForkRefNum);
+}
+
+- (void)cleanUpAfterFailure
 {
     NSString *path = [[dataSource contentPolicy] path];
+
+    [self closeFile];
+    
+    [[NSFileManager defaultManager] removeFileAtPath:path handler:nil];
+
+    [[NSWorkspace sharedWorkspace] noteFileSystemChanged:path];
+}
+
+- (WebError *)createFileIfNecessary
+{
+    if(fileRefPtr){
+        return nil;
+    }
+    
     NSFileManager *fileManager = [NSFileManager defaultManager];
+    NSString *path = [[dataSource contentPolicy] path];
+    NSObject <WebDownloadDecoder> *lastDecoder = [decoderSequence lastObject];
+        
+    NSString *filename = [lastDecoder filename];
+
+    if(filename){
+        path = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:filename];
+    }
 
     if([fileManager fileExistsAtPath:path]){
         NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
         NSString *extension = [path pathExtension];
-        NSString *newPathWithoutExtension;
+        NSString *pathWithAppendedNumber;
         unsigned i;
-        
+
         for(i=1; 1; i++){
-            newPathWithoutExtension = [NSString stringWithFormat:@"%@-%d", pathWithoutExtension, i];
-            path = [newPathWithoutExtension stringByAppendingPathExtension:extension];
+            pathWithAppendedNumber = [NSString stringWithFormat:@"%@-%d", pathWithoutExtension, i];
+            path = [pathWithAppendedNumber stringByAppendingPathExtension:extension];
             if(![fileManager fileExistsAtPath:path]){
-                [[dataSource contentPolicy] _setPath:path];
                 break;
             }
         }
     }
 
-    if(![fileManager createFileAtPath:path contents:nil attributes:nil]){
+    [[dataSource contentPolicy] _setPath:path];
+
+    if(![fileManager createFileAtPath:path contents:nil attributes:[lastDecoder fileAttributes]]){
+        ERROR("-[NSFileManager createFileAtPath:contents:attributes:] failed.");
         return [self errorWithCode:WebErrorCannotCreateFile];
     }
 
-    fileHandle = [[NSFileHandle fileHandleForWritingAtPath:path] retain];
-    if(!fileHandle){
-        return [self errorWithCode:WebErrorCannotOpenFile];
+    [[NSWorkspace sharedWorkspace] noteFileSystemChanged:path];
+
+    OSErr result = FSPathMakeRef([path UTF8String], &fileRef, nil);
+    if(result == noErr){
+        fileRefPtr = &fileRef;
+    }else{
+        ERROR("FSPathMakeRef failed.");
+        [self cleanUpAfterFailure];
+        return [self errorWithCode:WebErrorCannotCreateFile];
     }
 
-    NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
-    [workspace noteFileSystemChanged:path];
+    return nil;
+}
+
+- (BOOL)writeData:(NSData *)data toFork:(SInt16 *)forkRefNum
+{
+    OSErr result;
+    
+    if(*forkRefNum == 0){
+        HFSUniStr255 forkName;
+        if(forkRefNum == &dataForkRefNum){
+            result = FSGetDataForkName(&forkName);
+        }else{
+            result = FSGetResourceForkName(&forkName);
+        }
+                
+        if(result != noErr){
+            ERROR("Couldn't get fork name of download file.");
+            return NO;
+        }
+
+        result = FSOpenFork(fileRefPtr, forkName.length, forkName.unicode, fsWrPerm, forkRefNum);
+        if(result != noErr){
+            ERROR("Couldn't open fork of download file.");
+            return NO;
+        }
+    }
+
+    result = FSWriteFork(*forkRefNum, fsAtMark, 0, [data length], [data bytes], NULL);
+    if(result != noErr){
+        ERROR("Couldn't write to fork of download file.");
+        return NO;
+    }
+
+    return YES;
+}
+
+- (WebError *)writeDataForkData:(NSData *)dataForkData resourceForkData:(NSData *)resourceForkData
+{
+    WebError *error = [self createFileIfNecessary];
+    if(error){
+        return error;
+    }
+    
+    BOOL didWrite = YES;
+    
+    if(dataForkData && [dataForkData length]){
+        didWrite = [self writeData:dataForkData toFork:&dataForkRefNum];
+    }
+
+    if(didWrite && resourceForkData && [resourceForkData length]){
+        didWrite = [self writeData:resourceForkData toFork:&resourceForkRefNum];
+    }
+
+    if(!didWrite){
+        ERROR("Writing to download file failed.");
+        [self cleanUpAfterFailure];
+        return [self errorWithCode:WebErrorCannotWriteToFile];
+    }
+
+    return nil;
+}
+
+- (NSData *)dataIfDoneBufferingData:(NSData *)data
+{
+    if(!bufferedData){
+        bufferedData = [[NSMutableData dataWithData:data] retain];
+    }else if([bufferedData length] == 0){
+        // When bufferedData's length is 0, we're done buffering.
+        return data;
+    }else{
+        // Append new data. 
+        [bufferedData appendData:data];
+    }
+
+    if([bufferedData length] >= MinimumHeaderLength){
+        // We've have enough now. Make a copy so we can set bufferedData's length to 0,
+        // so we're know we're done buffering.
+        data = [NSData dataWithData:bufferedData];
+        [bufferedData setLength:0];
+        return data;
+    }else{
+        // Keep buffering. The header is not big enough to determine the encoding sequence.
+        return nil;
+    }
+}
+
+- (WebError *)receivedData:(NSData *)data
+{
+    ASSERT(data);
+
+    if([data length] == 0){
+        // Workaround for 3093170.
+        return nil;
+    }
+    
+    data = [self dataIfDoneBufferingData:data];
+    if(!data){
+        return nil;
+    }	
+    
+    NSData *dataForkData, *resourceForkData;
+    
+    if(![self decodeData:data dataForkData:&dataForkData resourceForkData:&resourceForkData]){
+        ERROR("Download decoding failed.");
+        [self cleanUpAfterFailure];
+        return [self errorWithCode:WebErrorDownloadDecodingFailedMidStream];
+    }
+
+    WebError *error = [self writeDataForkData:dataForkData resourceForkData:resourceForkData];
+    if(error){
+        return error;
+    }
 
     return nil;
 }
 
-- (void)receivedData:(NSData *)data
+- (BOOL)finishDecoding
 {
-    [fileHandle writeData:data];
+    NSObject <WebDownloadDecoder> *decoder;
+    unsigned i;
+    
+    for(i=0; i<[decoderSequence count]; i++){
+        decoder = [decoderSequence objectAtIndex:i];
+        if(![decoder finishDecoding]){
+            return NO;
+        }
+    }
+
+    return YES;
 }
 
 - (WebError *)finishedLoading
 {
+    if(![self finishDecoding]){
+        ERROR("Download decoding failed.");
+        [self cleanUpAfterFailure];
+        return [self errorWithCode:WebErrorDownloadDecodingFailedToComplete];
+    }
+
+    if([bufferedData length] > 0){
+        // All data has been buffered because we never received MinimumHeaderLength or more.
+        // Write it out now.
+        WebError *error = [self writeDataForkData:bufferedData resourceForkData:nil];
+        if(error){
+            return error;
+        }
+    }
+
+    [self closeFile];
+
     NSString *path = [[dataSource contentPolicy] path];
     
-    [fileHandle closeFile];
-
     LOG(Download, "Download complete. Saved to: %s", [path cString]);
     
     if([[dataSource contentPolicy] policyAction] == WebContentPolicySaveAndOpenExternally){
@@ -97,18 +350,9 @@
     return nil;
 }
 
-- (WebError *)cancel
+- (void)cancel
 {
-    NSString *path = [[dataSource contentPolicy] path];
-    
-    [fileHandle closeFile];
-    if(![[NSFileManager defaultManager] removeFileAtPath:path handler:nil]){
-        return [self errorWithCode:WebErrorCannotRemoveFile];
-    }else{
-        [[NSWorkspace sharedWorkspace] noteFileSystemChanged:path];
-    }
-
-    return nil;
+    [self cleanUpAfterFailure];
 }
 
 
diff --git a/WebKit/Downloads.subproj/WebDownloadDecoder.h b/WebKit/Downloads.subproj/WebDownloadDecoder.h
index 0fef9c0..a35fc2a 100644
--- a/WebKit/Downloads.subproj/WebDownloadDecoder.h
+++ b/WebKit/Downloads.subproj/WebDownloadDecoder.h
@@ -28,6 +28,9 @@
 // NSFileModificationDate, NSFileHFSCreatorCode, NSFileHFSTypeCode, NSFileCreationDate
 // fileAttributes is called after finishDecoding.
 - (NSDictionary *)fileAttributes;
+
+- (NSString *)filename;
+
 @end
 
 
diff --git a/WebKit/Downloads.subproj/WebDownloadHandler.h b/WebKit/Downloads.subproj/WebDownloadHandler.h
index 0596849..634b809 100644
--- a/WebKit/Downloads.subproj/WebDownloadHandler.h
+++ b/WebKit/Downloads.subproj/WebDownloadHandler.h
@@ -15,12 +15,20 @@
 @interface WebDownloadHandler : NSObject
 {
     WebDataSource *dataSource;
-    NSFileHandle *fileHandle;
+    
+    NSArray *decoderClasses;
+    NSMutableArray *decoderSequence;
+    NSMutableData *bufferedData;
+
+    FSRef fileRef;
+    FSRefPtr fileRefPtr;
+    
+    SInt16 dataForkRefNum;
+    SInt16 resourceForkRefNum;
 }
 
 - initWithDataSource:(WebDataSource *)dSource;
-- (WebError *)receivedResponse:(WebResourceResponse *)response; 
-- (void)receivedData:(NSData *)data;
+- (WebError *)receivedData:(NSData *)data;
 - (WebError *)finishedLoading;
-- (WebError *)cancel;
+- (void)cancel;
 @end
diff --git a/WebKit/Downloads.subproj/WebDownloadHandler.m b/WebKit/Downloads.subproj/WebDownloadHandler.m
index b879f10..eb110bf 100644
--- a/WebKit/Downloads.subproj/WebDownloadHandler.m
+++ b/WebKit/Downloads.subproj/WebDownloadHandler.m
@@ -8,13 +8,17 @@
 
 #import <WebKit/WebControllerPolicyDelegatePrivate.h>
 #import <WebKit/WebDataSourcePrivate.h>
+#import <WebKit/WebDownloadDecoder.h>
 #import <WebKit/WebDownloadHandler.h>
 #import <WebKit/WebKitErrors.h>
 #import <WebKit/WebKitLogging.h>
+#import <WebKit/WebMacBinaryDecoder.h>
 
 #import <WebFoundation/WebError.h>
 #import <WebFoundation/WebResourceRequest.h>
 
+#define MinimumHeaderLength 8192
+
 @implementation WebDownloadHandler
 
 - initWithDataSource:(WebDataSource *)dSource
@@ -22,15 +26,20 @@
     [super init];
     
     dataSource = [dSource retain];
+
+    decoderClasses = [[NSArray arrayWithObjects:[WebMacBinaryDecoder class], nil] retain];
+    
     LOG(Download, "Download started for: %s", [[[[dSource request] URL] absoluteString] cString]);
     return self;
 }
 
 - (void)dealloc
 {
-    [fileHandle release];
+    [bufferedData release];
     [dataSource release];
-    
+    [decoderClasses release];
+    [decoderSequence removeAllObjects];
+    [decoderSequence release];
     [super dealloc];
 }
 
@@ -39,53 +48,297 @@
     return [WebError errorWithCode:code inDomain:WebErrorDomainWebKit failingURL:[[dataSource URL] absoluteString]];
 }
 
-- (WebError *)receivedResponse:(WebResourceResponse *)response
+- (void)decodeHeaderData:(NSData *)headerData
+            dataForkData:(NSData **)dataForkData
+        resourceForkData:(NSData **)resourceForkData
+{
+    ASSERT(headerData);
+    ASSERT(dataForkData);
+    ASSERT(resourceForkData);
+    
+    NSObject <WebDownloadDecoder> *decoder;
+    BOOL didDecode;
+    unsigned i;
+
+    for(i=0; i<[decoderClasses count]; i++){
+        Class DecoderClass = [decoderClasses objectAtIndex:i];
+
+        if([DecoderClass canDecodeHeaderData:headerData]){
+            decoder = [[[DecoderClass alloc] init] autorelease];
+            didDecode = [decoder decodeData:headerData dataForkData:dataForkData resourceForkData:resourceForkData];
+
+            if(!didDecode){
+                // Though the decoder said it could decode the header, actual decoding failed. Shouldn't happen.
+                ERROR("Download decoder \"%s\" failed to decode header even though it claimed to handle it.",
+                      [[decoder className] lossyCString]);
+                continue;
+            }
+
+            [decoderSequence addObject:decoder];
+            
+            [self decodeHeaderData:*dataForkData dataForkData:dataForkData resourceForkData:resourceForkData];
+            break;
+        }
+    }
+}
+
+- (BOOL)decodeData:(NSData *)data
+      dataForkData:(NSData **)dataForkData
+  resourceForkData:(NSData **)resourceForkData
+{
+    ASSERT(data);
+    ASSERT([data length]);
+    ASSERT(dataForkData);
+    ASSERT(resourceForkData);
+    
+    if(!decoderSequence){
+        decoderSequence = [[NSMutableArray array] retain];
+        [self decodeHeaderData:data dataForkData:dataForkData resourceForkData:resourceForkData];
+    }
+    else{
+
+        NSObject <WebDownloadDecoder> *decoder;
+        BOOL didDecode;
+        unsigned i;
+        
+        for(i=0; i<[decoderSequence count]; i++){
+            decoder = [decoderSequence objectAtIndex:i];            
+            didDecode = [decoder decodeData:data dataForkData:dataForkData resourceForkData:resourceForkData];
+    
+            if(!didDecode){
+                return NO;
+            }
+            
+            data = *dataForkData;
+        }
+    }
+
+    if([decoderSequence count] == 0){
+        *dataForkData = data;
+        *resourceForkData = nil;
+    }
+    
+    return YES;
+}
+
+- (void)closeFile
+{
+    FSCloseFork(dataForkRefNum);
+    FSCloseFork(resourceForkRefNum);
+}
+
+- (void)cleanUpAfterFailure
 {
     NSString *path = [[dataSource contentPolicy] path];
+
+    [self closeFile];
+    
+    [[NSFileManager defaultManager] removeFileAtPath:path handler:nil];
+
+    [[NSWorkspace sharedWorkspace] noteFileSystemChanged:path];
+}
+
+- (WebError *)createFileIfNecessary
+{
+    if(fileRefPtr){
+        return nil;
+    }
+    
     NSFileManager *fileManager = [NSFileManager defaultManager];
+    NSString *path = [[dataSource contentPolicy] path];
+    NSObject <WebDownloadDecoder> *lastDecoder = [decoderSequence lastObject];
+        
+    NSString *filename = [lastDecoder filename];
+
+    if(filename){
+        path = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:filename];
+    }
 
     if([fileManager fileExistsAtPath:path]){
         NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
         NSString *extension = [path pathExtension];
-        NSString *newPathWithoutExtension;
+        NSString *pathWithAppendedNumber;
         unsigned i;
-        
+
         for(i=1; 1; i++){
-            newPathWithoutExtension = [NSString stringWithFormat:@"%@-%d", pathWithoutExtension, i];
-            path = [newPathWithoutExtension stringByAppendingPathExtension:extension];
+            pathWithAppendedNumber = [NSString stringWithFormat:@"%@-%d", pathWithoutExtension, i];
+            path = [pathWithAppendedNumber stringByAppendingPathExtension:extension];
             if(![fileManager fileExistsAtPath:path]){
-                [[dataSource contentPolicy] _setPath:path];
                 break;
             }
         }
     }
 
-    if(![fileManager createFileAtPath:path contents:nil attributes:nil]){
+    [[dataSource contentPolicy] _setPath:path];
+
+    if(![fileManager createFileAtPath:path contents:nil attributes:[lastDecoder fileAttributes]]){
+        ERROR("-[NSFileManager createFileAtPath:contents:attributes:] failed.");
         return [self errorWithCode:WebErrorCannotCreateFile];
     }
 
-    fileHandle = [[NSFileHandle fileHandleForWritingAtPath:path] retain];
-    if(!fileHandle){
-        return [self errorWithCode:WebErrorCannotOpenFile];
+    [[NSWorkspace sharedWorkspace] noteFileSystemChanged:path];
+
+    OSErr result = FSPathMakeRef([path UTF8String], &fileRef, nil);
+    if(result == noErr){
+        fileRefPtr = &fileRef;
+    }else{
+        ERROR("FSPathMakeRef failed.");
+        [self cleanUpAfterFailure];
+        return [self errorWithCode:WebErrorCannotCreateFile];
     }
 
-    NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
-    [workspace noteFileSystemChanged:path];
+    return nil;
+}
+
+- (BOOL)writeData:(NSData *)data toFork:(SInt16 *)forkRefNum
+{
+    OSErr result;
+    
+    if(*forkRefNum == 0){
+        HFSUniStr255 forkName;
+        if(forkRefNum == &dataForkRefNum){
+            result = FSGetDataForkName(&forkName);
+        }else{
+            result = FSGetResourceForkName(&forkName);
+        }
+                
+        if(result != noErr){
+            ERROR("Couldn't get fork name of download file.");
+            return NO;
+        }
+
+        result = FSOpenFork(fileRefPtr, forkName.length, forkName.unicode, fsWrPerm, forkRefNum);
+        if(result != noErr){
+            ERROR("Couldn't open fork of download file.");
+            return NO;
+        }
+    }
+
+    result = FSWriteFork(*forkRefNum, fsAtMark, 0, [data length], [data bytes], NULL);
+    if(result != noErr){
+        ERROR("Couldn't write to fork of download file.");
+        return NO;
+    }
+
+    return YES;
+}
+
+- (WebError *)writeDataForkData:(NSData *)dataForkData resourceForkData:(NSData *)resourceForkData
+{
+    WebError *error = [self createFileIfNecessary];
+    if(error){
+        return error;
+    }
+    
+    BOOL didWrite = YES;
+    
+    if(dataForkData && [dataForkData length]){
+        didWrite = [self writeData:dataForkData toFork:&dataForkRefNum];
+    }
+
+    if(didWrite && resourceForkData && [resourceForkData length]){
+        didWrite = [self writeData:resourceForkData toFork:&resourceForkRefNum];
+    }
+
+    if(!didWrite){
+        ERROR("Writing to download file failed.");
+        [self cleanUpAfterFailure];
+        return [self errorWithCode:WebErrorCannotWriteToFile];
+    }
+
+    return nil;
+}
+
+- (NSData *)dataIfDoneBufferingData:(NSData *)data
+{
+    if(!bufferedData){
+        bufferedData = [[NSMutableData dataWithData:data] retain];
+    }else if([bufferedData length] == 0){
+        // When bufferedData's length is 0, we're done buffering.
+        return data;
+    }else{
+        // Append new data. 
+        [bufferedData appendData:data];
+    }
+
+    if([bufferedData length] >= MinimumHeaderLength){
+        // We've have enough now. Make a copy so we can set bufferedData's length to 0,
+        // so we're know we're done buffering.
+        data = [NSData dataWithData:bufferedData];
+        [bufferedData setLength:0];
+        return data;
+    }else{
+        // Keep buffering. The header is not big enough to determine the encoding sequence.
+        return nil;
+    }
+}
+
+- (WebError *)receivedData:(NSData *)data
+{
+    ASSERT(data);
+
+    if([data length] == 0){
+        // Workaround for 3093170.
+        return nil;
+    }
+    
+    data = [self dataIfDoneBufferingData:data];
+    if(!data){
+        return nil;
+    }	
+    
+    NSData *dataForkData, *resourceForkData;
+    
+    if(![self decodeData:data dataForkData:&dataForkData resourceForkData:&resourceForkData]){
+        ERROR("Download decoding failed.");
+        [self cleanUpAfterFailure];
+        return [self errorWithCode:WebErrorDownloadDecodingFailedMidStream];
+    }
+
+    WebError *error = [self writeDataForkData:dataForkData resourceForkData:resourceForkData];
+    if(error){
+        return error;
+    }
 
     return nil;
 }
 
-- (void)receivedData:(NSData *)data
+- (BOOL)finishDecoding
 {
-    [fileHandle writeData:data];
+    NSObject <WebDownloadDecoder> *decoder;
+    unsigned i;
+    
+    for(i=0; i<[decoderSequence count]; i++){
+        decoder = [decoderSequence objectAtIndex:i];
+        if(![decoder finishDecoding]){
+            return NO;
+        }
+    }
+
+    return YES;
 }
 
 - (WebError *)finishedLoading
 {
+    if(![self finishDecoding]){
+        ERROR("Download decoding failed.");
+        [self cleanUpAfterFailure];
+        return [self errorWithCode:WebErrorDownloadDecodingFailedToComplete];
+    }
+
+    if([bufferedData length] > 0){
+        // All data has been buffered because we never received MinimumHeaderLength or more.
+        // Write it out now.
+        WebError *error = [self writeDataForkData:bufferedData resourceForkData:nil];
+        if(error){
+            return error;
+        }
+    }
+
+    [self closeFile];
+
     NSString *path = [[dataSource contentPolicy] path];
     
-    [fileHandle closeFile];
-
     LOG(Download, "Download complete. Saved to: %s", [path cString]);
     
     if([[dataSource contentPolicy] policyAction] == WebContentPolicySaveAndOpenExternally){
@@ -97,18 +350,9 @@
     return nil;
 }
 
-- (WebError *)cancel
+- (void)cancel
 {
-    NSString *path = [[dataSource contentPolicy] path];
-    
-    [fileHandle closeFile];
-    if(![[NSFileManager defaultManager] removeFileAtPath:path handler:nil]){
-        return [self errorWithCode:WebErrorCannotRemoveFile];
-    }else{
-        [[NSWorkspace sharedWorkspace] noteFileSystemChanged:path];
-    }
-
-    return nil;
+    [self cleanUpAfterFailure];
 }
 
 
diff --git a/WebKit/Downloads.subproj/WebMacBinaryDecoder.h b/WebKit/Downloads.subproj/WebMacBinaryDecoder.h
index f4b851f..c28c990 100644
--- a/WebKit/Downloads.subproj/WebMacBinaryDecoder.h
+++ b/WebKit/Downloads.subproj/WebMacBinaryDecoder.h
@@ -12,7 +12,7 @@
 {
     int _offset;
     
-    char _name[64];
+    unsigned char _name[64];
     int _dataForkLength;
     int _resourceForkLength;
     int _commentLength;
diff --git a/WebKit/Downloads.subproj/WebMacBinaryDecoder.m b/WebKit/Downloads.subproj/WebMacBinaryDecoder.m
index 35dcc92..1e105bc 100644
--- a/WebKit/Downloads.subproj/WebMacBinaryDecoder.m
+++ b/WebKit/Downloads.subproj/WebMacBinaryDecoder.m
@@ -76,8 +76,8 @@ enum {
     if (_offset == 0) {
         const u_int8_t *header = [data bytes];
         
-        ASSERT(header[1] <= sizeof(_name));
-        memcpy(_name, header + 1, header[1]);	// Copy the name
+        ASSERT(header[1] < sizeof(_name));
+        memcpy(_name, header + 1, header[1] + 1);	// Copy the name
         _fileType = (((((header[65] << 8) | header[66]) << 8) | header[67]) << 8) | header[68];
         _fileCreator = (((((header[69] << 8) | header[70]) << 8) | header[71]) << 8) | header[72];
         _dataForkLength = (((((header[83] << 8) | header[84]) << 8) | header[85]) << 8) | header[86];
@@ -128,7 +128,6 @@ enum {
 {
     ASSERT(_offset >= HEADER_SIZE);
     
-    // FIXME: What about the name?
     // FIXME: What about other parts of Finder info? Bundle bit, for example.
     return [NSDictionary dictionaryWithObjectsAndKeys:
         [NSDate dateWithTimeIntervalSinceReferenceDate:kCFAbsoluteTimeIntervalSince1904 + _creationDate], NSFileCreationDate,
@@ -138,4 +137,11 @@ enum {
         nil];
 }
 
+- (NSString *)filename
+{
+    // FIXME: We should use the encoding specified in the header if one is present.
+    return [(NSString *)CFStringCreateWithPascalString(NULL, _name, kCFStringEncodingMacRoman) autorelease];
+}
+
+
 @end
diff --git a/WebKit/Misc.subproj/WebKitErrors.h b/WebKit/Misc.subproj/WebKitErrors.h
index 538b320..f4cefc1 100644
--- a/WebKit/Misc.subproj/WebKitErrors.h
+++ b/WebKit/Misc.subproj/WebKitErrors.h
@@ -25,23 +25,27 @@ extern NSString *WebErrorDomainWebKit;
     @constant WebErrorCannotShowURL
     @constant WebErrorCannotNotFindApplicationForURL
     @constant WebErrorLocationChangeInterruptedByPolicyChange
+    @constant WebErrorDownloadDecodingFailedMidStream
+    @constant WebErrorDownloadDecodingFailedToComplete
 */
 enum {
-    WebErrorCannotFindFile = 10000,
-    WebErrorCannotCreateFile = 10001,
-    WebErrorCannotOpenFile = 10002,
-    WebErrorCannotReadFile = 10003,
-    WebErrorCannotWriteToFile = 10004,
-    WebErrorCannotRemoveFile = 10005,
-    WebErrorCannotFindApplicationForFile = 10006,
-    WebErrorFinderCannotOpenDirectory = 10007,
-    WebErrorCannotShowDirectory = 10008,
-    WebErrorCannotShowMIMEType = 10009,
-    WebErrorCannotShowURL = 10010,
-    WebErrorCannotNotFindApplicationForURL = 10011,
-    WebErrorLocationChangeInterruptedByPolicyChange = 10012,
-    WebErrorResourceLoadInterruptedByPolicyChange = 10013,
-    WebErrorCannotFindPlugin = 10014,
-    WebErrorCannotLoadPlugin = 10015,
-    WebErrorJavaUnavailable = 10016
+    WebErrorCannotFindFile,
+    WebErrorCannotCreateFile,
+    WebErrorCannotOpenFile,
+    WebErrorCannotReadFile,
+    WebErrorCannotWriteToFile,
+    WebErrorCannotRemoveFile,
+    WebErrorCannotFindApplicationForFile,
+    WebErrorFinderCannotOpenDirectory,
+    WebErrorCannotShowDirectory,
+    WebErrorCannotShowMIMEType,
+    WebErrorCannotShowURL,
+    WebErrorCannotNotFindApplicationForURL,
+    WebErrorLocationChangeInterruptedByPolicyChange,
+    WebErrorResourceLoadInterruptedByPolicyChange,
+    WebErrorCannotFindPlugin,
+    WebErrorCannotLoadPlugin,
+    WebErrorJavaUnavailable,
+    WebErrorDownloadDecodingFailedMidStream,
+    WebErrorDownloadDecodingFailedToComplete,
 };
diff --git a/WebKit/WebView.subproj/WebMainResourceClient.m b/WebKit/WebView.subproj/WebMainResourceClient.m
index ea362af..4b45280 100644
--- a/WebKit/WebView.subproj/WebMainResourceClient.m
+++ b/WebKit/WebView.subproj/WebMainResourceClient.m
@@ -188,12 +188,6 @@
             // handle delegate callbacks to go to the controller's download delegate.
             downloadHandler = [[WebDownloadHandler alloc] initWithDataSource:dataSource];
             [self setIsDownload: YES];
-            WebError *downloadError = [downloadHandler receivedResponse:r];
-            if (downloadError) {
-                [self receivedError:downloadError];
-                [handle cancel];
-                [[WebStandardPanels sharedStandardPanels] _didStopLoadingURL:currentURL inController:[dataSource controller]];
-            }
         }
         break;
     
@@ -215,15 +209,21 @@
 - (void)handle:(WebResourceHandle *)h didReceiveData:(NSData *)data
 {
     LOG(Loading, "URL = %@, data = %p, length %d", currentURL, data, [data length]);
-            
+
     if (downloadHandler) {
-        [downloadHandler receivedData:data];
+        WebError *downloadError = [downloadHandler receivedData:data];
+        if (downloadError) {
+            [self receivedError:downloadError];
+            [handle cancel];
+            [[WebStandardPanels sharedStandardPanels] _didStopLoadingURL:currentURL inController:[dataSource controller]];
+            return;
+        }
     } else {
         [resourceData appendData:data];
         [dataSource _receivedData:data];
         [[dataSource controller] _mainReceivedBytesSoFar:[resourceData length]
-                                                         fromDataSource:dataSource
-                                                               complete:NO];
+                                          fromDataSource:dataSource
+                                                complete:NO];
     }
     
     [super handle: h didReceiveData: data];
diff --git a/WebKit/WebView.subproj/WebMainResourceLoader.m b/WebKit/WebView.subproj/WebMainResourceLoader.m
index ea362af..4b45280 100644
--- a/WebKit/WebView.subproj/WebMainResourceLoader.m
+++ b/WebKit/WebView.subproj/WebMainResourceLoader.m
@@ -188,12 +188,6 @@
             // handle delegate callbacks to go to the controller's download delegate.
             downloadHandler = [[WebDownloadHandler alloc] initWithDataSource:dataSource];
             [self setIsDownload: YES];
-            WebError *downloadError = [downloadHandler receivedResponse:r];
-            if (downloadError) {
-                [self receivedError:downloadError];
-                [handle cancel];
-                [[WebStandardPanels sharedStandardPanels] _didStopLoadingURL:currentURL inController:[dataSource controller]];
-            }
         }
         break;
     
@@ -215,15 +209,21 @@
 - (void)handle:(WebResourceHandle *)h didReceiveData:(NSData *)data
 {
     LOG(Loading, "URL = %@, data = %p, length %d", currentURL, data, [data length]);
-            
+
     if (downloadHandler) {
-        [downloadHandler receivedData:data];
+        WebError *downloadError = [downloadHandler receivedData:data];
+        if (downloadError) {
+            [self receivedError:downloadError];
+            [handle cancel];
+            [[WebStandardPanels sharedStandardPanels] _didStopLoadingURL:currentURL inController:[dataSource controller]];
+            return;
+        }
     } else {
         [resourceData appendData:data];
         [dataSource _receivedData:data];
         [[dataSource controller] _mainReceivedBytesSoFar:[resourceData length]
-                                                         fromDataSource:dataSource
-                                                               complete:NO];
+                                          fromDataSource:dataSource
+                                                complete:NO];
     }
     
     [super handle: h didReceiveData: data];

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list