/// <summary> /// Recursivly adds the specified GGPK DirectoryTree to the TreeListView /// </summary> /// <param name="directoryTreeNode">Node to add to tree</param> /// <param name="parentControl">TreeViewItem to add children to</param> private void AddDirectoryTreeToControl(DirectoryTreeNode directoryTreeNode, TreeViewItem parentControl) { TreeViewItem rootItem = new TreeViewItem(); rootItem.Header = directoryTreeNode; if ((directoryTreeNode.ToString() == "ROOT") || (directoryTreeNode.ToString() == "")) rootItem.IsExpanded = true; if (parentControl == null) { treeView1.Items.Add(rootItem); } else { parentControl.Items.Add(rootItem); } directoryTreeNode.Children.Sort(); foreach (var item in directoryTreeNode.Children) { AddDirectoryTreeToControl(item, rootItem); } directoryTreeNode.Files.Sort(); foreach (var item in directoryTreeNode.Files) { rootItem.Items.Add(item); } }
/// <summary> /// Builds a directory tree by traversing the list of record headers found in the pack file /// </summary> /// <param name="recordOffsets">Map of record offsets and headers to create directory tree from</param> /// <returns>Root node of directory tree</returns> internal static DirectoryTreeNode BuildDirectoryTree(Dictionary <long, BaseRecord> recordOffsets) { // This offset is a directory, add it as a child of root and process all of it's entries GGPKRecord currentDirectory = recordOffsets[0] as GGPKRecord; DirectoryTreeNode root = new DirectoryTreeNode() { Children = new List <DirectoryTreeNode>(), Files = new List <FileRecord>(), Name = "", Parent = null, Record = null }; // First level only contains a empty string name directory record and a free record if (currentDirectory == null) { return(root); } foreach (var item in from Offset in currentDirectory.RecordOffsets where recordOffsets.ContainsKey(Offset) where recordOffsets[Offset] is DirectoryRecord select recordOffsets[Offset] as DirectoryRecord into firstDirectory from item in firstDirectory.Entries select item) { BuildDirectoryTree(item, root, recordOffsets); } return(root); }
/// <summary> /// Gets the absolute directory of this node /// </summary> /// <returns>Absolute directory of this node</returns> public string GetDirectoryPath() { if (directoryPath != null) { return(directoryPath); } Stack <string> pathQueue = new Stack <string>(); StringBuilder sb = new StringBuilder(); // Traverse the directory tree until we hit the root node, pushing all // encountered directory names onto the stack DirectoryTreeNode iter = this; while (iter != null && iter.Name.Length > 0) { pathQueue.Push(iter.Name); iter = iter.Parent; } foreach (var item in pathQueue) { sb.Append(item + Path.DirectorySeparatorChar); } directoryPath = sb.ToString(); return(directoryPath); }
private static void BuildDirectoryTree(long fileOffset, DirectoryTreeNode root, Dictionary <long, BaseRecord> recordOffsets) { if (!recordOffsets.ContainsKey(fileOffset)) { return; } if (recordOffsets[fileOffset] is DirectoryRecord) { DirectoryRecord directoryRecord = recordOffsets[fileOffset] as DirectoryRecord; DirectoryTreeNode directoryTreeNode = new DirectoryTreeNode { Name = directoryRecord.Name, Parent = root, Children = new List <DirectoryTreeNode>(), Files = new List <FileRecord>(), Record = directoryRecord }; root.Children.Add(directoryTreeNode); DirectoryRecord.DirectoryEntry[] entries = directoryRecord.Entries; for (int i = 0; i < entries.Length; i++) { DirectoryRecord.DirectoryEntry directoryEntry = entries[i]; DirectoryTreeMaker.BuildDirectoryTree(directoryEntry.Offset, directoryTreeNode, recordOffsets); } return; } if (recordOffsets[fileOffset] is FileRecord) { FileRecord fileRecord = recordOffsets[fileOffset] as FileRecord; fileRecord.ContainingDirectory = root; root.Files.Add(fileRecord); } }
/// <summary> /// Builds a directory tree by traversing the list of record headers found in the pack file /// </summary> /// <returns>Root node of directory tree</returns> private DirectoryTreeNode BuildDirectoryTree() { var ggpkRecord = RecordOffsets[0] as GgpkRecord; if (ggpkRecord == null) throw new Exception("First record isn't GGPK record"); // First level only contains a empty string name directory record and a free record var rootDirectoryOffset = ggpkRecord.RecordOffsets .Where(RecordOffsets.ContainsKey).FirstOrDefault(o => RecordOffsets[o] is DirectoryRecord); if (rootDirectoryOffset == 0) // default value throw new Exception("Couldn't find root directory offset"); var firstDirectory = RecordOffsets[rootDirectoryOffset] as DirectoryRecord; if (firstDirectory == null) throw new Exception("Couldn't find root directory record"); var root = new DirectoryTreeNode { Children = new List<DirectoryTreeNode>(), Files = new List<FileRecord>(), Name = "ROOT", Parent = null, Record = firstDirectory, }; // start building files tree foreach (var item in firstDirectory.Entries) { BuildDirectoryTree(item, root); } return root; }
public void DeleteDirectoryRecord(DirectoryTreeNode dir) { var parent = dir.Parent; if (parent == null) // root directory return; parent.RemoveDirectory(dir); }
/// <summary> /// Creates a directory tree using the parsed record headers and offsets /// </summary> /// <param name="output">Output function</param> private void CreateDirectoryTree(Action <string> output) { DirectoryRoot = BuildDirectoryTree(); output(String.Format("Found {0} directories and {1} files", _directories.Count, _files.Count) + Environment.NewLine); FreeRoot = BuildFreeList(); output(String.Format("Found {0} FREE records", _freeRecords.Count) + Environment.NewLine); }
/// <summary> /// Builds a directory tree by traversing the list of record headers found in the pack file /// </summary> /// <param name="recordOffsets">Map of record offsets and headers to create directory tree from</param> /// <returns>Root node of directory tree</returns> internal static DirectoryTreeNode BuildDirectoryTree(Dictionary<long, BaseRecord> recordOffsets) { // This offset is a directory, add it as a child of root and process all of it's entries GGPKRecord currentDirectory = recordOffsets[0] as GGPKRecord; DirectoryTreeNode root = new DirectoryTreeNode() { Children = new List<DirectoryTreeNode>(), Files = new List<FileRecord>(), Name = "", Parent = null, Record = null, }; // First level only contains a empty string name directory record and a free record foreach (var Offset in currentDirectory.RecordOffsets) { if (!recordOffsets.ContainsKey(Offset)) { continue; } if (recordOffsets[Offset] is DirectoryRecord) { DirectoryRecord firstDirectory = recordOffsets[Offset] as DirectoryRecord; foreach (var item in firstDirectory.Entries) { BuildDirectoryTree(item, root, recordOffsets); } } } return root; }
/// <summary> /// Recursivly creates a directory tree by traversing PDIR records. Adds FILE records to the current directory /// tree node. Recursivly traverses PDIR records and adds them to the current directory tree node's children. /// </summary> /// <param name="directoryEntry">Directory Entry</param> /// <param name="root">Parent node</param> private void BuildDirectoryTree(DirectoryRecord.DirectoryEntry directoryEntry, DirectoryTreeNode root) { if (!RecordOffsets.ContainsKey(directoryEntry.Offset)) { return; // TODO throw error } if (RecordOffsets[directoryEntry.Offset] is DirectoryRecord) { // This offset is a directory, add it as a child of root and process all of it's entries var currentDirectory = RecordOffsets[directoryEntry.Offset] as DirectoryRecord; _directories.Add(currentDirectory); var child = new DirectoryTreeNode { Name = currentDirectory.Name, Parent = root, Children = new List <DirectoryTreeNode>(), Files = new List <FileRecord>(), Record = currentDirectory, }; root.Children.Add(child); foreach (var entry in currentDirectory.Entries) { BuildDirectoryTree(entry, child); } } else if (RecordOffsets[directoryEntry.Offset] is FileRecord) { var currentFile = RecordOffsets[directoryEntry.Offset] as FileRecord; _files.Add(currentFile); currentFile.ContainingDirectory = root; root.Files.Add(currentFile); } }
/// <summary> /// Creates a directory tree using the parsed record headers and offsets /// </summary> /// <param name="output">Output function</param> private void CreateDirectoryTree(Action <string> output) { if (output == null) { throw new ArgumentNullException(nameof(output)); } DirectoryRoot = DirectoryTreeMaker.BuildDirectoryTree(RecordOffsets); FreeRoot = FreeListMaker.BuildFreeList(RecordOffsets); }
public void RemoveDirectory(DirectoryTreeNode dir) { if (!Children.Contains(dir)) { throw new Exception("Tried to removed directory than not belong to this directory: " + Name); } // remove from DirectoryTreeNode Children.Remove(dir); // remove from DirectoryRecord var entry = Record.Entries.FirstOrDefault(n => n.Offset == dir.Record.RecordBegin); Record.Entries.Remove(entry); }
/// <summary> /// Traverses a directory tree in PostOrder (Traverse children, then preform directory action) and preforms actions on the files and directories /// </summary> /// <param name="root">Root of directory tree</param> /// <param name="directoryAction">Action to preform on each directory</param> /// <param name="fileAction">Action to preform on each file</param> public static void TraverseTreePostorder(DirectoryTreeNode root, Action <DirectoryTreeNode> directoryAction, Action <FileRecord> fileAction) { foreach (var childDirectory in root.Children) { TraverseTreePostorder(childDirectory, directoryAction, fileAction); directoryAction?.Invoke(childDirectory); } if (fileAction != null) { foreach (var file in root.Files) { fileAction(file); } } }
public static void TraverseTreePostorder(DirectoryTreeNode root, Action <DirectoryTreeNode> directoryAction, Action <FileRecord> fileAction) { foreach (DirectoryTreeNode current in root.Children) { DirectoryTreeNode.TraverseTreePostorder(current, directoryAction, fileAction); if (directoryAction != null) { directoryAction(current); } } if (fileAction != null) { foreach (FileRecord current2 in root.Files) { fileAction(current2); } } }
/// <summary> /// Traverses a directory tree in PostOrder (Preform directory action, then traverse children) and preforms actions on the files and directories /// </summary> /// <param name="root">Root of directory tree</param> /// <param name="directoryAction">Action to preform on each directory</param> /// <param name="fileAction">Action to preform on each file</param> public static void TraverseTreePreorder(DirectoryTreeNode root, Action<DirectoryTreeNode> directoryAction, Action<FileRecord> fileAction) { foreach (var childDirectory in root.Children) { if (directoryAction != null) { directoryAction(childDirectory); } TraverseTreePreorder(childDirectory, directoryAction, fileAction); } if (fileAction != null) { foreach (var file in root.Files) { fileAction(file); } } }
internal static DirectoryTreeNode BuildDirectoryTree(Dictionary <long, BaseRecord> recordOffsets) { GGPKRecord gGPKRecord = recordOffsets[0L] as GGPKRecord; DirectoryTreeNode directoryTreeNode = new DirectoryTreeNode { Children = new List <DirectoryTreeNode>(), Files = new List <FileRecord>(), Name = "ROOT", Parent = null, Record = null }; long[] recordOffsets2 = gGPKRecord.RecordOffsets; for (int i = 0; i < recordOffsets2.Length; i++) { long fileOffset = recordOffsets2[i]; DirectoryTreeMaker.BuildDirectoryTree(fileOffset, directoryTreeNode, recordOffsets); } return(directoryTreeNode); }
/// <summary> /// Recursivly creates a directory tree by traversing PDIR records. Adds FILE records to the current directory /// tree node. Recursivly traverses PDIR records and adds them to the current directory tree node's children. /// </summary> /// <param name="directoryEntry">Directory Entry</param> /// <param name="root">Parent node</param> /// <param name="recordOffsets">Map of record offsets and headers to create directory tree from</param> private static void BuildDirectoryTree(DirectoryRecord.DirectoryEntry directoryEntry, DirectoryTreeNode root, IReadOnlyDictionary <long, BaseRecord> recordOffsets) { if (!recordOffsets.ContainsKey(directoryEntry.Offset)) { return; } var record = recordOffsets[directoryEntry.Offset] as DirectoryRecord; if (record != null) { // This offset is a directory, add it as a child of root and process all of it's entries DirectoryRecord currentDirectory = record; DirectoryTreeNode child = new DirectoryTreeNode { Name = currentDirectory.Name, Parent = root, Children = new List <DirectoryTreeNode>(), Files = new List <FileRecord>(), Record = currentDirectory, }; root.Children.Add(child); foreach (var entry in currentDirectory.Entries) { BuildDirectoryTree(entry, child, recordOffsets); } } else { var file = recordOffsets[directoryEntry.Offset] as FileRecord; if (file == null) { return; } FileRecord currentFile = file; currentFile.ContainingDirectory = root; root.Files.Add(currentFile); } }
public string GetDirectoryPath() { if (this.directoryPath != null) { return(this.directoryPath); } Stack <string> stack = new Stack <string>(); StringBuilder stringBuilder = new StringBuilder(); DirectoryTreeNode directoryTreeNode = this.ContainingDirectory; while (directoryTreeNode != null && directoryTreeNode.Name.Length > 0) { stack.Push(directoryTreeNode.Name); directoryTreeNode = directoryTreeNode.Parent; } foreach (string current in stack) { stringBuilder.Append(current + Path.DirectorySeparatorChar); } this.directoryPath = stringBuilder.ToString(); return(this.directoryPath); }
/// <summary> /// Traverses a directory tree in PostOrder (Preform directory action, then traverse children) /// and preforms actions on the files and directories /// </summary> /// <param name="root">Root of directory tree</param> /// <param name="directoryAction">Action to preform on each directory</param> /// <param name="fileAction">Action to preform on each file</param> public static void TraverseTreePreorder( DirectoryTreeNode root, Action <DirectoryTreeNode> directoryAction, Action <FileRecord> fileAction) { foreach (var childDirectory in root.Children) { if (directoryAction != null) { directoryAction(childDirectory); } TraverseTreePreorder(childDirectory, directoryAction, fileAction); } if (fileAction == null) { return; } foreach (var file in root.Files) { fileAction(file); } }
/// <summary> /// Recursivly creates a directory tree by traversing PDIR records. Adds FILE records to the current directory /// tree node. Recursivly traverses PDIR records and adds them to the current directory tree node's children. /// </summary> /// <param name="directoryEntry">Directory Entry</param> /// <param name="root">Parent node</param> /// <param name="recordOffsets">Map of record offsets and headers to create directory tree from</param> private static void BuildDirectoryTree(DirectoryRecord.DirectoryEntry directoryEntry, DirectoryTreeNode root, Dictionary <long, BaseRecord> recordOffsets) { if (!recordOffsets.ContainsKey(directoryEntry.Offset)) { return; } if (recordOffsets[directoryEntry.Offset] is DirectoryRecord) { // This offset is a directory, add it as a child of root and process all of it's entries DirectoryRecord currentDirectory = recordOffsets[directoryEntry.Offset] as DirectoryRecord; DirectoryTreeNode child = new DirectoryTreeNode() { Name = currentDirectory.Name, Parent = root, Children = new List <DirectoryTreeNode>(), Files = new List <FileRecord>(), Record = currentDirectory, }; root.Children.Add(child); foreach (var entry in currentDirectory.Entries) { BuildDirectoryTree(entry, child, recordOffsets); } } else if (recordOffsets[directoryEntry.Offset] is FileRecord) { FileRecord currentFile = recordOffsets[directoryEntry.Offset] as FileRecord; // Skip empty .dat Files under Data/ //if (root.Name.Equals("Data") && currentFile.DataLength == 12) // return; currentFile.ContainingDirectory = root; root.Files.Add(currentFile); } }
/// <summary> /// Recursivly creates a directory tree by traversing PDIR records. Adds FILE records to the current directory /// tree node. Recursivly traverses PDIR records and adds them to the current directory tree node's children. /// </summary> /// <param name="directoryEntry">Directory Entry</param> /// <param name="root">Parent node</param> /// <param name="recordOffsets">Map of record offsets and headers to create directory tree from</param> private static void BuildDirectoryTree(DirectoryRecord.DirectoryEntry directoryEntry, DirectoryTreeNode root, Dictionary<long, BaseRecord> recordOffsets) { if (!recordOffsets.ContainsKey(directoryEntry.Offset)) { return; } if (recordOffsets[directoryEntry.Offset] is DirectoryRecord) { // This offset is a directory, add it as a child of root and process all of it's entries DirectoryRecord currentDirectory = recordOffsets[directoryEntry.Offset] as DirectoryRecord; DirectoryTreeNode child = new DirectoryTreeNode() { Name = currentDirectory.Name, Parent = root, Children = new List<DirectoryTreeNode>(), Files = new List<FileRecord>(), Record = currentDirectory, }; root.Children.Add(child); foreach (var entry in currentDirectory.Entries) { BuildDirectoryTree(entry, child, recordOffsets); } } else if (recordOffsets[directoryEntry.Offset] is FileRecord) { FileRecord currentFile = recordOffsets[directoryEntry.Offset] as FileRecord; // Skip empty .dat Files under Data/ //if (root.Name.Equals("Data") && currentFile.DataLength == 12) // return; currentFile.ContainingDirectory = root; root.Files.Add(currentFile); } }
/// <summary> /// Creates a directory tree using the parsed record headers and offsets /// </summary> /// <param name="output">Output function</param> private void CreateDirectoryTree(Action<string> output) { DirectoryRoot = DirectoryTreeMaker.BuildDirectoryTree(RecordOffsets); FreeRoot = FreeListMaker.BuildFreeList(RecordOffsets); }
public void Save(string pathToGgpkNew, Action <string> output) { if (output != null) { output("Saving GGPK..." + Environment.NewLine); } FileStream readStream; FileStream writeStream; using (readStream = File.OpenRead(_pathToGppk)) using (writeStream = File.OpenWrite(pathToGgpkNew)) { var reader = new BinaryReader(readStream); var writer = new BinaryWriter(writeStream); var ggpkRecord = RecordOffsets[0] as GgpkRecord; if (ggpkRecord == null) { throw new Exception("First record isn't GGPK record"); } // Skip GGPK record for now writer.Seek((int)ggpkRecord.Length, SeekOrigin.Begin); // recursively write files and folders records var changedOffsets = new Dictionary <long, long>(); var previousPercentComplete = 0.0; var fileCopied = 0.0; DirectoryTreeNode.TraverseTreePostorder( DirectoryRoot, dir => dir.Record.Write(writer, changedOffsets), file => { var data = file.ReadFileContent(reader); file.Write(writer, changedOffsets); writer.Write(data); fileCopied++; var percentComplete = fileCopied / _files.Count; if (!(percentComplete - previousPercentComplete >= 0.05f)) { return; } if (output != null) { output(String.Format(" {0:00.00}%", 100.0 * percentComplete)); } previousPercentComplete = percentComplete; }); if (output != null) { output(" 100%"); } // write root directory var rootDirectoryOffset = writer.BaseStream.Position; DirectoryRoot.Record.Write(writer, changedOffsets); // write single Free record var firstFreeRecordOffset = writer.BaseStream.Position; var freeRecord = new FreeRecord(16, firstFreeRecordOffset, 0); freeRecord.Write(writer, null); // write GGPK record writer.Seek(0, SeekOrigin.Begin); var ggpkRecordNew = new GgpkRecord(ggpkRecord.Length); ggpkRecordNew.RecordOffsets[0] = rootDirectoryOffset; ggpkRecordNew.RecordOffsets[1] = firstFreeRecordOffset; ggpkRecordNew.Write(writer, changedOffsets); if (output != null) { output("Finished !!!"); } } }
/// <summary> /// Exports entire DirectoryTreeNode to disk, preserving directory structure /// </summary> /// <param name="selectedDirectoryNode">Node to export to disk</param> private void ExportAllItemsInDirectory(DirectoryTreeNode selectedDirectoryNode) { List<FileRecord> recordsToExport = new List<FileRecord>(); Action<FileRecord> fileAction = new Action<FileRecord>(recordsToExport.Add); DirectoryTreeNode.TraverseTreePreorder(selectedDirectoryNode, null, fileAction); try { SaveFileDialog saveFileDialog = new SaveFileDialog(); saveFileDialog.FileName = Settings.Strings["ExportAllItemsInDirectory_Default_FileName"]; if (saveFileDialog.ShowDialog() == true) { string exportDirectory = Path.GetDirectoryName(saveFileDialog.FileName) + Path.DirectorySeparatorChar; foreach (var item in recordsToExport) { item.ExtractFileWithDirectoryStructure(ggpkPath, exportDirectory); } MessageBox.Show(string.Format(Settings.Strings["ExportAllItemsInDirectory_Successful"], recordsToExport.Count), Settings.Strings["ExportAllItemsInDirectory_Successful_Caption"], MessageBoxButton.OK, MessageBoxImage.Information); } } catch (Exception ex) { MessageBox.Show(string.Format(Settings.Strings["ExportAllItemsInDirectory_Failed"], ex.Message), Settings.Strings["Error_Caption"], MessageBoxButton.OK, MessageBoxImage.Error); } }
private void CreateDirectoryTree(Action <string> output) { this.DirectoryRoot = DirectoryTreeMaker.BuildDirectoryTree(this.RecordOffsets); this.FreeRoot = FreeListMaker.BuildFreeList(this.RecordOffsets); }