Index: src/OFZooArchiveEntry.h ================================================================== --- src/OFZooArchiveEntry.h +++ src/OFZooArchiveEntry.h @@ -36,10 +36,11 @@ unsigned long long _nextHeaderOffset, _dataOffset; @protected uint16_t _lastModifiedFileDate, _lastModifiedFileTime; uint16_t _CRC16; unsigned long long _uncompressedSize, _compressedSize; + uint16_t _minVersionNeeded; bool _deleted; OFString *_Nullable _fileComment; OFString *_fileName, *_Nullable _directoryName; OFNumber *_Nullable _POSIXPermissions; int8_t _timeZone; @@ -54,10 +55,18 @@ /** * @brief The CRC16 of the file. */ @property (readonly, nonatomic) uint16_t CRC16; +/** + * @brief The minimum version required to extract the file. + * + * The upper 8 bits are the major version and the lower 8 bits the minor + * version. + */ +@property (readonly, nonatomic) uint16_t minVersionNeeded; + /** * @brief Whether the file was deleted. */ @property (readonly, nonatomic, getter=isDeleted) bool deleted; Index: src/OFZooArchiveEntry.m ================================================================== --- src/OFZooArchiveEntry.m +++ src/OFZooArchiveEntry.m @@ -26,11 +26,12 @@ #import "OFInvalidFormatException.h" @implementation OFZooArchiveEntry @synthesize compressionMethod = _compressionMethod, CRC16 = _CRC16; @synthesize uncompressedSize = _uncompressedSize; -@synthesize compressedSize = _compressedSize, deleted = _deleted; +@synthesize compressedSize = _compressedSize; +@synthesize minVersionNeeded = _minVersionNeeded, deleted = _deleted; @synthesize fileComment = _fileComment, POSIXPermissions = _POSIXPermissions; - (instancetype)init { OF_INVALID_INIT_METHOD @@ -41,11 +42,10 @@ { self = [super init]; @try { void *pool = objc_autoreleasePoolPush(); - uint8_t majorVersion; char fileNameBuffer[13]; uint32_t commentOffset; uint16_t commentLength; if ([stream readLittleEndianInt32] != 0xFDC4A7DC) @@ -61,13 +61,11 @@ _lastModifiedFileDate = [stream readLittleEndianInt16]; _lastModifiedFileTime = [stream readLittleEndianInt16]; _CRC16 = [stream readLittleEndianInt16]; _uncompressedSize = [stream readLittleEndianInt32]; _compressedSize = [stream readLittleEndianInt32]; - majorVersion = [stream readInt8]; - /* Minor version */ - [stream readInt8]; + _minVersionNeeded = [stream readBigEndianInt16]; _deleted = [stream readInt8]; /* Unknown. Most likely padding to get to 2 byte alignment? */ [stream readInt8]; commentOffset = [stream readLittleEndianInt32]; commentLength = [stream readLittleEndianInt16]; @@ -74,11 +72,11 @@ [stream readIntoBuffer: fileNameBuffer exactLength: 13]; if (fileNameBuffer[12] != '\0') fileNameBuffer[12] = '\0'; - if (majorVersion == 2) { + if ((_minVersionNeeded >> 8) == 2) { uint16_t extraLength = [stream readLittleEndianInt16]; uint8_t fileNameLength, directoryNameLength; if (extraLength < 10) @throw [OFInvalidFormatException exception]; Index: utils/ofarc/ZooArchive.m ================================================================== --- utils/ofarc/ZooArchive.m +++ utils/ofarc/ZooArchive.m @@ -200,23 +200,10 @@ @"list_timezone", @"Time zone: %[timezone]", @"timezone", timeZoneString)]; } - if (entry.POSIXPermissions != nil) { - OFString *permissionsString = [OFString - stringWithFormat: @"%llo", - entry.POSIXPermissions - .unsignedLongLongValue]; - - [OFStdOut writeString: @"\t"]; - [OFStdOut writeLine: OF_LOCALIZED( - @"list_posix_permissions", - @"POSIX permissions: %[perm]", - @"perm", permissionsString)]; - } - [OFStdOut writeString: @"\t"]; [OFStdOut writeLine: OF_LOCALIZED( @"list_deleted", @"[" @" 'Deleted: '," @@ -233,10 +220,37 @@ @"list_comment", @"Comment: %[comment]", @"comment", entry.fileComment)]; } } + + if (app->_outputLevel >= 2) { + uint16_t minVersionNeeded = entry.minVersionNeeded; + OFString *minVersionNeededString = [OFString + stringWithFormat: @"%u.%u", + minVersionNeeded >> 8, + minVersionNeeded & 0xFF]; + + [OFStdOut writeString: @"\t"]; + [OFStdOut writeLine: OF_LOCALIZED( + @"list_min_version_needed", + @"Minimum version needed: %[version]", + @"version", minVersionNeededString)]; + + if (entry.POSIXPermissions != nil) { + OFString *permissionsString = [OFString + stringWithFormat: @"%llo", + entry.POSIXPermissions + .unsignedLongLongValue]; + + [OFStdOut writeString: @"\t"]; + [OFStdOut writeLine: OF_LOCALIZED( + @"list_posix_permissions", + @"POSIX permissions: %[perm]", + @"perm", permissionsString)]; + } + } objc_autoreleasePoolPop(pool); } }