From de0fcec3cc494b76098db51eccd26c51de0eaec9 Mon Sep 17 00:00:00 2001 From: Timofey Solomko Date: Sat, 24 Mar 2018 19:33:34 +0300 Subject: [PATCH] [ZIP] Add structs for all "standard" extra fields These "standard" extra fields are already implemented in LocalHeader/CDEntry. --- SWCompression.xcodeproj/project.pbxproj | 4 + Sources/ZIP/StandardExtraFields.swift | 135 ++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 Sources/ZIP/StandardExtraFields.swift diff --git a/SWCompression.xcodeproj/project.pbxproj b/SWCompression.xcodeproj/project.pbxproj index 9902262a..b7e62172 100644 --- a/SWCompression.xcodeproj/project.pbxproj +++ b/SWCompression.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0606CF8120641209002B6EE9 /* StandardExtraFields.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0606CF8020641209002B6EE9 /* StandardExtraFields.swift */; }; 06092A1A1FA4CB0300DE9FD5 /* CompressionMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06092A191FA4CB0300DE9FD5 /* CompressionMethod.swift */; }; 06092A241FA4CC3D00DE9FD5 /* CompressionMethod+Zip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 06092A231FA4CC3D00DE9FD5 /* CompressionMethod+Zip.swift */; }; 061C06211F0E89D900832F0C /* XZError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 061C06201F0E89D900832F0C /* XZError.swift */; }; @@ -205,6 +206,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 0606CF8020641209002B6EE9 /* StandardExtraFields.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandardExtraFields.swift; sourceTree = ""; }; 06092A191FA4CB0300DE9FD5 /* CompressionMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompressionMethod.swift; sourceTree = ""; }; 06092A231FA4CC3D00DE9FD5 /* CompressionMethod+Zip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CompressionMethod+Zip.swift"; sourceTree = ""; }; 061C06201F0E89D900832F0C /* XZError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XZError.swift; sourceTree = ""; }; @@ -563,6 +565,7 @@ 061C06411F0E8AD500832F0C /* ZipEntry.swift */, 06BAC5931F8CFF28002443F4 /* ZipEntryInfo.swift */, 0642998A206017590044BA0C /* ZipExtraField.swift */, + 0606CF8020641209002B6EE9 /* StandardExtraFields.swift */, 061C063C1F0E8AB700832F0C /* ZipError.swift */, 06393DF41F1A7F8E00A647A0 /* ZipString.swift */, 061C064C1F0E901C00832F0C /* ZipLocalHeader.swift */, @@ -1047,6 +1050,7 @@ 06A3933A1DE0709300182E12 /* ZlibArchive.swift in Sources */, 06E30F391F82D2DD00F80167 /* HuffmanLength+Comparable.swift in Sources */, 061C063D1F0E8AB700832F0C /* ZipError.swift in Sources */, + 0606CF8120641209002B6EE9 /* StandardExtraFields.swift in Sources */, 0631CB061F81109E00A2E0AB /* Deflate+Constants.swift in Sources */, 06D95AC11F4C54E0006B46AC /* BZip2+Compress.swift in Sources */, 06912BD21F5C8F3D0070BB60 /* Deflate+Lengths.swift in Sources */, diff --git a/Sources/ZIP/StandardExtraFields.swift b/Sources/ZIP/StandardExtraFields.swift new file mode 100644 index 00000000..8a5ec1ef --- /dev/null +++ b/Sources/ZIP/StandardExtraFields.swift @@ -0,0 +1,135 @@ +// Copyright (c) 2018 Timofey Solomko +// Licensed under MIT License +// +// See LICENSE for license information + +import BitByteData + +struct ExtendedTimestampExtraField: ZipExtraField { + + static let id: UInt16 = 0x5455 + + let size: Int + let location: ZipExtraFieldLocation + + var accessTimestamp: UInt32? + var creationTimestamp: UInt32? + var modificationTimestamp: UInt32? + + init(_ byteReader: ByteReader, _ size: Int, location: ZipExtraFieldLocation) { + self.size = size + self.location = location + switch location { + case .centralDirectory: + let flags = byteReader.byte() + if flags & 0x01 != 0 { + self.modificationTimestamp = byteReader.uint32() + } + case .localHeader: + let flags = byteReader.byte() + if flags & 0x01 != 0 { + self.modificationTimestamp = byteReader.uint32() + } + if flags & 0x02 != 0 { + self.accessTimestamp = byteReader.uint32() + } + if flags & 0x04 != 0 { + self.creationTimestamp = byteReader.uint32() + } + } + } + +} + +struct NtfsExtraField: ZipExtraField { + + static let id: UInt16 = 0x000A + + let size: Int + let location: ZipExtraFieldLocation + + let ntfsAtime: UInt64 + let ntfsCtime: UInt64 + let ntfsMtime: UInt64 + + init?(_ byteReader: ByteReader, _ size: Int, location: ZipExtraFieldLocation) { + self.size = size + self.location = location + byteReader.offset += 4 // Skip reserved bytes + let tag = byteReader.uint16() // This attribute's tag + byteReader.offset += 2 // Skip size of this attribute + guard tag == 0x0001 + else { return nil } + self.ntfsMtime = byteReader.uint64() + self.ntfsAtime = byteReader.uint64() + self.ntfsCtime = byteReader.uint64() + } + +} + +struct InfoZipUnixExtraField: ZipExtraField { + + static let id: UInt16 = 0x7855 + + let size: Int + let location: ZipExtraFieldLocation + + let infoZipUid: UInt16 + let infoZipGid: UInt16 + + init?(_ byteReader: ByteReader, _ size: Int, location: ZipExtraFieldLocation) { + self.size = size + self.location = location + switch location { + case .centralDirectory: + return nil + case .localHeader: + self.infoZipUid = byteReader.uint16() + self.infoZipGid = byteReader.uint16() + } + } + +} + +struct InfoZipNewUnixExtraField: ZipExtraField { + + static let id: UInt16 = 0x7875 + + let size: Int + let location: ZipExtraFieldLocation + + var infoZipNewUid: Int? + var infoZipNewGid: Int? + + init?(_ byteReader: ByteReader, _ size: Int, location: ZipExtraFieldLocation) { + self.size = size + self.location = location + guard byteReader.byte() == 1 // Version must be 1 + else { return nil } + + let uidSize = byteReader.byte().toInt() + if uidSize > 8 { + byteReader.offset += uidSize + } else { + var uid = 0 + for i in 0.. 8 { + byteReader.offset += gidSize + } else { + var gid = 0 + for i in 0..