示例#1
0
        /// <inheritdoc />
        public bool TryGetFileInfo(string filePath, out MPQFileInfo fileInfo)
        {
            fileInfo = null;

            if (!ArchiveHashTable.TryFindEntry(filePath, out var hashEntry))
            {
                return(false);
            }

            var blockEntry = ArchiveBlockTable.GetEntry((int)hashEntry.GetBlockEntryIndex());

            if (HasFileAttributes())
            {
                fileInfo = new MPQFileInfo(filePath, hashEntry, blockEntry);
            }
            else
            {
                fileInfo = new MPQFileInfo
                           (
                    filePath,
                    hashEntry,
                    blockEntry,
                    _fileAttributes.FileAttributes[(int)hashEntry.GetBlockEntryIndex()]
                           );
            }

            return(true);
        }
示例#2
0
        public bool TryExtractFile(string filePath, [NotNullWhen(true)] out byte[]?data)
        {
            ThrowIfDisposed();

            data = null;

            // Reset all positions to be safe
            _archiveReader.BaseStream.Position = 0;

            if (!ArchiveHashTable.TryFindEntry(filePath, out var fileHashEntry))
            {
                return(false);
            }

            var fileBlockEntry = ArchiveBlockTable.GetEntry((int)fileHashEntry.GetBlockEntryIndex());

            // Drop out if the file has been deleted
            if (fileBlockEntry.IsDeleted())
            {
                return(false);
            }

            // Seek to the beginning of the file's sectors
            long adjustedBlockOffset;

            if (Header.GetFormat() == MPQFormat.ExtendedV1 && RequiresExtendedFormat())
            {
                var upperOffsetBits = ExtendedBlockTable ![(int)fileHashEntry.GetBlockEntryIndex()];
示例#3
0
        public byte[] ExtractFile(string filePath)
        {
            ThrowIfDisposed();

            if (!TryExtractFile(filePath, out var data))
            {
                if (!ArchiveHashTable.TryFindEntry(filePath, out var fileHashEntry))
                {
                    throw new FileNotFoundException("No file found at the given path.", filePath);
                }

                var fileBlockEntry = ArchiveBlockTable.GetEntry((int)fileHashEntry.GetBlockEntryIndex());
                if (fileBlockEntry.IsDeleted())
                {
                    throw new FileDeletedException("The given file is deleted.", filePath);
                }

                throw new IOException("An unknown failure prevented the file from being extracted.");
            }

            return(data);
        }
示例#4
0
        public bool TryExtractFile(string filePath, out byte[] data)
        {
            ThrowIfDisposed();

            data = null;

            // Reset all positions to be safe
            _archiveReader.BaseStream.Position = 0;

            if (!ArchiveHashTable.TryFindEntry(filePath, out var fileHashEntry))
            {
                return(false);
            }

            var fileBlockEntry = ArchiveBlockTable.GetEntry((int)fileHashEntry.GetBlockEntryIndex());

            // Drop out if the file has been deleted
            if (fileBlockEntry.IsDeleted())
            {
                return(false);
            }

            // Seek to the beginning of the file's sectors
            long adjustedBlockOffset;

            if (Header.GetFormat() == MPQFormat.ExtendedV1 && RequiresExtendedFormat())
            {
                var upperOffsetBits = ExtendedBlockTable[(int)fileHashEntry.GetBlockEntryIndex()];
                adjustedBlockOffset = (long)fileBlockEntry.GetExtendedBlockOffset(upperOffsetBits);
            }
            else
            {
                adjustedBlockOffset = fileBlockEntry.GetBlockOffset();
            }

            _archiveReader.BaseStream.Position = adjustedBlockOffset;

            // Calculate the decryption key if necessary
            var fileKey = MPQCrypt.CreateFileEncryptionKey
                          (
                filePath,
                fileBlockEntry.ShouldEncryptionKeyBeAdjusted(),
                adjustedBlockOffset,
                fileBlockEntry.GetFileSize()
                          );

            // Examine the file storage types and extract as necessary
            if (fileBlockEntry.IsSingleUnit())
            {
                data = ExtractSingleUnitFile(fileBlockEntry, fileKey);
                return(true);
            }

            if (fileBlockEntry.IsCompressed())
            {
                data = ExtractCompressedSectoredFile(fileBlockEntry, fileKey, adjustedBlockOffset);
                return(true);
            }

            data = ExtractUncompressedSectoredFile(fileBlockEntry, fileKey);
            return(true);
        }