@@ -135,35 +135,45 @@ @implementation OFZIPArchive @synthesize archiveComment = _archiveComment; + (instancetype)archiveWithSeekableStream: (OFSeekableStream *)stream + mode: (OFString *)mode { - return [[[self alloc] initWithSeekableStream: stream] autorelease]; + return [[[self alloc] initWithSeekableStream: stream + mode: mode] autorelease]; } #ifdef OF_HAVE_FILES + (instancetype)archiveWithPath: (OFString *)path + mode: (OFString *)mode { - return [[[self alloc] initWithPath: path] autorelease]; + return [[[self alloc] initWithPath: path + mode: mode] autorelease]; } #endif - init { OF_INVALID_INIT_METHOD } - initWithSeekableStream: (OFSeekableStream *)stream + mode: (OFString *)mode { self = [super init]; @try { _stream = [stream retain]; - [self of_readZIPInfo]; - [self of_readEntries]; + if ([mode isEqual: @"r"]) { + _mode = OF_ZIP_ARCHIVE_MODE_READ; + + [self of_readZIPInfo]; + [self of_readEntries]; + } else + @throw [OFInvalidArgumentException exception]; } @catch (id e) { [self release]; @throw e; } @@ -170,15 +180,17 @@ return self; } #ifdef OF_HAVE_FILES - initWithPath: (OFString *)path + mode: (OFString *)mode { OFFile *file = [[OFFile alloc] initWithPath: path - mode: @"r"]; + mode: mode]; @try { - self = [self initWithSeekableStream: file]; + self = [self initWithSeekableStream: file + mode: mode]; } @finally { [file release]; } return self; @@ -327,11 +339,15 @@ void *pool = objc_autoreleasePoolPush(); OFZIPArchiveEntry *entry = [_pathToEntryMap objectForKey: path]; OFZIPArchive_LocalFileHeader *localFileHeader; int64_t offset64; - if (entry == nil) + if (_mode != OF_ZIP_ARCHIVE_MODE_READ && + _mode != OF_ZIP_ARCHIVE_MODE_APPEND) + @throw [OFInvalidArgumentException exception]; + + if ((entry = [_pathToEntryMap objectForKey: path]) == nil) @throw [OFOpenItemFailedException exceptionWithPath: path mode: @"r" errNo: ENOENT]; [_lastReturnedStream close];