예제 #1
0
        public MpqManager(string mpqFile)
        {
            FileInfo info         = new FileInfo(mpqFile);
            string   destFileName = Path.Combine(Path.GetTempPath(), info.Name);

            File.Copy(mpqFile, destFileName, true);
            this._mpqArchive = new Foole.Mpq.MpqArchive(destFileName);
            this._mpqArchive.AddListfileFilenames();
        }
예제 #2
0
 internal MpqStream(MpqArchive archive, MpqEntry entry)
 {
     this._entry     = entry;
     this._stream    = archive.BaseStream;
     this._blockSize = archive.BlockSize;
     if (this._entry.IsCompressed && !this._entry.IsSingleUnit)
     {
         this.LoadBlockPositions();
     }
 }
예제 #3
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);
                MpqArchive.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);
        }
예제 #4
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 = MpqArchive.DetectFileSeed(_blockPositions[0], _blockPositions[1], blockpossize) + 1;
                    if (_entry.EncryptionSeed == 1)
                    {
                        throw new MpqParserException("Unable to determine encyption seed");
                    }
                }

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

                if (_blockPositions[0] != blockpossize)
                {
                    throw new MpqParserException("Decryption failed");
                }
                if (_blockPositions[1] > _blockSize + blockpossize)
                {
                    throw new MpqParserException("Decryption failed");
                }
            }
        }
예제 #5
0
 public MpqManager(string mpqFile)
 {
     //FileInfo info = new FileInfo(mpqFile);
     //string destFileName = Path.Combine(Path.GetTempPath(), info.Name);
     //File.Copy(mpqFile, destFileName, true);
     //this._mpqArchive = new Foole.Mpq.MpqArchive(destFileName);
     if (File.Exists(mpqFile))
     {
         this._mpqArchive = new Foole.Mpq.MpqArchive(mpqFile);
         this._mpqArchive.AddListfileFilenames();
         return;
     }
 }
예제 #6
0
        private uint CalculateEncryptionSeed()
        {
            if (this.Filename == null)
            {
                return(0);
            }
            uint num = MpqArchive.HashString(Path.GetFileName(this.Filename), 0x300);

            if ((this.Flags & MpqFileFlags.BlockOffsetAdjustedKey) == MpqFileFlags.BlockOffsetAdjustedKey)
            {
                num = (num + this._fileOffset) ^ this.FileSize;
            }
            return(num);
        }
예제 #7
0
        private uint CalculateEncryptionSeed()
        {
            if (Filename == null)
            {
                return(0);
            }

            uint seed = MpqArchive.HashString(Path.GetFileName(Filename), 0x300);

            if ((Flags & MpqFileFlags.BlockOffsetAdjustedKey) == MpqFileFlags.BlockOffsetAdjustedKey)
            {
                seed = (seed + _fileOffset) ^ FileSize;
            }
            return(seed);
        }
예제 #8
0
        private byte[] LoadBlock(int blockIndex, int expectedLength)
        {
            uint num;
            int  num2;

            if (this._entry.IsCompressed)
            {
                num  = this._blockPositions[blockIndex];
                num2 = (int)(this._blockPositions[blockIndex + 1] - num);
            }
            else
            {
                num  = (uint)(blockIndex * this._blockSize);
                num2 = expectedLength;
            }
            num += this._entry.FilePos;
            byte[] buffer = new byte[num2];
            lock (this._stream)
            {
                this._stream.Seek((long)num, SeekOrigin.Begin);
                if (this._stream.Read(buffer, 0, num2) != num2)
                {
                    throw new MpqParserException("Insufficient data or invalid data length");
                }
            }
            if (this._entry.IsEncrypted && (this._entry.FileSize > 3))
            {
                if (this._entry.EncryptionSeed == 0)
                {
                    throw new MpqParserException("Unable to determine encryption key");
                }
                uint num3 = ((uint)blockIndex) + this._entry.EncryptionSeed;
                MpqArchive.DecryptBlock(buffer, num3);
            }
            if (!this._entry.IsCompressed || (num2 == expectedLength))
            {
                return(buffer);
            }
            if ((this._entry.Flags & MpqFileFlags.CompressedMulti) != ((MpqFileFlags)0))
            {
                return(DecompressMulti(buffer, expectedLength));
            }
            return(PKDecompress(new MemoryStream(buffer), expectedLength));
        }
예제 #9
0
        private void LoadBlockPositions()
        {
            int num = ((int)(((this._entry.FileSize + this._blockSize) - 1) / ((long)this._blockSize))) + 1;

            if ((this._entry.Flags & MpqFileFlags.FileHasMetadata) != ((MpqFileFlags)0))
            {
                num++;
            }
            this._blockPositions = new uint[num];
            lock (this._stream)
            {
                this._stream.Seek((long)this._entry.FilePos, SeekOrigin.Begin);
                BinaryReader reader = new BinaryReader(this._stream);
                for (int i = 0; i < num; i++)
                {
                    this._blockPositions[i] = reader.ReadUInt32();
                }
            }
            uint decrypted = (uint)(num * 4);

            if (this._entry.IsEncrypted)
            {
                if (this._entry.EncryptionSeed == 0)
                {
                    this._entry.EncryptionSeed = MpqArchive.DetectFileSeed(this._blockPositions[0], this._blockPositions[1], decrypted) + 1;
                    if (this._entry.EncryptionSeed == 1)
                    {
                        throw new MpqParserException("Unable to determine encyption seed");
                    }
                }
                MpqArchive.DecryptBlock(this._blockPositions, this._entry.EncryptionSeed - 1);
                if (this._blockPositions[0] != decrypted)
                {
                    throw new MpqParserException("Decryption failed");
                }
                if (this._blockPositions[1] > (this._blockSize + decrypted))
                {
                    throw new MpqParserException("Decryption failed");
                }
            }
        }
예제 #10
0
 public void Close()
 {
     this._mpqArchive.Dispose();
     this._mpqArchive = null;
 }