Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 72 additions & 30 deletions BinaryObjectScanner/FileType/RAR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
using SharpCompress.Common;
using SharpCompress.Readers;
#endif

Expand Down Expand Up @@ -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)
{
Expand All @@ -91,5 +67,71 @@ public bool Extract(Stream? stream, string file, string outDir, bool lookForHead
return false;
#endif
}

#if NET462_OR_GREATER || NETCOREAPP

/// <summary>
/// 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.
/// </summary>
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;
}

/// <summary>
/// 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.
/// </summary>
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
}
}
}
102 changes: 72 additions & 30 deletions BinaryObjectScanner/FileType/SevenZip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#if NET462_OR_GREATER || NETCOREAPP
using SharpCompress.Archives;
using SharpCompress.Archives.SevenZip;
using SharpCompress.Common;
using SharpCompress.Readers;
#endif

Expand Down Expand Up @@ -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
/// <summary>
/// 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.
/// </summary>
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;
}

/// <summary>
/// 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.
/// </summary>
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
}
}
}
Loading