| /* |
| * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #import "WebArchive.h" |
| |
| #import "WebKitLogging.h" |
| #import "WebResourcePrivate.h" |
| #import "WebTypesInternal.h" |
| |
| NSString *WebArchivePboardType = @"Apple Web Archive pasteboard type"; |
| |
| static NSString * const WebMainResourceKey = @"WebMainResource"; |
| static NSString * const WebSubresourcesKey = @"WebSubresources"; |
| static NSString * const WebSubframeArchivesKey = @"WebSubframeArchives"; |
| |
| @interface WebArchivePrivate : NSObject |
| { |
| @public |
| WebResource *mainResource; |
| NSArray *subresources; |
| NSArray *subframeArchives; |
| } |
| @end |
| |
| @implementation WebArchivePrivate |
| |
| - (void)dealloc |
| { |
| [mainResource release]; |
| [subresources release]; |
| [subframeArchives release]; |
| [super dealloc]; |
| } |
| |
| @end |
| |
| static BOOL isArrayOfClass(id object, Class elementClass) |
| { |
| if (![object isKindOfClass:[NSArray class]]) |
| return NO; |
| NSArray *array = (NSArray *)object; |
| NSUInteger count = [array count]; |
| for (NSUInteger i = 0; i < count; ++i) |
| if (![[array objectAtIndex:i] isKindOfClass:elementClass]) |
| return NO; |
| return YES; |
| } |
| |
| @implementation WebArchive |
| |
| - (id)init |
| { |
| self = [super init]; |
| if (!self) |
| return nil; |
| _private = [[WebArchivePrivate alloc] init]; |
| return self; |
| } |
| |
| - (id)initWithMainResource:(WebResource *)mainResource subresources:(NSArray *)subresources subframeArchives:(NSArray *)subframeArchives |
| { |
| self = [self init]; |
| if (!self) |
| return nil; |
| |
| _private->mainResource = [mainResource retain]; |
| _private->subresources = [subresources retain]; |
| _private->subframeArchives = [subframeArchives retain]; |
| |
| if (!_private->mainResource) { |
| [self release]; |
| return nil; |
| } |
| |
| return self; |
| } |
| |
| - (id)_initWithPropertyList:(id)propertyList |
| { |
| self = [self init]; |
| if (!self) |
| return nil; |
| |
| if (![propertyList isKindOfClass:[NSDictionary class]]) { |
| [self release]; |
| return nil; |
| } |
| |
| _private->mainResource = [[WebResource alloc] _initWithPropertyList:[propertyList objectForKey:WebMainResourceKey]]; |
| if (!_private->mainResource) { |
| [self release]; |
| return nil; |
| } |
| |
| _private->subresources = [[WebResource _resourcesFromPropertyLists:[propertyList objectForKey:WebSubresourcesKey]] retain]; |
| |
| NSEnumerator *enumerator = [[propertyList objectForKey:WebSubframeArchivesKey] objectEnumerator]; |
| NSMutableArray *subframeArchives = [[NSMutableArray alloc] init]; |
| NSDictionary *archivePropertyList; |
| while ((archivePropertyList = [enumerator nextObject]) != nil) { |
| WebArchive *archive = [[WebArchive alloc] _initWithPropertyList:archivePropertyList]; |
| if (archive) { |
| [subframeArchives addObject:archive]; |
| [archive release]; |
| } |
| } |
| _private->subframeArchives = subframeArchives; |
| |
| return self; |
| } |
| |
| - (id)initWithData:(NSData *)data |
| { |
| #if !LOG_DISABLED |
| CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); |
| #endif |
| NSDictionary *propertyList = [NSPropertyListSerialization propertyListFromData:data |
| mutabilityOption:NSPropertyListImmutable |
| format:nil |
| errorDescription:nil]; |
| #if !LOG_DISABLED |
| CFAbsoluteTime end = CFAbsoluteTimeGetCurrent(); |
| CFAbsoluteTime duration = end - start; |
| #endif |
| LOG(Timing, "Parsing web archive with [NSPropertyListSerialization propertyListFromData::::] took %f seconds", duration); |
| |
| return [self _initWithPropertyList:propertyList]; |
| } |
| |
| - (id)initWithCoder:(NSCoder *)decoder |
| { |
| self = [self init]; |
| if (!self) |
| return nil; |
| |
| @try { |
| id object = [decoder decodeObjectForKey:WebMainResourceKey]; |
| if ([object isKindOfClass:[WebResource class]]) |
| _private->mainResource = [object retain]; |
| object = [decoder decodeObjectForKey:WebSubresourcesKey]; |
| if (isArrayOfClass(object, [WebResource class])) |
| _private->subresources = [object retain]; |
| object = [decoder decodeObjectForKey:WebSubframeArchivesKey]; |
| if (isArrayOfClass(object, [WebArchive class])) |
| _private->subframeArchives = [object retain]; |
| } @catch(id) { |
| [self release]; |
| return nil; |
| } |
| |
| if (!_private->mainResource) { |
| [self release]; |
| return nil; |
| } |
| |
| return self; |
| } |
| |
| - (void)encodeWithCoder:(NSCoder *)encoder |
| { |
| [encoder encodeObject:_private->mainResource forKey:WebMainResourceKey]; |
| [encoder encodeObject:_private->subresources forKey:WebSubresourcesKey]; |
| [encoder encodeObject:_private->subframeArchives forKey:WebSubframeArchivesKey]; |
| } |
| |
| - (void)dealloc |
| { |
| [_private release]; |
| [super dealloc]; |
| } |
| |
| - (id)copyWithZone:(NSZone *)zone |
| { |
| return [self retain]; |
| } |
| |
| - (WebResource *)mainResource |
| { |
| return [[_private->mainResource retain] autorelease]; |
| } |
| |
| - (NSArray *)subresources |
| { |
| return [[_private->subresources retain] autorelease]; |
| } |
| |
| - (NSArray *)subframeArchives |
| { |
| return [[_private->subframeArchives retain] autorelease]; |
| } |
| |
| - (NSDictionary *)_propertyListRepresentation |
| { |
| NSMutableDictionary *propertyList = [NSMutableDictionary dictionary]; |
| if (_private->mainResource) { |
| [propertyList setObject:[_private->mainResource _propertyListRepresentation] forKey:WebMainResourceKey]; |
| } |
| NSArray *propertyLists = [WebResource _propertyListsFromResources:_private->subresources]; |
| if ([propertyLists count] > 0) { |
| [propertyList setObject:propertyLists forKey:WebSubresourcesKey]; |
| } |
| NSEnumerator *enumerator = [_private->subframeArchives objectEnumerator]; |
| NSMutableArray *subarchivePropertyLists = [[NSMutableArray alloc] init]; |
| WebArchive *archive; |
| while ((archive = [enumerator nextObject]) != nil) { |
| [subarchivePropertyLists addObject:[archive _propertyListRepresentation]]; |
| } |
| if ([subarchivePropertyLists count] > 0) { |
| [propertyList setObject:subarchivePropertyLists forKey:WebSubframeArchivesKey]; |
| } |
| [subarchivePropertyLists release]; |
| return propertyList; |
| } |
| |
| - (NSData *)data |
| { |
| NSDictionary *propertyList = [self _propertyListRepresentation]; |
| #if !LOG_DISABLED |
| CFAbsoluteTime start = CFAbsoluteTimeGetCurrent(); |
| #endif |
| NSData *data = [NSPropertyListSerialization dataFromPropertyList:propertyList format:NSPropertyListBinaryFormat_v1_0 errorDescription:nil]; |
| #if !LOG_DISABLED |
| CFAbsoluteTime end = CFAbsoluteTimeGetCurrent(); |
| CFAbsoluteTime duration = end - start; |
| #endif |
| LOG(Timing, "Serializing web archive with [NSPropertyListSerialization dataFromPropertyList:::] took %f seconds", duration); |
| return data; |
| } |
| |
| @end |