예제 #1
0
파일: MainForm.cs 프로젝트: Drake53/War3App
        private static void OpenArchive()
        {
            var fileInfo = new FileInfo(_archiveInput.Text);

            if (fileInfo.Exists)
            {
                _archiveInput.Enabled             = false;
                _archiveInputBrowseButton.Enabled = false;
                _openCloseArchiveButton.Text      = "Close archive";
                _saveAsButton.Enabled             = true;

                _archive = MpqArchive.Open(fileInfo.FullName, true);
                _archive.DiscoverFileNames();

                var map = Map.Open(_archive);
                // _originScriptLanguage = map.Info.ScriptLanguage;

                var targetScriptLanguages = new HashSet <object>(new object[]
                {
                    // ScriptLanguage.Jass,
                    ScriptLanguage.Lua,
                });

                _targetScriptLanguagesComboBox.Items.AddRange(targetScriptLanguages.OrderByDescending(patch => (int)patch).ToArray());
                _targetScriptLanguagesComboBox.Enabled = true;
                if (_targetScriptLanguagesComboBox.Items.Count == 1)
                {
                    _targetScriptLanguagesComboBox.SelectedIndex = 0;
                }
            }
        }
예제 #2
0
        /// <exception cref="ArgumentException">Thrown when the <see cref="MpqArchive"/> does not contain an <see cref="Attributes"/> file.</exception>
        public static bool VerifyAttributes(this MpqArchive archive)
        {
            if (!archive.TryOpenFile(Attributes.FileName, out var attributesStream))
            {
                throw new ArgumentException($"The archive must contain an {Attributes.FileName} file.", nameof(archive));
            }

            using var reader = new BinaryReader(attributesStream);

            var attributes  = reader.ReadAttributes();
            var hasCrc32    = attributes.Flags.HasFlag(AttributesFlags.Crc32);
            var hasDateTime = attributes.Flags.HasFlag(AttributesFlags.DateTime);

            var count = 0;

            foreach (var mpqEntry in archive)
            {
                if (hasCrc32)
                {
                    using var mpqEntryStream = archive.OpenFile(mpqEntry);

                    var crc32 = mpqEntry.FileName == Attributes.FileName ? 0 : new Ionic.Crc.CRC32().GetCrc32(mpqEntryStream);
                    if (crc32 != attributes.Crc32s[count])
                    {
                        return(false);
                    }
                }

                count++;
            }

            return((!hasCrc32 || attributes.Crc32s.Count == count) &&
                   (!hasDateTime || attributes.DateTimes.Count == count));
        }
예제 #3
0
        public void TestWithPreArchiveData()
        {
            var memoryStream = new MemoryStream();
            var randomData   = new byte[999];

            randomData[100] = 99;
            memoryStream.Write(randomData, 0, randomData.Length);

            var randomFiles = new List <MpqFile>();

            for (var i = 0; i < 35; i++)
            {
                var fileStream = new MemoryStream();
                fileStream.Write(randomData, 0, randomData.Length);
                fileStream.Position = 0;
                randomFiles.Add(MpqFile.New(fileStream, $"file{i}"));
            }

            using var a = MpqArchive.Create(memoryStream, randomFiles);

            memoryStream.Position = 0;
            var archive = MpqArchive.Open(memoryStream);

            foreach (var file in archive.GetMpqFiles())
            {
                file.MpqStream.Seek(100, SeekOrigin.Begin);
                Assert.AreEqual(99, file.MpqStream.ReadByte());
            }

            archive.Dispose();
        }
예제 #4
0
        public void TestRecreatePKCompressed()
        {
            var inputArchivePath = TestDataProvider.GetFile(@"Maps\PKCompressed.w3x");

            using var inputArchive     = MpqArchive.Open(inputArchivePath);
            using var recreatedArchive = MpqArchive.Create(
                      (Stream?)null,
                      inputArchive.GetMpqFiles().ToArray(),
                      (ushort)inputArchive.Header.HashTableSize,
                      inputArchive.Header.BlockSize);

            for (var i = 0; i < inputArchive.Header.BlockTableSize; i++)
            {
                inputArchive.BaseStream.Position     = inputArchive[i].FilePosition;
                recreatedArchive.BaseStream.Position = recreatedArchive[i].FilePosition;

                var size1 = inputArchive[i].CompressedSize;
                var size2 = recreatedArchive[i].CompressedSize;
                StreamAssert.AreEqual(inputArchive.BaseStream, recreatedArchive.BaseStream, size1 > size2 ? size1 : size2);
            }

            inputArchive.BaseStream.Position     = 0;
            recreatedArchive.BaseStream.Position = 0;
            StreamAssert.AreEqual(inputArchive.BaseStream, recreatedArchive.BaseStream, MpqHeader.Size);
        }
예제 #5
0
파일: lsmpq.cs 프로젝트: xerohour/scsharp
    public static void Main(string[] args)
    {
        if (args.Length != 1)
        {
            Console.WriteLine("usage:  lsmpq.exe <mpq-file>");
            Environment.Exit(0);
        }

        Mpq mpq = new MpqArchive(args[0]);

        StreamReader sr = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream("list.txt"));

        string entry;

        while ((entry = sr.ReadLine()) != null)
        {
            entry = entry.ToLower();
            Stream mpq_stream = mpq.GetStreamForResource(entry);
            if (mpq_stream == null)
            {
                continue;
            }

            Console.WriteLine("{0} {1}", entry, mpq_stream.Length);
            mpq_stream.Dispose();
        }
    }
예제 #6
0
        /// <summary>
        /// Iterates all the data archives, extracting and BLT encoding all files
        /// <para>Patches are applied where applicable to get the most up-to-date variant of each file.</para>
        /// </summary>
        /// <param name="archives"></param>
        public void EnumerateDataArchives(IEnumerable <string> archives, bool applyTags = false)
        {
            Log.WriteLine("Exporting Data Archive files");

            foreach (var archivename in archives)
            {
                using var mpq = new MpqArchive(archivename, FileAccess.Read);
                Log.WriteLine("   Exporting " + Path.GetFileName(mpq.FilePath));

                if (TryGetListFile(mpq, out var files))
                {
                    mpq.AddPatchArchives(PatchArchives);
                    ExportFiles(mpq, files, applyTags).Wait();
                    mpq.Dispose();
                }
                else if (TryReadAlpha(mpq, archivename))
                {
                    mpq.Dispose();
                }
                else
                {
                    throw new FormatException(Path.GetFileName(archivename) + " HAS NO LISTFILE!");
                }
            }
        }
예제 #7
0
        public static Tuple <ReplayParseResult, Replay> ParseReplay(string fileName, bool deleteFile, ParseOptions parseOptions)
        {
            var replay = new Replay();

            try
            {
                // File in the version numbers for later use.
                MpqHeader.ParseHeader(replay, fileName);

                if (!parseOptions.IgnoreErrors && replay.ReplayBuild < 32455)
                {
                    return(new Tuple <ReplayParseResult, Replay>(ReplayParseResult.PreAlphaWipe, null));
                }

                using (var archive = new MpqArchive(fileName))
                    ParseReplayArchive(replay, archive, parseOptions);

                if (deleteFile)
                {
                    File.Delete(fileName);
                }

                return(ParseReplayResults(replay, parseOptions.IgnoreErrors, parseOptions.AllowPTR));
            }
            catch
            {
                return(new Tuple <ReplayParseResult, Replay>(ReplayParseResult.ParserException, new Replay {
                    ReplayBuild = replay.ReplayBuild
                }));
            }
        }
예제 #8
0
        /// <summary>
        /// Extract the root directory files from Base-{OS}.MPQ
        /// </summary>
        /// <returns></returns>
        private bool ExtractBaseMPQ()
        {
            Program.Log("Extracting Base MPQ...");

            string baseMPQ     = $"Base-{MFILDownloader.CurrentSession.OS}.mpq";
            string baseMPQpath = Path.Combine(_dataDirectory, baseMPQ);

            if (!File.Exists(baseMPQpath))
            {
                Program.Log($"{baseMPQ} not found!", ConsoleColor.Red);
                return(false);
            }

            using (var mpq = new MpqArchive(baseMPQpath, FileAccess.Read))
            {
                if (!TryGetFileList(mpq, true, out var files))
                {
                    Program.Log($"{baseMPQ} missing ListFile, manual extraction required.", ConsoleColor.Red);
                    return(false);
                }

                foreach (var file in files)
                {
                    mpq.ExtractFile(file, Path.Combine(_repo.DefaultDirectory, file));
                }
            }

            return(true);
        }
예제 #9
0
        public void TestStoreCompressedThenRetrieveFile(string filename)
        {
            var fileStream = File.OpenRead(filename);
            var mpqFile    = new MpqFile(fileStream, filename, MpqFileFlags.Exists | MpqFileFlags.Compressed, BlockSize);
            var archive    = MpqArchive.Create(new MemoryStream(), new List <MpqFile>()
            {
                mpqFile
            });

            var openedArchive = MpqArchive.Open(archive.BaseStream);
            var openedStream  = openedArchive.OpenFile(filename);

            // Reload file, since the filestream gets disposed when the mpqfile is added to an mpqarchive.
            fileStream = File.OpenRead(filename);

            Assert.AreEqual(fileStream.Length, openedStream.Length);

            using (var fileStreamReader = new StreamReader(fileStream))
            {
                using (var openedStreamReader = new StreamReader(openedStream))
                {
                    StringAssert.Equals(fileStreamReader.ReadToEnd(), openedStreamReader.ReadToEnd());
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Attempts to return a list of all files in the archive
        /// </summary>
        /// <param name="mpq"></param>
        /// <param name="files"></param>
        /// <returns></returns>
        private bool TryGetFileList(MpqArchive mpq, bool removeLists, out List <string> files)
        {
            files = new List <string>();

            if (!mpq.HasFile("(ListFile)"))
            {
                return(false);
            }

            using (var file = mpq.OpenFile("(ListFile)"))
                using (var sr = new StreamReader(file))
                {
                    if (!file.CanRead || file.Length == 0)
                    {
                        return(false);
                    }

                    string[] filenames = sr.ReadToEnd().Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                    files.AddRange(filenames);
                }

            if (removeLists)
            {
                files.RemoveAll(x => x.EndsWith(".lst"));
            }

            return(files.Count > 0);
        }
예제 #11
0
파일: LoadMPQ.cs 프로젝트: w9jds/WDBXEditor
        private async Task LoadMPQDBFiles()
        {
            lstFiles.DataSource = null;
            FileNames.Clear();

            await Task.Factory.StartNew(() =>
            {
                using (MpqArchive archive = new MpqArchive(filePath, FileAccess.Read))
                {
                    string line = string.Empty;
                    using (MpqFileStream file = archive.OpenFile("(listfile)"))
                        using (StreamReader sr = new StreamReader(file))
                        {
                            while ((line = sr.ReadLine()) != null)
                            {
                                if (fileExtensions.Contains(Path.GetExtension(line).ToLower()))
                                {
                                    FileNames.TryAdd(line, Path.GetFileName(line));

                                    var ms = new MemoryStream();
                                    archive.OpenFile(line).CopyTo(ms);
                                    Streams.TryAdd(line, ms);
                                }
                            }
                        }
                }
            });
        }
예제 #12
0
 /**
  * Imports a file to the archive.
  * Deletes/imports to overwrite.
  * It imports from "in/" folder
  */
 private void Import(String filename, MpqArchive archive)
 {
     try
     {
         Console.WriteLine("Importing file: in/" + filename);
         if (!File.Exists("in/" + filename))
         {
             Console.WriteLine("File does not exist: in/" + filename + " skipping. . .");
             return;
         }
         if (archive.HasFile(filename))
         {
             // We need to delete because stormlib doesn't overwrite
             Console.WriteLine("File already exists, deleting");
             archive.DeleteFile(filename);
         }
         Console.WriteLine("Inserting file");
         archive.AddFileFromDisk("in/" + filename, filename);
         if (!archive.HasFile(filename))
         {
             Console.WriteLine("Expected import file exists, but did not!");
             return;
         }
         Console.WriteLine("Successfully imported in/" + filename + " as " + filename);
     }
     catch (Exception ex)
     {
         Console.WriteLine("Failed to import file " + filename + ": " + ex.Message);
     }
 }
예제 #13
0
        public static Stream GetFile(string path)
        {
            if (File.Exists(path))
            {
                return(File.OpenRead(path));
            }
            else
            {
                // Assume file is contained in an mpq archive.
                var subPath  = path;
                var fullPath = new FileInfo(path).FullName;
                while (!File.Exists(subPath))
                {
                    subPath = new FileInfo(subPath).DirectoryName;
                }

                var relativePath = fullPath.Substring(subPath.Length + (subPath.EndsWith("\\") ? 0 : 1));

                var memoryStream = new MemoryStream();
                using (var archive = MpqArchive.Open(subPath))
                {
                    archive.OpenFile(relativePath).CopyTo(memoryStream);
                }

                memoryStream.Position = 0;
                return(memoryStream);
            }
        }
예제 #14
0
        public static Tuple <ReplayParseResult, Replay> ParseReplay(string fileName, bool ignoreErrors, bool deleteFile, bool allowPTRRegion = false)
        {
            try
            {
                var replay = new Replay();

                // File in the version numbers for later use.
                MpqHeader.ParseHeader(replay, fileName);

                if (!ignoreErrors && replay.ReplayBuild < 32455)
                {
                    return(new Tuple <ReplayParseResult, Replay>(ReplayParseResult.PreAlphaWipe, null));
                }

                using (var archive = new MpqArchive(fileName))
                    ParseReplayArchive(replay, archive, ignoreErrors);

                if (deleteFile)
                {
                    File.Delete(fileName);
                }

                return(ParseReplayResults(replay, ignoreErrors, allowPTRRegion));
            }
            catch (Exception e)
            {
                return(new Tuple <ReplayParseResult, Replay>(ReplayParseResult.Exception, null));
            }
        }
예제 #15
0
        public static bool FileExists(MpqArchive archive, string path)
        {
            if (archive.FileExists(path))
            {
                return(true);
            }

            // Check if file is contained in an mpq archive.
            var subPath      = path;
            var ignoreLength = new FileInfo(subPath).FullName.Length - path.Length;

            while (!archive.FileExists(subPath))
            {
                var directoryName = new FileInfo(subPath).DirectoryName;
                if (directoryName.Length <= ignoreLength)
                {
                    return(false);
                }

                subPath = directoryName.Substring(ignoreLength);
            }

            var relativePath = path.Substring(subPath.Length + (subPath.EndsWith(@"\", StringComparison.Ordinal) ? 0 : 1));

            using var subArchiveStream = archive.OpenFile(subPath);
            using var subArchive       = MpqArchive.Open(subArchiveStream);
            return(FileExists(subArchive, relativePath));
        }
예제 #16
0
        /// <exception cref="FileNotFoundException"></exception>
        public static Stream GetFile(string path)
        {
            if (File.Exists(path))
            {
                return(File.OpenRead(path));
            }

            // Assume file is contained in an mpq archive.
            var subPath  = path;
            var fullPath = new FileInfo(path).FullName;

            while (!File.Exists(subPath))
            {
                subPath = new FileInfo(subPath).DirectoryName;
                if (subPath is null)
                {
                    throw new FileNotFoundException($"File not found: {path}");
                }
            }

            var relativePath = fullPath.Substring(subPath.Length + (subPath.EndsWith(@"\", StringComparison.Ordinal) ? 0 : 1));

            using var archive = MpqArchive.Open(subPath);
            return(GetFile(archive, relativePath));
        }
예제 #17
0
        public static bool FileExists(string path)
        {
            if (File.Exists(path))
            {
                return(true);
            }

            // Check if file is contained in an mpq archive.
            var subPath  = path;
            var fullPath = new FileInfo(path).FullName;

            while (!File.Exists(subPath))
            {
                subPath = new FileInfo(subPath).DirectoryName;
                if (subPath is null)
                {
                    return(false);
                }
            }

            var relativePath = fullPath.Substring(subPath.Length + (subPath.EndsWith(@"\", StringComparison.Ordinal) ? 0 : 1));

            using var archive = MpqArchive.Open(subPath);
            return(FileExists(archive, relativePath));
        }
예제 #18
0
        public static Tuple<ReplayParseResult, Replay> ParseReplay(string fileName, bool ignoreErrors, bool deleteFile)
        {
            try
            {
                var replay = new Replay();

                // File in the version numbers for later use.
                MpqHeader.ParseHeader(replay, fileName);

                if (!ignoreErrors && replay.ReplayBuild < 32455)
                    return new Tuple<ReplayParseResult, Replay>(ReplayParseResult.PreAlphaWipe, null);

                using (var archive = new MpqArchive(fileName))
                    ParseReplayArchive(replay, archive, ignoreErrors);

                if (deleteFile)
                    File.Delete(fileName);

                return ParseReplayResults(replay, ignoreErrors);
            }
            catch
            {
                return new Tuple<ReplayParseResult, Replay>(ReplayParseResult.Exception, null);
            }
        }
예제 #19
0
        /// <exception cref="FileNotFoundException"></exception>
        public static Stream GetFile(MpqArchive archive, string path)
        {
            if (archive.FileExists(path))
            {
                return(GetArchiveFileStream(archive, path));
            }

            // Assume file is contained in an mpq archive.
            var subPath      = path;
            var ignoreLength = new FileInfo(subPath).FullName.Length - path.Length;

            while (!archive.FileExists(subPath))
            {
                var directoryName = new FileInfo(subPath).DirectoryName;
                if (directoryName.Length <= ignoreLength)
                {
                    throw new FileNotFoundException($"File not found: {path}");
                }

                subPath = directoryName.Substring(ignoreLength);
            }

            var relativePath = path.Substring(subPath.Length + (subPath.EndsWith(@"\", StringComparison.Ordinal) ? 0 : 1));

            using var subArchiveStream = archive.OpenFile(subPath);
            using var subArchive       = MpqArchive.Open(subArchiveStream);
            return(GetArchiveFileStream(subArchive, relativePath));
        }
예제 #20
0
        /// <summary>
        /// Attempts to read the listfile if present
        /// </summary>
        /// <param name="mpq"></param>
        /// <param name="filteredlist"></param>
        /// <returns></returns>
        private bool TryGetListFile(MpqArchive mpq, out List <string> filteredlist)
        {
            filteredlist = new List <string>();

            if (mpq.HasFile(LISTFILE_NAME))
            {
                using (var file = mpq.OpenFile(LISTFILE_NAME))
                    using (var sr = new StreamReader(file))
                    {
                        if (!file.CanRead || file.Length <= 1)
                        {
                            return(false);
                        }

                        while (!sr.EndOfStream)
                        {
                            filteredlist.Add(sr.ReadLine().WoWNormalise());
                        }
                    }

                // remove the MPQ documentation files
                filteredlist.RemoveAll(RemoveUnwantedFiles);
                filteredlist.TrimExcess();

                return(filteredlist.Count > 0);
            }

            return(false);
        }
예제 #21
0
        public static Tuple <ReplayParseResult, Replay> ParseReplay(byte[] bytes, bool ignoreErrors = false, bool allowPTRRegion = false)
        {
            try
            {
                var replay = new Replay();

                // File in the version numbers for later use.
                MpqHeader.ParseHeader(replay, bytes);

                if (!ignoreErrors && replay.ReplayBuild < 32455)
                {
                    return(new Tuple <ReplayParseResult, Replay>(ReplayParseResult.PreAlphaWipe, null));
                }

                using (var memoryStream = new MemoryStream(bytes))
                    using (var archive = new MpqArchive(memoryStream))
                        ParseReplayArchive(replay, archive, ignoreErrors);

                return(ParseReplayResults(replay, ignoreErrors, allowPTRRegion));
            }
            catch
            {
                return(new Tuple <ReplayParseResult, Replay>(ReplayParseResult.Exception, null));
            }
        }
예제 #22
0
        /// <summary>
        /// Appends to or creates a MPQ file
        /// <para>Picks the appropiate version based on the build number.</para>
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="version"></param>
        public void ToMPQ(string filename)
        {
            MpqArchiveVersion version = MpqArchiveVersion.Version2;

            if (this.Build <= (int)ExpansionFinalBuild.WotLK)
            {
                version = MpqArchiveVersion.Version2;
            }
            else if (this.Build <= (int)ExpansionFinalBuild.MoP)
            {
                version = MpqArchiveVersion.Version4;
            }
            else
            {
                MessageBox.Show("Only clients before WoD support MPQ archives.");
                return;
            }

            try
            {
                MpqArchive archive = null;
                if (File.Exists(filename))
                {
                    switch (ShowOverwriteDialog("You've selected an existing MPQ archive.\r\nWhich action would you like to take?", "Existing MPQ"))
                    {
                    case DialogResult.Yes:     //Append
                        archive = new MpqArchive(filename, FileAccess.Write);
                        break;

                    case DialogResult.No:     //Overwrite
                        archive = MpqArchive.CreateNew(filename, version);
                        break;

                    default:
                        return;
                    }
                }
                else
                {
                    archive = MpqArchive.CreateNew(filename, version);
                }

                string tmpPath  = Path.Combine(TEMP_FOLDER, TableStructure.Name);
                string fileName = Path.GetFileName(FilePath);
                string filePath = Path.Combine("DBFilesClient", fileName);

                new DBReader().Write(this, tmpPath);
                archive.AddFileFromDisk(tmpPath, filePath);

                int retval = archive.AddListFile(filePath);
                archive.Compact(filePath);
                archive.Flush();
                archive.Dispose();
            } //Save the file
            catch (Exception ex)
            {
                MessageBox.Show($"Error exporting to MPQ archive {ex.Message}");
            }
        }
예제 #23
0
        public void Can_read_user_data()
        {
            var expected = TestUtil.LoadBytesFromTextFile("TestArchives/Archive1-UserDataHeader.txt");
            var archive  = ObjectMother.ReadTestFile(Testfile, "2gMBq3cvcyaO2PLK7QWjuiigSQE=");
            var userData = MpqArchive.ParseUserDataHeader(archive);

            Assert.That(userData.UserData, Is.EqualTo(expected));
        }
예제 #24
0
        private static MemoryStream GetArchiveFileStream(MpqArchive archive, string filePath)
        {
            var memoryStream = new MemoryStream();

            archive.OpenFile(filePath).CopyTo(memoryStream);
            memoryStream.Position = 0;
            return(memoryStream);
        }
예제 #25
0
 public static bool VerifyReplayMessageEventCleared(string fileName)
 {
     using (var archive = new MpqArchive(fileName))
     {
         archive.AddListfileFilenames();
         return(GetMpqFile(archive, "replay.message.events").Length == 1);
     }
 }
예제 #26
0
        public MPQContentResolver(string rootDirectory)
        {
            this.RootDirectory = rootDirectory;

            fileSystem = new MpqFileSystem();
            var archive = new MpqArchive(System.IO.Path.Combine(rootDirectory, "d2data.mpq"));

            fileSystem.Archives.Add(archive);
        }
예제 #27
0
 public static byte[] GetMpqFile(MpqArchive archive, string fileName)
 {
     using (var mpqStream = archive.OpenFile(archive.Single(i => i.Filename == fileName)))
     {
         var buffer = new byte[mpqStream.Length];
         mpqStream.Read(buffer, 0, buffer.Length);
         return(buffer);
     }
 }
예제 #28
0
 private static byte[] GetMpqArchiveFileBytes(MpqArchive archive, string fileName)
 {
     using (var mpqStream = archive.OpenFile(archive.Single(i => i.Filename == fileName)))
     {
         var buffer = new byte[mpqStream.Length];
         mpqStream.Read(buffer, 0, buffer.Length);
         return buffer;
     }
 }
예제 #29
0
 public void Restore(string file)
 {
     using (MemoryStream stream = MpqArchive.Restore(file))
     {
         using (FileStream streamOut = File.Create(file))
         {
             stream.CopyTo(streamOut);
         }
     }
 }
예제 #30
0
    public static void Main(string[] args)
    {
        string entry_name = args[1];
        int    entry      = Int32.Parse(args[2]);

        Mpq         mpq    = new MpqArchive(args[0]);
        DumpIScript dumper = new DumpIScript(mpq);

        dumper.Dump(entry_name, entry);
    }
예제 #31
0
        internal MpqStream(MpqArchive archive, MpqEntry entry)
        {
            _entry = entry;

            _stream = archive.BaseStream;
            _blockSize = archive.BlockSize;

            if (_entry.IsCompressed && !_entry.IsSingleUnit)
                LoadBlockPositions();
        }
예제 #32
0
        private static bool ExtractWDT(string fileName, out string outputWdtPath)
        {
            outputWdtPath = string.Empty;
            try
            {
                using (MpqArchive archive = new MpqArchive(fileName))
                {
                    byte[] buf        = new byte[0x40000];
                    var    outputName = Path.GetFileNameWithoutExtension(fileName);

                    Console.WriteLine($"Extracting {outputName} ...");

                    foreach (MpqEntry entry in archive)
                    {
                        if (!entry.IsCompressed || entry.IsEncrypted)
                        {
                            continue;
                        }

                        entry.Filename = outputName;
                        string srcFile = entry.Filename;
                        outputWdtPath = Path.Combine(OutputDirectory, srcFile);

                        // Copy to destination file
                        using (Stream streamIn = archive.OpenFile(entry))
                        {
                            using (Stream streamOut = new FileStream(outputWdtPath, FileMode.Create))
                            {
                                while (true)
                                {
                                    int cb = streamIn.Read(buf, 0, buf.Length);
                                    if (cb == 0)
                                    {
                                        break;
                                    }

                                    streamOut.Write(buf, 0, cb);
                                    Program.UpdateLoadingStatus();
                                }

                                streamOut.Close();
                            }
                        }
                    }
                }

                return(true);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return(false);
        }
예제 #33
0
 internal MpqStream(MpqArchive File, MpqArchive.Block Block)
 {
     this.mCurrentBlockIndex = -1;
     this.mBlock = Block;
     this.mStream = File.BaseStream;
     this.mBlockSize = File.BlockSize;
     if (this.mBlock.IsCompressed)
     {
         this.LoadBlockPositions();
     }
 }
예제 #34
0
        public void TestWithPreArchiveDataAndNoFiles()
        {
            var memoryStream = new MemoryStream();
            var randomData   = new byte[999];

            memoryStream.Write(randomData, 0, randomData.Length);

            using var a = MpqArchive.Create(memoryStream, Array.Empty <MpqFile>(), new MpqArchiveCreateOptions());

            memoryStream.Position = 0;
            MpqArchive.Open(memoryStream).Dispose();
        }
예제 #35
0
 public MpqArchive.FileInfo[] FilterList(MpqArchive.FileInfo[] List, string FilterPattern)
 {
     List<MpqArchive.FileInfo> list = new List<MpqArchive.FileInfo>();
     FilterPattern = FilterPattern.ToLower();
     foreach (MpqArchive.FileInfo info in List)
     {
         string str = info.Name.ToLower();
         if ((FilterPattern.StartsWith("*") && str.EndsWith(FilterPattern.Substring(1))) || str.StartsWith(FilterPattern))
         {
             list.Add(info);
         }
     }
     list.Sort(new MpqArchive.FileInfo.Comparer());
     return list.ToArray();
 }
예제 #36
0
 public MpqArchive.FileInfo[] FilterList(MpqArchive.FileInfo[] List, string FilterPattern)
 {
     Regex regex = new Regex(FilterPattern, RegexOptions.IgnoreCase);
     List<MpqArchive.FileInfo> list = new List<MpqArchive.FileInfo>();
     FilterPattern = FilterPattern.ToLower();
     foreach (MpqArchive.FileInfo info in List)
     {
         string input = info.Name.ToLower();
         if (regex.IsMatch(input))
         {
             list.Add(info);
         }
     }
     list.Sort(new MpqArchive.FileInfo.Comparer());
     return list.ToArray();
 }
예제 #37
0
 public MpqDirectory(IEnumerable<string> MpqArchives)
 {
     foreach (string str in MpqArchives)
     {
         if (File.Exists(str))
         {
             MpqArchive archive = new MpqArchive(str);
             foreach (MpqArchive.FileInfo info in archive.Files)
             {
                 if (!this.m_Mpq.ContainsKey(info))
                 {
                     this.m_Mpq.Add(info, archive);
                 }
             }
         }
     }
 }
예제 #38
0
        static void Main(string[] args)
        {
            var heroesAccountsFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), @"Heroes of the Storm\Accounts");
            var randomReplayFileName = Directory.GetFiles(heroesAccountsFolder, "*.StormReplay", SearchOption.AllDirectories).OrderBy(i => Guid.NewGuid()).First();

            // Use temp directory for MpqLib directory permissions requirements
            var tmpPath = Path.GetTempFileName();
            File.Copy(randomReplayFileName, tmpPath, true);

            try
            {
                // Create our Replay object: this object will be filled as you parse the different files in the .StormReplay archive
                var replay = new Replay();
                Heroes.ReplayParser.MpqHeader.ParseHeader(replay, tmpPath);
                using (var archive = new MpqArchive(tmpPath))
                {
                    archive.AddListfileFilenames();
                    
                    ReplayDetails.Parse(replay, GetMpqArchiveFileBytes(archive, ReplayDetails.FileName));
                    ReplayTrackerEvents.Parse(replay, GetMpqArchiveFileBytes(archive, ReplayTrackerEvents.FileName));
                    ReplayInitData.Parse(replay, GetMpqArchiveFileBytes(archive, ReplayInitData.FileName), partialParse: false);
                    ReplayAttributeEvents.Parse(replay, GetMpqArchiveFileBytes(archive, ReplayAttributeEvents.FileName));
                    if (replay.ReplayBuild >= 32455)
                        ReplayGameEvents.Parse(replay, GetMpqArchiveFileBytes(archive, ReplayGameEvents.FileName));
                    ReplayServerBattlelobby.Parse(replay, GetMpqArchiveFileBytes(archive, ReplayServerBattlelobby.FileName));
                    ReplayMessageEvents.Parse(replay, GetMpqArchiveFileBytes(archive, ReplayMessageEvents.FileName));
                    Unit.ParseUnitData(replay);
                }

                // Our Replay object now has all currently available information
                Console.WriteLine("Replay Build: " + replay.ReplayBuild);
                Console.WriteLine("Map: " + replay.Map);
                foreach (var player in replay.Players.OrderByDescending(i => i.IsWinner))
                    Console.WriteLine("Player: " + player.Name + ", Win: " + player.IsWinner + ", Hero: " + player.Character + ", Lvl: " + player.CharacterLevel + (replay.ReplayBuild >= 32524 ? ", Talents: " + string.Join(",", player.Talents.OrderBy(i => i)) : ""));
                    
                Console.WriteLine("Press Any Key to Close");
                Console.Read();
            }
            finally
            {
                if (File.Exists(tmpPath))
                    File.Delete(tmpPath);
            }
        }
예제 #39
0
        public static Tuple<ReplayParseResult, Replay> ParseReplay(byte[] bytes, bool ignoreErrors = false)
        {
            try
            {
                var replay = new Replay();

                // File in the version numbers for later use.
                MpqHeader.ParseHeader(replay, bytes);

                if (!ignoreErrors && replay.ReplayBuild < 32455)
                    return new Tuple<ReplayParseResult, Replay>(ReplayParseResult.PreAlphaWipe, null);

                using (var memoryStream = new MemoryStream(bytes))
                using (var archive = new MpqArchive(memoryStream))
                    ParseReplayArchive(replay, archive, ignoreErrors);

                return ParseReplayResults(replay, ignoreErrors);
            }
            catch
            {
                return new Tuple<ReplayParseResult, Replay>(ReplayParseResult.Exception, null);
            }
        }
예제 #40
0
 internal WoWArchive(MpqArchive archive, WoWArchiveKind kind)
 {
     Archive = archive;
     Kind = kind;
 }
예제 #41
0
 public void OpenPatchFile(string mpqArchive)
 {
     MpqArchive archive = new MpqArchive(mpqArchive);
     foreach (MpqArchive.FileInfo info in archive.Files)
     {
         if (!this.m_Mpq.ContainsKey(info))
         {
             this.m_Mpq.Add(info, archive);
         }
         else
         {
             this.m_Mpq[info] = archive;
         }
     }
 }
예제 #42
0
 public Stream OpenFile(MpqArchive.FileInfo file)
 {
     /*
     if (this.m_Cache.ContainsKey(file))
     {
         if (this.m_Cache[file].CanRead)
         {
             return this.m_Cache[file];
         }
         this.m_Cache.Remove(file);
     }
     */
     if (this.FileExists(file))
     {
         Stream stream = this.m_Mpq[file].OpenFile(file.Name);
         //this.m_Cache.Add(file, stream);
         return stream;
     }
     return null;
 }
예제 #43
0
파일: App.cs 프로젝트: cyotek/mpqtool
        /// <summary>
        /// Extracts files from the archive matching the pattern (if any)
        /// </summary>
        void ExtractArchive()
        {
            using(MpqArchive archive = new MpqArchive(archiveFile))
            {
                // destination directory
                if(destDir == null || destDir == "")
                    destDir = Directory.GetCurrentDirectory();    // default to current dir of not specified

                archive.AddListfileFilenames();

                // setup external listfile if specified
                if (listFile != null && listFile != "")
                    using (Stream s = File.OpenRead(listFile))
                        archive.AddFilenames(s);

                // buffers
                byte[] buf = new byte[0x40000];

                if(!quietOutput)
                    Console.WriteLine("Extracting to {0}", destDir);

                foreach(MpqEntry entry in archive)
                {
                    // match pattern
                    if (regex != null && !regex.Match(entry.Filename).Success)
                        continue;

                    if(!quietOutput)
                        Console.Write(entry.Filename + " .. ");

                    string srcFile = entry.Filename;
                    if (stripPath)
                        srcFile = Path.GetFileName(srcFile);

                    // create destination directory
                    string destFile = Path.Combine(destDir, srcFile);
                    string absDestDir = Path.GetDirectoryName(destFile);
                    CreateDirectory(absDestDir);

                    // copy to destination file
                    using(Stream stmIn = archive.OpenFile(entry))
                    {
                        using(Stream stmOut = new FileStream(destFile, FileMode.Create))
                        {
                            while(true)
                            {
                                int cb = stmIn.Read(buf, 0, buf.Length);
                                if(cb == 0)
                                    break;

                                stmOut.Write(buf, 0, cb);
                            }

                            stmOut.Close();
                        }
                    }

                    if(!quietOutput)
                        Console.WriteLine("Done.");
                }
            }
        }
예제 #44
0
파일: App.cs 프로젝트: cyotek/mpqtool
        /// <summary>
        /// Lists the contents of the archive.
        /// </summary>
        void ListArchive()
        {
            using(MpqArchive archive = new MpqArchive(archiveFile))
            {
                archive.AddListfileFilenames();

                // setup external listfile if specified
                if(listFile != null && listFile != "")
                    using (Stream s = File.OpenRead(listFile))
                        archive.AddFilenames(s);

                Console.WriteLine("ucmp. size   cmp. size   ratio   cmp. type   filename");
                Console.WriteLine("----------   ---------   -----   ---------   --------");

                foreach (MpqEntry entry in archive)
                {
                    // match pattern
                    if (regex != null && !regex.Match(entry.Filename).Success)
                        continue;

                    string srcFile = entry.Filename;
                    if (stripPath)
                        srcFile = Path.GetFileName(srcFile);

                    // display info
                    Console.WriteLine("{0, 10}   {1, 9}   {2, 5}   {3, 9}   {4}",
                                      entry.FileSize, entry.CompressedSize,
                                      CompressionRatioString(entry.FileSize, entry.CompressedSize),
                                      CompressionTypeString(entry.Flags), srcFile);
                }
            }
        }
예제 #45
0
 public bool FileExists(MpqArchive.FileInfo file)
 {
     return (this.m_Mpq.ContainsKey(file) && this.m_Mpq[file].FileExists(file.Name));
 }
예제 #46
0
 public static bool VerifyReplayMessageEventCleared(string fileName)
 {
     using (var archive = new MpqArchive(fileName))
     {
         archive.AddListfileFilenames();
         return GetMpqFile(archive, "replay.message.events").Length == 1;
     }
 }
예제 #47
0
        private static void ParseReplayArchive(Replay replay, MpqArchive archive, bool ignoreErrors)
        {
            archive.AddListfileFilenames();

            // Replay Details
            ReplayDetails.Parse(replay, GetMpqFile(archive, ReplayDetails.FileName));

            if (!ignoreErrors && (replay.Players.Length != 10 || replay.Players.Count(i => i.IsWinner) != 5))
                // Filter out 'Try Me' games, any games without 10 players, and incomplete games
                return;
            else if (!ignoreErrors && replay.Timestamp < new DateTime(2014, 10, 6, 0, 0, 0, DateTimeKind.Utc))
                // Technical Alpha replays
                return;

            // Replay Init Data
            ReplayInitData.Parse(replay, GetMpqFile(archive, ReplayInitData.FileName));
            
            ReplayAttributeEvents.Parse(replay, GetMpqFile(archive, ReplayAttributeEvents.FileName));

            replay.TrackerEvents = ReplayTrackerEvents.Parse(GetMpqFile(archive, ReplayTrackerEvents.FileName));

            try
            {
                replay.GameEvents = ReplayGameEvents.Parse(GetMpqFile(archive, ReplayGameEvents.FileName), replay.ClientList, replay.ReplayBuild);
                replay.IsGameEventsParsedSuccessfully = true;
            }
            catch
            {
                replay.GameEvents = new List<GameEvent>();
            }

            {
                // Gather talent selections
                var talentGameEventsDictionary = replay.GameEvents
                    .Where(i => i.eventType == GameEventType.CHeroTalentSelectedEvent)
                    .GroupBy(i => i.player)
                    .ToDictionary(
                        i => i.Key,
                        i => i.Select(j => new Talent { TalentID = (int)j.data.unsignedInt.Value, TimeSpanSelected = j.TimeSpan }).OrderBy(j => j.TimeSpanSelected).ToArray());

                foreach (var player in talentGameEventsDictionary.Keys)
                    player.Talents = talentGameEventsDictionary[player];
            }

            // Replay Server Battlelobby
            if (!ignoreErrors)
                ReplayServerBattlelobby.Parse(replay, GetMpqFile(archive, ReplayServerBattlelobby.FileName));

            // Parse Unit Data using Tracker events
            Unit.ParseUnitData(replay);

            // Parse Statistics
            if (replay.ReplayBuild >= 40431)
                try
                {
                    Statistics.Parse(replay);
                    replay.IsStatisticsParsedSuccessfully = true;
                }
                catch
                {

                }

            // Replay Message Events
            // ReplayMessageEvents.Parse(replay, GetMpqFile(archive, ReplayMessageEvents.FileName));

            // Replay Resumable Events
            // So far it doesn't look like this file has anything we would be interested in
            // ReplayResumableEvents.Parse(replay, GetMpqFile(archive, "replay.resumable.events"));
        }