示例#1
0
        private bool TryGetHashEntry(string filename, out MpqHash hash)
        {
            uint index = StormBuffer.HashString(filename, 0);

            index &= _mpqHeader.HashTableSize - 1;
            uint name1 = StormBuffer.HashString(filename, 0x100);
            uint name2 = StormBuffer.HashString(filename, 0x200);

            for (uint i = index; i < _hashTable.Size; ++i)
            {
                hash = _hashTable[i];
                if (hash.Name1 == name1 && hash.Name2 == name2)
                {
                    return(true);
                }
            }
            for (uint i = 0; i < index; i++)
            {
                hash = _hashTable[i];
                if (hash.Name1 == name1 && hash.Name2 == name2)
                {
                    return(true);
                }
            }

            hash = new MpqHash();
            return(false);
        }
示例#2
0
        private byte[] LoadBlock(int blockIndex, int expectedLength)
        {
            uint offset;
            int  toread;
            uint encryptionseed;

            if (_entry.IsCompressed)
            {
                offset = _blockPositions[blockIndex];
                toread = (int)(_blockPositions[blockIndex + 1] - offset);
            }
            else
            {
                offset = (uint)(blockIndex * _blockSize);
                toread = expectedLength;
            }
            offset += _entry.FilePos;

            byte[] data = new byte[toread];
            lock (_stream)
            {
                _stream.Seek(offset, SeekOrigin.Begin);
                int read = _stream.Read(data, 0, toread);
                if (read != toread)
                {
                    throw new MpqParserException("Insufficient data or invalid data length");
                }
            }

            if (_entry.IsEncrypted && _entry.FileSize > 3)
            {
                if (_entry.EncryptionSeed == 0)
                {
                    throw new MpqParserException("Unable to determine encryption key");
                }

                encryptionseed = (uint)(blockIndex + _entry.EncryptionSeed);
                StormBuffer.DecryptBlock(data, encryptionseed);
            }

            if (_entry.IsCompressed && (toread != expectedLength))
            {
                if ((_entry.Flags & MpqFileFlags.CompressedMulti) != 0)
                {
                    data = DecompressMulti(data, expectedLength);
                }
                else
                {
                    data = PKDecompress(new MemoryStream(data), expectedLength);
                }
            }

            return(data);
        }
示例#3
0
        // Compressed files start with an array of offsets to make seeking possible
        private void LoadBlockPositions()
        {
            int blockposcount = (int)((_entry.FileSize + _blockSize - 1) / _blockSize) + 1;

            // Files with metadata have an extra block containing block checksums
            if ((_entry.Flags & MpqFileFlags.FileHasMetadata) != 0)
            {
                blockposcount++;
            }

            _blockPositions = new uint[blockposcount];

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

            uint blockpossize = (uint)blockposcount * 4;

            /*
             * if(_blockPositions[0] != blockpossize)
             *  _entry.Flags |= MpqFileFlags.Encrypted;
             */

            if (_entry.IsEncrypted)
            {
                if (_entry.EncryptionSeed == 0)  // This should only happen when the file name is not known
                {
                    _entry.EncryptionSeed = StormBuffer.DetectFileSeed(_blockPositions[0], _blockPositions[1], blockpossize) + 1;
                    if (_entry.EncryptionSeed == 1)
                    {
                        throw new MpqParserException("Unable to determine encyption seed");
                    }
                }

                StormBuffer.DecryptBlock(_blockPositions, _entry.EncryptionSeed - 1);

                if (_blockPositions[0] != blockpossize)
                {
                    throw new MpqParserException("Decryption failed");
                }
                if (_blockPositions[1] > _blockSize + blockpossize)
                {
                    throw new MpqParserException("Decryption failed");
                }
            }
        }
示例#4
0
 public static uint GetIndex(string path, uint mask)
 {
     return(StormBuffer.HashString(path, 0) & mask);
 }
示例#5
0
 public MpqHash(string fileName, uint mask, uint locale, uint blockIndex)
     : this(StormBuffer.HashString(fileName, 0x100), StormBuffer.HashString(fileName, 0x200), locale, blockIndex, mask)
 {
 }
示例#6
0
 public static void Decrypt(byte[] data, string key)
 {
     StormBuffer.DecryptBlock(data, StormBuffer.HashString(key, 0x300));
 }