mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
Overtime size of source files became unmanageble, so it is better to split them. Also internal zip structure have been renamed to include word zip.
82 lines
3.0 KiB
Swift
82 lines
3.0 KiB
Swift
// Copyright (c) 2017 Timofey Solomko
|
|
// Licensed under MIT License
|
|
//
|
|
// See LICENSE for license information
|
|
|
|
import Foundation
|
|
|
|
struct ZipLocalHeader {
|
|
|
|
let versionNeeded: Int
|
|
let generalPurposeBitFlags: Int
|
|
let compressionMethod: Int
|
|
let lastModFileTime: Int
|
|
let lastModFileDate: Int
|
|
|
|
let crc32: UInt32
|
|
private(set) var compSize: UInt64
|
|
private(set) var uncompSize: UInt64
|
|
|
|
private(set) var zip64FieldsArePresent: Bool = false
|
|
|
|
let fileName: String
|
|
|
|
init(_ pointerData: inout DataWithPointer) throws {
|
|
// Check signature.
|
|
guard pointerData.uint32FromAlignedBytes(count: 4) == 0x04034b50
|
|
else { throw ZipError.wrongSignature }
|
|
|
|
self.versionNeeded = pointerData.intFromAlignedBytes(count: 2)
|
|
|
|
self.generalPurposeBitFlags = pointerData.intFromAlignedBytes(count: 2)
|
|
|
|
self.compressionMethod = pointerData.intFromAlignedBytes(count: 2)
|
|
|
|
self.lastModFileTime = pointerData.intFromAlignedBytes(count: 2)
|
|
self.lastModFileDate = pointerData.intFromAlignedBytes(count: 2)
|
|
|
|
self.crc32 = pointerData.uint32FromAlignedBytes(count: 4)
|
|
|
|
self.compSize = pointerData.uint64FromAlignedBytes(count: 4)
|
|
self.uncompSize = pointerData.uint64FromAlignedBytes(count: 4)
|
|
|
|
let fileNameLength = pointerData.intFromAlignedBytes(count: 2)
|
|
let extraFieldLength = pointerData.intFromAlignedBytes(count: 2)
|
|
|
|
guard let fileName = String(data: Data(bytes: pointerData.alignedBytes(count: fileNameLength)),
|
|
encoding: .utf8)
|
|
else { throw ZipError.wrongTextField }
|
|
self.fileName = fileName
|
|
|
|
let extraFieldStart = pointerData.index
|
|
while pointerData.index - extraFieldStart < extraFieldLength {
|
|
// There are a lot of possible extra fields.
|
|
// But we are (currently) only interested in Zip64 related fields (with headerID = 0x0001),
|
|
// because they directly impact further extraction process.
|
|
let headerID = pointerData.intFromAlignedBytes(count: 2)
|
|
let size = pointerData.intFromAlignedBytes(count: 2)
|
|
switch headerID {
|
|
case 0x0001:
|
|
// In local header both uncompressed size and compressed size fields are required.
|
|
self.uncompSize = pointerData.uint64FromAlignedBytes(count: 8)
|
|
self.compSize = pointerData.uint64FromAlignedBytes(count: 8)
|
|
|
|
self.zip64FieldsArePresent = true
|
|
default:
|
|
pointerData.index += size
|
|
}
|
|
}
|
|
|
|
// Let's check headers's values for consistency.
|
|
guard self.versionNeeded & 0xFF <= 63
|
|
else { throw ZipError.wrongVersion }
|
|
guard self.generalPurposeBitFlags & 0x2000 == 0 &&
|
|
self.generalPurposeBitFlags & 0x40 == 0 &&
|
|
self.generalPurposeBitFlags & 0x01 == 0
|
|
else { throw ZipError.encryptionNotSupported }
|
|
guard self.generalPurposeBitFlags & 0x20 == 0
|
|
else { throw ZipError.patchingNotSupported }
|
|
}
|
|
|
|
}
|