/// <summary> /// Extract all files from absolute path. /// </summary> /// <param name="fullpath">Absolute path to a file in a PAK archive.</param> public void ExtractFile(string fullpath) { string pakFilePath = Regex.Match(fullpath, ".*.pak").Value; string fileMatch = Path.GetFileName(Regex.Replace(fullpath, ".*.pak", "").Trim()); PakReader?.Dispose(); PakReader = new PakReader(pakFilePath); byte[] fileBytes = PakReader.GetFile(fileMatch); Encdec.ConsoleInfo.LogWait(Level.Info, "{Extract} " + fileMatch); if (fileBytes != null) { FileInfo f = new FileInfo(Path.Combine(Program.Arguments.Input, Path.GetFileNameWithoutExtension(pakFilePath), fileMatch).Replace("/", "\\")); f.Directory.Create(); if (!File.Exists(f.FullName)) { File.WriteAllBytes(f.FullName, fileBytes); } else { int idx = 1; string newPath; while (File.Exists(newPath = Path.Combine(f.Directory.FullName, Path.GetFileNameWithoutExtension(f.Name) + "_" + idx + f.Extension))) { idx++; } File.WriteAllBytes(newPath, fileBytes); } } }
private string GetPakFileListing(string filename) { using (var pr = new PakReader(filename)) { return(string.Join("\r\n", pr.Files.Keys.OrderBy(o => o))); } }
private void PreviewFileFromPakEntryInfo(PakEntryInfo pakEntry) { using (var pr = new PakReader(pakEntry.PakFile)) { switch (GetPreviewTypeFromFilename(pakEntry.EntryFilename)) { case PreviewType.Text: using (var ms = new MemoryStream(pr.GetFile(pakEntry.EntryFilename))) { var text = new StreamReader(ms).ReadToEnd(); ShowTextViewer(text); } break; case PreviewType.Html: using (var ms = new MemoryStream(pr.GetFile(pakEntry.EntryFilename))) { try { var text = EncryptedHtml.DecodeToString(pakEntry.EntryFilename, ms); ShowTextViewer(text); } catch { // maybe not encrypted, show raw text ms.Seek(0, SeekOrigin.Begin); var text = new StreamReader(ms).ReadToEnd(); ShowTextViewer(text); } } break; case PreviewType.Xml: using (var ms = new MemoryStream(pr.GetFile(pakEntry.EntryFilename))) { var text = new StreamReader(new AionXmlStreamReader(ms, true)).ReadToEnd(); ShowTextViewer(text); } break; case PreviewType.Image: using (var ms = new MemoryStream(pr.GetFile(pakEntry.EntryFilename))) { ShowImageViewer(ms); } break; case PreviewType.Cgf: using (var ms = new MemoryStream(pr.GetFile(pakEntry.EntryFilename))) { ShowCgfViewer(new CgfLoader(ms)); } break; default: break; } } }
private static void SaveFile(BinaryReader binaryReader, string directory, string subDirectory, PakItem item) { var path = Path.Combine(directory, subDirectory, item.Path.Substring(1)); var dir = Path.GetDirectoryName(path); Directory.CreateDirectory(dir); using (var fs = File.Open(path, FileMode.Create)) { var bytes = PakReader.ReadItem(binaryReader, item); fs.Write(bytes, 0, bytes.Length); } }
private static void ExtractPackage() { PakReader reader = null; try { reader = new PakReader(_pakFile); } catch (FileNotFoundException e) { _hasErrored = true; Console.Error.WriteLine(e.Message); Console.Error.WriteLine("File: '{0}'", e.FileName); } PakFile file = null; try { file = reader.Read(); } catch (PakReaderException e) { _hasErrored = true; Console.Error.WriteLine(e.Message); Console.Error.WriteLine("Reason: {0}", e.InnerException.Message); return; } if (_outputDir == "") { _outputDir = Path.GetDirectoryName(_pakFile); } for (int i = 0; i < file.Entries.Count; i++) { var entry = file.Entries[i]; entry.Extract(_outputDir); Console.WriteLine("[{0}/{1}] Extracted {2}", i + 1, file.Entries.Count, entry.ArchivePath); Thread.Sleep(10); } Console.WriteLine("Extracted all files successfully!"); }
// Rules: // - Filenames are lowercase and use backslash. // - Filenames include directories and are relative to the root path. // - .pak files are excluded from the listing since they get expanded. // - Files contained in .pak files take precedence over local files. // - The filemap maps relative paths to a PakReader. If PakReader is null, path is a local file. private SortedDictionary <string, PakReader> GenerateFileListing(string subpath) { var paksToLoad = new List <string>(); // load pak names and local files foreach (var path in Directory.EnumerateFiles(Path.Combine(m_rootPath, subpath), "*", SearchOption.AllDirectories)) { if (Path.GetExtension(path).Equals(".pak", StringComparison.OrdinalIgnoreCase)) { paksToLoad.Add(path); continue; } m_fileListing.Add(GetRelativePath(path), null); } // load filenames from pak, and map each to a PakReader. foreach (var pak in paksToLoad) { var pr = new PakReader(pak); foreach (var file in pr.Files.Keys) { string relativePath = GetRelativePath(Path.Combine(Path.GetDirectoryName(pak), file)); PakReader existing; if (m_fileListing.TryGetValue(relativePath, out existing)) { if (existing == null) { m_fileListing[relativePath] = pr; } // TODO aion gamedata has colliding names... (especially in levels/common) // how should that be handled? could check if models are the same. just ignoring for now... //else //Log.WriteLine("duplicate filename encountered: " + relativePath); //throw new InvalidOperationException("duplicate filename encountered: " + relativePath); } else { m_fileListing.Add(relativePath, pr); } } } return(m_fileListing); }
/// <summary> /// Fetches all items in the given pak. /// </summary> /// <param name="pakPath">File path to pak.</param> public void Fetch(string pakPath) { using (FileStream fs = File.Open(pakPath, FileMode.Open)) using (BinaryReader binaryReader = new BinaryReader(fs)) { PakReader reader = new PakReader(); PakData pak = reader.Read(binaryReader); foreach (PakItem item in pak.Items) { string ext = Path.GetExtension(item.Path); if (Extensions == null || Extensions.Count == 0 || ext.Length > 0 && Extensions.Contains(ext.Substring(1).ToLowerInvariant())) { byte[] data = PakReader.ReadItem(binaryReader, item); string s = Encoding.UTF8.GetString(data); OnItemFound?.Invoke(item.Path, s); } } } }
private static void Run(Options options) { var inp = options.InputPath; var outp = options.OutputPath; var save = !string.IsNullOrWhiteSpace(outp) && Directory.Exists(outp); var pat = options.Pattern; var isDirectory = Directory.Exists(inp); Console.WriteLine("Starbound - Asset Search"); Console.Write("- "); Console.Write($"{(isDirectory ? "Directory" : "File")}: ".PadLeft(11)); WriteColoredLine(ConsoleColor.Cyan, inp); Console.Write("- "); Console.Write("Pattern: ".PadLeft(11)); WriteColoredLine(ConsoleColor.Cyan, pat); if (save) { Console.Write("- "); Console.Write("Output: ".PadLeft(11)); WriteColoredLine(ConsoleColor.Cyan, outp); } Console.WriteLine("Starting search..."); // Get files var files = isDirectory ? GetPaks(options.InputPath) : File.Exists(inp) ? new[] { options.InputPath } : null; if (!(files?.Length > 0)) { Wait("No file(s) found."); return; } if (string.IsNullOrEmpty(pat)) { pat = "*"; } else if (!pat.Contains("/")) { pat = $"*/{pat}"; } pat = $"^{pat}$"; var pattern = new Regex(pat.Replace(".", "\\.").Replace('?', '.').Replace("*", ".*")); var reader = new PakReader(); // Scan files foreach (var file in files) { var fileName = Path.GetFileNameWithoutExtension(file); WriteColoredLine(ConsoleColor.Yellow, $"{file}"); using (var fs = File.Open(file, FileMode.Open)) using (var binaryReader = new BinaryReader(fs)) { var pak = reader.Read(binaryReader); foreach (var item in pak.Items) { if (!pattern.IsMatch(item.Path)) { continue; } Console.WriteLine($"- {item.Path}"); if (save) { SaveFile(binaryReader, outp, fileName, item); } } ; } //if (save) //WriteColoredLine(); } if (options.KeepOpen) { Wait("Press any key to exit..."); } }
private void PopulatePakTreeNode(TreeNode node) { var file = node.Tag as FileInfo; if (file == null) { return; } var ext = Path.GetExtension(file.Name); if (ext.Equals(".pak", StringComparison.InvariantCultureIgnoreCase)) { if (node.Nodes.Count == 1 && node.Nodes[0].Text == "Loading...") { node.Nodes.Clear(); using (var pr = new PakReader(node.FullPath)) { var filenames = pr.Files.Keys.OrderBy(o => o); // collect directories var subdirs = new List <string>(); foreach (var pakFilename in filenames) { var lastPathSep = pakFilename.LastIndexOf('/'); if (lastPathSep == -1) { continue; } subdirs.Add(pakFilename.Substring(0, lastPathSep)); } // build the directory structure var dirs = new Dictionary <string, TreeNode>(); foreach (var s in subdirs.Distinct().OrderBy(o => o)) { var curNode = node; string curFullDirName = ""; foreach (var dirName in s.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)) { curFullDirName += (curFullDirName == "" ? "" : "/") + dirName; if (curNode.Nodes.ContainsKey(dirName)) { curNode = curNode.Nodes[dirName]; continue; } var dirNode = new TreeNode(dirName); dirNode.Name = dirName; dirNode.ImageIndex = 1; dirNode.SelectedImageIndex = 1; curNode.Nodes.Add(dirNode); curNode = dirNode; dirs.Add(curFullDirName, dirNode); } } // insert the files foreach (var f in filenames) { TreeNode dir; var fileNode = new TreeNode(); var lastSlash = f.LastIndexOf('/'); if (lastSlash == -1) { dir = node; fileNode.Text = f; } else { dir = dirs[f.Substring(0, lastSlash)]; fileNode.Text = f.Substring(lastSlash + 1); } SetNodeIconFromFilename(fileNode, f); fileNode.Tag = new PakEntryInfo { PakFile = file.FullName, EntryFilename = f }; dir.Nodes.Add(fileNode); } } } } }
private void M_treeView_ItemDrag(object sender, ItemDragEventArgs e) { var node = e.Item as TreeNode; if (node == null) { return; } // TODO - drag start immediately copies the file, even if dragging within the app. should only copy if needed. // TODO - drag directory List <string> selection = new List <string>(); string tempfile = null; string tempdir = null; var file = node.Tag as FileInfo; if (file != null) { // just copy the file selection.Add(file.FullName); } else { var pei = node.Tag as PakEntryInfo; if (pei != null) { if (string.IsNullOrWhiteSpace(pei.EntryFilename) || pei.EntryFilename.EndsWith("\\") || pei.EntryFilename.EndsWith("/")) { return; } tempdir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); tempfile = Path.Combine(tempdir, pei.EntryFilename.Replace("/", "\\")); tempdir = Path.GetDirectoryName(tempfile); Directory.CreateDirectory(tempdir); var pr = new PakReader(pei.PakFile); File.WriteAllBytes(tempfile, pr.GetFile(pei.EntryFilename)); selection.Add(tempfile); } } if (!selection.Any()) { return; } DataObject data = new DataObject(DataFormats.FileDrop, selection.ToArray()); DoDragDrop(data, DragDropEffects.Copy); if (tempfile != null) { try { File.Delete(tempfile); Directory.Delete(tempdir); } catch { } } }
private string MakePathRelativeToPak(string relativePath, PakReader pr) { string relativeToPak = Path.GetDirectoryName(pr.OriginalPakPath).Substring(m_rootPath.Length); return(relativePath.Substring(relativeToPak.Length).TrimStart(new[] { '\\', '/' })); }