public ArchiveDatabase ReadDatabase(IPasswordProvider pass)
        {
            var db = new ArchiveDatabase();
            db.Clear();

            db.MajorVersion = _header[6];
            db.MinorVersion = _header[7];

            if (db.MajorVersion != 0)
                throw new InvalidOperationException();

            uint crcFromArchive = DataReader.Get32(_header, 8);
            long nextHeaderOffset = (long)DataReader.Get64(_header, 0xC);
            long nextHeaderSize = (long)DataReader.Get64(_header, 0x14);
            uint nextHeaderCrc = DataReader.Get32(_header, 0x1C);

            uint crc = CRC.kInitCRC;
            crc = CRC.Update(crc, nextHeaderOffset);
            crc = CRC.Update(crc, nextHeaderSize);
            crc = CRC.Update(crc, nextHeaderCrc);
            crc = CRC.Finish(crc);

            if (crc != crcFromArchive)
                throw new InvalidOperationException();

            db.StartPositionAfterHeader = _streamOrigin + 0x20;

            // empty header is ok
            if (nextHeaderSize == 0)
            {
                db.Fill();
                return db;
            }

            if (nextHeaderOffset < 0 || nextHeaderSize < 0 || nextHeaderSize > Int32.MaxValue)
                throw new InvalidOperationException();

            if (nextHeaderOffset > _streamEnding - db.StartPositionAfterHeader)
                throw new IndexOutOfRangeException();

            _stream.Seek(nextHeaderOffset, SeekOrigin.Current);

            byte[] header = new byte[nextHeaderSize];
            _stream.ReadExact(header, 0, header.Length);

            if (CRC.Finish(CRC.Update(CRC.kInitCRC, header, 0, header.Length)) != nextHeaderCrc)
                throw new InvalidOperationException();

            using (CStreamSwitch streamSwitch = new CStreamSwitch())
            {
                streamSwitch.Set(this, header);

                BlockType? type = ReadId();
                if (type != BlockType.Header)
                {
                    if (type != BlockType.EncodedHeader)
                        throw new InvalidOperationException();

                    var dataVector = ReadAndDecodePackedStreams(db.StartPositionAfterHeader, pass);

                    // compressed header without content is odd but ok
                    if (dataVector.Count == 0)
                    {
                        db.Fill();
                        return db;
                    }

                    if (dataVector.Count != 1)
                        throw new InvalidOperationException();

                    streamSwitch.Set(this, dataVector[0]);

                    if (ReadId() != BlockType.Header)
                        throw new InvalidOperationException();
                }

                ReadHeader(db, pass);
            }
            db.Fill();
            return db;
        }
 public ArchiveDatabase ReadDatabase(IPasswordProvider pass)
 {
     ArchiveDatabase db = new ArchiveDatabase();
     db.Clear();
     db.MajorVersion = this._header[6];
     db.MinorVersion = this._header[7];
     if (db.MajorVersion != 0)
     {
         throw new InvalidOperationException();
     }
     uint num = DataReader.Get32(this._header, 8);
     long num2 = (long) DataReader.Get64(this._header, 12);
     long num3 = (long) DataReader.Get64(this._header, 20);
     uint num4 = DataReader.Get32(this._header, 0x1c);
     uint maxValue = uint.MaxValue;
     if (CRC.Finish(CRC.Update(CRC.Update(CRC.Update(maxValue, num2), num3), num4)) != num)
     {
         throw new InvalidOperationException();
     }
     db.StartPositionAfterHeader = this._streamOrigin + 0x20L;
     if (num3 == 0L)
     {
         db.Fill();
         return db;
     }
     if (((num2 < 0L) || (num3 < 0L)) || (num3 > 0x7fffffffL))
     {
         throw new InvalidOperationException();
     }
     if (num2 > (this._streamEnding - db.StartPositionAfterHeader))
     {
         throw new IndexOutOfRangeException();
     }
     this._stream.Seek(num2, SeekOrigin.Current);
     byte[] buffer = new byte[num3];
     Utils.ReadExact(this._stream, buffer, 0, buffer.Length);
     if (CRC.Finish(CRC.Update(uint.MaxValue, buffer, 0, buffer.Length)) != num4)
     {
         throw new InvalidOperationException();
     }
     using (CStreamSwitch switch2 = new CStreamSwitch())
     {
         switch2.Set(this, buffer);
         BlockType? nullable = this.ReadId();
         if (((BlockType) nullable) != BlockType.Header)
         {
             if (((BlockType) nullable) != BlockType.EncodedHeader)
             {
                 throw new InvalidOperationException();
             }
             List<byte[]> list = this.ReadAndDecodePackedStreams(db.StartPositionAfterHeader, pass);
             if (list.Count == 0)
             {
                 db.Fill();
                 return db;
             }
             if (list.Count != 1)
             {
                 throw new InvalidOperationException();
             }
             switch2.Set(this, list[0]);
             if (((BlockType) this.ReadId()) != BlockType.Header)
             {
                 throw new InvalidOperationException();
             }
         }
         this.ReadHeader(db, pass);
     }
     db.Fill();
     return db;
 }