public void TestRecreatePKCompressed() { const string inputArchivePath = @"TestArchives\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); }
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, new MpqArchiveCreateOptions() { ListFileCreateMode = MpqFileCreateMode.None, AttributesCreateMode = MpqFileCreateMode.None }); 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(); }
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()); } } }
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(); }
public void TestStoreThenRetrieveFile(string filename) { var fileStream = File.OpenRead(filename); var mpqFile = MpqFile.New(fileStream, filename, true); var archive = MpqArchive.Create(new MemoryStream(), new List <MpqFile>() { mpqFile }); var openedArchive = MpqArchive.Open(archive.BaseStream); var openedStream = openedArchive.OpenFile(filename); StreamAssert.AreEqual(fileStream, openedStream, true); }
public void TestStoreThenRetrieveEmptyFileWithFlags(MpqFileFlags flags) { const string FileName = "someRandomFile.empty"; using var mpqFile = MpqFile.New(null, FileName); mpqFile.TargetFlags = flags; using var archive = MpqArchive.Create(new MemoryStream(), new List <MpqFile>() { mpqFile }, new MpqArchiveCreateOptions { BlockSize = BlockSize }); using var openedArchive = MpqArchive.Open(archive.BaseStream); var openedStream = openedArchive.OpenFile(FileName); Assert.IsTrue(openedStream.Length == 0); }
public void TestStoreThenRetrieveFileWithFlags(string fileName, MpqFileFlags flags) { using var fileStream = File.OpenRead(fileName); var mpqFile = MpqFile.New(fileStream, fileName, true); mpqFile.TargetFlags = flags; using var archive = MpqArchive.Create(new MemoryStream(), new List <MpqFile>() { mpqFile }, new MpqArchiveCreateOptions { BlockSize = BlockSize }); using var openedArchive = MpqArchive.Open(archive.BaseStream); var openedStream = openedArchive.OpenFile(fileName); StreamAssert.AreEqual(fileStream, openedStream, true); }
public void TestStoreThenRetrieveFile(string filename) { var fileStream = File.OpenRead(filename); // var mpqFile = new MpqKnownFile(filename, fileStream, MpqFileFlags.Exists, MpqLocale.Neutral, true); var mpqFile = MpqFile.New(fileStream, filename); var archive = MpqArchive.Create(new MemoryStream(), new List <MpqFile>() { mpqFile }); var openedArchive = MpqArchive.Open(archive.BaseStream); var openedStream = openedArchive.OpenFile(filename); fileStream.Position = 0; StreamAssert.AreEqual(fileStream, openedStream); }
public void TestDeleteFile() { const string inputArchivePath = @".\TestArchives\NewLuaMap.w3m"; const string fileName = "war3map.lua"; using var inputArchive = MpqArchive.Open(inputArchivePath); var newFile = MpqFile.New(null, fileName); var mpqFiles = inputArchive.GetMpqFiles(); var oldFile = mpqFiles.FirstOrDefault(file => file.IsSameAs(newFile)) ?? throw new FileNotFoundException($"File not found: {fileName}"); var newFiles = mpqFiles.Select(file => ReferenceEquals(file, oldFile) ? newFile : file).ToArray(); using var outputArchive = MpqArchive.Create((Stream?)null, newFiles, (ushort)inputArchive.Header.HashTableSize, inputArchive.Header.BlockSize); Assert.IsTrue(outputArchive.FileExists(fileName, out var entryIndex)); Assert.AreEqual(0U, outputArchive[entryIndex].FileSize); }
public void TestDeleteFile() { var inputArchivePath = TestDataProvider.GetFile(@"Maps\NewLuaMap.w3m"); const string fileName = "war3map.lua"; using var inputArchive = MpqArchive.Open(inputArchivePath); var newFile = MpqFile.New(null, fileName); var mpqFiles = inputArchive.GetMpqFiles(); var oldFile = mpqFiles.FirstOrDefault(file => file.Equals(newFile)) ?? throw new FileNotFoundException($"File not found: {fileName}"); var newFiles = mpqFiles.Select(file => ReferenceEquals(file, oldFile) ? newFile : file).ToArray(); using var outputArchive = MpqArchive.Create((Stream?)null, newFiles, new MpqArchiveCreateOptions { BlockSize = inputArchive.Header.BlockSize, HashTableSize = (ushort)inputArchive.Header.HashTableSize, AttributesFlags = AttributesFlags.DateTime | AttributesFlags.Crc32 }); Assert.IsTrue(outputArchive.FileExists(fileName, out var entryIndex)); Assert.AreEqual(0U, outputArchive[entryIndex].FileSize); }
public void TestStoreThenRetrieveEmptyFileWithFlags(MpqFileFlags flags) { const string FileName = "someRandomFile.empty"; // var mpqFile = new MpqKnownFile(FileName, null, flags, MpqLocale.Neutral); var mpqFile = MpqFile.New(null, FileName); mpqFile.TargetFlags = flags; var archive = MpqArchive.Create(new MemoryStream(), new List <MpqFile>() { mpqFile }, blockSize: BlockSize); var openedArchive = MpqArchive.Open(archive.BaseStream); var openedStream = openedArchive.OpenFile(FileName); Assert.IsTrue(openedStream.Length == 0); }
public void TestRecreatePKCompressed() { var inputArchivePath = TestDataProvider.GetPath(@"Maps\PKCompressed.w3x"); using var inputArchive = MpqArchive.Open(inputArchivePath); using var recreatedArchive = MpqArchive.Create((Stream?)null, inputArchive.GetMpqFiles().ToArray(), new MpqArchiveCreateOptions { BlockSize = inputArchive.Header.BlockSize, HashTableSize = (ushort)inputArchive.Header.HashTableSize, ListFileCreateMode = MpqFileCreateMode.None, AttributesCreateMode = MpqFileCreateMode.None }); 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); StreamAssert.AreEqual(inputArchive.BaseStream, recreatedArchive.BaseStream); } inputArchive.BaseStream.Position = 0; recreatedArchive.BaseStream.Position = 0; StreamAssert.AreEqual(inputArchive.BaseStream, recreatedArchive.BaseStream, MpqHeader.Size); }
public void TestRecreateArchive(string inputArchivePath, bool loadListFile) { using var inputArchive = MpqArchive.Open(inputArchivePath, loadListFile); if (loadListFile && !inputArchive.FileExists(ListFile.FileName)) { return; } var mpqFiles = inputArchive.GetMpqFiles().ToArray(); using var recreatedArchive = MpqArchive.Create((Stream?)null, mpqFiles, new MpqArchiveCreateOptions { BlockSize = inputArchive.Header.BlockSize, ListFileCreateMode = MpqFileCreateMode.None, AttributesCreateMode = MpqFileCreateMode.None }); // TODO: fix assumption that recreated archive's hashtable cannot be smaller than original // TODO: fix assumption of how recreated blocktable's entries are laid out relative to input mpqFiles array? (aka: replace the 'offset' variable) var offsetPerUnknownFile = (recreatedArchive.HashTable.Size / inputArchive.HashTable.Size) - 1; var mpqEncryptedFileCount = mpqFiles.Where(mpqFile => mpqFile.IsFilePositionFixed).Count(); var offset = mpqEncryptedFileCount * (offsetPerUnknownFile + 1); mpqEncryptedFileCount = 0; for (var index = 0; index < mpqFiles.Length; index++) { var mpqFile = mpqFiles[index]; MpqEntry?inputEntry; if (mpqFile is MpqKnownFile knownFile) { inputEntry = inputArchive.GetMpqEntries(knownFile.FileName).FirstOrDefault(); } else if (mpqFile is MpqUnknownFile unknownFile) { inputArchive.TryGetEntryFromHashTable(mpqFile.HashIndex & inputArchive.HashTable.Mask, out inputEntry); } else if (mpqFile is MpqOrphanedFile orphanedFile) { // TODO throw new NotSupportedException("found orphaned mpqfile"); } else { throw new NotImplementedException(); } var blockIndex = index + (int)offset; if (mpqFile.IsFilePositionFixed) { blockIndex = mpqEncryptedFileCount * ((int)offsetPerUnknownFile + 1); mpqEncryptedFileCount++; } var recreatedEntry = recreatedArchive[blockIndex]; if (inputEntry is not null) { if (!mpqFile.MpqStream.CanBeDecrypted) { // Check if both files have the same encryption seed. Assert.IsTrue(!mpqFile.TargetFlags.HasFlag(MpqFileFlags.BlockOffsetAdjustedKey) || inputEntry.FileOffset == recreatedEntry.FileOffset); inputArchive.BaseStream.Position = inputEntry.FilePosition; recreatedArchive.BaseStream.Position = recreatedEntry.FilePosition; var size1 = inputEntry.CompressedSize; var size2 = recreatedEntry.CompressedSize; StreamAssert.AreEqual(inputArchive.BaseStream, recreatedArchive.BaseStream, size1 > size2 ? size1 : size2); } else { using var inputStream = inputArchive.OpenFile(inputEntry); using var recreatedStream = recreatedArchive.OpenFile(recreatedEntry); StreamAssert.AreEqual(inputStream, recreatedStream, mpqFile is MpqKnownFile known ? known.FileName : "<unknown file>"); } } else { Assert.IsFalse(recreatedEntry.Flags.HasFlag(MpqFileFlags.Exists)); } if (mpqFile is MpqUnknownFile && !mpqFile.IsFilePositionFixed) { offset += offsetPerUnknownFile; } } }