[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