diff --git a/BinaryObjectScanner/FileType/RAR.cs b/BinaryObjectScanner/FileType/RAR.cs
index 3a33c19e..277534c0 100644
--- a/BinaryObjectScanner/FileType/RAR.cs
+++ b/BinaryObjectScanner/FileType/RAR.cs
@@ -4,6 +4,7 @@
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
+using SharpCompress.Common;
using SharpCompress.Readers;
#endif
@@ -51,36 +52,11 @@ public bool Extract(Stream? stream, string file, string outDir, bool lookForHead
if (!rarFile.IsComplete)
return false;
- foreach (var entry in rarFile.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(outDir, 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);
- }
- }
+ if (rarFile.IsSolid)
+ return ExtractSolid(rarFile, outDir, includeDebug);
+ else
+ return ExtractNonSolid(rarFile, outDir, includeDebug);
- return true;
}
catch (Exception ex)
{
@@ -91,5 +67,71 @@ public bool Extract(Stream? stream, string file, string outDir, bool lookForHead
return false;
#endif
}
+
+#if NET462_OR_GREATER || NETCOREAPP
+
+ ///
+ /// Extraction method for non-solid archives. This iterates over each entry in the archive to extract every
+ /// file individually, in order to extract all valid files from the archive.
+ ///
+ private bool ExtractNonSolid(RarArchive rarFile, string outDir, bool includeDebug)
+ {
+ foreach (var entry in rarFile.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(outDir, 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 true;
+ }
+
+ ///
+ /// Extraction method for solid archives. Uses ExtractAllEntries because extraction for solid archives must be
+ /// done sequentially, and files beyond a corrupted point in a solid archive will be unreadable anyways.
+ ///
+ private bool ExtractSolid(RarArchive rarFile, string outDir, bool includeDebug)
+ {
+ try
+ {
+ if (!Directory.Exists(outDir))
+ Directory.CreateDirectory(outDir);
+
+ rarFile.WriteToDirectory(outDir, new ExtractionOptions()
+ {
+ ExtractFullPath = true,
+ Overwrite = true,
+ });
+
+ }
+ catch (Exception ex)
+ {
+ if (includeDebug) Console.WriteLine(ex);
+ }
+
+ return true;
+ }
+#endif
}
-}
+}
\ No newline at end of file
diff --git a/BinaryObjectScanner/FileType/SevenZip.cs b/BinaryObjectScanner/FileType/SevenZip.cs
index 850ad250..04fcfab2 100644
--- a/BinaryObjectScanner/FileType/SevenZip.cs
+++ b/BinaryObjectScanner/FileType/SevenZip.cs
@@ -4,6 +4,7 @@
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
+using SharpCompress.Common;
using SharpCompress.Readers;
#endif
@@ -43,50 +44,91 @@ public bool Extract(Stream? stream, string file, string outDir, bool lookForHead
{
var readerOptions = new ReaderOptions() { LookForHeader = lookForHeader };
var sevenZip = SevenZipArchive.Open(stream, readerOptions);
-
// Try to read the file path if no entries are found
if (sevenZip.Entries.Count == 0 && !string.IsNullOrEmpty(file) && File.Exists(file))
sevenZip = SevenZipArchive.Open(file, readerOptions);
- foreach (var entry in sevenZip.Entries)
+ // Currently doesn't flag solid 7z archives with only 1 solid block as solid, but practically speaking
+ // this is not much of a concern.
+ if (sevenZip.IsSolid)
+ return ExtractSolid(sevenZip, outDir, includeDebug);
+ else
+ return ExtractNonSolid(sevenZip, outDir, includeDebug);
+
+ }
+ catch (Exception ex)
+ {
+ if (includeDebug) Console.WriteLine(ex);
+ return false;
+ }
+#else
+ return false;
+#endif
+ }
+
+#if NET462_OR_GREATER || NETCOREAPP
+ ///
+ /// Extraction method for non-solid archives. This iterates over each entry in the archive to extract every
+ /// file individually, in order to extract all valid files from the archive.
+ ///
+ private bool ExtractNonSolid(SevenZipArchive sevenZip, string outDir, bool includeDebug)
+ {
+ foreach (var entry in sevenZip.Entries)
+ {
+ try
{
- try
- {
- // If the entry is a directory
- if (entry.IsDirectory)
- continue;
+ // If the entry is a directory
+ if (entry.IsDirectory)
+ continue;
- // If the entry has an invalid key
- if (entry.Key == null)
- 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;
+ // If we have a partial entry due to an incomplete multi-part archive, skip it
+ if (!entry.IsComplete)
+ continue;
- string tempFile = Path.Combine(outDir, entry.Key);
- var directoryName = Path.GetDirectoryName(tempFile);
- if (directoryName != null && !Directory.Exists(directoryName))
- Directory.CreateDirectory(directoryName);
+ string tempFile = Path.Combine(outDir, 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);
- }
+ entry.WriteToFile(tempFile);
+ }
+ catch (Exception ex)
+ {
+ if (includeDebug) Console.WriteLine(ex);
}
-
- return true;
+ }
+ return true;
+ }
+
+ ///
+ /// Extraction method for solid archives. Uses ExtractAllEntries because extraction for solid archives must be
+ /// done sequentially, and files beyond a corrupted point in a solid archive will be unreadable anyways.
+ ///
+ private bool ExtractSolid(SevenZipArchive sevenZip, string outDir, bool includeDebug)
+ {
+ try
+ {
+ if (!Directory.Exists(outDir))
+ Directory.CreateDirectory(outDir);
+
+ sevenZip.WriteToDirectory(outDir, new ExtractionOptions()
+ {
+ ExtractFullPath = true,
+ Overwrite = true,
+ });
+
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
- return false;
}
-#else
- return false;
-#endif
+
+ return true;
}
+#endif
}
-}
+}
\ No newline at end of file