@@ -111,70 +111,73 @@ static void parsePermissionsExtension(OFLHAArchiveEntry *entry, OFData *extension, OFStringEncoding encoding) { - uint16_t mode; + uint16_t POSIXPermissions; if (extension.count != 3) @throw [OFInvalidFormatException exception]; - memcpy(&mode, (char *)extension.items + 1, 2); - mode = OFFromLittleEndian16(mode); + memcpy(&POSIXPermissions, (char *)extension.items + 1, 2); + POSIXPermissions = OFFromLittleEndian16(POSIXPermissions); - [entry->_mode release]; - entry->_mode = nil; + [entry->_POSIXPermissions release]; + entry->_POSIXPermissions = nil; - entry->_mode = [[OFNumber alloc] initWithUnsignedShort: mode]; + entry->_POSIXPermissions = + [[OFNumber alloc] initWithUnsignedShort: POSIXPermissions]; } static void parseGIDUIDExtension(OFLHAArchiveEntry *entry, OFData *extension, OFStringEncoding encoding) { - uint16_t UID, GID; + uint16_t ownerAccountID, groupOwnerAccountID; if (extension.count != 5) @throw [OFInvalidFormatException exception]; - memcpy(&GID, (char *)extension.items + 1, 2); - GID = OFFromLittleEndian16(GID); - - memcpy(&UID, (char *)extension.items + 3, 2); - UID = OFFromLittleEndian16(UID); - - [entry->_GID release]; - entry->_GID = nil; - - [entry->_UID release]; - entry->_UID = nil; - - entry->_GID = [[OFNumber alloc] initWithUnsignedShort: GID]; - entry->_UID = [[OFNumber alloc] initWithUnsignedShort: UID]; + memcpy(&groupOwnerAccountID, (char *)extension.items + 1, 2); + groupOwnerAccountID = OFFromLittleEndian16(groupOwnerAccountID); + + memcpy(&ownerAccountID, (char *)extension.items + 3, 2); + ownerAccountID = OFFromLittleEndian16(ownerAccountID); + + [entry->_groupOwnerAccountID release]; + entry->_groupOwnerAccountID = nil; + + [entry->_ownerAccountID release]; + entry->_ownerAccountID = nil; + + entry->_groupOwnerAccountID = + [[OFNumber alloc] initWithUnsignedShort: groupOwnerAccountID]; + entry->_ownerAccountID = + [[OFNumber alloc] initWithUnsignedShort: ownerAccountID]; } static void parseGroupExtension(OFLHAArchiveEntry *entry, OFData *extension, OFStringEncoding encoding) { - [entry->_group release]; - entry->_group = nil; + [entry->_groupOwnerAccountName release]; + entry->_groupOwnerAccountName = nil; - entry->_group = [[OFString alloc] + entry->_groupOwnerAccountName = [[OFString alloc] initWithCString: (char *)extension.items + 1 encoding: encoding length: extension.count - 1]; } static void parseOwnerExtension(OFLHAArchiveEntry *entry, OFData *extension, OFStringEncoding encoding) { - [entry->_owner release]; - entry->_owner = nil; + [entry->_ownerAccountName release]; + entry->_ownerAccountName = nil; - entry->_owner = [[OFString alloc] + entry->_ownerAccountName = [[OFString alloc] initWithCString: (char *)extension.items + 1 encoding: encoding length: extension.count - 1]; } @@ -301,28 +304,22 @@ *fileNameLength = length - pos; *directoryName = cString; *directoryNameLength = pos; } -+ (instancetype)entryWithFileName: (OFString *)fileName -{ - return [[[self alloc] initWithFileName: fileName] autorelease]; -} - - (instancetype)init { OF_INVALID_INIT_METHOD } -- (instancetype)initWithFileName: (OFString *)fileName +- (instancetype)of_init { self = [super init]; @try { - _fileName = [fileName copy]; _compressionMethod = @"-lh0-"; - _date = [[OFDate alloc] initWithTimeIntervalSince1970: 0]; + _modificationDate = [[OFDate alloc] init]; } @catch (id e) { [self release]; @throw e; } @@ -341,15 +338,21 @@ _compressionMethod = [[OFString alloc] initWithCString: header + 2 encoding: OFStringEncodingASCII length: 5]; + if (_compressedSize > UINT32_MAX || + _uncompressedSize > UINT32_MAX) + @throw [OFOutOfRangeException exception]; + memcpy(&_compressedSize, header + 7, 4); - _compressedSize = OFFromLittleEndian32(_compressedSize); + _compressedSize = + OFFromLittleEndian32((uint32_t)_compressedSize); memcpy(&_uncompressedSize, header + 11, 4); - _uncompressedSize = OFFromLittleEndian32(_uncompressedSize); + _uncompressedSize = + OFFromLittleEndian32((uint32_t)_uncompressedSize); memcpy(&date, header + 15, 4); date = OFFromLittleEndian32(date); _headerLevel = header[20]; @@ -360,11 +363,11 @@ case 1:; void *pool = objc_autoreleasePoolPush(); uint8_t fileNameLength; OFString *tmp; - _date = [parseMSDOSDate(date) retain]; + _modificationDate = [parseMSDOSDate(date) retain]; fileNameLength = [stream readInt8]; tmp = [stream readStringWithLength: fileNameLength encoding: encoding]; tmp = [tmp stringByReplacingOccurrencesOfString: @"\\" @@ -380,11 +383,11 @@ } objc_autoreleasePoolPop(pool); break; case 2: - _date = [[OFDate alloc] + _modificationDate = [[OFDate alloc] initWithTimeIntervalSince1970: date]; _CRC16 = [stream readLittleEndianInt16]; _operatingSystemIdentifier = [stream readInt8]; @@ -414,17 +417,17 @@ - (void)dealloc { [_compressionMethod release]; [_fileName release]; [_directoryName release]; - [_date release]; + [_modificationDate release]; [_fileComment release]; - [_mode release]; - [_UID release]; - [_GID release]; - [_owner release]; - [_group release]; + [_POSIXPermissions release]; + [_ownerAccountID release]; + [_groupOwnerAccountID release]; + [_ownerAccountName release]; + [_groupOwnerAccountName release]; [_extensions release]; [super dealloc]; } @@ -440,28 +443,27 @@ @try { [copy->_compressionMethod release]; copy->_compressionMethod = nil; - [copy->_date release]; - copy->_date = nil; + [copy->_modificationDate release]; + copy->_modificationDate = nil; copy->_directoryName = [_directoryName copy]; copy->_compressionMethod = [_compressionMethod copy]; copy->_compressedSize = _compressedSize; copy->_uncompressedSize = _uncompressedSize; - copy->_date = [_date copy]; + copy->_modificationDate = [_modificationDate 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->_POSIXPermissions = [_POSIXPermissions retain]; + copy->_ownerAccountID = [_ownerAccountID retain]; + copy->_groupOwnerAccountID = [_groupOwnerAccountID retain]; + copy->_ownerAccountName = [_ownerAccountName copy]; + copy->_groupOwnerAccountName = [_groupOwnerAccountName copy]; copy->_extensions = [_extensions copy]; } @catch (id e) { [copy release]; @throw e; } @@ -480,23 +482,23 @@ - (OFString *)compressionMethod { return _compressionMethod; } -- (uint32_t)compressedSize +- (unsigned long long)compressedSize { return _compressedSize; } -- (uint32_t)uncompressedSize +- (unsigned long long)uncompressedSize { return _uncompressedSize; } -- (OFDate *)date +- (OFDate *)modificationDate { - return _date; + return _modificationDate; } - (uint8_t)headerLevel { return _headerLevel; @@ -515,38 +517,33 @@ - (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; +- (OFNumber *)POSIXPermissions +{ + return _POSIXPermissions; +} + +- (OFNumber *)ownerAccountID +{ + return _ownerAccountID; +} + +- (OFNumber *)groupOwnerAccountID +{ + return _groupOwnerAccountID; +} + +- (OFString *)ownerAccountName +{ + return _ownerAccountName; +} + +- (OFString *)groupOwnerAccountName +{ + return _groupOwnerAccountName; } - (OFArray OF_GENERIC(OFData *) *)extensions { return _extensions; @@ -569,27 +566,29 @@ getFileNameAndDirectoryName(self, encoding, &fileName, &fileNameLength, &directoryName, &directoryNameLength); if (fileNameLength > UINT16_MAX - 3 || - directoryNameLength > UINT16_MAX - 3) + directoryNameLength > UINT16_MAX - 3 || + _compressedSize > UINT32_MAX || _uncompressedSize > UINT32_MAX) @throw [OFOutOfRangeException exception]; /* Length. Filled in after we're done. */ [data increaseCountBy: 2]; [data addItems: [_compressionMethod cStringWithEncoding: OFStringEncodingASCII] count: 5]; - tmp32 = OFToLittleEndian32(_compressedSize); + tmp32 = OFToLittleEndian32((uint32_t)_compressedSize); [data addItems: &tmp32 count: sizeof(tmp32)]; - tmp32 = OFToLittleEndian32(_uncompressedSize); + tmp32 = OFToLittleEndian32((uint32_t)_uncompressedSize); [data addItems: &tmp32 count: sizeof(tmp32)]; - tmp32 = OFToLittleEndian32((uint32_t)_date.timeIntervalSince1970); + tmp32 = OFToLittleEndian32( + (uint32_t)_modificationDate.timeIntervalSince1970); [data addItems: &tmp32 count: sizeof(tmp32)]; /* Reserved */ [data increaseCountBy: 1]; @@ -633,70 +632,64 @@ [data addItem: "\x3F"]; [data addItems: [_fileComment cStringWithEncoding: encoding] count: fileCommentLength]; } - if (_mode != nil) { + if (_POSIXPermissions != nil) { tmp16 = OFToLittleEndian16(5); [data addItems: &tmp16 count: sizeof(tmp16)]; [data addItem: "\x50"]; - tmp16 = OFToLittleEndian16(_mode.unsignedShortValue); + tmp16 = + OFToLittleEndian16(_POSIXPermissions.unsignedShortValue); [data addItems: &tmp16 count: sizeof(tmp16)]; } - if (_UID != nil || _GID != nil) { - if (_UID == nil || _GID == nil) + if (_ownerAccountID != nil || _groupOwnerAccountID != nil) { + if (_ownerAccountID == nil || _groupOwnerAccountID == nil) @throw [OFInvalidArgumentException exception]; tmp16 = OFToLittleEndian16(7); [data addItems: &tmp16 count: sizeof(tmp16)]; [data addItem: "\x51"]; - tmp16 = OFToLittleEndian16(_GID.unsignedShortValue); - [data addItems: &tmp16 count: sizeof(tmp16)]; - - tmp16 = OFToLittleEndian16(_UID.unsignedShortValue); - [data addItems: &tmp16 count: sizeof(tmp16)]; - } - - if (_group != nil) { - size_t groupLength = - [_group cStringLengthWithEncoding: encoding]; - - if (groupLength > UINT16_MAX - 3) - @throw [OFOutOfRangeException exception]; - - tmp16 = OFToLittleEndian16((uint16_t)groupLength + 3); - [data addItems: &tmp16 count: sizeof(tmp16)]; - [data addItem: "\x52"]; - [data addItems: [_group cStringWithEncoding: encoding] - count: groupLength]; - } - - if (_owner != nil) { - size_t ownerLength = - [_owner cStringLengthWithEncoding: encoding]; - - if (ownerLength > UINT16_MAX - 3) - @throw [OFOutOfRangeException exception]; - - tmp16 = OFToLittleEndian16((uint16_t)ownerLength + 3); - [data addItems: &tmp16 count: sizeof(tmp16)]; - [data addItem: "\x53"]; - [data addItems: [_owner cStringWithEncoding: encoding] - count: ownerLength]; - } - - if (_modificationDate != nil) { - tmp16 = OFToLittleEndian16(7); - [data addItems: &tmp16 count: sizeof(tmp16)]; - [data addItem: "\x54"]; - - tmp32 = OFToLittleEndian32( - (uint32_t)_modificationDate.timeIntervalSince1970); - [data addItems: &tmp32 count: sizeof(tmp32)]; + tmp16 = OFToLittleEndian16( + _groupOwnerAccountID.unsignedShortValue); + [data addItems: &tmp16 count: sizeof(tmp16)]; + + tmp16 = OFToLittleEndian16(_ownerAccountID.unsignedShortValue); + [data addItems: &tmp16 count: sizeof(tmp16)]; + } + + if (_groupOwnerAccountName != nil) { + size_t length = [_groupOwnerAccountName + cStringLengthWithEncoding: encoding]; + + if (length > UINT16_MAX - 3) + @throw [OFOutOfRangeException exception]; + + tmp16 = OFToLittleEndian16((uint16_t)length + 3); + [data addItems: &tmp16 count: sizeof(tmp16)]; + [data addItem: "\x52"]; + [data addItems: [_groupOwnerAccountName + cStringWithEncoding: encoding] + count: length]; + } + + if (_ownerAccountName != nil) { + size_t length = + [_ownerAccountName cStringLengthWithEncoding: encoding]; + + if (length > UINT16_MAX - 3) + @throw [OFOutOfRangeException exception]; + + tmp16 = OFToLittleEndian16((uint16_t)length + 3); + [data addItems: &tmp16 count: sizeof(tmp16)]; + [data addItem: "\x53"]; + [data addItems: [_ownerAccountName + cStringWithEncoding: encoding] + count: length]; } for (OFData *extension in _extensions) { size_t extensionLength = extension.count; @@ -733,41 +726,46 @@ } - (OFString *)description { void *pool = objc_autoreleasePoolPush(); - OFString *mode = (_mode == nil ? nil - : [OFString stringWithFormat: @"%ho", _mode.unsignedShortValue]); + OFString *POSIXPermissions = nil; OFString *extensions = [_extensions.description stringByReplacingOccurrencesOfString: @"\n" withString: @"\n\t"]; - OFString *ret = [OFString stringWithFormat: + OFString *ret; + + if (_POSIXPermissions != nil) + POSIXPermissions = [OFString stringWithFormat: @"%ho", + _POSIXPermissions.unsignedShortValue]; + + ret = [OFString stringWithFormat: @"<%@:\n" @"\tFile name = %@\n" @"\tCompression method = %@\n" - @"\tCompressed size = %" @PRIu32 "\n" - @"\tUncompressed size = %" @PRIu32 "\n" - @"\tDate = %@\n" + @"\tCompressed size = %llu\n" + @"\tUncompressed size = %llu\n" + @"\tModification date = %@\n" @"\tHeader level = %u\n" @"\tCRC16 = %04" @PRIX16 @"\n" @"\tOperating system identifier = %c\n" @"\tComment = %@\n" - @"\tMode = %@\n" - @"\tUID = %@\n" - @"\tGID = %@\n" - @"\tOwner = %@\n" - @"\tGroup = %@\n" - @"\tModification date = %@\n" + @"\tPOSIX permissions = %@\n" + @"\tOwner account ID = %@\n" + @"\tGroup owner account ID = %@\n" + @"\tOwner account name = %@\n" + @"\tGroup owner accounut name = %@\n" @"\tExtensions: %@" @">", self.class, self.fileName, _compressionMethod, _compressedSize, - _uncompressedSize, _date, _headerLevel, _CRC16, - _operatingSystemIdentifier, _fileComment, mode, _UID, _GID, _owner, - _group, _modificationDate, extensions]; + _uncompressedSize, _modificationDate, _headerLevel, _CRC16, + _operatingSystemIdentifier, _fileComment, POSIXPermissions, + _ownerAccountID, _groupOwnerAccountID, _ownerAccountName, + _groupOwnerAccountName, extensions]; [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } @end