Beispiel #1
0
        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;
        }
Beispiel #2
0
        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);
            }
        }