Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -44,10 +44,11 @@ OFMessagePackExtension.m \ OFMethodSignature.m \ OFMutableArray.m \ OFMutableData.m \ OFMutableDictionary.m \ + OFMutableLHAArchiveEntry.m \ OFMutablePair.m \ OFMutableSet.m \ OFMutableString.m \ OFMutableTarArchiveEntry.m \ OFMutableTriple.m \ Index: src/OFLHAArchiveEntry.h ================================================================== --- src/OFLHAArchiveEntry.h +++ src/OFLHAArchiveEntry.h @@ -27,22 +27,21 @@ @class OFString; /*! * @class OFLHAArchiveEntry OFLHAArchiveEntry.h ObjFW/OFLHAArchiveEntry.h * - * @brief A class which represents an entry in the central directory of a LHA - * archive. + * @brief A class which represents an entry in an LHA archive. */ -@interface OFLHAArchiveEntry: OFObject +@interface OFLHAArchiveEntry: OFObject { #ifdef OF_LHA_ARCHIVE_ENTRY_M @public #endif OFString *_fileName, *_Nullable _directoryName, *_compressionMethod; uint32_t _compressedSize, _uncompressedSize; OFDate *_date; - uint8_t _level; + uint8_t _headerLevel; uint16_t _CRC16; uint8_t _operatingSystemIdentifier; OFString *_Nullable _fileComment; OFNumber *_Nullable _mode, *_Nullable _UID, *_Nullable _GID; OFString *_Nullable _owner, *_Nullable _group; @@ -76,11 +75,11 @@ @property (readonly, retain, nonatomic) OFDate *date; /*! * @brief The LHA level of the file. */ -@property (readonly, nonatomic) uint8_t level; +@property (readonly, nonatomic) uint8_t headerLevel; /*! * @brief The CRC16 of the file. */ @property (readonly, nonatomic) uint16_t CRC16; @@ -94,15 +93,10 @@ * @brief The comment of the file. */ @property OF_NULLABLE_PROPERTY (readonly, copy, nonatomic) OFString *fileComment; -/*! - * @brief The LHA extensions of the file. - */ -@property (readonly, copy, nonatomic) OFArray OF_GENERIC(OFData *) *extensions; - /*! * @brief The mode of the entry. */ @property OF_NULLABLE_PROPERTY (readonly, retain, nonatomic) OFNumber *mode; @@ -130,9 +124,33 @@ * @brief The date of the last modification of the file. */ @property OF_NULLABLE_PROPERTY (readonly, retain, nonatomic) OFDate *modificationDate; +/*! + * @brief The LHA extensions of the file. + */ +@property (readonly, copy, nonatomic) OFArray OF_GENERIC(OFData *) *extensions; + +/*! + * @brief Creates a new OFLHAArchiveEntry with the specified file name. + * + * @param fileName The file name for the OFLHAArchiveEntry + * @return A new, autoreleased OFLHAArchiveEntry + */ ++ (instancetype)entryWithFileName: (OFString *)fileName; + - (instancetype)init OF_UNAVAILABLE; + +/*! + * @brief Initializes an already allocated OFLHAArchiveEntry with the specified + * file name. + * + * @param fileName The file name for the OFLHAArchiveEntry + * @return An initialized OFLHAArchiveEntry + */ +- (instancetype)initWithFileName: (OFString *)fileName; @end OF_ASSUME_NONNULL_END + +#import "OFMutableLHAArchiveEntry.h" Index: src/OFLHAArchiveEntry.m ================================================================== --- src/OFLHAArchiveEntry.m +++ src/OFLHAArchiveEntry.m @@ -252,33 +252,45 @@ extension = [stream readDataWithCount: size - 2]; if (!parseExtension(entry, extension, encoding, allowFileName)) [entry->_extensions addObject: extension]; - if (entry->_level == 1) { + if (entry->_headerLevel == 1) { if (entry->_compressedSize < size) @throw [OFInvalidFormatException exception]; entry->_compressedSize -= size; } } } @implementation OFLHAArchiveEntry -@synthesize compressionMethod = _compressionMethod; -@synthesize compressedSize = _compressedSize; -@synthesize uncompressedSize = _uncompressedSize, date = _date; -@synthesize level = _level, CRC16 = _CRC16; -@synthesize operatingSystemIdentifier = _operatingSystemIdentifier; -@synthesize fileComment = _fileComment, mode = _mode, UID = _UID, GID = _GID; -@synthesize owner = _owner, group = _group; -@synthesize modificationDate = _modificationDate, extensions = _extensions; ++ (instancetype)entryWithFileName: (OFString *)fileName +{ + return [[[self alloc] initWithFileName: fileName] autorelease]; +} - (instancetype)init { OF_INVALID_INIT_METHOD } + +- (instancetype)initWithFileName: (OFString *)fileName +{ + self = [super init]; + + @try { + _fileName = [fileName copy]; + _compressionMethod = @"-lh0-"; + _date = [[OFDate alloc] initWithTimeIntervalSince1970: 0]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} - (instancetype)of_initWithHeader: (char [21])header stream: (OFStream *)stream encoding: (of_string_encoding_t)encoding { @@ -299,14 +311,14 @@ _uncompressedSize = OF_BSWAP32_IF_BE(_uncompressedSize); memcpy(&date, header + 15, 4); date = OF_BSWAP32_IF_BE(date); - _level = header[20]; + _headerLevel = header[20]; _extensions = [[OFMutableArray alloc] init]; - switch (_level) { + switch (_headerLevel) { case 0: case 1:; void *pool = objc_autoreleasePoolPush(); uint8_t fileNameLength; OFString *tmp; @@ -320,11 +332,11 @@ withString: @"/"]; _fileName = [tmp copy]; _CRC16 = [stream readLittleEndianInt16]; - if (_level == 1) { + if (_headerLevel == 1) { _operatingSystemIdentifier = [stream readInt8]; readExtensions(self, stream, encoding, false); } @@ -340,11 +352,11 @@ readExtensions(self, stream, encoding, true); break; default:; OFString *version = [OFString - stringWithFormat: @"%u", _level]; + stringWithFormat: @"%u", _headerLevel]; @throw [OFUnsupportedVersionException exceptionWithVersion: version]; } @@ -376,18 +388,129 @@ - (id)copy { return [self retain]; } + +- (id)mutableCopy +{ + OFLHAArchiveEntry *copy = [[OFMutableLHAArchiveEntry alloc] + initWithFileName: _fileName]; + + @try { + [copy->_compressionMethod release]; + copy->_compressionMethod = nil; + + [copy->_date release]; + copy->_date = nil; + + copy->_directoryName = [_directoryName copy]; + copy->_compressionMethod = [_compressionMethod copy]; + copy->_compressedSize = _compressedSize; + copy->_uncompressedSize = _uncompressedSize; + copy->_date = [_date copy]; + copy->_headerLevel = _headerLevel; + copy->_CRC16 = _CRC16; + copy->_operatingSystemIdentifier = _operatingSystemIdentifier; + copy->_fileComment = [_fileComment copy]; + copy->_mode = [_mode retain]; + copy->_UID = [_UID retain]; + copy->_GID = [_GID retain]; + copy->_owner = [_owner copy]; + copy->_group = [_group copy]; + copy->_modificationDate = [_modificationDate retain]; + copy->_extensions = [_extensions copy]; + } @catch (id e) { + [copy release]; + @throw e; + } + + return copy; +} - (OFString *)fileName { if (_directoryName == nil) return _fileName; return [_directoryName stringByAppendingString: _fileName]; } + +- (OFString *)compressionMethod +{ + return _compressionMethod; +} + +- (uint32_t)compressedSize +{ + return _compressedSize; +} + +- (uint32_t)uncompressedSize +{ + return _uncompressedSize; +} + +- (OFDate *)date +{ + return _date; +} + +- (uint8_t)headerLevel +{ + return _headerLevel; +} + +- (uint16_t)CRC16 +{ + return _CRC16; +} + +- (uint8_t)operatingSystemIdentifier +{ + return _operatingSystemIdentifier; +} + +- (OFString *)fileComment +{ + return _fileComment; +} + +- (OFNumber *)mode +{ + return _mode; +} + +- (OFNumber *)UID +{ + return _UID; +} + +- (OFNumber *)GID +{ + return _GID; +} + +- (OFString *)owner +{ + return _owner; +} + +- (OFString *)group +{ + return _group; +} + +- (OFDate *)modificationDate +{ + return _modificationDate; +} + +- (OFArray OF_GENERIC(OFData *) *)extensions +{ + return _extensions; +} - (OFString *)description { void *pool = objc_autoreleasePoolPush(); OFString *mode = (_mode == nil @@ -401,11 +524,11 @@ @"\tFile name = %@\n" @"\tCompression method = %@\n" @"\tCompressed size = %" @PRIu32 "\n" @"\tUncompressed size = %" @PRIu32 "\n" @"\tDate = %@\n" - @"\tLevel = %u\n" + @"\tHeader level = %u\n" @"\tCRC16 = %04" @PRIX16 @"\n" @"\tOperating system identifier = %c\n" @"\tComment = %@\n" @"\tMode = %@\n" @"\tUID = %@\n" @@ -414,11 +537,11 @@ @"\tGroup = %@\n" @"\tModification date = %@\n" @"\tExtensions: %@" @">", [self class], [self fileName], _compressionMethod, _compressedSize, - _uncompressedSize, _date, _level, _CRC16, + _uncompressedSize, _date, _headerLevel, _CRC16, _operatingSystemIdentifier, _fileComment, mode, _UID, _GID, _owner, _group, _modificationDate, extensions]; [ret retain]; ADDED src/OFMutableLHAArchiveEntry.h Index: src/OFMutableLHAArchiveEntry.h ================================================================== --- src/OFMutableLHAArchiveEntry.h +++ src/OFMutableLHAArchiveEntry.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * 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 "OFLHAArchiveEntry.h" + +OF_ASSUME_NONNULL_BEGIN + +/*! + * @class OFMutableLHAArchiveEntry \ + * OFMutableLHAArchiveEntry.h ObjFW/OFMutableLHAArchiveEntry.h + * + * @brief A class which represents a mutable entry in an LHA archive. + */ +@interface OFMutableLHAArchiveEntry: OFLHAArchiveEntry + +/*! + * @brief The file name of the entry. + */ +@property (readwrite, copy, nonatomic) OFString *fileName; + +/*! + * @brief The compression method of the entry. + */ +@property (readwrite, copy, nonatomic) OFString *compressionMethod; + +/*! + * @brief The compressed size of the entry's file. + */ +@property (readwrite, nonatomic) uint32_t compressedSize; + +/*! + * @brief The uncompressed size of the entry's file. + */ +@property (readwrite, nonatomic) uint32_t uncompressedSize; + +/*! + * @brief The date of the file. + */ +@property (readwrite, retain, nonatomic) OFDate *date; + +/*! + * @brief The LHA level of the file. + */ +@property (readwrite, nonatomic) uint8_t headerLevel; + +/*! + * @brief The CRC16 of the file. + */ +@property (readwrite, nonatomic) uint16_t CRC16; + +/*! + * @brief The operating system identifier of the file. + */ +@property (readwrite, nonatomic) uint8_t operatingSystemIdentifier; + +/*! + * @brief The comment of the file. + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) + OFString *fileComment; + +/*! + * @brief The mode of the entry. + */ +@property OF_NULLABLE_PROPERTY (readwrite, retain, nonatomic) OFNumber *mode; + +/*! + * @brief The UID of the owner. + */ +@property OF_NULLABLE_PROPERTY (readwrite, retain, nonatomic) OFNumber *UID; + +/*! + * @brief The GID of the group. + */ +@property OF_NULLABLE_PROPERTY (readwrite, retain, nonatomic) OFNumber *GID; + +/*! + * @brief The owner of the file. + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *owner; + +/*! + * @brief The group of the file. + */ +@property OF_NULLABLE_PROPERTY (readwrite, copy, nonatomic) OFString *group; + +/*! + * @brief The date of the last modification of the file. + */ +@property OF_NULLABLE_PROPERTY (readwrite, retain, nonatomic) + OFDate *modificationDate; + +/*! + * @brief The LHA extensions of the file. + */ +@property (readwrite, copy, nonatomic) OFArray OF_GENERIC(OFData *) *extensions; + +- (instancetype)init OF_UNAVAILABLE; + +/*! + * @brief Converts the OFMutableLHAArchiveEntry to an immutable + * OFLHAArchiveEntry. + */ +- (void)makeImmutable; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFMutableLHAArchiveEntry.m Index: src/OFMutableLHAArchiveEntry.m ================================================================== --- src/OFMutableLHAArchiveEntry.m +++ src/OFMutableLHAArchiveEntry.m @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * 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 "OFMutableLHAArchiveEntry.h" + +#import "OFArray.h" +#import "OFData.h" +#import "OFDate.h" +#import "OFNumber.h" +#import "OFString.h" + +@implementation OFMutableLHAArchiveEntry +@dynamic fileName, compressionMethod, compressedSize, uncompressedSize, date; +@dynamic headerLevel, CRC16, operatingSystemIdentifier, fileComment, mode, UID; +@dynamic GID, owner, group, modificationDate, extensions; + +- (id)copy +{ + OFMutableLHAArchiveEntry *copy = [self mutableCopy]; + + [copy makeImmutable]; + + return copy; +} + +- (void)setFileName: (OFString *)fileName +{ + OFString *old = _fileName; + _fileName = [fileName copy]; + [old release]; + + [_directoryName release]; + _directoryName = nil; +} + +- (void)setCompressionMethod: (OFString *)compressionMethod +{ + OFString *old = _compressionMethod; + _compressionMethod = [compressionMethod copy]; + [old release]; +} + +- (void)setCompressedSize: (uint32_t)compressedSize +{ + _compressedSize = compressedSize; +} + +- (void)setUncompressedSize: (uint32_t)uncompressedSize +{ + _uncompressedSize = uncompressedSize; +} + +- (void)setDate: (OFDate *)date +{ + OFDate *old = _date; + _date = [date retain]; + [old release]; +} + +- (void)setHeaderLevel: (uint8_t)headerLevel +{ + _headerLevel = headerLevel; +} + +- (void)setCRC16: (uint16_t)CRC16 +{ + _CRC16 = CRC16; +} + +- (void)setOperatingSystemIdentifier: (uint8_t)operatingSystemIdentifier +{ + _operatingSystemIdentifier = operatingSystemIdentifier; +} + +- (void)setFileComment: (OFString *)fileComment +{ + OFString *old = _fileComment; + _fileComment = [fileComment copy]; + [old release]; +} + +- (void)setMode: (OFNumber *)mode +{ + OFNumber *old = _mode; + _mode = [mode retain]; + [old release]; +} + +- (void)setUID: (OFNumber *)UID +{ + OFNumber *old = _UID; + _UID = [UID retain]; + [old release]; +} + +- (void)setGID: (OFNumber *)GID +{ + OFNumber *old = _GID; + _GID = [GID retain]; + [old release]; +} + +- (void)setOwner: (OFString *)owner +{ + OFString *old = _owner; + _owner = [owner copy]; + [old release]; +} + +- (void)setGroup: (OFString *)group +{ + OFString *old = _group; + _group = [group copy]; + [old release]; +} + +- (void)setModificationDate: (OFDate *)modificationDate +{ + OFDate *old = _modificationDate; + _modificationDate = [modificationDate retain]; + [old release]; +} + +- (void)setExtensions: (OFArray OF_GENERIC(OFData *) *)extensions +{ + OFArray OF_GENERIC(OFData *) *old = _extensions; + _extensions = [extensions copy]; + [old release]; +} + +- (void)makeImmutable +{ + object_setClass(self, [OFLHAArchiveEntry class]); +} +@end Index: utils/ofzip/LHAArchive.m ================================================================== --- utils/ofzip/LHAArchive.m +++ utils/ofzip/LHAArchive.m @@ -120,10 +120,15 @@ [of_stdout writeLine: OF_LOCALIZED( @"list_uncompressed_size", @"Uncompressed: %[size] bytes", @"size", uncompressedSize)]; [of_stdout writeString: @"\t"]; + [of_stdout writeLine: OF_LOCALIZED( + @"list_compression_method", + @"Compression method: %[method]", + @"method", [entry compressionMethod])]; + [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED(@"list_crc16", @"CRC16: %[crc16]", @"crc16", CRC16)]; [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED(@"list_date", @@ -162,24 +167,19 @@ @"Group: %[group]", @"group", [entry group])]; } if (app->_outputLevel >= 2) { - OFString *level = [OFString stringWithFormat: - @"%" PRIu8, [entry level]]; + OFString *headerLevel = [OFString + stringWithFormat: @"%" PRIu8, + [entry headerLevel]]; [of_stdout writeString: @"\t"]; [of_stdout writeLine: OF_LOCALIZED( - @"list_level", - @"Level: %[level]", - @"level", level)]; - - [of_stdout writeString: @"\t"]; - [of_stdout writeLine: OF_LOCALIZED( - @"list_compression_method", - @"Compression method: %[method]", - @"method", [entry compressionMethod])]; + @"list_header_level", + @"Header level: %[level]", + @"level", headerLevel)]; if ([entry operatingSystemIdentifier] != '\0') { OFString *OSID = [OFString stringWithFormat: @"%c", [entry operatingSystemIdentifier]]; Index: utils/ofzip/lang/de.json ================================================================== --- utils/ofzip/lang/de.json +++ utils/ofzip/lang/de.json @@ -70,10 +70,11 @@ ], "list_size": "Größe: %[size] Bytes", "list_mode": "Modus: %[mode]", "list_owner": "Besitzer: %[owner]", "list_group": "Gruppe: %[group]", + "list_header_level": "Header-Level: %[level]", "list_modification_date": "Änderungsdatum: %[date]", "list_type_normal": "Typ: Normale Datei", "list_type_hardlink": "Typ: Harter Link", "list_type_symlink": "Typ: Symbolischer Link", "list_link_target": "Zieldateiname: %[target]",