Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -53,10 +53,11 @@ OFMutableSet.m \ OFMutableString.m \ OFMutableTarArchiveEntry.m \ OFMutableTriple.m \ OFMutableZIPArchiveEntry.m \ + OFMutableZooArchiveEntry.m \ OFNotification.m \ OFNotificationCenter.m \ OFNull.m \ OFNumber.m \ OFObject.m \ Index: src/OFMutableLHAArchiveEntry.h ================================================================== --- src/OFMutableLHAArchiveEntry.h +++ src/OFMutableLHAArchiveEntry.h @@ -12,11 +12,10 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFLHAArchiveEntry.h" -#import "OFMutableArchiveEntry.h" OF_ASSUME_NONNULL_BEGIN /** * @class OFMutableLHAArchiveEntry OFLHAArchiveEntry.h ObjFW/OFHAArchiveEntry.h Index: src/OFMutableLHAArchiveEntry.m ================================================================== --- src/OFMutableLHAArchiveEntry.m +++ src/OFMutableLHAArchiveEntry.m @@ -15,11 +15,10 @@ #include "config.h" #import "OFMutableLHAArchiveEntry.h" #import "OFLHAArchiveEntry+Private.h" - #import "OFArray.h" #import "OFData.h" #import "OFDate.h" #import "OFNumber.h" #import "OFString.h" Index: src/OFMutableTarArchiveEntry.h ================================================================== --- src/OFMutableTarArchiveEntry.h +++ src/OFMutableTarArchiveEntry.h @@ -12,11 +12,10 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFTarArchiveEntry.h" -#import "OFMutableArchiveEntry.h" OF_ASSUME_NONNULL_BEGIN /** * @class OFMutableTarArchiveEntry OFTarArchiveEntry.h ObjFW/OFTarArchiveEntry.h Index: src/OFMutableZIPArchiveEntry.h ================================================================== --- src/OFMutableZIPArchiveEntry.h +++ src/OFMutableZIPArchiveEntry.h @@ -12,11 +12,10 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFZIPArchiveEntry.h" -#import "OFMutableArchiveEntry.h" OF_ASSUME_NONNULL_BEGIN /** * @class OFMutableZIPArchiveEntry OFZIPArchiveEntry.h ObjFW/OFZIPArchiveEntry.h Index: src/OFMutableZIPArchiveEntry.m ================================================================== --- src/OFMutableZIPArchiveEntry.m +++ src/OFMutableZIPArchiveEntry.m @@ -15,13 +15,13 @@ #include "config.h" #import "OFMutableZIPArchiveEntry.h" #import "OFZIPArchiveEntry+Private.h" -#import "OFString.h" #import "OFData.h" #import "OFDate.h" +#import "OFString.h" #import "OFInvalidArgumentException.h" #import "OFOutOfRangeException.h" @implementation OFMutableZIPArchiveEntry ADDED src/OFMutableZooArchiveEntry.h Index: src/OFMutableZooArchiveEntry.h ================================================================== --- /dev/null +++ src/OFMutableZooArchiveEntry.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFZooArchiveEntry.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @class OFMutableZooArchiveEntry OFZooArchiveEntry.h ObjFW/OFZooArchiveEntry.h + * + * @brief A class which represents a mutable entry in a Zoo archive. + */ +@interface OFMutableZooArchiveEntry: OFZooArchiveEntry +{ + OF_RESERVE_IVARS(OFMutableZooArchiveEntry, 4) +} + +/** + * @brief The header type of the entry. + */ +@property (readwrite, nonatomic) uint8_t headerType; + +/** + * @brief The compression method of the entry. + */ +@property (readwrite, nonatomic) uint8_t compressionMethod; + +/** + * @brief The CRC16 of the file. + */ +@property (readwrite, 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 (readwrite, nonatomic) uint16_t minVersionNeeded; + +/** + * @brief Whether the file was deleted. + */ +@property (readwrite, nonatomic, getter=isDeleted) bool deleted; + +/** + * @brief The operating system identifier of the file. + */ +@property (readwrite, nonatomic) uint16_t operatingSystemIdentifier; + +/** + * @brief The time zone in which the file was stored, as an offset in hours + * from UTC (as a float). + * + * @note Make sure to set the correct time zone before setting the modification + * date! + */ +@property OF_NULLABLE_PROPERTY (readwrite, retain, nonatomic) + OFNumber *timeZone; + +/** + * @brief Creates a new OFMutableZooArchiveEntry with the specified file name. + * + * @param fileName The file name for the OFZooArchiveEntry + * @return A new, autoreleased OFZooArchiveEntry + */ ++ (instancetype)entryWithFileName: (OFString *)fileName; + +/** + * @brief Initializes an already allocated OFMutableZooArchiveEntry with the + * specified file name. + * + * @param fileName The file name for the OFZooArchiveEntry + * @return An initialized OFZooArchiveEntry + */ +- (instancetype)initWithFileName: (OFString *)fileName; + +/** + * @brief Converts the OFMutableZooArchiveEntry to an immutable + * OFZooArchiveEntry. + */ +- (void)makeImmutable; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFMutableZooArchiveEntry.m Index: src/OFMutableZooArchiveEntry.m ================================================================== --- /dev/null +++ src/OFMutableZooArchiveEntry.m @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2008-2024 Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFMutableZooArchiveEntry.h" +#import "OFZooArchiveEntry+Private.h" +#import "OFDate.h" +#import "OFNumber.h" +#import "OFString.h" + +@implementation OFMutableZooArchiveEntry +@dynamic headerType, compressionMethod, modificationDate, CRC16; +@dynamic uncompressedSize, compressedSize, minVersionNeeded, deleted; +@dynamic fileComment, fileName, operatingSystemIdentifier, POSIXPermissions; +@dynamic timeZone; + ++ (instancetype)entryWithFileName: (OFString *)fileName +{ + return [[[self alloc] initWithFileName: fileName] autorelease]; +} + +- (instancetype)initWithFileName: (OFString *)fileName +{ + self = [super of_init]; + + @try { + void *pool = objc_autoreleasePoolPush(); + + _fileName = [fileName copy]; + self.modificationDate = [OFDate date]; + + objc_autoreleasePoolPop(pool); + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (id)copy +{ + OFMutableZooArchiveEntry *copy = [self mutableCopy]; + + [copy makeImmutable]; + + return copy; +} + +- (void)setHeaderType: (uint8_t)headerType +{ + _headerType = headerType; +} + +- (void)setCompressionMethod: (uint8_t)compressionMethod +{ + _compressionMethod = compressionMethod; +} + +- (void)setModificationDate: (OFDate *)date +{ + void *pool = objc_autoreleasePoolPush(); + + if (_timeZone != 0x7F) + date = [date dateByAddingTimeInterval: + -(OFTimeInterval)_timeZone * 900]; + + _lastModifiedFileDate = (((date.year - 1980) & 0xFF) << 9) | + ((date.monthOfYear & 0x0F) << 5) | (date.dayOfMonth & 0x1F); + _lastModifiedFileTime = ((date.hour & 0x1F) << 11) | + ((date.minute & 0x3F) << 5) | ((date.second >> 1) & 0x0F); + + objc_autoreleasePoolPop(pool); +} + +- (void)setCRC16: (uint16_t)CRC16 +{ + _CRC16 = CRC16; +} + +- (void)setUncompressedSize: (unsigned long long)uncompressedSize +{ + _uncompressedSize = uncompressedSize; +} + +- (void)setCompressedSize: (unsigned long long)compressedSize +{ + _compressedSize = compressedSize; +} + +- (void)setMinVersionNeeded: (uint16_t)minVersionNeeded +{ + _minVersionNeeded = minVersionNeeded; +} + +- (void)setDeleted: (bool)deleted +{ + _deleted = deleted; +} + +- (void)setFileComment: (OFString *)fileComment +{ + OFString *old = _fileComment; + _fileComment = [fileComment copy]; + [old release]; +} + +- (void)setFileName: (OFString *)fileName +{ + OFString *old = _fileName; + _fileName = [fileName copy]; + [old release]; + + [_directoryName release]; + _directoryName = nil; +} + +- (void)setOperatingSystemIdentifier: (uint16_t)operatingSystemIdentifier +{ + _operatingSystemIdentifier = operatingSystemIdentifier; +} + +- (void)setPOSIXPermissions: (OFNumber *)POSIXPermissions +{ + OFNumber *old = _POSIXPermissions; + _POSIXPermissions = [POSIXPermissions copy]; + [old release]; +} + +- (void)setTimeZone: (OFNumber *)timeZone +{ + if (timeZone == nil) + _timeZone = 0x7F; + else + _timeZone = -timeZone.floatValue * 4; +} + +- (void)makeImmutable +{ + object_setClass(self, [OFZooArchiveEntry class]); +} +@end Index: src/OFZooArchiveEntry+Private.h ================================================================== --- src/OFZooArchiveEntry+Private.h +++ src/OFZooArchiveEntry+Private.h @@ -16,10 +16,11 @@ #import "OFZooArchive.h" OF_ASSUME_NONNULL_BEGIN @interface OFZooArchiveEntry () +- (instancetype)of_init OF_METHOD_FAMILY(init); - (nullable instancetype)of_initWithStream: (OF_KINDOF(OFStream *))stream encoding: (OFStringEncoding)encoding OF_METHOD_FAMILY(init) OF_DIRECT; @end Index: src/OFZooArchiveEntry.h ================================================================== --- src/OFZooArchiveEntry.h +++ src/OFZooArchiveEntry.h @@ -23,13 +23,14 @@ @class OFString; /** * @class OFZooArchiveEntry OFZooArchiveEntry.h ObjFW/OFZooArchiveEntry.h * - * @brief A class which represents an entry in an Zoo archive. + * @brief A class which represents an entry in a Zoo archive. */ -@interface OFZooArchiveEntry: OFObject +@interface OFZooArchiveEntry: OFObject { uint8_t _headerType, _compressionMethod; #ifdef OF_ZOO_ARCHIVE_M @public #endif @@ -40,13 +41,13 @@ unsigned long long _uncompressedSize, _compressedSize; uint16_t _minVersionNeeded; bool _deleted; OFString *_Nullable _fileComment; OFString *_fileName, *_Nullable _directoryName; + uint16_t _operatingSystemIdentifier; OFNumber *_Nullable _POSIXPermissions; int8_t _timeZone; - uint16_t _operatingSystemIdentifier; OF_RESERVE_IVARS(OFZooArchiveEntry, 4) } /** * @brief The header type of the entry. @@ -83,11 +84,13 @@ /** * @brief The time zone in which the file was stored, as an offset in hours * from UTC (as a float). */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFNumber *timeZone; +@property OF_NULLABLE_PROPERTY (readonly, retain, nonatomic) OFNumber *timeZone; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END + +#import "OFMutableZooArchiveEntry.h" Index: src/OFZooArchiveEntry.m ================================================================== --- src/OFZooArchiveEntry.m +++ src/OFZooArchiveEntry.m @@ -25,22 +25,29 @@ #import "OFInvalidFormatException.h" #import "OFUnsupportedVersionException.h" @implementation OFZooArchiveEntry -@synthesize headerType = _headerType, compressionMethod = _compressionMethod; -@synthesize CRC16 = _CRC16, uncompressedSize = _uncompressedSize; -@synthesize compressedSize = _compressedSize; -@synthesize minVersionNeeded = _minVersionNeeded, deleted = _deleted; -@synthesize fileComment = _fileComment; -@synthesize operatingSystemIdentifier = _operatingSystemIdentifier; -@synthesize POSIXPermissions = _POSIXPermissions; - - (instancetype)init { OF_INVALID_INIT_METHOD } + +- (instancetype)of_init +{ + self = [super init]; + + @try { + _headerType = 2; + _minVersionNeeded = 0x100; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} - (instancetype)of_initWithStream: (OF_KINDOF(OFStream *))stream encoding: (OFStringEncoding)encoding { self = [super init]; @@ -185,16 +192,48 @@ - (id)copy { return [self retain]; } -- (OFString *)fileName +- (id)mutableCopy +{ + OFZooArchiveEntry *copy = [[OFMutableZooArchiveEntry alloc] + initWithFileName: _fileName]; + + @try { + copy->_headerType = _headerType; + copy->_compressionMethod = _compressionMethod; + copy->_nextHeaderOffset = _nextHeaderOffset; + copy->_dataOffset = _dataOffset; + copy->_lastModifiedFileDate = _lastModifiedFileDate; + copy->_lastModifiedFileTime = _lastModifiedFileTime; + copy->_CRC16 = _CRC16; + copy->_uncompressedSize = _uncompressedSize; + copy->_compressedSize = _compressedSize; + copy->_minVersionNeeded = _minVersionNeeded; + copy->_deleted = _deleted; + copy->_fileComment = [_fileComment copy]; + copy->_directoryName = [_directoryName copy]; + copy->_operatingSystemIdentifier = _operatingSystemIdentifier; + copy->_POSIXPermissions = [_POSIXPermissions retain]; + copy->_timeZone = _timeZone; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (uint8_t)headerType +{ + return _headerType; +} + +- (uint8_t)compressionMethod { - if (_directoryName == nil) - return _fileName; - - return [OFString stringWithFormat: @"%@/%@", _directoryName, _fileName]; + return _compressionMethod; } - (OFDate *)modificationDate { void *pool = objc_autoreleasePoolPush(); @@ -224,10 +263,58 @@ objc_autoreleasePoolPop(pool); return [date autorelease]; } + +- (uint16_t)CRC16 +{ + return _CRC16; +} + +- (unsigned long long)uncompressedSize +{ + return _uncompressedSize; +} + +- (unsigned long long)compressedSize +{ + return _compressedSize; +} + +- (uint16_t)minVersionNeeded +{ + return _minVersionNeeded; +} + +- (bool)isDeleted +{ + return _deleted; +} + +- (OFString *)fileComment +{ + return _fileComment; +} + +- (OFString *)fileName +{ + if (_directoryName == nil) + return _fileName; + + return [OFString stringWithFormat: @"%@/%@", _directoryName, _fileName]; +} + +- (uint16_t)operatingSystemIdentifier +{ + return _operatingSystemIdentifier; +} + +- (OFNumber *)POSIXPermissions +{ + return _POSIXPermissions; +} - (OFNumber *)timeZone { if (_timeZone == 0x7F) return nil;