Start cleaning up duplicate and unnecessary code

This commit is contained in:
Matt Nadareski
2025-08-29 09:37:03 -04:00
parent fa31cd0e98
commit 8626a87860
5 changed files with 101 additions and 153 deletions

View File

@@ -1,6 +1,5 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
using SabreTools.IO.Extensions;
using SabreTools.Serialization.Wrappers;
@@ -140,9 +139,8 @@ namespace ExtractionTool
break;
// IS-CAB archive
case InstallShieldCabinet:
// TODO: Move this handling to Serialization directly
ExtractInstallShieldCabinet(file, outputDirectory, includeDebug);
case InstallShieldCabinet iscab:
iscab.Extract(outputDirectory, includeDebug);
break;
// LZ-compressed file, KWAJ variant
@@ -247,85 +245,5 @@ namespace ExtractionTool
break;
}
}
/// <summary>
/// Handle IS-CAB archives
/// </summary>
private static bool ExtractInstallShieldCabinet(string file, string outputDirectory, bool includeDebug)
{
// Get the name of the first cabinet file or header
var directory = Path.GetDirectoryName(file);
string noExtension = Path.GetFileNameWithoutExtension(file);
bool shouldScanCabinet;
if (directory == null)
{
string filenamePattern = noExtension;
filenamePattern = new Regex(@"\d+$").Replace(filenamePattern, string.Empty);
bool cabinetHeaderExists = File.Exists(filenamePattern + "1.hdr");
shouldScanCabinet = cabinetHeaderExists
? file.Equals(filenamePattern + "1.hdr", StringComparison.OrdinalIgnoreCase)
: file.Equals(filenamePattern + "1.cab", StringComparison.OrdinalIgnoreCase);
}
else
{
string filenamePattern = Path.Combine(directory, noExtension);
filenamePattern = new Regex(@"\d+$").Replace(filenamePattern, string.Empty);
bool cabinetHeaderExists = File.Exists(Path.Combine(directory, filenamePattern + "1.hdr"));
shouldScanCabinet = cabinetHeaderExists
? file.Equals(Path.Combine(directory, filenamePattern + "1.hdr"), StringComparison.OrdinalIgnoreCase)
: file.Equals(Path.Combine(directory, filenamePattern + "1.cab"), StringComparison.OrdinalIgnoreCase);
}
// If we have anything but the first file
if (!shouldScanCabinet)
return false;
try
{
if (!File.Exists(file))
return false;
var cabfile = UnshieldSharpInternal.InstallShieldCabinet.Open(file);
if (cabfile?.HeaderList == null)
return false;
for (int i = 0; i < cabfile.HeaderList.FileCount; i++)
{
try
{
// Check if the file is valid first
if (!cabfile.HeaderList.FileIsValid(i))
continue;
// Ensure directory separators are consistent
string filename = cabfile.HeaderList.GetFileName(i) ?? $"BAD_FILENAME{i}";
if (Path.DirectorySeparatorChar == '\\')
filename = filename.Replace('/', '\\');
else if (Path.DirectorySeparatorChar == '/')
filename = filename.Replace('\\', '/');
// Ensure the full output directory exists
filename = Path.Combine(outputDirectory, filename);
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
cabfile.FileSave(i, filename);
}
catch (Exception ex)
{
if (includeDebug) Console.Error.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.Error.WriteLine(ex);
return false;
}
}
}
}

View File

@@ -27,7 +27,6 @@
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="ExtractionTool" />
<InternalsVisibleTo Include="SabreTools.Serialization.Test" />
</ItemGroup>

View File

@@ -13,48 +13,24 @@ namespace UnshieldSharpInternal
/// <summary>
/// Linked CAB headers
/// </summary>
public Header? HeaderList { get; private set; }
public Header HeaderList { get; private set; }
/// <summary>
/// Base filename path for related CAB files
/// </summary>
public string? FilenamePattern { get; private set; }
public string FilenamePattern { get; private set; }
/// <summary>
/// Default buffer size
/// </summary>
private const int BUFFER_SIZE = 64 * 1024;
/// <summary>
/// Maximum size of the window in bits
/// </summary>
/// TODO: Remove when Serialization is updated
private const int MAX_WBITS = 15;
#region Constructors
#region Open Cabinet
/// <summary>
/// Open a file as an InstallShield CAB
/// </summary>
public static InstallShieldCabinet? Open(string filename)
public InstallShieldCabinet(string filenamePattern, Header headerList)
{
var cabinet = new InstallShieldCabinet();
cabinet.FilenamePattern = Header.CreateFilenamePattern(filename);
if (cabinet.FilenamePattern == null)
{
Console.Error.WriteLine("Failed to create filename pattern");
return null;
}
cabinet.HeaderList = Header.OpenSet(cabinet.FilenamePattern);
if (cabinet.HeaderList == null)
{
Console.Error.WriteLine("Failed to read header files");
return null;
}
return cabinet;
FilenamePattern = filenamePattern;
HeaderList = headerList;
}
#endregion
@@ -66,12 +42,6 @@ namespace UnshieldSharpInternal
/// </summary>
public bool FileSave(int index, string filename, bool useOld = false)
{
if (HeaderList == null)
{
Console.Error.WriteLine("Header list is not built");
return false;
}
// Get the file descriptor
if (!HeaderList.TryGetFileDescriptor(index, out var fileDescriptor) || fileDescriptor == null)
return false;
@@ -219,12 +189,6 @@ namespace UnshieldSharpInternal
/// </summary>
public bool FileSaveRaw(int index, string filename)
{
if (HeaderList == null)
{
Console.Error.WriteLine("Header list is not built");
return false;
}
// Get the file descriptor
if (!HeaderList.TryGetFileDescriptor(index, out var fileDescriptor) || fileDescriptor == null)
return false;

View File

@@ -13,17 +13,17 @@ namespace UnshieldSharpInternal
/// <summary>
/// Cabinet file to read from
/// </summary>
private InstallShieldCabinet? _cabinet;
private readonly InstallShieldCabinet _cabinet;
/// <summary>
/// Currently selected index
/// </summary>
private uint _index;
private readonly uint _index;
/// <summary>
/// File descriptor defining the currently selected index
/// </summary>
private FileDescriptor? _fileDescriptor;
private readonly FileDescriptor _fileDescriptor;
/// <summary>
/// Number of bytes left in the current volume
@@ -52,25 +52,23 @@ namespace UnshieldSharpInternal
#endregion
#region Constructors
private Reader(InstallShieldCabinet cabinet, uint index, FileDescriptor fileDescriptor)
{
_cabinet = cabinet;
_index = index;
_fileDescriptor = fileDescriptor;
}
#endregion
/// <summary>
/// Create a new <see cref="Reader"> from an existing cabinet, index, and file descriptor
/// </summary>
public static Reader? Create(InstallShieldCabinet cabinet, int index, FileDescriptor fileDescriptor)
{
var reader = new Reader
{
_cabinet = cabinet,
_index = (uint)index,
_fileDescriptor = fileDescriptor,
};
// If the cabinet header list is invalid
if (reader._cabinet.HeaderList == null)
{
Console.Error.WriteLine($"Header list is invalid");
return null;
}
var reader = new Reader(cabinet, (uint)index, fileDescriptor);
for (; ; )
{
// If the volume is invalid
@@ -151,9 +149,9 @@ namespace UnshieldSharpInternal
}
#if NET20 || NET35
if ((_fileDescriptor!.Flags & FileFlags.FILE_OBFUSCATED) != 0)
if ((_fileDescriptor.Flags & FileFlags.FILE_OBFUSCATED) != 0)
#else
if (_fileDescriptor!.Flags.HasFlag(FileFlags.FILE_OBFUSCATED))
if (_fileDescriptor.Flags.HasFlag(FileFlags.FILE_OBFUSCATED))
#endif
SabreTools.Serialization.Wrappers.InstallShieldCabinet.Deobfuscate(buffer, size, ref _obfuscationOffset);
@@ -170,7 +168,7 @@ namespace UnshieldSharpInternal
volume = 1;
_volumeFile?.Close();
_volumeFile = SabreTools.Serialization.Wrappers.InstallShieldCabinet.OpenFileForReading(_cabinet!.FilenamePattern, volume, CABINET_SUFFIX);
_volumeFile = SabreTools.Serialization.Wrappers.InstallShieldCabinet.OpenFileForReading(_cabinet.FilenamePattern, volume, CABINET_SUFFIX);
if (_volumeFile == null)
{
Console.Error.WriteLine($"Failed to open input cabinet file {volume}");
@@ -181,7 +179,7 @@ namespace UnshieldSharpInternal
if (commonHeader == default)
return false;
_volumeHeader = SabreTools.Serialization.Deserializers.InstallShieldCabinet.ParseVolumeHeader(_volumeFile, _cabinet.HeaderList!.MajorVersion);
_volumeHeader = SabreTools.Serialization.Deserializers.InstallShieldCabinet.ParseVolumeHeader(_volumeFile, _cabinet.HeaderList.MajorVersion);
if (_volumeHeader == null)
return false;
@@ -190,13 +188,13 @@ namespace UnshieldSharpInternal
{
if (_index < (_cabinet.HeaderList.FileCount - 1)
&& _index == _volumeHeader.LastFileIndex
&& _volumeHeader.LastFileSizeCompressed != _fileDescriptor!.CompressedSize)
&& _volumeHeader.LastFileSizeCompressed != _fileDescriptor.CompressedSize)
{
_fileDescriptor.Flags |= FileFlags.FILE_SPLIT;
}
else if (_index > 0
&& _index == _volumeHeader.FirstFileIndex
&& _volumeHeader.FirstFileSizeCompressed != _fileDescriptor!.CompressedSize)
&& _volumeHeader.FirstFileSizeCompressed != _fileDescriptor.CompressedSize)
{
_fileDescriptor.Flags |= FileFlags.FILE_SPLIT;
}
@@ -204,9 +202,9 @@ namespace UnshieldSharpInternal
ulong dataOffset, volumeBytesLeftCompressed, volumeBytesLeftExpanded;
#if NET20 || NET35
if ((_fileDescriptor!.Flags & FileFlags.FILE_SPLIT) != 0)
if ((_fileDescriptor.Flags & FileFlags.FILE_SPLIT) != 0)
#else
if (_fileDescriptor!.Flags.HasFlag(FileFlags.FILE_SPLIT))
if (_fileDescriptor.Flags.HasFlag(FileFlags.FILE_SPLIT))
#endif
{
if (_index == _volumeHeader.LastFileIndex && _volumeHeader.LastFileOffset != 0x7FFFFFFF)

View File

@@ -3,11 +3,12 @@ using System.IO;
using System.Text.RegularExpressions;
using SabreTools.IO.Compression.zlib;
using SabreTools.Models.InstallShieldCabinet;
using SabreTools.Serialization.Interfaces;
using static SabreTools.Models.InstallShieldCabinet.Constants;
namespace SabreTools.Serialization.Wrappers
{
public partial class InstallShieldCabinet : WrapperBase<Cabinet>
public partial class InstallShieldCabinet : WrapperBase<Cabinet>, IExtractable
{
#region Descriptive Properties
@@ -353,6 +354,74 @@ namespace SabreTools.Serialization.Wrappers
#region Extraction
/// <inheritdoc/>
public bool Extract(string outputDirectory, bool includeDebug)
{
// Open the full set if possible
var cabinet = this;
string pattern = string.Empty;
if (Filename != null)
{
// Get the name of the first cabinet file or header
pattern = CreateFilenamePattern(Filename)!;
bool cabinetHeaderExists = File.Exists(pattern + "1.hdr");
bool shouldScanCabinet = cabinetHeaderExists
? Filename.Equals(pattern + "1.hdr", StringComparison.OrdinalIgnoreCase)
: Filename.Equals(pattern + "1.cab", StringComparison.OrdinalIgnoreCase);
// If we have anything but the first file
if (!shouldScanCabinet)
return false;
// Open the set from the pattern
cabinet = OpenSet(pattern);
}
// If the cabinet set could not be opened
if (cabinet == null)
return false;
try
{
var cabfile = new UnshieldSharpInternal.InstallShieldCabinet(pattern, cabinet);
for (int i = 0; i < cabinet.FileCount; i++)
{
try
{
// Check if the file is valid first
if (!cabinet.FileIsValid(i))
continue;
// Ensure directory separators are consistent
string filename = cabinet.GetFileName(i) ?? $"BAD_FILENAME{i}";
if (Path.DirectorySeparatorChar == '\\')
filename = filename.Replace('/', '\\');
else if (Path.DirectorySeparatorChar == '/')
filename = filename.Replace('\\', '/');
// Ensure the full output directory exists
filename = Path.Combine(outputDirectory, filename);
var directoryName = Path.GetDirectoryName(filename);
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
cabfile.FileSave(i, filename);
}
catch (Exception ex)
{
if (includeDebug) Console.Error.WriteLine(ex);
}
}
return true;
}
catch (Exception ex)
{
if (includeDebug) Console.Error.WriteLine(ex);
return false;
}
}
/// <summary>
/// Uncompress a source byte array to a destination
/// </summary>