public BitVector ReadBitVector2(int length) { byte allSet = ReadByte(); if(allSet == 0) return ReadBitVector(length); var bits = new BitVector(length); for(int i = 0; i < length; i++) bits.SetBit(i); return bits; }
private void ReadSubStreamsInfo(DataReader mReader, FolderInfo[] folders, out int[] numUnpackStreamsInFolders, out List<ulong> unpackSizes, out BitVector crcDefined, out uint[] crcs) { numUnpackStreamsInFolders = new int[folders.Length]; for(int i = 0; i < numUnpackStreamsInFolders.Length; i++) numUnpackStreamsInFolders[i] = 1; BlockType? type; for(; ; ) { type = ReadBlockType(mReader); if(type == BlockType.NumUnpackStream) { for(int i = 0; i < numUnpackStreamsInFolders.Length; i++) numUnpackStreamsInFolders[i] = mReader.ReadPackedUInt31(); continue; } if(type == BlockType.End || type == BlockType.CRC || type == BlockType.Size) break; SkipAttribute(mReader); } for(int i = 0; i < numUnpackStreamsInFolders.Length; i++) { int numSubstreams = numUnpackStreamsInFolders[i]; if(numSubstreams == 0) continue; ulong sum = 0; if(type == BlockType.Size) { for(int j = 1; j < numSubstreams; j++) { ulong size = mReader.ReadPackedUInt64(); unpackSizes.Add(size); sum += size; } } unpackSizes.Add(folders[i].GetUnpackSize() - sum); } if(type == BlockType.Size) type = ReadBlockType(mReader); int numCRCs = 0; int numCRCsTotal = 0; for(int i = 0; i < folders.Length; i++) { int numSubstreams = numUnpackStreamsInFolders[i]; if(numSubstreams != 1 || folders[i].UnpackCRC == null) numCRCs += numSubstreams; numCRCsTotal += numSubstreams; } for(; ; ) { if(type == BlockType.CRC) { BitVector defined2; uint[] crcs2; ReadHashDigests(mReader, numCRCs, out defined2, out crcs2); } else if(type == BlockType.End) break; else SkipAttribute(mReader); type = ReadBlockType(mReader); } if(crcDefined == null) { throw new NotImplementedException(); } }
public BitVector ReadBitVector(int length) { byte value = 0; byte mask = 0; BitVector bits = new BitVector(length); for(int i = 0; i < length; i++) { if(mask == 0) { value = ReadByte(); mask = 0x80; } if((value & mask) != 0) bits.SetBit(i); mask >>= 1; } // TODO: Make this a warning, not an exception. //while(mask != 0) //{ // if((value & mask) != 0) // throw new InvalidDataException(); // // mask >>= 1; //} return bits; }
private void ReadStreamsInfo(DataReader mReader, out ulong[] packSizes, out BitVector packCRCsDefined, out uint[] packCRCs, out FolderInfo[] folders, out int[] numUnpackStreamsInFolders, out List<ulong> unpackSizes, out BitVector crcDefined, out uint[] crcs) { packSizes = null; packCRCsDefined = null; packCRCs = null; folders = null; numUnpackStreamsInFolders = null; unpackSizes = null; crcDefined = null; crcs = null; for(; ; ) { var type = ReadBlockType(mReader); switch(type) { case BlockType.End: return; case BlockType.PackInfo: ReadPackInfo(mReader, out packSizes, out packCRCsDefined, out packCRCs); break; case BlockType.UnpackInfo: ReadUnpackInfo(mReader, out folders); break; case BlockType.SubStreamsInfo: ReadSubStreamsInfo(mReader, folders, out numUnpackStreamsInFolders, out unpackSizes, out crcDefined, out crcs); break; default: throw new InvalidDataException(); } } }
private void ReadPackInfo(DataReader mReader, out ulong[] packSizes, out BitVector packCRCsDefined, out uint[] packCRCs) { packCRCsDefined = null; packCRCs = null; ulong dataOffset = mReader.ReadPackedUInt64(); int numPackStreams = mReader.ReadPackedUInt31(); WaitAttribute(mReader, BlockType.Size); { packSizes = new ulong[numPackStreams]; for(int i = 0; i < numPackStreams; i++) packSizes[i] = mReader.ReadPackedUInt64(); } for(; ; ) { var type = ReadBlockType(mReader); if(type == BlockType.End) break; if(type == BlockType.CRC) ReadHashDigests(mReader, numPackStreams, out packCRCsDefined, out packCRCs); else SkipAttribute(mReader); } if(packCRCsDefined == null) { packCRCsDefined = new BitVector(numPackStreams); packCRCs = new uint[numPackStreams]; } }
private void ReadHashDigests(DataReader mReader, int count, out BitVector defined, out uint[] digests) { defined = mReader.ReadBitVector2(count); digests = new uint[count]; for(int i = 0; i < digests.Length; i++) if(defined[i]) digests[i] = mReader.ReadUInt32(); }
private void ReadHeader(CArchiveDatabaseEx db, IPasswordProvider getTextPassword) { Log.WriteLine("-- ReadHeader --"); Log.PushIndent(); try { BlockType? type = ReadId(); if (type == BlockType.ArchiveProperties) { ReadArchiveProperties(); type = ReadId(); } List<byte[]> dataVector = null; if (type == BlockType.AdditionalStreamsInfo) { dataVector = ReadAndDecodePackedStreams(db.StartPositionAfterHeader, getTextPassword); type = ReadId(); } List<long> unpackSizes; List<uint?> digests; if (type == BlockType.MainStreamsInfo) { ReadStreamsInfo(dataVector, out db.DataStartPosition, out db.PackSizes, out db.PackCRCs, out db.Folders, out db.NumUnpackStreamsVector, out unpackSizes, out digests); db.DataStartPosition += db.StartPositionAfterHeader; type = ReadId(); } else { unpackSizes = new List<long>(db.Folders.Count); digests = new List<uint?>(db.Folders.Count); db.NumUnpackStreamsVector = new List<int>(db.Folders.Count); for (int i = 0; i < db.Folders.Count; i++) { var folder = db.Folders[i]; unpackSizes.Add(folder.GetUnpackSize()); digests.Add(folder.UnpackCRC); db.NumUnpackStreamsVector.Add(1); } } db.Files.Clear(); if (type == BlockType.End) return; if (type != BlockType.FilesInfo) throw new InvalidDataException(); int numFiles = ReadNum(); Log.WriteLine("NumFiles: " + numFiles); db.Files = new List<CFileItem>(numFiles); for (int i = 0; i < numFiles; i++) db.Files.Add(new CFileItem()); BitVector emptyStreamVector = new BitVector(numFiles); BitVector emptyFileVector = null; BitVector antiFileVector = null; int numEmptyStreams = 0; for (;;) { type = ReadId(); if (type == BlockType.End) break; long size = checked((long)ReadNumber()); // TODO: throw invalid data on negative int oldPos = _currentReader.Offset; switch (type) { case BlockType.Name: using (var streamSwitch = new CStreamSwitch()) { streamSwitch.Set(this, dataVector); Log.Write("FileNames:"); for (int i = 0; i < db.Files.Count; i++) { db.Files[i].Name = _currentReader.ReadString(); Log.Write(" " + db.Files[i].Name); } Log.WriteLine(); } break; case BlockType.WinAttributes: Log.Write("WinAttributes:"); ReadAttributeVector(dataVector, numFiles, delegate (int i, uint? attr) { db.Files[i].Attrib = attr; Log.Write(" " + (attr.HasValue ? attr.Value.ToString("x8") : "n/a")); }); Log.WriteLine(); break; case BlockType.EmptyStream: emptyStreamVector = ReadBitVector(numFiles); Log.Write("EmptyStream: "); for (int i = 0; i < emptyStreamVector.Length; i++) { if (emptyStreamVector[i]) { Log.Write("x"); numEmptyStreams++; } else { Log.Write("."); } } Log.WriteLine(); emptyFileVector = new BitVector(numEmptyStreams); antiFileVector = new BitVector(numEmptyStreams); break; case BlockType.EmptyFile: emptyFileVector = ReadBitVector(numEmptyStreams); Log.Write("EmptyFile: "); for (int i = 0; i < numEmptyStreams; i++) Log.Write(emptyFileVector[i] ? "x" : "."); Log.WriteLine(); break; case BlockType.Anti: antiFileVector = ReadBitVector(numEmptyStreams); Log.Write("Anti: "); for (int i = 0; i < numEmptyStreams; i++) Log.Write(antiFileVector[i] ? "x" : "."); Log.WriteLine(); break; case BlockType.StartPos: Log.Write("StartPos:"); ReadNumberVector(dataVector, numFiles, delegate (int i, long? startPos) { db.Files[i].StartPos = startPos; Log.Write(" " + (startPos.HasValue ? startPos.Value.ToString() : "n/a")); }); Log.WriteLine(); break; case BlockType.CTime: Log.Write("CTime:"); ReadDateTimeVector(dataVector, numFiles, delegate (int i, DateTime? time) { db.Files[i].CTime = time; Log.Write(" " + (time.HasValue ? time.Value.ToString() : "n/a")); }); Log.WriteLine(); break; case BlockType.ATime: Log.Write("ATime:"); ReadDateTimeVector(dataVector, numFiles, delegate (int i, DateTime? time) { db.Files[i].ATime = time; Log.Write(" " + (time.HasValue ? time.Value.ToString() : "n/a")); }); Log.WriteLine(); break; case BlockType.MTime: Log.Write("MTime:"); ReadDateTimeVector(dataVector, numFiles, delegate (int i, DateTime? time) { db.Files[i].MTime = time; Log.Write(" " + (time.HasValue ? time.Value.ToString() : "n/a")); }); Log.WriteLine(); break; case BlockType.Dummy: Log.Write("Dummy: " + size); for (long j = 0; j < size; j++) if (ReadByte() != 0) throw new InvalidDataException(); break; default: SkipData(size); break; } // since 0.3 record sizes must be correct bool checkRecordsSize = (db.MajorVersion > 0 || db.MinorVersion > 2); if (checkRecordsSize && _currentReader.Offset - oldPos != size) throw new InvalidDataException(); } int emptyFileIndex = 0; int sizeIndex = 0; for (int i = 0; i < numFiles; i++) { CFileItem file = db.Files[i]; file.HasStream = !emptyStreamVector[i]; if (file.HasStream) { file.IsDir = false; file.IsAnti = false; file.Size = unpackSizes[sizeIndex]; file.Crc = digests[sizeIndex]; sizeIndex++; } else { file.IsDir = !emptyFileVector[emptyFileIndex]; file.IsAnti = antiFileVector[emptyFileIndex]; emptyFileIndex++; file.Size = 0; file.Crc = null; } } } finally { Log.PopIndent(); } }
private BitVector ReadBitVector(int length) { var bits = new BitVector(length); byte data = 0; byte mask = 0; for (int i = 0; i < length; i++) { if (mask == 0) { data = ReadByte(); mask = 0x80; } if ((data & mask) != 0) bits.SetBit(i); mask >>= 1; } return bits; }