From 54cb996fce2c67ec38f6fd01f19aee74208f6dc2 Mon Sep 17 00:00:00 2001 From: TheRogueArchivist <24215969+TheRogueArchivist@users.noreply.github.com> Date: Wed, 25 Sep 2024 22:30:25 -0600 Subject: [PATCH] [WIP] Add 7-Zip SFX extraction (#321) * Add 7-Zip SFX extraction Newest SharpCompress added support for extracting 7-Zip SFX files, so we can add support for them here too. * Clean up 7z SFX extraction method * Remove unneeded import * Use file instead of stream for 7z SFX * Update 7z SFX to be more consistent with other packers --- BinaryObjectScanner/Packer/SevenZipSFX.cs | 58 ++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/BinaryObjectScanner/Packer/SevenZipSFX.cs b/BinaryObjectScanner/Packer/SevenZipSFX.cs index 29614da0..71b3495e 100644 --- a/BinaryObjectScanner/Packer/SevenZipSFX.cs +++ b/BinaryObjectScanner/Packer/SevenZipSFX.cs @@ -1,10 +1,16 @@ +using System; +using System.IO; using System.Linq; using BinaryObjectScanner.Interfaces; using SabreTools.Serialization.Wrappers; +#if NET462_OR_GREATER || NETCOREAPP +using SharpCompress.Archives; +using SharpCompress.Archives.SevenZip; +using SharpCompress.Readers; +#endif namespace BinaryObjectScanner.Packer { - // TODO: Add extraction public class SevenZipSFX : IExtractablePortableExecutable, IPortableExecutableCheck { /// @@ -47,7 +53,57 @@ namespace BinaryObjectScanner.Packer /// public string? Extract(string file, PortableExecutable pex, bool includeDebug) { + if (!File.Exists(file)) + return null; + +#if NET462_OR_GREATER || NETCOREAPP + try + { + // Create a temp output directory + string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + Directory.CreateDirectory(tempPath); + + using (SevenZipArchive sevenZipFile = SevenZipArchive.Open(file, new ReaderOptions() { LookForHeader = true })) + { + foreach (var entry in sevenZipFile.Entries) + { + try + { + // If the entry is a directory + if (entry.IsDirectory) + continue; + + // If the entry has an invalid key + if (entry.Key == null) + continue; + + // If we have a partial entry due to an incomplete multi-part archive, skip it + if (!entry.IsComplete) + continue; + + string tempFile = Path.Combine(tempPath, entry.Key); + var directoryName = Path.GetDirectoryName(tempFile); + if (directoryName != null && !Directory.Exists(directoryName)) + Directory.CreateDirectory(directoryName); + entry.WriteToFile(tempFile); + } + catch (Exception ex) + { + if (includeDebug) Console.WriteLine(ex); + } + } + } + + return tempPath; + } + catch (Exception ex) + { + if (includeDebug) Console.WriteLine(ex); + return null; + } +#else return null; +#endif } } }