Example #1
0
        // Compressed files start with an array of offsets to make seeking possible
        private void LoadBlockPositions()
        {
            int blockposcount = (int)((mBlock.FileSize + mBlockSize - 1) / mBlockSize) + 1;

            mBlockPositions = new uint[blockposcount];

            lock (mStream)
            {
                mStream.Seek(mBlock.FilePos, SeekOrigin.Begin);
                BinaryReader br = new BinaryReader(mStream);
                for (int i = 0; i < blockposcount; i++)
                {
                    mBlockPositions[i] = br.ReadUInt32();
                }
            }

            uint blockpossize = (uint)blockposcount * 4;

            // StormLib takes this to mean the data is encrypted
            if (mBlockPositions[0] != blockpossize)
            {
                if (mSeed1 == 0)
                {
                    mSeed1 = MpqArchive.DetectFileSeed(mBlockPositions, blockpossize);
                    if (mSeed1 == 0)
                    {
                        throw new Exception("Unable to determine encyption seed");
                    }
                }
                MpqArchive.DecryptBlock(mBlockPositions, mSeed1);
                mSeed1++;                 // Add 1 because the first block is the offset list
            }
        }
Example #2
0
        // Compressed files start with an array of offsets to make seeking possible
        private void LoadBlockPositions()
        {
            int blockposcount = (int)((mBlock.FileSize + mBlockSize - 1) / mBlockSize) + 1;

            mBlockPositions = new uint[blockposcount];

            lock (mStream)
            {
                mStream.Seek(mBlock.FilePos, SeekOrigin.Begin);
                BinaryReader br = new BinaryReader(mStream);
                for (int i = 0; i < blockposcount; i++)
                {
                    mBlockPositions[i] = br.ReadUInt32();
                }
            }

            uint blockpossize = (uint)blockposcount * 4;

            // OW:

            // If the archive if protected some way, perform additional check
            // Sometimes, the file appears not to be encrypted, but it is.
            // Edit: In WoW 1.10+, there's a new flag. With this flag present,
            // there's one additional entry in the block table. If this flag
            // is present, we skip this test to keep the file readable.

            if ((mBlock.Flags & MpqFileFlags.FileHasMetadata) == 0)
            {
                if (mBlockPositions[0] != blockpossize)
                {
                    mBlock.Flags |= MpqFileFlags.Encrypted;
                }
            }

            if (mBlock.IsEncrypted)
            {
                if (mSeed1 == 0)
                {
                    mSeed1 = MpqArchive.DetectFileSeed(mBlockPositions, blockpossize);
                    if (mSeed1 == 0)
                    {
                        throw new MpqParserException("Unable to determine encyption seed");
                    }
                }

                MpqArchive.DecryptBlock(mBlockPositions, mSeed1);
                mSeed1++; // Add 1 because the first block is the offset list
            }

            /*
             * // StormLib takes this to mean the data is encrypted
             * if (mBlockPositions[0] != blockpossize)
             * {
             *  if (mSeed1 == 0)
             *  {
             *      mSeed1 = MpqArchive.DetectFileSeed(mBlockPositions, blockpossize);
             *      if (mSeed1 == 0)
             *          throw new Exception("Unable to determine encyption seed");
             *  }
             *  MpqArchive.DecryptBlock(mBlockPositions, mSeed1);
             *  mSeed1++; // Add 1 because the first block is the offset list
             * }
             */
        }
Example #3
0
        private byte[] LoadBlock(int BlockIndex, int ExpectedLength)
        {
            uint offset;
            int  toread;

            if (mBlock.IsCompressed)
            {
                offset = mBlockPositions[BlockIndex];
                toread = (int)(mBlockPositions[BlockIndex + 1] - offset);
            }
            else
            {
                offset = (uint)(BlockIndex * mBlockSize);
                toread = ExpectedLength;
            }
            offset += mBlock.FilePos;

            byte[] data = new byte[toread];
            lock (mStream)
            {
                mStream.Seek(offset, SeekOrigin.Begin);
                mStream.Read(data, 0, toread);
            }

            if (mBlock.IsEncrypted && mBlock.FileSize > 3)
            {
                if (mSeed1 == 0)
                {
                    uint value0 = BitConverter.ToUInt32(data, 0);
                    uint value1 = BitConverter.ToUInt32(data, 4);
                    mSeed1 = MpqArchive.DetectFileSeed(value0, value1, 0x2fbfbbef, 0x3d3d3d2f);                     // .J unicode magic
                    if (mSeed1 == 0)
                    {
                        mSeed1 = MpqArchive.DetectFileSeed(value0, value1, 0x3d3d2f2f, 0x3d3d3d3d); // .J ascii
                        if (mSeed1 == 0)
                        {
                            mSeed1 = MpqArchive.DetectFileSeed(value0, value1, 0x46464952, mBlock.FileSize - 8); // RIFF
                            if (mSeed1 == 0)
                            {
                                throw new MpqParserException("Unable to determine encryption key");
                            }
                        }
                    }
                }
                MpqArchive.DecryptBlock(data, (uint)(mSeed1 + BlockIndex));
            }

            if (mBlock.IsCompressed && data.Length != ExpectedLength)
            {
                if ((mBlock.Flags & MpqFileFlags.CompressedMulti) != 0)
                {
                    data = DecompressMulti(data, ExpectedLength);
                }
                else
                {
                    data = PKDecompress(new MemoryStream(data), ExpectedLength);
                }
            }

            return(data);
        }