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); }
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); }
// 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"); } } }
public static uint GetIndex(string path, uint mask) { return(StormBuffer.HashString(path, 0) & mask); }
public MpqHash(string fileName, uint mask, uint locale, uint blockIndex) : this(StormBuffer.HashString(fileName, 0x100), StormBuffer.HashString(fileName, 0x200), locale, blockIndex, mask) { }
public static void Decrypt(byte[] data, string key) { StormBuffer.DecryptBlock(data, StormBuffer.HashString(key, 0x300)); }