mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-08 18:06:34 +00:00
Add branching and specific SharpCompress calls for solid vs non-solid archives in order to extract solid archives properly. (#375)
* Add branching for solid vs non-solid archives in order to extract solid archives properly. * Change comments on sevenzip, reuse archive-level solid flag for rar * Fully simplify identifying if archive is solid. * Finish implementing first round of feedback. * Fix second round of formatting issues. * Final formatting fixes.
This commit is contained in:
committed by
GitHub
parent
dff15ef799
commit
249a17be1f
@@ -4,6 +4,7 @@ using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Readers;
|
||||
#endif
|
||||
|
||||
@@ -51,36 +52,11 @@ namespace BinaryObjectScanner.FileType
|
||||
if (!rarFile.IsComplete)
|
||||
return false;
|
||||
|
||||
foreach (var entry in rarFile.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
if (rarFile.IsSolid)
|
||||
return ExtractSolid(rarFile, outDir, includeDebug);
|
||||
else
|
||||
return ExtractNonSolid(rarFile, outDir, includeDebug);
|
||||
|
||||
// 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;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -91,5 +67,71 @@ namespace BinaryObjectScanner.FileType
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.SevenZip;
|
||||
using SharpCompress.Common;
|
||||
using SharpCompress.Readers;
|
||||
#endif
|
||||
|
||||
@@ -43,41 +44,17 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
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)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
// 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);
|
||||
|
||||
// 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;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -88,5 +65,70 @@ namespace BinaryObjectScanner.FileType
|
||||
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
|
||||
{
|
||||
// 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(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 true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user