mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
[ZIP] Add support for custom extra fields
This commit is contained in:
@@ -39,6 +39,8 @@ struct ZipCentralDirectoryEntry {
|
||||
/// 0x7875 extra field.
|
||||
private(set) var infoZipNewUnixExtraField: InfoZipNewUnixExtraField?
|
||||
|
||||
let customExtraFields: [ZipExtraField]
|
||||
|
||||
let nextEntryOffset: Int
|
||||
|
||||
init(_ byteReader: ByteReader) throws {
|
||||
@@ -78,6 +80,7 @@ struct ZipCentralDirectoryEntry {
|
||||
self.fileName = fileName
|
||||
|
||||
let extraFieldStart = byteReader.offset
|
||||
var customExtraFields = [ZipExtraField]()
|
||||
while byteReader.offset - extraFieldStart < extraFieldLength {
|
||||
// There are a lot of possible extra fields.
|
||||
let headerID = byteReader.uint16()
|
||||
@@ -107,9 +110,21 @@ struct ZipCentralDirectoryEntry {
|
||||
case 0x7875: // Info-ZIP New Unix Extra Field
|
||||
self.infoZipNewUnixExtraField = InfoZipNewUnixExtraField(byteReader, size, location: .centralDirectory)
|
||||
default:
|
||||
byteReader.offset += size
|
||||
let customFieldOffset = byteReader.offset
|
||||
if let customExtraFieldType = ZipContainer.customExtraFields[headerID],
|
||||
customExtraFieldType.id == headerID,
|
||||
let customExtraField = customExtraFieldType.init(byteReader, size, location: .centralDirectory),
|
||||
customExtraField.id == headerID {
|
||||
customExtraFields.append(customExtraField)
|
||||
guard byteReader.offset == customFieldOffset + size
|
||||
else { fatalError("Custom field in Central Directory with ID=\(headerID) of" +
|
||||
"type=\(customExtraFieldType) failed to read exactly \(size) bytes.") }
|
||||
} else {
|
||||
byteReader.offset = customFieldOffset + size
|
||||
}
|
||||
}
|
||||
}
|
||||
self.customExtraFields = customExtraFields
|
||||
|
||||
guard let fileComment = byteReader.getZipStringField(fileCommentLength, useUtf8)
|
||||
else { throw ZipError.wrongTextField }
|
||||
|
||||
@@ -9,6 +9,8 @@ import BitByteData
|
||||
/// Provides functions for work with ZIP containers.
|
||||
public class ZipContainer: Container {
|
||||
|
||||
public static var customExtraFields = [UInt16: ZipExtraField.Type]()
|
||||
|
||||
/**
|
||||
Processes ZIP container and returns an array of `ZipEntry` with information and data for all entries.
|
||||
|
||||
|
||||
@@ -92,6 +92,8 @@ public struct ZipEntryInfo: ContainerEntryInfo {
|
||||
*/
|
||||
public let groupID: Int?
|
||||
|
||||
public let customExtraFields: [ZipExtraField]
|
||||
|
||||
let cdEntry: ZipCentralDirectoryEntry
|
||||
let localHeader: ZipLocalHeader
|
||||
|
||||
@@ -200,6 +202,11 @@ public struct ZipEntryInfo: ContainerEntryInfo {
|
||||
// Owner's group ID.
|
||||
self.groupID = localHeader.infoZipNewUnixExtraField?.infoZipNewGid ??
|
||||
localHeader.infoZipUnixExtraField?.infoZipGid.toInt()
|
||||
|
||||
// Custom extra fields.
|
||||
var customExtraFields = cdEntry.customExtraFields
|
||||
customExtraFields.append(contentsOf: localHeader.customExtraFields)
|
||||
self.customExtraFields = customExtraFields
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ struct ZipLocalHeader {
|
||||
/// 0x7875 extra field.
|
||||
private(set) var infoZipNewUnixExtraField: InfoZipNewUnixExtraField?
|
||||
|
||||
let customExtraFields: [ZipExtraField]
|
||||
|
||||
let dataOffset: Int
|
||||
|
||||
init(_ byteReader: ByteReader) throws {
|
||||
@@ -64,6 +66,7 @@ struct ZipLocalHeader {
|
||||
self.fileName = fileName
|
||||
|
||||
let extraFieldStart = byteReader.offset
|
||||
var customExtraFields = [ZipExtraField]()
|
||||
while byteReader.offset - extraFieldStart < extraFieldLength {
|
||||
// There are a lot of possible extra fields.
|
||||
let headerID = byteReader.uint16()
|
||||
@@ -85,9 +88,21 @@ struct ZipLocalHeader {
|
||||
case 0x7875: // Info-ZIP New Unix Extra Field
|
||||
self.infoZipNewUnixExtraField = InfoZipNewUnixExtraField(byteReader, size, location: .localHeader)
|
||||
default:
|
||||
byteReader.offset += size
|
||||
let customFieldOffset = byteReader.offset
|
||||
if let customExtraFieldType = ZipContainer.customExtraFields[headerID],
|
||||
customExtraFieldType.id == headerID,
|
||||
let customExtraField = customExtraFieldType.init(byteReader, size, location: .localHeader),
|
||||
customExtraField.id == headerID {
|
||||
customExtraFields.append(customExtraField)
|
||||
guard byteReader.offset == customFieldOffset + size
|
||||
else { fatalError("Custom field in Local Header with ID=\(headerID) of" +
|
||||
"type=\(customExtraFieldType) failed to read exactly \(size) bytes.") }
|
||||
} else {
|
||||
byteReader.offset = customFieldOffset + size
|
||||
}
|
||||
}
|
||||
}
|
||||
self.customExtraFields = customExtraFields
|
||||
|
||||
self.dataOffset = byteReader.offset
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user