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

kocienda kocienda at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 07:39:02 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit c7cad5604d7f1aca0a4cb2641e2819782ccda3e5
Author: kocienda <kocienda at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Apr 28 23:01:56 2003 +0000

    WebFoundation:
    
            Reviewed by Chris
    
    	Large reworking of NSURLResponse internals and
    	NSCachedURLResponse internals to move this code to
    	the API-approved design. Quite a bit of SPI has
    	shifted around as well.
    
            * CacheLoader.subproj/NSCachedURLResponse.h:
    	Name change: WebCacheObjectInternal -> NSCachedURLResponseInternal.
    
    	Added new init methods that conform to approved API. Removed old
    	initWithResponse: init method.
    
    	Also removed a host of other cache-related accessors and methods:
    	createdDate, setCreatedDate:, expiresDate, setExpiresDate:,
    	lastModifiedDate, setLastModifiedDate:, maxAgeValue, setMaxAgeValue:,
    	mustRevalidate, setMustRevalidate:, isExpired, age, and
    	freshnessLifetime. The getters have moved to SPI on NSURLResponse. The
    	setters have been obsoleted as there are now default values in the
    	case of non-HTTP responses, and the information can be derived from
    	the HTTP header in all cases for HTTP responses.
    
    	Removed: objectSize and setObjectSize: methods. This figure can be
    	derived from the length of the NSCachedURLResponse's data field.
    
    	Removed: canStoreInMemory, setCanStoreInMemory:, canStoreOnDisk, and
    	setCanStoreOnDisk: methods. These are obsoleted by the new
    	NSURLCacheStoragePolicy API construct.
    
    
            * CacheLoader.subproj/NSCachedURLResponse.m:
    
    	Name change: WebCacheObjectVersion -> NSCachedURLResponseVersion.
    	Bumped the version number as well.
    
    	Removed instance variables used for now-obsoleted getter and setter
    	methods.
    
    	Added NSData, user-info NSDictionary and NSURLCacheStoragePolicy
    	instance variables, and added the API-approved getters for them.
    
    	Added implementation for new init methods; removed old init method
    	implementation.
    
    	Modified copy and coding methods accordingly.
    
    	Removed all method implementations mentioned in the
    	NSCachedURLResponse.h comment.
    
    
            * CacheLoader.subproj/NSURLCache.m:
            (-[NSURLCache storeCacheObject:forKey:]): Rewrote implementation
    	to use new NSURLCacheStoragePolicy construct in place of older
    	canCache accessors.
    
    
            * CacheLoader.subproj/NSURLCachePrivate.h: Added _cacheStatistics
    	SPI method that used to be API but did not make the cut.
    
            * CacheLoader.subproj/NSURLConnection.m:
            (-[NSURLConnection _didFinishReturnCachedResponse:]): Use new
    	API to access cache object data.
            (-[NSURLConnection _didFinishLoading]): Use new API to create
    	an NSCachedURLResponse.
    
    
            * CacheLoader.subproj/NSURLResponse.h: Now implements NSCopying.
    
    
            * CacheLoader.subproj/NSURLResponse.m:
    
    	Bumped NSURLResponseVersion.
    
    	Removed createdTime and lastModifiedTime instance variables from
    	NSURLResponseInternal. Added createdDate instance variable. This is
    	part of the new way to track this information in responses.
    
    	Removed resourceData instance variable from NSURLResponseInternal.
    	This is no longer stored in the response object; it has moved to
    	NSCachedURLResponse.
    
    	Fixed silly retain of a static string in NSURLResponseInternal.
    
    	Updated NSURLResponseInternal dealloc and coding methods for new
    	instance variable set.
    
    	Added copyWithZone: method.
    
    	Removed accessors for obsoleted instance variables.
    
    	Added SPI accessor methods to NSURLResponseInternal: _createdDate,
    	_expiresDate, _lastModifiedDate, _maxAge, _mustRevalidate, and
    	_freshnessLifetime. Most of these return default values that give
    	objects very permissive cache constraints.
    
    	Name change: WebHTTPResponseVersion -> NSHTTPURLResponseVersion.
    	Bumped the value.
    
    	Added a collection of transient instance variables to
    	NSHTTPURLResponseInternal to track the values the HTTP response
    	subclass returns for _createdDate, _expiresDate, _lastModifiedDate,
    	_maxAge, _mustRevalidate, and _freshnessLifetime methods.
    
    	Updated NSHTTPURLResponseInternal dealloc method for new instance
    	variable set.
    
    	Name change in NSHTTPURLResponseInternal: setHeader: ->
    	setAllHeaderFields:.
    
    	Added SPI accessor methods: _createdDate, _expiresDate,
    	_lastModifiedDate, _maxAge, _mustRevalidate, and _freshnessLifetime
    	that use HTTP header information to return protocol-correct values.
    	Added _parseCacheControl helper method.
    
    
            * CacheLoader.subproj/NSURLResponsePrivate.h:
    
    	Removed a collection of accessors having to do with cache processing
    	and replaced with a modified set of SPI methods which work
    	together with API-approved NSURLResponse and NSCachedURLResponse
    	designs.
    
    
            * CacheLoader.subproj/WebCacheObjectPrivate.h: Removed.
    
    
            * CacheLoader.subproj/WebDiskCache.m:
            (-[WebDiskCache storeCacheObject:forKey:]): Access NSCachedURLResponse
    	data instance variable to determine the size of a cache object.
            (-[WebDiskCache removeCacheObjectForKey:]): Ditto.
    
    
            * CacheLoader.subproj/WebMemoryCache.m:
            (-[WebMemoryCache _truncateToSizeLimit]): Ditto.
            (-[WebMemoryCache storeCacheObject:forKey:]): Ditto.
    
    
            * Downloads.subproj/NSURLDownload.m:
            (-[NSURLDownload _createFileIfNecessary]): _createdDate is now
    	NSURLResponse SPI, not API.
    
    
            * Misc.subproj/WebNSCalendarDateExtras.h: Modified convenience method:
    
    	+(NSTimeInterval)_web_timeIntervalFromHTTPDateString:(NSString *)string
    	   is now
    	+(NSDate *)_web_dateFromHTTPDateString:(NSString *)string
    
    
            * Misc.subproj/WebNSCalendarDateExtras.m:
            (+[NSCalendarDate _web_dateFromHTTPDateString:]): Ditto.
    
    
            * Misc.subproj/WebNSStringExtras.h: Added a new method:
    	-(BOOL)_web_hasCaseInsensitiveSubstring:(NSString *)substring;
    
    
            * Misc.subproj/WebNSStringExtras.m: Ditto.
            (-[NSString _web_hasCaseInsensitiveSubstring:]):
    
    
            * ProtocolHandlers.subproj/WebCFNetworkHTTPProtocol.m:
            (-[WebCFNetworkHTTPProtocol addConditionalFieldsToHeader]): Use new
    	_web_dateFromHTTPDateString: method.
    
    
            * ProtocolHandlers.subproj/WebHTTPProtocol.h: Remove unused
    	timeIntervalFromHTTPResponseHeader: method.
    
    
            * ProtocolHandlers.subproj/WebHTTPProtocol.m: Ditto.
    
    	Modify a wide range of cache-related methods to use new API and
    	SPI made available by NSURLResponse and NSCachedURLResponse. In
    	many cases, this involved deleting code that now lives in one
    	of these two classes, which allows the protocol to rely more
    	on helpers.
            (-[WebHTTPProtocol cachedResponseMustBeRevalidated]):
            (-[WebHTTPProtocol _cachedResponseHasExpired]):
            (-[WebHTTPProtocol HTTPResponse]):
            (-[WebHTTPProtocol _cachePolicyForResponse]):
            (-[WebHTTPProtocol setResponseHeader:]):
    
            * ProtocolHandlers.subproj/WebSimpleHTTPProtocol.m:
            (-[WebSimpleHTTPProtocol buildHTTPRequest]): Tweaks to call new-style
    	NSURLResponse and NSCachedURLResponse accessors.
    
    
            * WebFoundation.pbproj/project.pbxproj: PB knows best.
    
    WebKit:
    
            Reviewed by Chris
    
            * Plugins.subproj/WebBaseNetscapePluginStream.m:
            (-[WebBaseNetscapePluginStream setResponse:]): _lastModifiedDate on
    	NSURLResponse is now SPI.
            * WebView.subproj/WebDataSourcePrivate.m:
            (-[WebDataSource _commitIfReady:]): Ditto.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@4200 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebKit/ChangeLog b/WebKit/ChangeLog
index 8ae3f0d..cdd0846 100644
--- a/WebKit/ChangeLog
+++ b/WebKit/ChangeLog
@@ -1,3 +1,13 @@
+2003-04-28  Ken Kocienda  <kocienda at apple.com>
+
+        Reviewed by Chris
+
+        * Plugins.subproj/WebBaseNetscapePluginStream.m:
+        (-[WebBaseNetscapePluginStream setResponse:]): _lastModifiedDate on
+	NSURLResponse is now SPI.
+        * WebView.subproj/WebDataSourcePrivate.m:
+        (-[WebDataSource _commitIfReady:]): Ditto.
+
 2003-04-27  Chris Blumenberg  <cblu at apple.com>
 
 	Improved headerdoc comments.	
diff --git a/WebKit/Downloads.subproj/WebDownload.m b/WebKit/Downloads.subproj/WebDownload.m
new file mode 100644
index 0000000..0a6bbde
--- /dev/null
+++ b/WebKit/Downloads.subproj/WebDownload.m
@@ -0,0 +1,995 @@
+//
+//  WebDownload.m
+//  WebKit
+//
+//  Created by Chris Blumenberg on Thu Apr 11 2002.
+//  Copyright (c) 2003 Apple Computer, Inc.
+//
+
+#import <WebKit/WebDownloadPrivate.h>
+
+#import <WebKit/WebBinHexDecoder.h>
+#import <WebKit/WebDownloadDecoder.h>
+#import <WebKit/WebGZipDecoder.h>
+#import <WebKit/WebKitErrorsPrivate.h>
+#import <WebKit/WebKitLogging.h>
+#import <WebKit/WebMacBinaryDecoder.h>
+#import <WebKit/WebMainResourceClient.h>
+#import <WebKit/WebNSWorkspaceExtras.h>
+
+#import <WebFoundation/WebNSErrorExtras.h>
+#import <WebFoundation/WebNSFileManagerExtras.h>
+#import <WebFoundation/WebNSStringExtras.h>
+#import <WebFoundation/NSURLRequest.h>
+#import <WebFoundation/NSURLConnection.h>
+#import <WebFoundation/NSURLResponse.h>
+#import <WebFoundation/NSURLResponsePrivate.h>
+
+typedef struct WebFSForkIOParam
+{
+    FSForkIOParam paramBlock;
+    WebDownload *download;
+    NSData *data;
+} WebFSForkIOParam;
+
+typedef struct WebFSRefParam
+{
+    FSRefParam paramBlock;
+    WebDownload *download;
+} WebFSRefParam;
+
+ at interface WebDownloadPrivate : NSObject
+{
+ at public
+    NSMutableArray *decoderSequence;
+    NSMutableData *bufferedData;
+
+    FSRefPtr fileRefPtr;
+
+    SInt16 dataForkRefNum;
+    SInt16 resourceForkRefNum;
+
+    BOOL deleteFile;
+    BOOL isDownloading;
+    BOOL areWritesCancelled;
+    BOOL encounteredCloseError;
+
+    NSURLConnection *connection;
+    NSURLRequest *request;
+    NSURLResponse *response;
+    WebResourceDelegateProxy *proxy;
+
+    id delegate;
+
+    NSString *path;
+    NSString *tempPath;
+    NSString *directoryPath;
+}
+ at end
+
+static NSArray *decoderClasses = nil;
+
+static void WriteCompletionCallback(ParmBlkPtr paramBlock);
+static void CloseCompletionCallback(ParmBlkPtr paramBlock);
+static void DeleteCompletionCallback(ParmBlkPtr paramBlock);
+
+ at interface WebDownload (ForwardDeclarations)
+#pragma mark LOADING
+- (void)_downloadStarted;
+- (void)_downloadEnded;
+- (void)_setRequest:(NSURLRequest *)request;
+- (void)_setResponse:(NSURLResponse *)response;
+#pragma mark CREATING
+- (NSString *)_pathWithUniqueFilenameForPath:(NSString *)path;
+- (BOOL)_createFSRefForPath:(NSString *)path;
+- (BOOL)_createFileIfNecessary;
+#pragma mark DECODING
+- (void)_decodeHeaderData:(NSData *)headerData dataForkData:(NSData **)dataForkData resourceForkData:(NSData **)resourceForkData;
+- (BOOL)_decodeData:(NSData *)data dataForkData:(NSData **)dataForkData resourceForkData:(NSData **)resourceForkData;
+- (NSError *)_decodeData:(NSData *)data;
+- (NSData *)_dataIfDoneBufferingData:(NSData *)data;
+- (BOOL)_finishDecoding;
+#pragma mark WRITING
+- (BOOL)_writeForkData:(NSData *)data isDataFork:(BOOL)isDataFork;
+- (NSError *)_writeDataForkData:(NSData *)dataForkData resourceForkData:(NSData *)resourceForkData;
+#pragma mark CLOSING;
+- (BOOL)_isFileClosed;
+- (void)_didCloseFile:(NSError *)error;
+- (void)_closeForkAsync:(SInt16)forkRefNum;
+- (BOOL)_closeForkSync:(SInt16)forkRefNum;
+- (void)_closeFileAsync;
+- (BOOL)_closeFileSync;
+#pragma mark DELETING
+- (void)_didDeleteFile;
+- (void)_deleteFileAsnyc;
+- (void)_closeAndDeleteFileAsync;
+- (void)_cancelWithError:(NSError *)error;
+- (void)_cancelWithErrorCode:(int)code;
+#pragma mark MISC
+- (void)_setDelegate:(id)delegate;
+- (void)_setPath:(NSString *)path;
+- (NSString *)_currentPath;
+- (NSError *)_errorWithCode:(int)code;
+- (SInt16)_dataForkReferenceNumber;
+- (void)_setDataForkReferenceNumber:(SInt16)forkRefNum;
+- (SInt16)_resourceForkReferenceNumber;
+- (void)_setResourceForkReferenceNumber:(SInt16)forkRefNum;
+- (BOOL)_areWritesCancelled;
+- (void)_setWritesCancelled:(BOOL)cancelled;
+- (BOOL)_encounteredCloseError;
+- (void)_setEncounteredCloseError:(BOOL)encounteredCloseError;
+ at end
+
+ at implementation WebDownloadPrivate
+
++ (void)initialize
+{
+    decoderClasses = [[NSArray arrayWithObjects:
+        [WebBinHexDecoder class],
+        [WebMacBinaryDecoder class],
+        [WebGZipDecoder class],
+        nil] retain];
+}
+
+- (void)dealloc
+{
+    ASSERT(!connection);
+    ASSERT(!delegate);
+    ASSERT(!isDownloading);
+
+    free(fileRefPtr);
+    
+    [bufferedData release];
+    [decoderSequence release];
+    [request release];
+    [connection release];
+    [response release];
+    [proxy setDelegate:nil];
+    [proxy release];
+    [path release];
+    [tempPath release];
+    [directoryPath release];
+    [super dealloc];
+}
+
+ at end
+
+ at implementation WebDownload
+
+- initWithRequest:(NSURLRequest *)request
+{
+    ASSERT(request);
+    
+    [super init];
+    
+    _private = [[WebDownloadPrivate alloc] init];
+    _private->request = [request retain];
+    
+    return self;
+}
+
+- _initWithLoadingResource:(NSURLConnection *)connection
+                   request:(NSURLRequest *)request
+                  response:(NSURLResponse *)response
+                  delegate:(id)delegate
+                     proxy:(WebResourceDelegateProxy *)proxy
+{
+    [super init];
+     
+    _private = [[WebDownloadPrivate alloc] init];
+    [self _downloadStarted];
+    
+    _private->request =  [request retain];
+    _private->connection = [connection retain];
+    _private->response = [response retain];
+    _private->proxy = 	 [proxy retain];
+    [self _setDelegate:delegate];
+    [_private->proxy setDelegate:self];
+
+    // Replay the delegate methods that would be called in the standalone download case.
+    if ([_private->delegate respondsToSelector:@selector(download:didStartFromRequest:)]) {
+        [_private->delegate download:self didStartFromRequest:_private->request];
+    }
+
+    if ([_private->delegate respondsToSelector:@selector(download:willSendRequest:redirectResponse:)]) {
+        NSURLRequest *request = [_private->delegate download:self willSendRequest:_private->request redirectResponse:nil];
+        if (request != _private->request) {
+            // If the request is altered, cancel the connection and start a new one.
+            [self cancel];
+            if (request) {
+                [self _setRequest:request];
+                [self _setResponse:nil];
+                [_private->connection release];
+                _private->connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
+                [self _downloadStarted];
+            }
+            return self;
+        }
+    }
+
+    if ([_private->delegate respondsToSelector:@selector(download:didReceiveResponse:)]) {
+        [_private->delegate download:self didReceiveResponse:_private->response];
+    }
+    
+    return self;
+}
+
++ _downloadWithLoadingResource:(NSURLConnection *)connection
+                       request:(NSURLRequest *)request
+                      response:(NSURLResponse *)response
+                      delegate:(id)delegate
+                         proxy:(WebResourceDelegateProxy *)proxy
+{
+    return [[[WebDownload alloc] _initWithLoadingResource:connection
+                                                  request:request
+                                                 response:response
+                                                 delegate:delegate
+                                                    proxy:proxy] autorelease];
+}
+
+- (void)dealloc
+{
+    [_private release];
+    [super dealloc];
+}
+
+- (void)loadWithDelegate:(id)delegate
+{
+    if (!_private->isDownloading) {
+        [self _setDelegate:delegate];
+        // send this synthetic delegate callback since clients expect it, and
+        // we no longer send the callback from within NSURLConnection for
+        // initial requests.
+        NSURLRequest *request = [self connection:nil willSendRequest:_private->request redirectResponse:nil];
+        _private->connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
+        [self _downloadStarted];
+        
+        if ([_private->delegate respondsToSelector:@selector(download:didStartFromRequest:)]) {
+            [_private->delegate download:self didStartFromRequest:request];
+        }
+    }
+}
+
+- (void)cancel
+{
+    [self _cancelWithError:nil];
+}
+
+- (NSString *)path
+{
+    return _private->path;
+}
+
+// setPath: is not public. This is the WebDownloadDecisionListener method.
+- (void)setPath:(NSString *)path
+{
+    [self _setPath:path];
+}
+
+#pragma mark LOADING
+
+- (void)_downloadStarted
+{
+    if (!_private->isDownloading) {
+        _private->isDownloading = YES;
+        
+        // Retain self while loading so we aren't released during the load.
+        [self retain];
+    }
+}
+
+- (void)_downloadEnded
+{
+    if (_private->isDownloading) {
+        _private->isDownloading = NO;
+
+        [_private->connection release];
+        _private->connection = nil;
+
+        [self _setDelegate:nil];
+
+        // Balance the retain from when the load started.
+        [self release];
+    }
+}
+
+- (void)_setRequest:(NSURLRequest *)request
+{
+    if (_private->request != request) {
+        [_private->request release];
+        _private->request = [request retain];
+    }
+}
+
+- (void)_setResponse:(NSURLResponse *)response
+{
+    if (_private->response != response) {
+        [_private->response release];
+        _private->response = [response retain];
+    }
+}
+
+- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)theRequest redirectResponse:(NSURLResponse *)redirectResponse
+{
+    NSURLRequest *request = nil;
+    
+    if ([_private->delegate respondsToSelector:@selector(download:willSendRequest:redirectResponse:)]) {
+        request = [_private->delegate download:self willSendRequest:theRequest redirectResponse:redirectResponse];
+    } else {
+        request = theRequest;
+    }
+
+    [self _setRequest:request];
+    
+    if (!request) {
+        [self _downloadEnded];
+    }
+
+    return request;
+}
+
+- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
+{
+    [self _setResponse:response];
+    
+    if ([_private->delegate respondsToSelector:@selector(download:didReceiveResponse:)]) {
+        [_private->delegate download:self didReceiveResponse:response];
+    }
+}
+
+- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
+{
+    if ([_private->delegate respondsToSelector:@selector(download:didReceiveDataOfLength:)]) {
+        [_private->delegate download:self didReceiveDataOfLength:[data length]];
+    }
+    
+    NSError *error = [self _decodeData:[self _dataIfDoneBufferingData:data]];
+    if (error) {
+        [self _cancelWithError:error];
+    }
+}
+
+- (void)connectionDidFinishLoading:(NSURLConnection *)connection
+{    
+    NSError *error = [self _decodeData:_private->bufferedData];
+    [_private->bufferedData release];
+    _private->bufferedData = nil;
+    if (error) {
+        [self _cancelWithError:error];
+        return;
+    }
+
+    if (![self _finishDecoding]) {
+        ERROR("Download decoding failed.");
+        [self _cancelWithErrorCode:WebKitErrorDownloadDecodingFailedToComplete];
+        return;
+    }
+
+    [self _closeFileAsync];
+}
+
+- (void)connection:(NSURLConnection *)connection didFailLoadingWithError:(NSError *)error
+{    
+    [self _cancelWithError:error];
+}
+
+#pragma mark CREATING
+
+- (NSString *)_pathWithUniqueFilenameForPath:(NSString *)path
+{
+    // "Fix" the filename of the path.
+    NSString *filename = [[path lastPathComponent] _web_filenameByFixingIllegalCharacters];
+    path = [[path stringByDeletingLastPathComponent] stringByAppendingPathComponent:filename];
+        
+    NSFileManager *fileManager = [NSFileManager defaultManager];
+    if ([fileManager fileExistsAtPath:path]) {
+        // Don't overwrite existing files by appending "-n" or "-n.ext" to the filename.
+        NSString *pathWithoutExtension = [path stringByDeletingPathExtension];
+        NSString *extension = [path pathExtension];
+        NSString *pathWithAppendedNumber;
+        unsigned i;
+
+        for (i = 1; 1; i++) {
+            pathWithAppendedNumber = [NSString stringWithFormat:@"%@-%d", pathWithoutExtension, i];
+            if (extension && [extension length]) {
+                path = [pathWithAppendedNumber stringByAppendingPathExtension:extension];
+            } else {
+                path = pathWithAppendedNumber;
+            }
+            if (![fileManager fileExistsAtPath:path]) {
+                break;
+            }
+        }
+    }
+
+    return path;
+}
+
+- (BOOL)_createFSRefForPath:(NSString *)path
+{
+    free(_private->fileRefPtr);    
+    _private->fileRefPtr = malloc(sizeof(FSRef));
+    
+    OSErr result = FSPathMakeRef((const UInt8 *)[path fileSystemRepresentation], _private->fileRefPtr, NULL);
+    if (result != noErr) {
+        ERROR("FSPathMakeRef failed.");
+        free(_private->fileRefPtr);
+        _private->fileRefPtr = NULL;
+        return NO;
+    }
+
+    return YES;
+}
+
+- (BOOL)_createFileIfNecessary
+{
+    if (_private->fileRefPtr) {
+        // File is already created.
+        return YES;
+    }
+
+    NSObject <WebDownloadDecoder> *lastDecoder = [_private->decoderSequence lastObject];
+    NSMutableDictionary *attributes = [[lastDecoder fileAttributes] mutableCopy];
+    NSFileManager *fileManager = [NSFileManager defaultManager];
+
+    if (!attributes) {
+        attributes = [[NSMutableDictionary alloc] init];
+    }
+    if (![attributes objectForKey:NSFileCreationDate]) {
+        [attributes setObject:[_private->response _createdDate] forKey:NSFileCreationDate];
+    }
+    if (![attributes objectForKey:NSFileModificationDate]) {
+        [attributes setObject:[_private->response _createdDate] forKey:NSFileModificationDate];
+    }
+
+    NSString *filename = [[lastDecoder filename] _web_filenameByFixingIllegalCharacters];
+    if ([filename length] == 0) {
+        filename = [_private->response suggestedFilename];
+    }
+
+    ASSERT(!_private->path);
+
+    NSString *path = nil;
+        
+    // Check if the directory is predetermined. If not, ask for a path.
+    if (_private->directoryPath) {
+        path = [_private->directoryPath stringByAppendingPathComponent:filename];
+        [self _setPath:path];
+    } else {
+        if ([_private->delegate respondsToSelector:@selector(download:decidePathWithListener:suggestedFilename:)]) {
+            [_private->delegate download:self
+                  decidePathWithListener:(id <WebDownloadDecisionListener>)self
+                       suggestedFilename:filename];
+        }
+    }
+
+    if (_private->path) {
+        // Path was immeditately set.
+        path = _private->path;
+    } else {
+        // Path wasn't immeditately set. Create the file in /tmp.
+        // FIXME: Consider downloading the file to the default download directory or some other location.
+        char *pathC = strdup("/tmp/WebKitDownload.XXXXXX");
+        if (mktemp(pathC)) {
+            _private->tempPath = [[NSString alloc] initWithCString:pathC];
+            path = _private->tempPath;
+        }
+        free(pathC);
+        if (!path) {
+            ERROR("mktemp failed to create a unique filename in /tmp.");
+            return NO;
+        }
+    }
+
+    if (![fileManager _web_createFileAtPath:path contents:nil attributes:attributes]) {
+        ERROR("-[NSFileManager _web_createFileAtPath:contents:attributes:] failed.");
+        return NO;
+    }
+
+    if (![self _createFSRefForPath:path]) {
+        return NO;
+    }
+
+    [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:path];
+
+    if (_private->path && [_private->delegate respondsToSelector:@selector(download:didCreateFileAtPath:)]) {
+        [_private->delegate download:self didCreateFileAtPath:_private->path];
+    }
+    
+    return YES;
+}
+
+
+#pragma mark DECODING
+
+- (void)_decodeHeaderData:(NSData *)headerData
+             dataForkData:(NSData **)dataForkData
+         resourceForkData:(NSData **)resourceForkData
+{
+    ASSERT(headerData);
+    ASSERT([headerData length]);
+    ASSERT(dataForkData);
+    ASSERT(resourceForkData);
+
+    unsigned i;
+    for (i = 0; i < [decoderClasses count]; i++) {
+        Class decoderClass = [decoderClasses objectAtIndex:i];
+        
+        if ([decoderClass canDecodeHeaderData:headerData]) {
+            NSObject <WebDownloadDecoder> *decoder = [[[decoderClass alloc] init] autorelease];
+            BOOL 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;
+            }
+
+            [_private->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 (!_private->decoderSequence) {
+        _private->decoderSequence = [[NSMutableArray array] retain];
+        [self _decodeHeaderData:data dataForkData:dataForkData resourceForkData:resourceForkData];
+
+        if ([_private->decoderSequence count] > 0 &&
+            [_private->delegate respondsToSelector:@selector(downloadShouldDecodeEncodedFile:)] &&
+            ![_private->delegate downloadShouldDecodeEncodedFile:self]) {
+            [_private->decoderSequence removeAllObjects];
+        }
+    } else {
+        unsigned i;
+        for (i = 0; i< [_private->decoderSequence count]; i++) {
+            NSObject <WebDownloadDecoder> *decoder = [_private->decoderSequence objectAtIndex:i];
+            BOOL didDecode = [decoder decodeData:data dataForkData:dataForkData resourceForkData:resourceForkData];
+
+            if (!didDecode) {
+                return NO;
+            }
+
+            data = *dataForkData;
+        }
+    }
+
+    if ([_private->decoderSequence count] == 0) {
+        *dataForkData = data;
+        *resourceForkData = nil;
+    }
+
+    return YES;
+}
+
+- (NSError *)_decodeData:(NSData *)data
+{
+    if ([data length] == 0) {
+        return nil;
+    }
+
+    NSData *dataForkData = nil;
+    NSData *resourceForkData = nil;
+
+    if (![self _decodeData:data dataForkData:&dataForkData resourceForkData:&resourceForkData]) {
+        ERROR("Download decoding failed.");
+        return [self _errorWithCode:WebKitErrorDownloadDecodingFailedMidStream];
+    }
+
+    NSError *error = [self _writeDataForkData:dataForkData resourceForkData:resourceForkData];
+    if (error) {
+        return error;
+    }
+
+    return nil;
+}
+
+- (NSData *)_dataIfDoneBufferingData:(NSData *)data
+{
+    ASSERT([data length] > 0);
+    
+    if (!_private->bufferedData) {
+        _private->bufferedData = [data mutableCopy];
+    } else if ([_private->bufferedData length] == 0) {
+        // When bufferedData's length is 0, we're done buffering.
+        return data;
+    } else {
+        // Append new data.
+        [_private->bufferedData appendData:data];
+    }
+
+    if ([_private->bufferedData length] >= WEB_DOWNLOAD_DECODER_MINIMUM_HEADER_LENGTH) {
+        // 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 = [[_private->bufferedData copy] autorelease];
+        [_private->bufferedData release];
+        _private->bufferedData = [[NSMutableData alloc] init];
+        return data;
+    } else {
+        // Keep buffering. The header is not big enough to determine the encoding sequence.
+        return nil;
+    }
+}
+
+- (BOOL)_finishDecoding
+{
+    NSObject <WebDownloadDecoder> *decoder;
+    unsigned i;
+
+    for (i = 0; i < [_private->decoderSequence count]; i++) {
+        decoder = [_private->decoderSequence objectAtIndex:i];
+        if (![decoder finishDecoding]) {
+            return NO;
+        }
+    }
+
+    return YES;
+}
+
+#pragma mark WRITING
+
+- (BOOL)_writeForkData:(NSData *)data isDataFork:(BOOL)isDataFork
+{
+    SInt16 *forkRefNum = isDataFork ? &_private->dataForkRefNum : &_private->resourceForkRefNum;
+
+    if (*forkRefNum == 0) {
+        HFSUniStr255 forkName;
+        OSErr result = isDataFork ? FSGetDataForkName(&forkName) : FSGetResourceForkName(&forkName);
+        if (result != noErr) {
+            ERROR("Couldn't get fork name of download file.");
+            return NO;
+        }
+
+        result = FSOpenFork(_private->fileRefPtr, forkName.length, forkName.unicode, fsWrPerm, forkRefNum);
+        if (result != noErr) {
+            ERROR("Couldn't open fork of download file.");
+            return NO;
+        }
+    }
+
+    data = [data copy];
+    WebFSForkIOParam *block = malloc(sizeof(WebFSForkIOParam));
+    block->paramBlock.ioCompletion = WriteCompletionCallback;
+    block->paramBlock.forkRefNum = *forkRefNum;
+    block->paramBlock.positionMode = fsAtMark;
+    block->paramBlock.positionOffset = 0;
+    block->paramBlock.requestCount = [data length];
+    block->paramBlock.buffer = (Ptr)[data bytes];
+    block->download = [self retain];
+    block->data = data;
+    PBWriteForkAsync(&block->paramBlock);
+
+    return YES;
+}
+
+- (NSError *)_writeDataForkData:(NSData *)dataForkData resourceForkData:(NSData *)resourceForkData
+{
+    if (![self _createFileIfNecessary]) {
+        return [self _errorWithCode:WebKitErrorCannotCreateFile];
+    }
+
+    BOOL didWrite = YES;
+
+    if ([dataForkData length]) {
+        didWrite = [self _writeForkData:dataForkData isDataFork:YES];
+    }
+
+    if (didWrite && [resourceForkData length]) {
+        didWrite = [self _writeForkData:resourceForkData isDataFork:NO];
+    }
+
+    if (!didWrite) {
+        [self _closeAndDeleteFileAsync];
+        return [self _errorWithCode:WebKitErrorCannotWriteToFile];
+    }
+
+    return nil;
+}
+
+#pragma mark CLOSING
+
+- (BOOL)_isFileClosed
+{
+    return (_private->dataForkRefNum == 0 && _private->resourceForkRefNum == 0);
+}
+
+- (void)_didCloseFile:(NSError *)error
+{        
+    if (_private->deleteFile) {
+        [self _deleteFileAsnyc];
+    } else if (error) {
+        [self _cancelWithError:error];
+    } else {
+        [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:[self _currentPath]];
+        if ([_private->delegate respondsToSelector:@selector(downloadDidFinishDownloading:)]) {
+            [_private->delegate downloadDidFinishDownloading:self];
+        }
+        [self _downloadEnded];
+    }
+}
+
+- (void)_closeForkAsync:(SInt16)forkRefNum
+{
+    if (forkRefNum) {
+        WebFSForkIOParam *block = malloc(sizeof(WebFSForkIOParam));
+        block->paramBlock.ioCompletion = CloseCompletionCallback;
+        block->paramBlock.forkRefNum = forkRefNum;
+        block->download = [self retain];
+        PBCloseForkAsync(&block->paramBlock);
+    }
+}
+
+- (BOOL)_closeForkSync:(SInt16)forkRefNum
+{
+    if (forkRefNum) {
+        OSErr error = FSCloseFork(forkRefNum);
+        if (error != noErr) {
+            ERROR("FSCloseFork failed to close fork of download file with error %d", error);
+            return NO;
+        }
+    }
+
+    return YES;
+}
+
+- (void)_closeFileAsync
+{
+    [self _closeForkAsync:_private->dataForkRefNum];
+    [self _closeForkAsync:_private->resourceForkRefNum];
+}
+
+- (BOOL)_closeFileSync
+{
+    BOOL result = YES;
+
+    if (![self _closeForkSync:_private->dataForkRefNum]) {
+        result = NO;
+    }
+    
+    if (![self _closeForkSync:_private->resourceForkRefNum]) {
+        result = NO;
+    }
+    
+    _private->dataForkRefNum = 0;
+    _private->resourceForkRefNum = 0;
+
+    return result;
+}
+
+#pragma mark DELETING
+
+- (void)_didDeleteFile
+{
+    [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:[self _currentPath]];
+}
+
+- (void)_deleteFileAsnyc
+{
+    if (_private->fileRefPtr) {
+        WebFSRefParam *deleteBlock = malloc(sizeof(WebFSRefParam));
+        deleteBlock->paramBlock.ioCompletion = DeleteCompletionCallback;
+        deleteBlock->paramBlock.ref = _private->fileRefPtr;
+        deleteBlock->download = [self retain];
+        PBDeleteObjectAsync(&deleteBlock->paramBlock);
+        free(_private->fileRefPtr);
+        _private->fileRefPtr = NULL;
+    }
+}
+
+- (void)_closeAndDeleteFileAsync
+{
+    if ([self _isFileClosed]) {
+        [self _deleteFileAsnyc];
+    } else {
+        [self _closeFileAsync];
+        _private->deleteFile = YES;
+    }
+}
+
+- (void)_cancelWithError:(NSError *)error
+{
+    [_private->connection cancel];
+    
+    if (error) {
+        if ([_private->delegate respondsToSelector:@selector(download:didFailDownloadingWithError:)]) {
+            [_private->delegate download:self didFailDownloadingWithError:error];
+        }
+    }
+
+    [self _closeAndDeleteFileAsync];
+    [self _downloadEnded];
+}
+
+- (void)_cancelWithErrorCode:(int)code
+{
+    [self _cancelWithError:[self _errorWithCode:code]];
+}
+
+#pragma mark MISCELLANEOUS
+
+- (void)_setDelegate:(id)delegate;
+{
+    [delegate retain];
+    [_private->delegate release];
+    _private->delegate = delegate;
+}
+
+- (void)_setPath:(NSString *)path
+{
+    ASSERT(path);
+    ASSERT(!_private->path);
+    ASSERT([path isAbsolutePath]);
+
+    // Path has already been set.
+    if (_private->path) {
+        return;
+    }
+
+    if (!path || ![path isAbsolutePath]) {
+        ERROR("setPath: cannot be called with a nil or non-absolute path.");
+        [self cancel];
+        return;
+    }
+
+    // Make sure we don't overwrite an existing file.
+    _private->path = [[self _pathWithUniqueFilenameForPath:path] retain];
+
+    // FIXME: Moving the downloading file synchronously may block the main thread for a long time
+    // if the move is across volumes.
+    if (_private->tempPath && ![_private->tempPath isEqualToString:_private->path]) {
+        if (![self _closeFileSync]) {
+            [self _cancelWithErrorCode:WebKitErrorCannotCloseFile];
+            return;
+        }
+        if (![[NSFileManager defaultManager] movePath:_private->tempPath toPath:_private->path handler:nil]) {
+            [self _cancelWithErrorCode:WebKitErrorCannotMoveFile];
+            return;
+        }
+        if (![self _createFSRefForPath:_private->path]) {
+            [self _cancelWithErrorCode:WebKitErrorCannotCreateFile];
+            return;
+        }
+
+        [[NSWorkspace sharedWorkspace] _web_noteFileChangedAtPath:_private->path];
+
+        if ([_private->delegate respondsToSelector:@selector(download:didCreateFileAtPath:)]) {
+            [_private->delegate download:self didCreateFileAtPath:_private->path];
+        }
+    }
+}
+
+- (void)_setDirectoryPath:(NSString *)directoryPath
+{
+    NSString *copy = [directoryPath copy];
+    [_private->directoryPath release];
+    _private->directoryPath = copy;
+}
+
+- (NSString *)_currentPath
+{
+    return _private->path ? _private->path : _private->tempPath;
+}
+
+- (NSError *)_errorWithCode:(int)code
+{
+    return [NSError _webKitErrorWithCode:code failingURL:[[_private->request URL] absoluteString]];
+}
+
+- (SInt16)_dataForkReferenceNumber
+{
+    return _private->dataForkRefNum;
+}
+
+- (void)_setDataForkReferenceNumber:(SInt16)forkRefNum
+{
+    _private->dataForkRefNum = forkRefNum;
+}
+
+- (SInt16)_resourceForkReferenceNumber
+{
+    return _private->resourceForkRefNum;
+}
+
+- (void)_setResourceForkReferenceNumber:(SInt16)forkRefNum
+{
+    _private->resourceForkRefNum = forkRefNum;
+}
+
+- (BOOL)_areWritesCancelled
+{
+    return _private->areWritesCancelled;
+}
+
+- (void)_setWritesCancelled:(BOOL)cancelled
+{
+    _private->areWritesCancelled = cancelled;
+}
+
+- (BOOL)_encounteredCloseError
+{
+    return _private->encounteredCloseError;
+}
+
+- (void)_setEncounteredCloseError:(BOOL)encounteredCloseError
+{
+    _private->encounteredCloseError = encounteredCloseError;
+}
+
+ at end
+
+static void WriteCompletionCallback(ParmBlkPtr paramBlock)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    WebFSForkIOParam *block = (WebFSForkIOParam *)paramBlock;
+    WebDownload *download = block->download;
+    
+    if (block->paramBlock.ioResult != noErr && ![download _areWritesCancelled]) {
+        ERROR("Writing to fork of download file failed with error: %d", block->paramBlock.ioResult);
+        // Prevent multiple errors from being reported by setting the areWritesCancelled boolean.
+        [download _setWritesCancelled:YES];
+        [download performSelectorOnMainThread:@selector(_cancelWithError:)
+                                   withObject:[download _errorWithCode:WebKitErrorCannotWriteToFile]
+                                waitUntilDone:NO];
+    }
+
+    [download release];
+    [block->data release];
+    [pool release];
+    free(block);
+}
+
+static void CloseCompletionCallback(ParmBlkPtr paramBlock)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    WebFSForkIOParam *block = (WebFSForkIOParam *)paramBlock;
+    WebDownload *download = block->download;
+    
+    if (block->paramBlock.ioResult != noErr) {
+        ERROR("Closing fork of download file failed with error: %d", block->paramBlock.ioResult);
+        [download _setEncounteredCloseError:YES];
+    }
+
+    if (block->paramBlock.forkRefNum == [download _dataForkReferenceNumber]) {
+        [download _setDataForkReferenceNumber:0];
+    } else {
+        [download _setResourceForkReferenceNumber:0];
+    }
+
+    if ([download _isFileClosed]) {
+        NSError *error = [download _encounteredCloseError] ? [download _errorWithCode:WebKitErrorCannotCloseFile] : nil;
+        [download performSelectorOnMainThread:@selector(_didCloseFile:) withObject:error waitUntilDone:NO];
+    }
+    
+    [download release];
+    [pool release];
+    free(block);
+}
+
+static void DeleteCompletionCallback(ParmBlkPtr paramBlock)
+{
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    WebFSRefParam *block = (WebFSRefParam *)paramBlock;
+    WebDownload *download = block->download;
+    
+    if (block->paramBlock.ioResult != noErr) {
+        ERROR("Removal of download file failed with error: %d", block->paramBlock.ioResult);
+    } else {
+        [download performSelectorOnMainThread:@selector(_didDeleteFile) withObject:nil waitUntilDone:NO];
+    }
+    
+    [download release];
+    [pool release];
+    free(block);
+}
+
diff --git a/WebKit/Plugins.subproj/WebBaseNetscapePluginStream.m b/WebKit/Plugins.subproj/WebBaseNetscapePluginStream.m
index 959ab79..3b2692a 100644
--- a/WebKit/Plugins.subproj/WebBaseNetscapePluginStream.m
+++ b/WebKit/Plugins.subproj/WebBaseNetscapePluginStream.m
@@ -63,7 +63,7 @@
     stream.ndata = self;
     stream.URL = cURL;
     stream.end = [r expectedContentLength];
-    stream.lastmodified = [[r lastModifiedDate] timeIntervalSince1970];
+    stream.lastmodified = [[r _lastModifiedDate] timeIntervalSince1970];
     stream.notifyData = notifyData;
 
     offset = 0;
diff --git a/WebKit/WebView.subproj/WebDataSourcePrivate.m b/WebKit/WebView.subproj/WebDataSourcePrivate.m
index 060fafd..5c3555d 100644
--- a/WebKit/WebView.subproj/WebDataSourcePrivate.m
+++ b/WebKit/WebView.subproj/WebDataSourcePrivate.m
@@ -531,7 +531,7 @@
                          reload:reload 
                     contentType:[_private->response MIMEType]
                         refresh:[headers objectForKey:@"Refresh"]
-                   lastModified:(pageCache ? nil : [_private->response lastModifiedDate])
+                   lastModified:(pageCache ? nil : [_private->response _lastModifiedDate])
                       pageCache:pageCache];
 
         [frame _opened];

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list