Index: src/OFZIPArchive.m ================================================================== --- src/OFZIPArchive.m +++ src/OFZIPArchive.m @@ -71,19 +71,18 @@ @end @interface OFZIPArchive_FileStream: OFStream { OFStream *_stream, *_decompressedStream; - OFZIPArchive_LocalFileHeader *_localFileHeader; - bool _hasDataDescriptor; - uint64_t _size; + OFZIPArchiveEntry *_entry; + uint64_t _toRead; uint32_t _CRC32; bool _atEndOfStream; } - initWithStream: (OFStream *)path - localFileHeader: (OFZIPArchive_LocalFileHeader *)localFileHeader; + entry: (OFZIPArchiveEntry *)localFileHeader; @end uint32_t of_zip_archive_read_field32(const uint8_t **data, uint16_t *size) { @@ -358,11 +357,11 @@ exceptionWithVersion: version]; } _lastReturnedStream = [[OFZIPArchive_FileStream alloc] initWithStream: _stream - localFileHeader: localFileHeader]; + entry: entry]; objc_autoreleasePoolPop(pool); return _lastReturnedStream; } @@ -451,18 +450,18 @@ } @end @implementation OFZIPArchive_FileStream - initWithStream: (OFStream *)stream - localFileHeader: (OFZIPArchive_LocalFileHeader *)localFileHeader + entry: (OFZIPArchiveEntry *)entry { self = [super init]; @try { _stream = [stream retain]; - switch (localFileHeader->_compressionMethod) { + switch ([entry compressionMethod]) { case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_NONE: _decompressedStream = [stream retain]; break; case OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_DEFLATE: _decompressedStream = [[OFInflateStream alloc] @@ -476,14 +475,12 @@ @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; } - _localFileHeader = [localFileHeader retain]; - _hasDataDescriptor = (localFileHeader->_generalPurposeBitFlag & - (1 << 3)); - _size = localFileHeader->_uncompressedSize; + _entry = [entry retain]; + _toRead = [entry uncompressedSize]; _CRC32 = ~0; } @catch (id e) { [self release]; @throw e; } @@ -493,12 +490,13 @@ - (void)dealloc { [self close]; + [_stream release]; [_decompressedStream release]; - [_localFileHeader release]; + [_entry release]; [super dealloc]; } - (bool)lowlevelIsAtEndOfStream @@ -507,58 +505,36 @@ } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { - size_t min, ret; + size_t ret; if (_stream == nil) @throw [OFNotOpenException exceptionWithObject: self]; if (_atEndOfStream) return 0; - if (_hasDataDescriptor) { - if ([_decompressedStream isAtEndOfStream]) { - uint32_t CRC32; - - _atEndOfStream = true; - - CRC32 = [_stream readLittleEndianInt32]; - if (CRC32 == 0x08074B50) - CRC32 = [_stream readLittleEndianInt32]; - - if (~_CRC32 != CRC32) - @throw [OFChecksumFailedException exception]; - - /* - * FIXME: Check (un)compressed length! - * (Note: Both are 64 bit if the entry uses ZIP64!) - */ - - return 0; - } - - ret = [_decompressedStream readIntoBuffer: buffer - length: length]; - } else { - if (_size == 0) { - _atEndOfStream = true; - - if (~_CRC32 != _localFileHeader->_CRC32) - @throw [OFChecksumFailedException exception]; - - return 0; - } - - min = (length < _size ? length : (size_t)_size); - ret = [_decompressedStream readIntoBuffer: buffer - length: min]; - _size -= ret; - } - - _CRC32 = of_crc32(_CRC32, buffer, ret); + if (length > UINT64_MAX) + @throw [OFOutOfRangeException exception]; + + if ((uint64_t)length > _toRead) + length = (size_t)_toRead; + + ret = [_decompressedStream readIntoBuffer: buffer + length: length]; + + if (ret == 0) + _atEndOfStream = true; + + _toRead -= ret; + _CRC32 = of_crc32(_CRC32, buffer, ret); + + if (_toRead == 0) + if (~_CRC32 != [_entry CRC32]) + @throw [OFChecksumFailedException exception]; return ret; } - (void)close