mirror of
https://github.com/claunia/SabreTools.git
synced 2025-12-16 19:14:27 +00:00
Create FileTypeTool and move static methods
This commit is contained in:
@@ -147,13 +147,13 @@ namespace SabreTools.DatTools
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Initialize possible archive variables
|
// Initialize possible archive variables
|
||||||
BaseArchive? archive = BaseArchive.Create(item);
|
BaseArchive? archive = FileTypeTool.CreateArchiveType(item);
|
||||||
|
|
||||||
// Process archives according to flags
|
// Process archives according to flags
|
||||||
if (archive != null)
|
if (archive != null)
|
||||||
{
|
{
|
||||||
// Set the archive flags
|
// Set the archive flags
|
||||||
archive.AvailableHashTypes = _hashes;
|
archive.SetHashTypes(_hashes);
|
||||||
|
|
||||||
// Skip if we're treating archives as files and skipping files
|
// Skip if we're treating archives as files and skipping files
|
||||||
#if NET20 || NET35
|
#if NET20 || NET35
|
||||||
@@ -406,7 +406,7 @@ namespace SabreTools.DatTools
|
|||||||
{
|
{
|
||||||
logger.Verbose($"'{Path.GetFileName(item)}' treated like a file");
|
logger.Verbose($"'{Path.GetFileName(item)}' treated like a file");
|
||||||
var header = datFile.Header.GetStringFieldValue(Models.Metadata.Header.HeaderKey);
|
var header = datFile.Header.GetStringFieldValue(Models.Metadata.Header.HeaderKey);
|
||||||
BaseFile? baseFile = BaseFile.GetInfo(item, header, _hashes, asFiles);
|
BaseFile? baseFile = FileTypeTool.GetInfo(item, header, _hashes, asFiles);
|
||||||
DatItem? datItem = DatItem.Create(baseFile);
|
DatItem? datItem = DatItem.Create(baseFile);
|
||||||
if (datItem != null)
|
if (datItem != null)
|
||||||
ProcessFileHelper(datFile, item, datItem, basePath, string.Empty);
|
ProcessFileHelper(datFile, item, datItem, basePath, string.Empty);
|
||||||
|
|||||||
@@ -311,19 +311,19 @@ namespace SabreTools.DatTools
|
|||||||
bool isSingleTorrent = tgz.IsTorrent() || txz.IsTorrent();
|
bool isSingleTorrent = tgz.IsTorrent() || txz.IsTorrent();
|
||||||
|
|
||||||
// Get the base archive first
|
// Get the base archive first
|
||||||
BaseArchive? archive = BaseArchive.Create(file);
|
BaseArchive? archive = FileTypeTool.CreateArchiveType(file);
|
||||||
|
|
||||||
// Now get all extracted items from the archive
|
// Now get all extracted items from the archive
|
||||||
if (archive != null)
|
if (archive != null)
|
||||||
{
|
{
|
||||||
archive.AvailableHashTypes = quickScan ? [HashType.CRC32] : [HashType.CRC32, HashType.MD5, HashType.SHA1];
|
archive.SetHashTypes(quickScan ? [HashType.CRC32] : [HashType.CRC32, HashType.MD5, HashType.SHA1]);
|
||||||
entries = archive.GetChildren();
|
entries = archive.GetChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the entries list is null, we encountered an error or have a file and should scan externally
|
// If the entries list is null, we encountered an error or have a file and should scan externally
|
||||||
if (entries == null && System.IO.File.Exists(file))
|
if (entries == null && System.IO.File.Exists(file))
|
||||||
{
|
{
|
||||||
BaseFile? internalFileInfo = BaseFile.GetInfo(file, asFiles: asFiles);
|
BaseFile? internalFileInfo = FileTypeTool.GetInfo(file, asFiles: asFiles);
|
||||||
|
|
||||||
// Create the correct DatItem
|
// Create the correct DatItem
|
||||||
DatItem? internalDatItem;
|
DatItem? internalDatItem;
|
||||||
@@ -498,7 +498,7 @@ namespace SabreTools.DatTools
|
|||||||
if (rule.TransformStream(fileStream, transformStream, keepReadOpen: true, keepWriteOpen: true))
|
if (rule.TransformStream(fileStream, transformStream, keepReadOpen: true, keepWriteOpen: true))
|
||||||
{
|
{
|
||||||
// Get the file informations that we will be using
|
// Get the file informations that we will be using
|
||||||
Rom headerless = new(BaseFile.GetInfo(transformStream, keepReadOpen: true));
|
Rom headerless = new(FileTypeTool.GetInfo(transformStream, keepReadOpen: true));
|
||||||
|
|
||||||
// If we have duplicates and we're not filtering
|
// If we have duplicates and we're not filtering
|
||||||
if (ShouldRebuild(datFile, headerless, transformStream, false, out dupes))
|
if (ShouldRebuild(datFile, headerless, transformStream, false, out dupes))
|
||||||
@@ -572,7 +572,7 @@ namespace SabreTools.DatTools
|
|||||||
string? machinename = null;
|
string? machinename = null;
|
||||||
|
|
||||||
// Get the item from the current file
|
// Get the item from the current file
|
||||||
Rom item = new(BaseFile.GetInfo(stream, keepReadOpen: true));
|
Rom item = new(FileTypeTool.GetInfo(stream, keepReadOpen: true));
|
||||||
item.GetFieldValue<Machine>(DatItem.MachineKey)!.SetFieldValue<string?>(Models.Metadata.Machine.DescriptionKey, Path.GetFileNameWithoutExtension(item.GetName()));
|
item.GetFieldValue<Machine>(DatItem.MachineKey)!.SetFieldValue<string?>(Models.Metadata.Machine.DescriptionKey, Path.GetFileNameWithoutExtension(item.GetName()));
|
||||||
item.GetFieldValue<Machine>(DatItem.MachineKey)!.SetFieldValue<string?>(Models.Metadata.Machine.NameKey, Path.GetFileNameWithoutExtension(item.GetName()));
|
item.GetFieldValue<Machine>(DatItem.MachineKey)!.SetFieldValue<string?>(Models.Metadata.Machine.NameKey, Path.GetFileNameWithoutExtension(item.GetName()));
|
||||||
|
|
||||||
@@ -629,7 +629,7 @@ namespace SabreTools.DatTools
|
|||||||
string? machinename = null;
|
string? machinename = null;
|
||||||
|
|
||||||
// Get the item from the current file
|
// Get the item from the current file
|
||||||
var item = new Rom(BaseFile.GetInfo(stream, keepReadOpen: true));
|
var item = new Rom(FileTypeTool.GetInfo(stream, keepReadOpen: true));
|
||||||
|
|
||||||
// Create a machine for the current item
|
// Create a machine for the current item
|
||||||
var machine = new Machine();
|
var machine = new Machine();
|
||||||
@@ -764,7 +764,7 @@ namespace SabreTools.DatTools
|
|||||||
// If we have a zipfile, extract the stream to memory
|
// If we have a zipfile, extract the stream to memory
|
||||||
if (isZip != null)
|
if (isZip != null)
|
||||||
{
|
{
|
||||||
BaseArchive? archive = BaseArchive.Create(file);
|
BaseArchive? archive = FileTypeTool.CreateArchiveType(file);
|
||||||
if (archive == null)
|
if (archive == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -823,7 +823,7 @@ namespace SabreTools.DatTools
|
|||||||
/// <returns>Folder configured with proper flags</returns>
|
/// <returns>Folder configured with proper flags</returns>
|
||||||
private static Folder? GetPreconfiguredFolder(DatFile datFile, bool date, OutputFormat outputFormat)
|
private static Folder? GetPreconfiguredFolder(DatFile datFile, bool date, OutputFormat outputFormat)
|
||||||
{
|
{
|
||||||
Folder? outputArchive = Folder.Create(outputFormat);
|
Folder? outputArchive = FileTypeTool.CreateFolderType(outputFormat);
|
||||||
if (outputArchive is BaseArchive baseArchive && date)
|
if (outputArchive is BaseArchive baseArchive && date)
|
||||||
baseArchive.UseDates = date;
|
baseArchive.UseDates = date;
|
||||||
|
|
||||||
|
|||||||
@@ -105,16 +105,16 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
catch (EndOfStreamException ex)
|
catch (EndOfStreamException ex)
|
||||||
{
|
{
|
||||||
// Catch this but don't count it as an error because SharpCompress is unsafe
|
// Catch this but don't count it as an error because SharpCompress is unsafe
|
||||||
logger.Verbose(ex);
|
_logger.Verbose(ex);
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
logger.Warning(ex);
|
_logger.Warning(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
BaseFile gzipEntryRom = new();
|
BaseFile gzipEntryRom = new();
|
||||||
|
|
||||||
// Perform a quickscan, if flagged to
|
// Perform a quickscan, if flagged to
|
||||||
if (AvailableHashTypes.Length == 1 && AvailableHashTypes[0] == HashType.CRC32)
|
if (_hashTypes.Length == 1 && _hashTypes[0] == HashType.CRC32)
|
||||||
{
|
{
|
||||||
gzipEntryRom.Filename = gamename;
|
gzipEntryRom.Filename = gamename;
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
var gz = new gZip();
|
var gz = new gZip();
|
||||||
ZipReturn ret = gz.ZipFileOpen(Filename);
|
ZipReturn ret = gz.ZipFileOpen(Filename);
|
||||||
ret = gz.ZipFileOpenReadStream(0, out Stream? gzstream, out ulong streamSize);
|
ret = gz.ZipFileOpenReadStream(0, out Stream? gzstream, out ulong streamSize);
|
||||||
gzipEntryRom = GetInfo(gzstream, hashes: AvailableHashTypes);
|
gzipEntryRom = GetInfo(gzstream, hashes: _hashTypes);
|
||||||
gzipEntryRom.Filename = gz.GetLocalFile(0).Filename;
|
gzipEntryRom.Filename = gz.GetLocalFile(0).Filename;
|
||||||
gzipEntryRom.Parent = gamename;
|
gzipEntryRom.Parent = gamename;
|
||||||
gzipEntryRom.Date = (gz.TimeStamp > 0 ? gz.TimeStamp.ToString() : null);
|
gzipEntryRom.Date = (gz.TimeStamp > 0 ? gz.TimeStamp.ToString() : null);
|
||||||
@@ -252,7 +252,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,21 +279,21 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
// If we have the romba depot files, just skip them gracefully
|
// If we have the romba depot files, just skip them gracefully
|
||||||
if (datum == ".romba_size" || datum == ".romba_size.backup")
|
if (datum == ".romba_size" || datum == ".romba_size.backup")
|
||||||
{
|
{
|
||||||
logger.Verbose($"Romba depot file found, skipping: {Filename}");
|
_logger.Verbose($"Romba depot file found, skipping: {Filename}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the name is the right length
|
// Check if the name is the right length
|
||||||
if (!Regex.IsMatch(datum, @"^[0-9a-f]{" + Constants.SHA1Length + @"}\.gz"))
|
if (!Regex.IsMatch(datum, @"^[0-9a-f]{" + Constants.SHA1Length + @"}\.gz"))
|
||||||
{
|
{
|
||||||
logger.Warning($"Non SHA-1 filename found, skipping: '{Path.GetFullPath(Filename)}'");
|
_logger.Warning($"Non SHA-1 filename found, skipping: '{Path.GetFullPath(Filename)}'");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the file is at least the minimum length
|
// Check if the file is at least the minimum length
|
||||||
if (filesize < 40 /* bytes */)
|
if (filesize < 40 /* bytes */)
|
||||||
{
|
{
|
||||||
logger.Warning($"Possibly corrupt file '{Path.GetFullPath(Filename)}' with size {filesize}");
|
_logger.Warning($"Possibly corrupt file '{Path.GetFullPath(Filename)}' with size {filesize}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,21 +340,21 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
// If we have the romba depot files, just skip them gracefully
|
// If we have the romba depot files, just skip them gracefully
|
||||||
if (datum == ".romba_size" || datum == ".romba_size.backup")
|
if (datum == ".romba_size" || datum == ".romba_size.backup")
|
||||||
{
|
{
|
||||||
logger.Verbose($"Romba depot file found, skipping: {Filename}");
|
_logger.Verbose($"Romba depot file found, skipping: {Filename}");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the name is the right length
|
// Check if the name is the right length
|
||||||
if (!Regex.IsMatch(datum, @"^[0-9a-f]{" + Constants.SHA1Length + @"}\.gz"))
|
if (!Regex.IsMatch(datum, @"^[0-9a-f]{" + Constants.SHA1Length + @"}\.gz"))
|
||||||
{
|
{
|
||||||
logger.Warning($"Non SHA-1 filename found, skipping: '{Path.GetFullPath(Filename)}'");
|
_logger.Warning($"Non SHA-1 filename found, skipping: '{Path.GetFullPath(Filename)}'");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the file is at least the minimum length
|
// Check if the file is at least the minimum length
|
||||||
if (filesize < 40 /* bytes */)
|
if (filesize < 40 /* bytes */)
|
||||||
{
|
{
|
||||||
logger.Warning($"Possibly corrupt file '{Path.GetFullPath(Filename)}' with size {filesize}");
|
_logger.Warning($"Possibly corrupt file '{Path.GetFullPath(Filename)}' with size {filesize}");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +414,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
// Check that the input file exists
|
// Check that the input file exists
|
||||||
if (!File.Exists(inputFile))
|
if (!File.Exists(inputFile))
|
||||||
{
|
{
|
||||||
logger.Warning($"File '{inputFile}' does not exist!");
|
_logger.Warning($"File '{inputFile}' does not exist!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,16 +67,16 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
catch (EndOfStreamException ex)
|
catch (EndOfStreamException ex)
|
||||||
{
|
{
|
||||||
// Catch this but don't count it as an error because SharpCompress is unsafe
|
// Catch this but don't count it as an error because SharpCompress is unsafe
|
||||||
logger.Verbose(ex);
|
_logger.Verbose(ex);
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
logger.Warning(ex);
|
_logger.Warning(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -201,7 +201,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
BaseFile rarEntryRom = new();
|
BaseFile rarEntryRom = new();
|
||||||
|
|
||||||
// Perform a quickscan, if flagged to
|
// Perform a quickscan, if flagged to
|
||||||
if (AvailableHashTypes.Length == 1 && AvailableHashTypes[0] == HashType.CRC32)
|
if (_hashTypes.Length == 1 && _hashTypes[0] == HashType.CRC32)
|
||||||
{
|
{
|
||||||
rarEntryRom.Size = entry.Size;
|
rarEntryRom.Size = entry.Size;
|
||||||
rarEntryRom.CRC = BitConverter.GetBytes(entry.Crc);
|
rarEntryRom.CRC = BitConverter.GetBytes(entry.Crc);
|
||||||
@@ -210,7 +210,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
using Stream entryStream = entry.OpenEntryStream();
|
using Stream entryStream = entry.OpenEntryStream();
|
||||||
rarEntryRom = GetInfo(entryStream, size: entry.Size, hashes: AvailableHashTypes);
|
rarEntryRom = GetInfo(entryStream, size: entry.Size, hashes: _hashTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in common details and add to the list
|
// Fill in common details and add to the list
|
||||||
@@ -225,7 +225,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +271,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return empties;
|
return empties;
|
||||||
|
|||||||
@@ -118,16 +118,16 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
catch (EndOfStreamException ex)
|
catch (EndOfStreamException ex)
|
||||||
{
|
{
|
||||||
// Catch this but don't count it as an error because SharpCompress is unsafe
|
// Catch this but don't count it as an error because SharpCompress is unsafe
|
||||||
logger.Verbose(ex);
|
_logger.Verbose(ex);
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
logger.Warning(ex);
|
_logger.Warning(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +221,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,7 +265,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
// If we get a read error, log it and continue
|
// If we get a read error, log it and continue
|
||||||
if (zr != ZipReturn.ZipGood)
|
if (zr != ZipReturn.ZipGood)
|
||||||
{
|
{
|
||||||
logger.Warning($"An error occurred while reading archive {Filename}: Zip Error - {zr}");
|
_logger.Warning($"An error occurred while reading archive {Filename}: Zip Error - {zr}");
|
||||||
zr = zf.ZipFileCloseReadStream();
|
zr = zf.ZipFileCloseReadStream();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -274,7 +274,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
BaseFile zipEntryRom = new();
|
BaseFile zipEntryRom = new();
|
||||||
|
|
||||||
// Perform a quickscan, if flagged to
|
// Perform a quickscan, if flagged to
|
||||||
if (AvailableHashTypes.Length == 1 && AvailableHashTypes[0] == HashType.CRC32)
|
if (_hashTypes.Length == 1 && _hashTypes[0] == HashType.CRC32)
|
||||||
{
|
{
|
||||||
zipEntryRom.Size = (long)zf.GetLocalFile(i).UncompressedSize;
|
zipEntryRom.Size = (long)zf.GetLocalFile(i).UncompressedSize;
|
||||||
zipEntryRom.CRC = zf.GetLocalFile(i).CRC;
|
zipEntryRom.CRC = zf.GetLocalFile(i).CRC;
|
||||||
@@ -282,7 +282,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
// Otherwise, use the stream directly
|
// Otherwise, use the stream directly
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
zipEntryRom = GetInfo(readStream, size: (long)zf.GetLocalFile(i).UncompressedSize, hashes: AvailableHashTypes, keepReadOpen: true);
|
zipEntryRom = GetInfo(readStream, size: (long)zf.GetLocalFile(i).UncompressedSize, hashes: _hashTypes, keepReadOpen: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in common details and add to the list
|
// Fill in common details and add to the list
|
||||||
@@ -297,7 +297,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,7 +347,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return empties;
|
return empties;
|
||||||
@@ -560,7 +560,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -774,7 +774,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,16 +68,16 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
catch (EndOfStreamException ex)
|
catch (EndOfStreamException ex)
|
||||||
{
|
{
|
||||||
// Catch this but don't count it as an error because SharpCompress is unsafe
|
// Catch this but don't count it as an error because SharpCompress is unsafe
|
||||||
logger.Verbose(ex);
|
_logger.Verbose(ex);
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
logger.Warning(ex);
|
_logger.Warning(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -194,7 +194,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
BaseFile tarEntryRom = new();
|
BaseFile tarEntryRom = new();
|
||||||
|
|
||||||
// Perform a quickscan, if flagged to
|
// Perform a quickscan, if flagged to
|
||||||
if (AvailableHashTypes.Length == 1 && AvailableHashTypes[0] == HashType.CRC32)
|
if (_hashTypes.Length == 1 && _hashTypes[0] == HashType.CRC32)
|
||||||
{
|
{
|
||||||
tarEntryRom.Size = entry.Size;
|
tarEntryRom.Size = entry.Size;
|
||||||
tarEntryRom.CRC = BitConverter.GetBytes(entry.Crc);
|
tarEntryRom.CRC = BitConverter.GetBytes(entry.Crc);
|
||||||
@@ -203,7 +203,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
using Stream entryStream = entry.OpenEntryStream();
|
using Stream entryStream = entry.OpenEntryStream();
|
||||||
tarEntryRom = GetInfo(entryStream, size: entry.Size, hashes: AvailableHashTypes);
|
tarEntryRom = GetInfo(entryStream, size: entry.Size, hashes: _hashTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in common details and add to the list
|
// Fill in common details and add to the list
|
||||||
@@ -218,7 +218,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +260,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return empties;
|
return empties;
|
||||||
@@ -409,7 +409,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -578,7 +578,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|||||||
@@ -80,16 +80,16 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
catch (EndOfStreamException ex)
|
catch (EndOfStreamException ex)
|
||||||
{
|
{
|
||||||
// Catch this but don't count it as an error because SharpCompress is unsafe
|
// Catch this but don't count it as an error because SharpCompress is unsafe
|
||||||
logger.Verbose(ex);
|
_logger.Verbose(ex);
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
logger.Warning(ex);
|
_logger.Warning(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -200,7 +200,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
BaseFile xzEntryRom = new();
|
BaseFile xzEntryRom = new();
|
||||||
|
|
||||||
// Perform a quickscan, if flagged to
|
// Perform a quickscan, if flagged to
|
||||||
if (AvailableHashTypes.Length == 1 && AvailableHashTypes[0] == HashType.CRC32)
|
if (_hashTypes.Length == 1 && _hashTypes[0] == HashType.CRC32)
|
||||||
{
|
{
|
||||||
xzEntryRom.Filename = gamename;
|
xzEntryRom.Filename = gamename;
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var xzStream = new XZStream(File.OpenRead(Filename!));
|
var xzStream = new XZStream(File.OpenRead(Filename!));
|
||||||
xzEntryRom = GetInfo(xzStream, hashes: AvailableHashTypes);
|
xzEntryRom = GetInfo(xzStream, hashes: _hashTypes);
|
||||||
xzEntryRom.Filename = gamename;
|
xzEntryRom.Filename = gamename;
|
||||||
xzStream.Dispose();
|
xzStream.Dispose();
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,7 +254,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
// Check if the name is the right length
|
// Check if the name is the right length
|
||||||
if (!Regex.IsMatch(datum, @"^[0-9a-f]{" + Constants.SHA1Length + @"}\.xz"))
|
if (!Regex.IsMatch(datum, @"^[0-9a-f]{" + Constants.SHA1Length + @"}\.xz"))
|
||||||
{
|
{
|
||||||
logger.Warning($"Non SHA-1 filename found, skipping: '{Path.GetFullPath(Filename)}'");
|
_logger.Warning($"Non SHA-1 filename found, skipping: '{Path.GetFullPath(Filename)}'");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +276,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
// Check if the name is the right length
|
// Check if the name is the right length
|
||||||
if (!Regex.IsMatch(datum, @"^[0-9a-f]{" + Constants.SHA1Length + @"}\.xz"))
|
if (!Regex.IsMatch(datum, @"^[0-9a-f]{" + Constants.SHA1Length + @"}\.xz"))
|
||||||
{
|
{
|
||||||
logger.Warning($"Non SHA-1 filename found, skipping: '{Path.GetFullPath(Filename)}'");
|
_logger.Warning($"Non SHA-1 filename found, skipping: '{Path.GetFullPath(Filename)}'");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +301,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
// Check that the input file exists
|
// Check that the input file exists
|
||||||
if (!File.Exists(inputFile))
|
if (!File.Exists(inputFile))
|
||||||
{
|
{
|
||||||
logger.Warning($"File '{inputFile}' does not exist!");
|
_logger.Warning($"File '{inputFile}' does not exist!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,16 +157,16 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
catch (EndOfStreamException ex)
|
catch (EndOfStreamException ex)
|
||||||
{
|
{
|
||||||
// Catch this but don't count it as an error because SharpCompress is unsafe
|
// Catch this but don't count it as an error because SharpCompress is unsafe
|
||||||
logger.Verbose(ex);
|
_logger.Verbose(ex);
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException ex)
|
catch (InvalidOperationException ex)
|
||||||
{
|
{
|
||||||
logger.Warning(ex);
|
_logger.Warning(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
encounteredErrors = true;
|
encounteredErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -345,7 +345,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
// If we get a read error, log it and continue
|
// If we get a read error, log it and continue
|
||||||
if (zr != ZipReturn.ZipGood || readStream == null)
|
if (zr != ZipReturn.ZipGood || readStream == null)
|
||||||
{
|
{
|
||||||
logger.Warning($"An error occurred while reading archive {Filename}: Zip Error - {zr}");
|
_logger.Warning($"An error occurred while reading archive {Filename}: Zip Error - {zr}");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
var zipEntryRom = new BaseFile();
|
var zipEntryRom = new BaseFile();
|
||||||
|
|
||||||
// Perform a quickscan, if flagged to
|
// Perform a quickscan, if flagged to
|
||||||
if (AvailableHashTypes.Length == 1 && AvailableHashTypes[0] == HashType.CRC32)
|
if (_hashTypes.Length == 1 && _hashTypes[0] == HashType.CRC32)
|
||||||
{
|
{
|
||||||
zipEntryRom.Size = (long)localFile.UncompressedSize;
|
zipEntryRom.Size = (long)localFile.UncompressedSize;
|
||||||
zipEntryRom.CRC = localFile.CRC;
|
zipEntryRom.CRC = localFile.CRC;
|
||||||
@@ -363,7 +363,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
{
|
{
|
||||||
zipEntryRom = GetInfo(readStream,
|
zipEntryRom = GetInfo(readStream,
|
||||||
size: (long)localFile.UncompressedSize,
|
size: (long)localFile.UncompressedSize,
|
||||||
hashes: AvailableHashTypes,
|
hashes: _hashTypes,
|
||||||
keepReadOpen: true);
|
keepReadOpen: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +406,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
var zipEntryRom = new BaseFile();
|
var zipEntryRom = new BaseFile();
|
||||||
|
|
||||||
// Perform a quickscan, if flagged to
|
// Perform a quickscan, if flagged to
|
||||||
if (AvailableHashTypes.Length == 1 && AvailableHashTypes[0] == HashType.CRC32)
|
if (_hashTypes.Length == 1 && _hashTypes[0] == HashType.CRC32)
|
||||||
{
|
{
|
||||||
zipEntryRom.Size = localFile.Length;
|
zipEntryRom.Size = localFile.Length;
|
||||||
#if NETCOREAPP
|
#if NETCOREAPP
|
||||||
@@ -420,7 +420,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
{
|
{
|
||||||
zipEntryRom = GetInfo(readStream,
|
zipEntryRom = GetInfo(readStream,
|
||||||
size: localFile.Length,
|
size: localFile.Length,
|
||||||
hashes: AvailableHashTypes,
|
hashes: _hashTypes,
|
||||||
keepReadOpen: false);
|
keepReadOpen: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +437,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,7 +532,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return empties;
|
return empties;
|
||||||
@@ -734,7 +734,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -949,7 +949,7 @@ namespace SabreTools.FileTypes.Archives
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using SabreTools.FileTypes.Archives;
|
|
||||||
|
|
||||||
namespace SabreTools.FileTypes
|
namespace SabreTools.FileTypes
|
||||||
{
|
{
|
||||||
@@ -29,84 +28,13 @@ namespace SabreTools.FileTypes
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new Archive with no base file
|
/// Create a new Archive with no base file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BaseArchive()
|
public BaseArchive() : base() { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new BaseArchive from the given file
|
/// Create a new BaseArchive from the given file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">Name of the file to use</param>
|
/// <param name="filename">Name of the file to use</param>
|
||||||
public BaseArchive(string filename)
|
public BaseArchive(string filename) : base(filename) { }
|
||||||
: base(filename)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create an archive object from a filename, if possible
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input">Name of the file to create the archive from</param>
|
|
||||||
/// <returns>Archive object representing the inputs</returns>
|
|
||||||
public static BaseArchive? Create(string input)
|
|
||||||
{
|
|
||||||
BaseArchive? archive = null;
|
|
||||||
|
|
||||||
// First get the archive type
|
|
||||||
FileType? at = GetFileType(input);
|
|
||||||
|
|
||||||
// If we got back null, then it's not an archive, so we we return
|
|
||||||
if (at == null)
|
|
||||||
return archive;
|
|
||||||
|
|
||||||
// Create the archive based on the type
|
|
||||||
staticLogger.Verbose($"Found archive of type: {at}");
|
|
||||||
switch (at)
|
|
||||||
{
|
|
||||||
case FileType.GZipArchive:
|
|
||||||
archive = new GZipArchive(input);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FileType.RarArchive:
|
|
||||||
archive = new RarArchive(input);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FileType.SevenZipArchive:
|
|
||||||
archive = new SevenZipArchive(input);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FileType.TapeArchive:
|
|
||||||
archive = new TapeArchive(input);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FileType.ZipArchive:
|
|
||||||
archive = new ZipArchive(input);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// We ignore all other types for now
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return archive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create an archive object of the specified type, if possible
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="archiveType">SharpCompress.Common.ArchiveType representing the archive to create</param>
|
|
||||||
/// <returns>Archive object representing the inputs</returns>
|
|
||||||
public static BaseArchive? Create(FileType archiveType)
|
|
||||||
{
|
|
||||||
return archiveType switch
|
|
||||||
{
|
|
||||||
FileType.GZipArchive => new GZipArchive(),
|
|
||||||
FileType.RarArchive => new RarArchive(),
|
|
||||||
FileType.SevenZipArchive => new SevenZipArchive(),
|
|
||||||
FileType.TapeArchive => new TapeArchive(),
|
|
||||||
FileType.ZipArchive => new ZipArchive(),
|
|
||||||
_ => null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,7 @@
|
|||||||
using System.IO;
|
namespace SabreTools.FileTypes
|
||||||
using SabreTools.FileTypes.Aaru;
|
|
||||||
using SabreTools.FileTypes.CHD;
|
|
||||||
using SabreTools.Hashing;
|
|
||||||
using SabreTools.IO.Extensions;
|
|
||||||
using SabreTools.Matching;
|
|
||||||
using SabreTools.Skippers;
|
|
||||||
|
|
||||||
namespace SabreTools.FileTypes
|
|
||||||
{
|
{
|
||||||
public class BaseFile
|
public class BaseFile
|
||||||
{
|
{
|
||||||
#region Constants
|
|
||||||
|
|
||||||
protected static readonly byte[] SevenZipSignature = [0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c];
|
|
||||||
protected static readonly byte[] AaruFormatSignature = [0x41, 0x41, 0x52, 0x55, 0x46, 0x52, 0x4d, 0x54];
|
|
||||||
protected static readonly byte[] CHDSignature = [0x4d, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x48, 0x44];
|
|
||||||
protected static readonly byte[] GzSignature = [0x1f, 0x8b, 0x08];
|
|
||||||
protected static readonly byte[] RarSignature = [0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00];
|
|
||||||
protected static readonly byte[] RarFiveSignature = [0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00];
|
|
||||||
protected static readonly byte[] TarSignature = [0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00];
|
|
||||||
protected static readonly byte[] TarZeroSignature = [0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30];
|
|
||||||
protected static readonly byte[] XZSignature = [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00];
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Fields
|
#region Fields
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -46,56 +24,47 @@ namespace SabreTools.FileTypes
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public long? Size { get; set; }
|
public long? Size { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Hashes that are available for the file
|
|
||||||
/// </summary>
|
|
||||||
public HashType[] AvailableHashTypes { get; set; } = [HashType.CRC32, HashType.MD5, HashType.SHA1];
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// CRC32 hash of the file
|
/// CRC32 hash of the file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[]? CRC { get; set; } = null;
|
public byte[]? CRC { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// MD5 hash of the file
|
/// MD5 hash of the file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[]? MD5 { get; set; } = null;
|
public byte[]? MD5 { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SHA-1 hash of the file
|
/// SHA-1 hash of the file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[]? SHA1 { get; set; } = null;
|
public byte[]? SHA1 { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SHA-256 hash of the file
|
/// SHA-256 hash of the file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[]? SHA256 { get; set; } = null;
|
public byte[]? SHA256 { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SHA-384 hash of the file
|
/// SHA-384 hash of the file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[]? SHA384 { get; set; } = null;
|
public byte[]? SHA384 { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SHA-512 hash of the file
|
/// SHA-512 hash of the file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[]? SHA512 { get; set; } = null;
|
public byte[]? SHA512 { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// SpamSum fuzzy hash of the file
|
/// SpamSum fuzzy hash of the file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[]? SpamSum { get; set; } = null;
|
public byte[]? SpamSum { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Construtors
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new BaseFile with no base file
|
/// Create a new BaseFile with no base file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BaseFile()
|
public BaseFile() { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new BaseFile from the given file
|
/// Create a new BaseFile from the given file
|
||||||
@@ -105,235 +74,5 @@ namespace SabreTools.FileTypes
|
|||||||
{
|
{
|
||||||
Filename = filename;
|
Filename = filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Static Methods
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the file type of an input file
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input">Input file to check</param>
|
|
||||||
/// <returns>FileType of inputted file (null on error)</returns>
|
|
||||||
public static FileType? GetFileType(string input)
|
|
||||||
{
|
|
||||||
FileType? outFileType = null;
|
|
||||||
|
|
||||||
// If the file is null, then we have no archive type
|
|
||||||
if (input == null)
|
|
||||||
return outFileType;
|
|
||||||
|
|
||||||
// First line of defense is going to be the extension, for better or worse
|
|
||||||
if (!HasValidArchiveExtension(input))
|
|
||||||
return outFileType;
|
|
||||||
|
|
||||||
// Read the first bytes of the file and get the magic number
|
|
||||||
BinaryReader br = new(File.OpenRead(input));
|
|
||||||
byte[] magic = br.ReadBytes(8);
|
|
||||||
#if NET40_OR_GREATER
|
|
||||||
br.Dispose();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Now try to match it to a known signature
|
|
||||||
if (magic.StartsWith(SevenZipSignature))
|
|
||||||
{
|
|
||||||
outFileType = FileType.SevenZipArchive;
|
|
||||||
}
|
|
||||||
else if (magic.StartsWith(AaruFormatSignature))
|
|
||||||
{
|
|
||||||
outFileType = FileType.AaruFormat;
|
|
||||||
}
|
|
||||||
else if (magic.StartsWith(CHDSignature))
|
|
||||||
{
|
|
||||||
outFileType = FileType.CHD;
|
|
||||||
}
|
|
||||||
else if (magic.StartsWith(GzSignature))
|
|
||||||
{
|
|
||||||
outFileType = FileType.GZipArchive;
|
|
||||||
}
|
|
||||||
else if (magic.StartsWith(RarSignature)
|
|
||||||
|| magic.StartsWith(RarFiveSignature))
|
|
||||||
{
|
|
||||||
outFileType = FileType.RarArchive;
|
|
||||||
}
|
|
||||||
else if (magic.StartsWith(TarSignature)
|
|
||||||
|| magic.StartsWith(TarZeroSignature))
|
|
||||||
{
|
|
||||||
outFileType = FileType.TapeArchive;
|
|
||||||
}
|
|
||||||
else if (magic.StartsWith(XZSignature))
|
|
||||||
{
|
|
||||||
outFileType = FileType.XZArchive;
|
|
||||||
}
|
|
||||||
else if (magic.StartsWith(Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)
|
|
||||||
|| magic.StartsWith(Models.PKZIP.Constants.EndOfCentralDirectoryRecordSignatureBytes)
|
|
||||||
|| magic.StartsWith(Models.PKZIP.Constants.DataDescriptorSignatureBytes))
|
|
||||||
{
|
|
||||||
outFileType = FileType.ZipArchive;
|
|
||||||
}
|
|
||||||
|
|
||||||
return outFileType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieve file information for a single file
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input">Filename to get information from</param>
|
|
||||||
/// <param name="header">Populated string representing the name of the skipper to use, a blank string to use the first available checker, null otherwise</param>
|
|
||||||
/// <param name="hashes">Hashes to include in the information</param>
|
|
||||||
/// <param name="asFiles">TreatAsFiles representing special format scanning</param>
|
|
||||||
/// <returns>Populated BaseFile object if success, empty one on error</returns>
|
|
||||||
public static BaseFile? GetInfo(string input, string? header = null, HashType[]? hashes = null, TreatAsFile asFiles = 0x00)
|
|
||||||
{
|
|
||||||
// Add safeguard if file doesn't exist
|
|
||||||
if (!File.Exists(input))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
// If no hashes are set, use the standard array
|
|
||||||
hashes ??= [HashType.CRC32, HashType.MD5, HashType.SHA1];
|
|
||||||
|
|
||||||
// Get input information
|
|
||||||
var fileType = GetFileType(input);
|
|
||||||
Stream inputStream = File.OpenRead(input);
|
|
||||||
|
|
||||||
// Try to match the supplied header skipper
|
|
||||||
if (header != null)
|
|
||||||
{
|
|
||||||
SkipperMatch.Init();
|
|
||||||
var rule = SkipperMatch.GetMatchingRule(input, Path.GetFileNameWithoutExtension(header));
|
|
||||||
|
|
||||||
// If there's a match, transform the stream before getting info
|
|
||||||
if (rule.Tests != null && rule.Tests.Length != 0)
|
|
||||||
{
|
|
||||||
// Create the output stream
|
|
||||||
MemoryStream outputStream = new();
|
|
||||||
|
|
||||||
// Transform the stream and get the information from it
|
|
||||||
rule.TransformStream(inputStream, outputStream, keepReadOpen: false, keepWriteOpen: true);
|
|
||||||
inputStream = outputStream;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the info in the proper manner
|
|
||||||
BaseFile? baseFile;
|
|
||||||
#if NET20 || NET35
|
|
||||||
if (fileType == FileType.AaruFormat && (asFiles & TreatAsFile.AaruFormat) == 0)
|
|
||||||
baseFile = AaruFormat.Create(inputStream);
|
|
||||||
else if (fileType == FileType.CHD && (asFiles & TreatAsFile.CHD) == 0)
|
|
||||||
baseFile = CHDFile.Create(inputStream);
|
|
||||||
#else
|
|
||||||
if (fileType == FileType.AaruFormat && !asFiles.HasFlag(TreatAsFile.AaruFormat))
|
|
||||||
baseFile = AaruFormat.Create(inputStream);
|
|
||||||
else if (fileType == FileType.CHD && !asFiles.HasFlag(TreatAsFile.CHD))
|
|
||||||
baseFile = CHDFile.Create(inputStream);
|
|
||||||
#endif
|
|
||||||
else
|
|
||||||
baseFile = GetInfo(inputStream, hashes: hashes, keepReadOpen: false);
|
|
||||||
|
|
||||||
// Dispose of the input stream
|
|
||||||
inputStream?.Dispose();
|
|
||||||
|
|
||||||
// Add unique data from the file
|
|
||||||
baseFile!.Filename = Path.GetFileName(input);
|
|
||||||
baseFile.Date = new FileInfo(input).LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss");
|
|
||||||
|
|
||||||
return baseFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Retrieve file information for a single file
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input">Filename to get information from</param>
|
|
||||||
/// <param name="size">Size of the input stream</param>
|
|
||||||
/// <param name="hashes">Hashes to include in the information</param>
|
|
||||||
/// <param name="keepReadOpen">True if the underlying read stream should be kept open, false otherwise</param>
|
|
||||||
/// <returns>Populated BaseFile object if success, empty one on error</returns>
|
|
||||||
public static BaseFile GetInfo(Stream? input, long size = -1, HashType[]? hashes = null, bool keepReadOpen = false)
|
|
||||||
{
|
|
||||||
// If we have no stream
|
|
||||||
if (input == null)
|
|
||||||
return new BaseFile();
|
|
||||||
|
|
||||||
// If no hashes are set, use the standard array
|
|
||||||
hashes ??= [HashType.CRC32, HashType.MD5, HashType.SHA1];
|
|
||||||
|
|
||||||
// If we want to automatically set the size
|
|
||||||
if (size == -1)
|
|
||||||
size = input.Length;
|
|
||||||
|
|
||||||
// Run the hashing on the input stream
|
|
||||||
var hashDict = HashTool.GetStreamHashes(input, hashes);
|
|
||||||
if (hashDict == null)
|
|
||||||
return new BaseFile();
|
|
||||||
|
|
||||||
// Create a base file with the resulting hashes
|
|
||||||
var baseFile = new BaseFile()
|
|
||||||
{
|
|
||||||
Size = size,
|
|
||||||
CRC = hashDict.ContainsKey(HashType.CRC32) ? hashDict[HashType.CRC32].FromHexString() : null,
|
|
||||||
MD5 = hashDict.ContainsKey(HashType.MD5) ? hashDict[HashType.MD5].FromHexString() : null,
|
|
||||||
SHA1 = hashDict.ContainsKey(HashType.SHA1) ? hashDict[HashType.SHA1].FromHexString() : null,
|
|
||||||
SHA256 = hashDict.ContainsKey(HashType.SHA256) ? hashDict[HashType.SHA256].FromHexString() : null,
|
|
||||||
SHA384 = hashDict.ContainsKey(HashType.SHA384) ? hashDict[HashType.SHA384].FromHexString() : null,
|
|
||||||
SHA512 = hashDict.ContainsKey(HashType.SHA512) ? hashDict[HashType.SHA512].FromHexString() : null,
|
|
||||||
SpamSum = hashDict.ContainsKey(HashType.SpamSum) ? hashDict[HashType.SpamSum].FromHexString() : null,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Deal with the input stream
|
|
||||||
if (!keepReadOpen)
|
|
||||||
{
|
|
||||||
input.Close();
|
|
||||||
input.Dispose();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
input.SeekIfPossible();
|
|
||||||
}
|
|
||||||
|
|
||||||
return baseFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Get if the given path has a valid DAT extension
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">Path to check</param>
|
|
||||||
/// <returns>True if the extension is valid, false otherwise</returns>
|
|
||||||
private static bool HasValidArchiveExtension(string path)
|
|
||||||
{
|
|
||||||
// Get the extension from the path, if possible
|
|
||||||
string? ext = path.GetNormalizedExtension();
|
|
||||||
|
|
||||||
// Check against the list of known archive extensions
|
|
||||||
return ext switch
|
|
||||||
{
|
|
||||||
// Aaruformat
|
|
||||||
"aaru" => true,
|
|
||||||
"aaruf" => true,
|
|
||||||
"aaruformat" => true,
|
|
||||||
"aif" => true,
|
|
||||||
"dicf" => true,
|
|
||||||
|
|
||||||
// Archive
|
|
||||||
"7z" => true,
|
|
||||||
"gz" => true,
|
|
||||||
"lzma" => true,
|
|
||||||
"rar" => true,
|
|
||||||
"rev" => true,
|
|
||||||
"r00" => true,
|
|
||||||
"r01" => true,
|
|
||||||
"tar" => true,
|
|
||||||
"tgz" => true,
|
|
||||||
"tlz" => true,
|
|
||||||
"zip" => true,
|
|
||||||
"zipx" => true,
|
|
||||||
|
|
||||||
// CHD
|
|
||||||
"chd" => true,
|
|
||||||
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
303
SabreTools.FileTypes/FileTypeTool.cs
Normal file
303
SabreTools.FileTypes/FileTypeTool.cs
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using SabreTools.FileTypes.Aaru;
|
||||||
|
using SabreTools.FileTypes.Archives;
|
||||||
|
using SabreTools.FileTypes.CHD;
|
||||||
|
using SabreTools.Hashing;
|
||||||
|
using SabreTools.IO.Extensions;
|
||||||
|
using SabreTools.Matching;
|
||||||
|
using SabreTools.Skippers;
|
||||||
|
|
||||||
|
namespace SabreTools.FileTypes
|
||||||
|
{
|
||||||
|
public static class FileTypeTool
|
||||||
|
{
|
||||||
|
#region Constants
|
||||||
|
|
||||||
|
private static readonly byte[] SevenZipSignature = [0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c];
|
||||||
|
private static readonly byte[] AaruFormatSignature = [0x41, 0x41, 0x52, 0x55, 0x46, 0x52, 0x4d, 0x54];
|
||||||
|
private static readonly byte[] CHDSignature = [0x4d, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x48, 0x44];
|
||||||
|
private static readonly byte[] GzSignature = [0x1f, 0x8b, 0x08];
|
||||||
|
private static readonly byte[] RarSignature = [0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00];
|
||||||
|
private static readonly byte[] RarFiveSignature = [0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00];
|
||||||
|
private static readonly byte[] TarSignature = [0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00];
|
||||||
|
private static readonly byte[] TarZeroSignature = [0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30];
|
||||||
|
private static readonly byte[] XZSignature = [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, 0x00];
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region File Info
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve file information for a single file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">Filename to get information from</param>
|
||||||
|
/// <param name="header">Populated string representing the name of the skipper to use, a blank string to use the first available checker, null otherwise</param>
|
||||||
|
/// <param name="hashes">Hashes to include in the information</param>
|
||||||
|
/// <param name="asFiles">TreatAsFiles representing special format scanning</param>
|
||||||
|
/// <returns>Populated BaseFile object if success, empty one on error</returns>
|
||||||
|
public static BaseFile? GetInfo(string input, string? header = null, HashType[]? hashes = null, TreatAsFile asFiles = 0x00)
|
||||||
|
{
|
||||||
|
// Add safeguard if file doesn't exist
|
||||||
|
if (!File.Exists(input))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// If no hashes are set, use the standard array
|
||||||
|
hashes ??= [HashType.CRC32, HashType.MD5, HashType.SHA1];
|
||||||
|
|
||||||
|
// Get input information
|
||||||
|
var fileType = GetFileType(input);
|
||||||
|
Stream inputStream = File.OpenRead(input);
|
||||||
|
|
||||||
|
// Try to match the supplied header skipper
|
||||||
|
if (header != null)
|
||||||
|
{
|
||||||
|
SkipperMatch.Init();
|
||||||
|
var rule = SkipperMatch.GetMatchingRule(input, Path.GetFileNameWithoutExtension(header));
|
||||||
|
|
||||||
|
// If there's a match, transform the stream before getting info
|
||||||
|
if (rule.Tests != null && rule.Tests.Length != 0)
|
||||||
|
{
|
||||||
|
// Create the output stream
|
||||||
|
MemoryStream outputStream = new();
|
||||||
|
|
||||||
|
// Transform the stream and get the information from it
|
||||||
|
rule.TransformStream(inputStream, outputStream, keepReadOpen: false, keepWriteOpen: true);
|
||||||
|
inputStream = outputStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the info in the proper manner
|
||||||
|
BaseFile? baseFile;
|
||||||
|
#if NET20 || NET35
|
||||||
|
if (fileType == FileType.AaruFormat && (asFiles & TreatAsFile.AaruFormat) == 0)
|
||||||
|
baseFile = AaruFormat.Create(inputStream);
|
||||||
|
else if (fileType == FileType.CHD && (asFiles & TreatAsFile.CHD) == 0)
|
||||||
|
baseFile = CHDFile.Create(inputStream);
|
||||||
|
#else
|
||||||
|
if (fileType == FileType.AaruFormat && !asFiles.HasFlag(TreatAsFile.AaruFormat))
|
||||||
|
baseFile = AaruFormat.Create(inputStream);
|
||||||
|
else if (fileType == FileType.CHD && !asFiles.HasFlag(TreatAsFile.CHD))
|
||||||
|
baseFile = CHDFile.Create(inputStream);
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
baseFile = GetInfo(inputStream, hashes: hashes, keepReadOpen: false);
|
||||||
|
|
||||||
|
// Dispose of the input stream
|
||||||
|
inputStream?.Dispose();
|
||||||
|
|
||||||
|
// Add unique data from the file
|
||||||
|
baseFile!.Filename = Path.GetFileName(input);
|
||||||
|
baseFile.Date = new FileInfo(input).LastWriteTime.ToString("yyyy/MM/dd HH:mm:ss");
|
||||||
|
|
||||||
|
return baseFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve file information for a single file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">Filename to get information from</param>
|
||||||
|
/// <param name="size">Size of the input stream</param>
|
||||||
|
/// <param name="hashes">Hashes to include in the information</param>
|
||||||
|
/// <param name="keepReadOpen">True if the underlying read stream should be kept open, false otherwise</param>
|
||||||
|
/// <returns>Populated BaseFile object if success, empty one on error</returns>
|
||||||
|
public static BaseFile GetInfo(Stream? input, long size = -1, HashType[]? hashes = null, bool keepReadOpen = false)
|
||||||
|
{
|
||||||
|
// If we have no stream
|
||||||
|
if (input == null)
|
||||||
|
return new BaseFile();
|
||||||
|
|
||||||
|
// If no hashes are set, use the standard array
|
||||||
|
hashes ??= [HashType.CRC32, HashType.MD5, HashType.SHA1];
|
||||||
|
|
||||||
|
// If we want to automatically set the size
|
||||||
|
if (size == -1)
|
||||||
|
size = input.Length;
|
||||||
|
|
||||||
|
// Run the hashing on the input stream
|
||||||
|
var hashDict = HashTool.GetStreamHashes(input, hashes);
|
||||||
|
if (hashDict == null)
|
||||||
|
return new BaseFile();
|
||||||
|
|
||||||
|
// Create a base file with the resulting hashes
|
||||||
|
var baseFile = new BaseFile()
|
||||||
|
{
|
||||||
|
Size = size,
|
||||||
|
CRC = hashDict.ContainsKey(HashType.CRC32) ? hashDict[HashType.CRC32].FromHexString() : null,
|
||||||
|
MD5 = hashDict.ContainsKey(HashType.MD5) ? hashDict[HashType.MD5].FromHexString() : null,
|
||||||
|
SHA1 = hashDict.ContainsKey(HashType.SHA1) ? hashDict[HashType.SHA1].FromHexString() : null,
|
||||||
|
SHA256 = hashDict.ContainsKey(HashType.SHA256) ? hashDict[HashType.SHA256].FromHexString() : null,
|
||||||
|
SHA384 = hashDict.ContainsKey(HashType.SHA384) ? hashDict[HashType.SHA384].FromHexString() : null,
|
||||||
|
SHA512 = hashDict.ContainsKey(HashType.SHA512) ? hashDict[HashType.SHA512].FromHexString() : null,
|
||||||
|
SpamSum = hashDict.ContainsKey(HashType.SpamSum) ? hashDict[HashType.SpamSum].FromHexString() : null,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Deal with the input stream
|
||||||
|
if (!keepReadOpen)
|
||||||
|
{
|
||||||
|
input.Close();
|
||||||
|
input.Dispose();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
input.SeekIfPossible();
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region File Type
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create an archive object from a filename, if possible
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">Name of the file to create the archive from</param>
|
||||||
|
/// <returns>Archive object representing the inputs</returns>
|
||||||
|
public static BaseArchive? CreateArchiveType(string input)
|
||||||
|
{
|
||||||
|
FileType? fileType = GetFileType(input);
|
||||||
|
return fileType switch
|
||||||
|
{
|
||||||
|
FileType.GZipArchive => new GZipArchive(input),
|
||||||
|
FileType.RarArchive => new RarArchive(input),
|
||||||
|
FileType.SevenZipArchive => new SevenZipArchive(input),
|
||||||
|
FileType.TapeArchive => new TapeArchive(input),
|
||||||
|
FileType.ZipArchive => new ZipArchive(input),
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create an Folder object of the specified type, if possible
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="outputFormat">OutputFormat representing the archive to create</param>
|
||||||
|
/// <returns>Archive object representing the inputs</returns>
|
||||||
|
public static Folder? CreateFolderType(OutputFormat outputFormat)
|
||||||
|
{
|
||||||
|
return outputFormat switch
|
||||||
|
{
|
||||||
|
OutputFormat.Folder => new Folder(false),
|
||||||
|
OutputFormat.ParentFolder => new Folder(true),
|
||||||
|
OutputFormat.TapeArchive => new TapeArchive(),
|
||||||
|
OutputFormat.Torrent7Zip => new SevenZipArchive(),
|
||||||
|
OutputFormat.TorrentGzip => new GZipArchive(),
|
||||||
|
OutputFormat.TorrentGzipRomba => new GZipArchive(),
|
||||||
|
OutputFormat.TorrentRar => new RarArchive(),
|
||||||
|
OutputFormat.TorrentXZ => new XZArchive(),
|
||||||
|
OutputFormat.TorrentXZRomba => new XZArchive(),
|
||||||
|
OutputFormat.TorrentZip => new ZipArchive(),
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the file type of an input file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">Input file to check</param>
|
||||||
|
/// <returns>FileType of inputted file (null on error)</returns>
|
||||||
|
public static FileType? GetFileType(string input)
|
||||||
|
{
|
||||||
|
FileType? outFileType = null;
|
||||||
|
|
||||||
|
// If the file is null, then we have no archive type
|
||||||
|
if (input == null)
|
||||||
|
return outFileType;
|
||||||
|
|
||||||
|
// First line of defense is going to be the extension, for better or worse
|
||||||
|
if (!HasValidArchiveExtension(input))
|
||||||
|
return outFileType;
|
||||||
|
|
||||||
|
// Read the first bytes of the file and get the magic number
|
||||||
|
BinaryReader br = new(File.OpenRead(input));
|
||||||
|
byte[] magic = br.ReadBytes(8);
|
||||||
|
#if NET40_OR_GREATER
|
||||||
|
br.Dispose();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Now try to match it to a known signature
|
||||||
|
if (magic.StartsWith(SevenZipSignature))
|
||||||
|
{
|
||||||
|
outFileType = FileType.SevenZipArchive;
|
||||||
|
}
|
||||||
|
else if (magic.StartsWith(AaruFormatSignature))
|
||||||
|
{
|
||||||
|
outFileType = FileType.AaruFormat;
|
||||||
|
}
|
||||||
|
else if (magic.StartsWith(CHDSignature))
|
||||||
|
{
|
||||||
|
outFileType = FileType.CHD;
|
||||||
|
}
|
||||||
|
else if (magic.StartsWith(GzSignature))
|
||||||
|
{
|
||||||
|
outFileType = FileType.GZipArchive;
|
||||||
|
}
|
||||||
|
else if (magic.StartsWith(RarSignature)
|
||||||
|
|| magic.StartsWith(RarFiveSignature))
|
||||||
|
{
|
||||||
|
outFileType = FileType.RarArchive;
|
||||||
|
}
|
||||||
|
else if (magic.StartsWith(TarSignature)
|
||||||
|
|| magic.StartsWith(TarZeroSignature))
|
||||||
|
{
|
||||||
|
outFileType = FileType.TapeArchive;
|
||||||
|
}
|
||||||
|
else if (magic.StartsWith(XZSignature))
|
||||||
|
{
|
||||||
|
outFileType = FileType.XZArchive;
|
||||||
|
}
|
||||||
|
else if (magic.StartsWith(Models.PKZIP.Constants.LocalFileHeaderSignatureBytes)
|
||||||
|
|| magic.StartsWith(Models.PKZIP.Constants.EndOfCentralDirectoryRecordSignatureBytes)
|
||||||
|
|| magic.StartsWith(Models.PKZIP.Constants.DataDescriptorSignatureBytes))
|
||||||
|
{
|
||||||
|
outFileType = FileType.ZipArchive;
|
||||||
|
}
|
||||||
|
|
||||||
|
return outFileType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get if the given path has a valid DAT extension
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">Path to check</param>
|
||||||
|
/// <returns>True if the extension is valid, false otherwise</returns>
|
||||||
|
private static bool HasValidArchiveExtension(string path)
|
||||||
|
{
|
||||||
|
// Get the extension from the path, if possible
|
||||||
|
string? ext = path.GetNormalizedExtension();
|
||||||
|
|
||||||
|
// Check against the list of known archive extensions
|
||||||
|
return ext switch
|
||||||
|
{
|
||||||
|
// Aaruformat
|
||||||
|
"aaru" => true,
|
||||||
|
"aaruf" => true,
|
||||||
|
"aaruformat" => true,
|
||||||
|
"aif" => true,
|
||||||
|
"dicf" => true,
|
||||||
|
|
||||||
|
// Archive
|
||||||
|
"7z" => true,
|
||||||
|
"gz" => true,
|
||||||
|
"lzma" => true,
|
||||||
|
"rar" => true,
|
||||||
|
"rev" => true,
|
||||||
|
"r00" => true,
|
||||||
|
"r01" => true,
|
||||||
|
"tar" => true,
|
||||||
|
"tgz" => true,
|
||||||
|
"tlz" => true,
|
||||||
|
"zip" => true,
|
||||||
|
"zipx" => true,
|
||||||
|
|
||||||
|
// CHD
|
||||||
|
"chd" => true,
|
||||||
|
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using SabreTools.Core.Tools;
|
using SabreTools.Core.Tools;
|
||||||
using SabreTools.FileTypes.Archives;
|
using SabreTools.Hashing;
|
||||||
using SabreTools.IO;
|
using SabreTools.IO;
|
||||||
using SabreTools.IO.Extensions;
|
using SabreTools.IO.Extensions;
|
||||||
using SabreTools.IO.Logging;
|
using SabreTools.IO.Logging;
|
||||||
@@ -16,17 +16,25 @@ namespace SabreTools.FileTypes
|
|||||||
{
|
{
|
||||||
#region Protected instance variables
|
#region Protected instance variables
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hashes that are available for children
|
||||||
|
/// </summary>
|
||||||
|
protected HashType[] _hashTypes = [HashType.CRC32, HashType.MD5, HashType.SHA1];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set of children file objects
|
||||||
|
/// </summary>
|
||||||
protected List<BaseFile>? _children;
|
protected List<BaseFile>? _children;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logging object
|
/// Logging object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected Logger logger;
|
protected Logger _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Static logger for static methods
|
/// Static logger for static methods
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected static Logger staticLogger = new();
|
protected static Logger _staticLogger = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flag specific to Folder to omit Machine name from output path
|
/// Flag specific to Folder to omit Machine name from output path
|
||||||
@@ -41,11 +49,10 @@ namespace SabreTools.FileTypes
|
|||||||
/// Create a new Folder with no base file
|
/// Create a new Folder with no base file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="writeToParent">True to write directly to parent, false otherwise</param>
|
/// <param name="writeToParent">True to write directly to parent, false otherwise</param>
|
||||||
public Folder(bool writeToParent = false)
|
public Folder(bool writeToParent = false) : base()
|
||||||
: base()
|
|
||||||
{
|
{
|
||||||
_writeToParent = writeToParent;
|
_writeToParent = writeToParent;
|
||||||
logger = new Logger(this);
|
_logger = new Logger(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -53,34 +60,10 @@ namespace SabreTools.FileTypes
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">Name of the folder to use</param>
|
/// <param name="filename">Name of the folder to use</param>
|
||||||
/// <param name="writeToParent">True to write directly to parent, false otherwise</param>
|
/// <param name="writeToParent">True to write directly to parent, false otherwise</param>
|
||||||
public Folder(string filename, bool writeToParent = false)
|
public Folder(string filename, bool writeToParent = false) : base(filename)
|
||||||
: base(filename)
|
|
||||||
{
|
{
|
||||||
_writeToParent = writeToParent;
|
_writeToParent = writeToParent;
|
||||||
logger = new Logger(this);
|
_logger = new Logger(this);
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Create an folder object of the specified type, if possible
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="outputFormat">OutputFormat representing the archive to create</param>
|
|
||||||
/// <returns>Archive object representing the inputs</returns>
|
|
||||||
public static Folder? Create(OutputFormat outputFormat)
|
|
||||||
{
|
|
||||||
return outputFormat switch
|
|
||||||
{
|
|
||||||
OutputFormat.Folder => new Folder(false),
|
|
||||||
OutputFormat.ParentFolder => new Folder(true),
|
|
||||||
OutputFormat.TapeArchive => new TapeArchive(),
|
|
||||||
OutputFormat.Torrent7Zip => new SevenZipArchive(),
|
|
||||||
OutputFormat.TorrentGzip => new GZipArchive(),
|
|
||||||
OutputFormat.TorrentGzipRomba => new GZipArchive(),
|
|
||||||
OutputFormat.TorrentRar => new RarArchive(),
|
|
||||||
OutputFormat.TorrentXZ => new XZArchive(),
|
|
||||||
OutputFormat.TorrentXZRomba => new XZArchive(),
|
|
||||||
OutputFormat.TorrentZip => new ZipArchive(),
|
|
||||||
_ => null,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -109,7 +92,7 @@ namespace SabreTools.FileTypes
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +174,7 @@ namespace SabreTools.FileTypes
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return realentry;
|
return realentry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +215,7 @@ namespace SabreTools.FileTypes
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,6 +224,18 @@ namespace SabreTools.FileTypes
|
|||||||
|
|
||||||
#region Information
|
#region Information
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the hash type that can be included in children
|
||||||
|
/// </summary>
|
||||||
|
public void SetHashType(HashType hashType)
|
||||||
|
=> SetHashTypes([hashType]);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the hash types that can be included in children
|
||||||
|
/// </summary>
|
||||||
|
public void SetHashTypes(HashType[] hashTypes)
|
||||||
|
=> _hashTypes = hashTypes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate a list of immediate children from the current folder
|
/// Generate a list of immediate children from the current folder
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -260,7 +255,7 @@ namespace SabreTools.FileTypes
|
|||||||
foreach (string file in Directory.EnumerateFiles(Filename, "*", SearchOption.TopDirectoryOnly))
|
foreach (string file in Directory.EnumerateFiles(Filename, "*", SearchOption.TopDirectoryOnly))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
BaseFile? nf = GetInfo(file, hashes: AvailableHashTypes);
|
BaseFile? nf = FileTypeTool.GetInfo(file, hashes: _hashTypes);
|
||||||
if (nf != null)
|
if (nf != null)
|
||||||
_children.Add(nf);
|
_children.Add(nf);
|
||||||
}
|
}
|
||||||
@@ -384,7 +379,7 @@ namespace SabreTools.FileTypes
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.Error(ex);
|
_logger.Error(ex);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|||||||
Reference in New Issue
Block a user