@@ -22,10 +22,12 @@ #import "crc32.h" #import "OFChecksumFailedException.h" #import "OFInvalidFormatException.h" +#import "OFNotOpenException.h" +#import "OFTruncatedDataException.h" @implementation OFGZIPStream + (instancetype)streamWithStream: (OFStream *)stream { return [[[self alloc] initWithStream: stream] autorelease]; @@ -51,23 +53,34 @@ return self; } - (void)dealloc { - [_stream release]; + [self close]; + [_inflateStream release]; [_modificationDate release]; [super dealloc]; } - (size_t)lowlevelReadIntoBuffer: (void *)buffer length: (size_t)length { - uint8_t byte; + if (_stream == nil) + @throw [OFNotOpenException exceptionWithObject: self]; for (;;) { + uint8_t byte; + + if ([_stream isAtEndOfStream]) { + if (_state != OF_GZIP_STREAM_ID1) + @throw [OFTruncatedDataException exception]; + + return 0; + } + switch (_state) { case OF_GZIP_STREAM_ID1: case OF_GZIP_STREAM_ID2: case OF_GZIP_STREAM_COMPRESSION_METHOD: if ([_stream readIntoBuffer: &byte @@ -95,10 +108,13 @@ readIntoBuffer: _buffer + _bytesRead length: 4 - _bytesRead]; if (_bytesRead < 4) return 0; + + [_modificationDate release]; + _modificationDate = nil; _modificationDate = [[OFDate alloc] initWithTimeIntervalSince1970: (_buffer[3] << 24) | (_buffer[2] << 16) | (_buffer[1] << 8) | _buffer[0]]; @@ -260,10 +276,13 @@ } } - (bool)lowlevelIsAtEndOfStream { + if (_stream == nil) + @throw [OFNotOpenException exceptionWithObject: self]; + return [_stream isAtEndOfStream]; } - (bool)hasDataInReadBuffer { @@ -271,6 +290,14 @@ return ([super hasDataInReadBuffer] || [_inflateStream hasDataInReadBuffer]); return ([super hasDataInReadBuffer] || [_stream hasDataInReadBuffer]); } + +- (void)close +{ + [_stream release]; + _stream = nil; + + [super close]; +} @end