From 43377b306cfbc0a7cd44a32395bd9be9716067b0 Mon Sep 17 00:00:00 2001 From: Pear-231 <61670316+Pear-231@users.noreply.github.com> Date: Sun, 16 Nov 2025 22:13:19 +0000 Subject: [PATCH] Change Notes: - Fixed a potential filename length calculation issue due to some special characters by using UTF-8 byte count instead of character count. - Fixed potential issue with temp files by using FileMode.Create instead to prevent reusing incorrect data. - Moved SystemFilePath to after file move to prevent reads from a potentially wrong file. - Added assertion against saving with encryption as we don't support that. --- .../PackFiles/Models/PackFileContainer.cs | 40 ++++++++----------- .../SharedCore/PackFiles/PackFileService.cs | 4 +- .../Commands/ExportToDirectoryCommand.cs | 13 +++--- 3 files changed, 24 insertions(+), 33 deletions(-) diff --git a/Shared/SharedCore/PackFiles/Models/PackFileContainer.cs b/Shared/SharedCore/PackFiles/Models/PackFileContainer.cs index 0aed81a50..c722d5a4c 100644 --- a/Shared/SharedCore/PackFiles/Models/PackFileContainer.cs +++ b/Shared/SharedCore/PackFiles/Models/PackFileContainer.cs @@ -33,29 +33,24 @@ public void MergePackFileContainer(PackFileContainer other) public void SaveToByteArray(BinaryWriter writer, GameInformation gameInformation) { - long fileNamesOffset = 0; - var sortedFiles = FileList.OrderBy(x => x.Key, StringComparer.Ordinal).ToList(); - foreach (var file in sortedFiles) - { - if (Header.Version == PackFileVersion.PFH5) - fileNamesOffset += 1; - if (Header.HasIndexWithTimeStamp) - fileNamesOffset += 4; - fileNamesOffset += 4 + file.Key.Length + 1; // Size + filename with zero terminator - } + if (Header.HasEncryptedData || Header.HasEncryptedIndex) + throw new InvalidOperationException("Saving encrypted packs is not supported."); - long headerSpesificBytes = 0; + long headerSpecificBytes = 0; if (Header.HasIndexWithTimeStamp) - headerSpesificBytes += 4; + headerSpecificBytes += 4; if (Header.Version == PackFileVersion.PFH5) - headerSpesificBytes += 1; + headerSpecificBytes += 1; - long fileNamesOffset2 = 0; + long fileNamesOffset = 0; + + var sortedFiles = FileList.OrderBy(x => x.Key, StringComparer.Ordinal).ToList(); foreach (var file in sortedFiles) { var fileSize = 4; - var strLength = file.Key.Length + 1; - fileNamesOffset2 += fileSize + headerSpesificBytes + strLength; + var zeroTerminator = 1; + var fileNameBytes = Encoding.UTF8.GetByteCount(file.Key); + fileNamesOffset += fileSize + headerSpecificBytes + fileNameBytes + zeroTerminator; } Header.FileCount = (uint)FileList.Count; @@ -110,7 +105,6 @@ public void SaveToByteArray(BinaryWriter writer, GameInformation gameInformation { var packFile = file.PackFile; byte[] data; - var fileSize = 0; uint uncompressedFileSize = 0; // Read the data @@ -125,7 +119,6 @@ public void SaveToByteArray(BinaryWriter writer, GameInformation gameInformation // Compress the data into the right format var compressedData = PackFileCompression.Compress(uncompressedData, file.IntendedCompressionFormat); data = compressedData; - fileSize = compressedData.Length; } else if (packFile.DataSource is PackedFileSource packedFileSource && isCorrectCompressionFormat) { @@ -133,13 +126,11 @@ public void SaveToByteArray(BinaryWriter writer, GameInformation gameInformation uncompressedFileSize = packedFileSource.UncompressedSize; var compressedData = packedFileSource.ReadDataWithoutDecompressing(); data = compressedData; - fileSize = data.Length; } else - { data = packFile.DataSource.ReadData(); - fileSize = data.Length; - } + + var fileSize = (uint)data.Length; // Write the data var offset = writer.BaseStream.Position; @@ -151,12 +142,15 @@ public void SaveToByteArray(BinaryWriter writer, GameInformation gameInformation writer.Write(fileSize); writer.BaseStream.Position = currentPosition; + // We do not encrypt + var isEncrypted = false; + // Update DataSource packFile.DataSource = new PackedFileSource( packedFileSourceParent, offset, fileSize, - Header.HasEncryptedData, + isEncrypted, shouldCompress, file.IntendedCompressionFormat, uncompressedFileSize); diff --git a/Shared/SharedCore/PackFiles/PackFileService.cs b/Shared/SharedCore/PackFiles/PackFileService.cs index 63430750b..cd1182c79 100644 --- a/Shared/SharedCore/PackFiles/PackFileService.cs +++ b/Shared/SharedCore/PackFiles/PackFileService.cs @@ -273,8 +273,7 @@ public void SavePackContainer(PackFileContainer pf, string path, bool createBack throw new Exception("File has been changed outside of AssetEditor. Can not save the file as it will cause corruptions"); } - pf.SystemFilePath = path; - using (var memoryStream = new FileStream(path + "_temp", FileMode.OpenOrCreate)) + using (var memoryStream = new FileStream(path + "_temp", FileMode.Create)) { using var writer = new BinaryWriter(memoryStream); pf.SaveToByteArray(writer, gameInformation); @@ -283,6 +282,7 @@ public void SavePackContainer(PackFileContainer pf, string path, bool createBack File.Delete(path); File.Move(path + "_temp", path); + pf.SystemFilePath = path; pf.OriginalLoadByteSize = new FileInfo(path).Length; _globalEventHub?.PublishGlobalEvent(new PackFileContainerSavedEvent(pf)); diff --git a/Shared/SharedUI/BaseDialogs/PackFileTree/ContextMenu/Commands/ExportToDirectoryCommand.cs b/Shared/SharedUI/BaseDialogs/PackFileTree/ContextMenu/Commands/ExportToDirectoryCommand.cs index b15df1d36..3cecbea6d 100644 --- a/Shared/SharedUI/BaseDialogs/PackFileTree/ContextMenu/Commands/ExportToDirectoryCommand.cs +++ b/Shared/SharedUI/BaseDialogs/PackFileTree/ContextMenu/Commands/ExportToDirectoryCommand.cs @@ -9,14 +9,15 @@ public class ExportToDirectoryCommand() : IContextMenuCommand public string GetDisplayName(TreeNode node) => "Export to system folder"; public bool IsEnabled(TreeNode node) => true; - public void Execute(TreeNode _selectedNode) + public void Execute(TreeNode selectedNode) { + // TODO: Fix bug where if you export the packfilecontainer itself it doesn't export correctly. var dialog = new FolderBrowserDialog(); if (dialog.ShowDialog() == DialogResult.OK) { - var nodeStartDir = Path.GetDirectoryName(_selectedNode.GetFullPath()); + var nodeStartDir = Path.GetDirectoryName(selectedNode.GetFullPath()); var fileCounter = 0; - SaveSelfAndChildren(_selectedNode, dialog.SelectedPath, nodeStartDir, ref fileCounter); + SaveSelfAndChildren(selectedNode, dialog.SelectedPath, nodeStartDir, ref fileCounter); MessageBox.Show($"{fileCounter} files exported!"); } } @@ -33,7 +34,7 @@ void SaveSelfAndChildren(TreeNode node, string outputDirectory, string rootPath, var nodeOriginalPath = node.GetFullPath(); var nodePathWithoutRoot = nodeOriginalPath; - if (rootPath.Length != 0) + if (rootPath != null && rootPath.Length != 0) nodePathWithoutRoot = nodeOriginalPath.Replace(rootPath, ""); if (nodePathWithoutRoot.StartsWith("\\") == false) @@ -56,7 +57,3 @@ void SaveSelfAndChildren(TreeNode node, string outputDirectory, string rootPath, } } - -/* - - */