Complete 7zip structures implementations

Though some questions, problems and opportunities for improvements are remaining.
This commit is contained in:
Timofey Solomko
2017-07-25 00:35:57 +03:00
parent f76c2b575a
commit 097aaf7b24
6 changed files with 98 additions and 133 deletions
+7 -6
View File
@@ -13,8 +13,8 @@ struct SevenZipCodec {
let id: [UInt8]
var numInStreams: Int?
var numOutStreams: Int?
let numInStreams: Int
let numOutStreams: Int
var propertiesSize: Int?
var properties: [UInt8]?
@@ -29,10 +29,11 @@ struct SevenZipCodec {
id = pointerData.bytes(count: idSize)
if isComplex {
numInStreams = try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger
numOutStreams = try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger
}
// TODO: Introduce typealias for SevenZipError.multiByteIntegerError.
numInStreams = isComplex ? try pointerData
.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger : 1
numOutStreams = isComplex ? try pointerData
.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger : 1
if attributesExist {
propertiesSize = try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger
+32 -15
View File
@@ -10,10 +10,10 @@ struct SevenZipCoderInfo {
let numFolders: Int
let external: UInt8
var folders: [SevenZipFolder]?
var folders = [SevenZipFolder]()
var dataStreamIndex: Int?
let unpackSizes: [Int]
var digests = [UInt32?]()
init(_ pointerData: DataWithPointer) throws {
guard pointerData.byte() == 0x0B
@@ -22,9 +22,8 @@ struct SevenZipCoderInfo {
external = pointerData.byte()
switch external {
case 0:
folders = []
for _ in 0..<numFolders {
folders?.append(try SevenZipFolder(pointerData))
folders.append(try SevenZipFolder(pointerData))
}
case 1:
dataStreamIndex = try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger
@@ -36,7 +35,7 @@ struct SevenZipCoderInfo {
else { throw SevenZipError.wrongPropertyID }
var sizes = [Int]()
if external == 0 {
for folder in folders! {
for folder in folders {
for _ in 0..<folder.numPackedStreams { // TODO: ???
sizes.append(try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger)
}
@@ -44,15 +43,33 @@ struct SevenZipCoderInfo {
}
unpackSizes = sizes
// TODO:
//
// []
// BYTE NID::kCRC (0x0A)
// UnPackDigests[NumFolders]
// []
//
guard pointerData.byte() == 0x00
else { throw SevenZipError.wrongPropertyID }
switch pointerData.byte() {
case 0x0A:
// TODO: Extract digests code.
let allDefined = pointerData.byte()
let definedBits: [UInt8]
if allDefined == 0 {
let bitReader = BitReader(data: pointerData.data, bitOrder: .reversed) // TODO: Bit order???
bitReader.index = pointerData.index
definedBits = bitReader.bits(count: numFolders)
bitReader.skipUntilNextByte()
pointerData.index = bitReader.index
} else {
definedBits = Array(repeating: 1, count: numFolders)
}
for bit in definedBits {
if bit == 1 {
digests.append(pointerData.uint32())
} else {
digests.append(nil)
}
}
guard pointerData.byte() == 0x00
else { throw SevenZipError.wrongPropertyID }
case 0x00:
break
default:
throw SevenZipError.wrongPropertyID
}
}
}
+7 -79
View File
@@ -16,95 +16,23 @@ struct SevenZipFileInfo {
let numFiles: Int
var files = [File]()
var properties = [(Int, [UInt8])]()
init(_ pointerData: DataWithPointer) throws {
numFiles = try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger
for _ in 0..<numFiles {
files.append(File())
}
let bitReader = BitReader(data: pointerData.data, bitOrder: .reversed) // TODO: bitOrder ???
var totalEmptyStreams = 0
while true {
let propertyType = pointerData.byte()
if propertyType == 0 {
break
}
switch propertyType {
case 0x0E: // Empty stream
for i in 0..<numFiles {
let isEmptyStream = bitReader.bit() != 0
files[i].isEmptyStream = isEmptyStream
totalEmptyStreams += isEmptyStream ? 1 : 0 // TODO: Should we skipUntilNextByte() ???
}
case 0x0F: // Empty file
break
default:
break // TODO: Should we throw error?
}
let size = try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger
properties.append((propertyType.toInt(), pointerData.bytes(count: size)))
// TODO: Add properties parsing.
}
}
//
// for (;;)
// {
// BYTE PropertyType;
// if (aType == 0)
// break;
//
// UINT64 Size;
//
// switch(PropertyType)
// {
//
// kEmptyFile: (0x0F)
// for(EmptyStreams)
// BIT IsEmptyFile
//
// kAnti: (0x10)
// for(EmptyStreams)
// BIT IsAntiFile
//
// case kCTime: (0x12)
// case kATime: (0x13)
// case kMTime: (0x14)
// BYTE AllAreDefined
// if (AllAreDefined == 0)
// {
// for(NumFiles)
// BIT TimeDefined
// }
// BYTE External;
// if(External != 0)
// UINT64 DataIndex
// []
// for(Definded Items)
// UINT64 Time
// []
//
// kNames: (0x11)
// BYTE External;
// if(External != 0)
// UINT64 DataIndex
// []
// for(Files)
// {
// wchar_t Names[NameSize];
// wchar_t 0;
// }
// []
//
// kAttributes: (0x15)
// BYTE AllAreDefined
// if (AllAreDefined == 0)
// {
// for(NumFiles)
// BIT AttributesAreDefined
// }
// BYTE External;
// if(External != 0)
// UINT64 DataIndex
// []
// for(Definded Attributes)
// UINT32 Attributes
// []
// }
// }
}
+2 -2
View File
@@ -37,8 +37,8 @@ struct SevenZipFolder {
for _ in 0..<numCodecs {
let codec = try SevenZipCodec(pointerData)
codecs.append(codec)
outStreamsTotal += codec.numOutStreams ?? 0
inStreamsTotal += codec.numInStreams ?? 0
outStreamsTotal += codec.numOutStreams
inStreamsTotal += codec.numInStreams
}
self.codecs = codecs
numBindPairs = outStreamsTotal - 1
+22 -10
View File
@@ -9,8 +9,8 @@ struct SevenZipPackInfo {
let packPosition: Int
let numPackStreams: Int
var packSizes: [Int]?
var packSizes = [Int]()
var digests = [UInt32?]()
init(_ pointerData: DataWithPointer) throws {
packPosition = try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger
@@ -22,17 +22,29 @@ struct SevenZipPackInfo {
}
switch structureType {
case 0x09: // **PackInfo - PackSizes**
packSizes = []
for _ in 0..<numPackStreams {
packSizes?.append(try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger)
packSizes.append(try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger)
}
case 0x0A: // **PackInfo - PackStreamDigests**
// TODO:
// []
// BYTE NID::kCRC (0x0A)
// PackStreamDigests[NumPackStreams]
// []
break
let allDefined = pointerData.byte()
let definedBits: [UInt8]
let numStreams = numPackStreams
if allDefined == 0 {
let bitReader = BitReader(data: pointerData.data, bitOrder: .reversed) // TODO: Bit order???
bitReader.index = pointerData.index
definedBits = bitReader.bits(count: numStreams)
bitReader.skipUntilNextByte()
pointerData.index = bitReader.index
} else {
definedBits = Array(repeating: 1, count: numStreams)
}
for bit in definedBits {
if bit == 1 {
digests.append(pointerData.uint32())
} else {
digests.append(nil)
}
}
default:
throw SevenZipError.wrongPropertyID
}
+28 -21
View File
@@ -7,8 +7,9 @@ import Foundation
struct SevenZipSubstreamInfo {
var numUnpackStreamsInFolders: [Int]?
var unpackSizes: [Int]?
var numUnpackStreamsInFolders = [Int]()
var unpackSizes = [Int]()
var digests = [UInt32?]()
init(_ pointerData: DataWithPointer, _ numFolders: Int) throws {
while true {
@@ -18,29 +19,35 @@ struct SevenZipSubstreamInfo {
}
switch structureType {
case 0x0D: // **SubstreamsInfo - NumUnpackStreamsInFolders**
numUnpackStreamsInFolders = []
for _ in 0..<numFolders {
numUnpackStreamsInFolders?
numUnpackStreamsInFolders
.append(try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger)
}
case 0x09: // **SubstreamsInfo - Size**
// TODO: How many sizes?
//
// []
// BYTE NID::kSize (0x09)
// UINT64 UnPackSizes[]
// []
//
break
case 0x0A: // **SubstreamsInfo - CRC**
// TODO:
//
// []
// BYTE NID::kCRC (0x0A)
// Digests[Number of streams with unknown CRC]
// []
//
break
let numStreams = numUnpackStreamsInFolders.reduce(0, { $0 + $1 })
for _ in 0..<numStreams {
unpackSizes.append(try pointerData.multiByteDecode(SevenZipError.multiByteIntegerError).multiByteInteger)
}
case 0x0A: // **SubstreamsInfo - CRC** // TODO: Unknown numStreams???
let allDefined = pointerData.byte()
let definedBits: [UInt8]
let numStreams = numUnpackStreamsInFolders.reduce(0, { $0 + $1 })
if allDefined == 0 {
let bitReader = BitReader(data: pointerData.data, bitOrder: .reversed) // TODO: Bit order???
bitReader.index = pointerData.index
definedBits = bitReader.bits(count: numStreams)
bitReader.skipUntilNextByte()
pointerData.index = bitReader.index
} else {
definedBits = Array(repeating: 1, count: numStreams)
}
for bit in definedBits {
if bit == 1 {
digests.append(pointerData.uint32())
} else {
digests.append(nil)
}
}
default:
throw SevenZipError.wrongPropertyID
}