private FolderInfo GetNextFolderItem(DataReader mReader) { FolderInfo folder = new FolderInfo(); int numInStreams = 0; int numOutStreams = 0; int numCoders = mReader.ReadPackedUInt31(); folder.Coders = new CoderInfo[numCoders]; for(int i = 0; i < numCoders; i++) { CoderInfo coder = new CoderInfo(); folder.Coders[i] = coder; byte mainByte = mReader.ReadByte(); int idSize = mainByte & 15; if(idSize > 8) // standard 7z also is limited to 8 byte coder ids throw new InvalidDataException(); ulong id = 0; for(int j = idSize - 1; j >= 0; j--) id += (ulong)mReader.ReadByte() << (j * 8); coder.MethodId = id; if((mainByte & 0x10) != 0) { coder.NumInStreams = mReader.ReadPackedUInt31(); coder.NumOutStreams = mReader.ReadPackedUInt31(); } else { coder.NumInStreams = 1; coder.NumOutStreams = 1; } if((mainByte & 0x20) != 0) { int propsSize = mReader.ReadPackedUInt31(); coder.Props = mReader.ReadBytes(propsSize); } // TODO: Warn if 0x40 is set, since it is not defined in the supported versions of the format. if((mainByte & 0x80) != 0) throw new InvalidDataException(); numInStreams += coder.NumInStreams; numOutStreams += coder.NumOutStreams; } int numBindPairs = mReader.ReadPackedUInt31(); folder.BindPairs = new BindPair[numBindPairs]; for(int i = 0; i < numBindPairs; i++) { int inIndex = mReader.ReadPackedUInt31(); int outIndex = mReader.ReadPackedUInt31(); folder.BindPairs[i] = new BindPair(inIndex, outIndex); } if(numInStreams < numBindPairs) throw new InvalidDataException(); int numPackStreams = numInStreams - numBindPairs; folder.PackStreams = new int[numPackStreams]; if(numPackStreams == 1) { bool found = false; for(int i = 0; i < numInStreams; i++) { if(folder.FindBindPairForInStream(i) < 0) { folder.PackStreams[0] = i; found = true; break; } } if(!found) throw new InvalidDataException(); } else { for(int i = 0; i < numPackStreams; i++) folder.PackStreams[i] = mReader.ReadPackedUInt31(); } return folder; }
private void ReadHeader(DataReader mReader) { byte[] signature = mReader.ReadBytes(kSignature.Length); if(signature.Length != kSignature.Length) throw new InvalidDataException(); for(int i = 0; i < signature.Length; i++) if(signature[i] != kSignature[i]) throw new InvalidDataException(); mMajorVersion = mReader.ReadByte(); mMinorVersion = mReader.ReadByte(); if(mMajorVersion != 0) throw new NotSupportedException(); // TODO: Weak check of supported minor versions uint startHeaderCRC = mReader.ReadUInt32(); long nextHeaderOffset = mReader.ReadInt64(); long nextHeaderLength = mReader.ReadInt64(); uint nextHeaderCRC = mReader.ReadUInt32(); Utils.Assert(mReader.Position == kPrimaryHeaderSize); if(mCheckCRC) { uint crc = CRC.kInitCRC; crc = CRC.Update(crc, nextHeaderOffset); crc = CRC.Update(crc, nextHeaderLength); crc = CRC.Update(crc, nextHeaderCRC); crc = CRC.Finish(crc); if(crc != startHeaderCRC) throw new InvalidDataException(); } if(nextHeaderLength < 0 || nextHeaderOffset < 0 || nextHeaderOffset > mReader.Remaining - nextHeaderLength) throw new InvalidDataException(); if(nextHeaderLength > 0) // zero is ok, empty archive { mReader.Skip(nextHeaderOffset); if(mCheckCRC) { if(mReader.CalculateCRC(nextHeaderLength) != nextHeaderCRC) throw new InvalidDataException(); mReader.Seek(kPrimaryHeaderSize + nextHeaderOffset); } using(mReader.Constrain(nextHeaderLength)) ReadHeader2(mReader); } }