diff --git a/ExtractionTool/Program.cs b/ExtractionTool/Program.cs
index 46bcdfe2..684855ec 100644
--- a/ExtractionTool/Program.cs
+++ b/ExtractionTool/Program.cs
@@ -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;
}
}
-
- ///
- /// Handle IS-CAB archives
- ///
- 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;
- }
- }
}
}
diff --git a/SabreTools.Serialization/SabreTools.Serialization.csproj b/SabreTools.Serialization/SabreTools.Serialization.csproj
index 772b15df..8c232075 100644
--- a/SabreTools.Serialization/SabreTools.Serialization.csproj
+++ b/SabreTools.Serialization/SabreTools.Serialization.csproj
@@ -27,7 +27,6 @@
-
diff --git a/SabreTools.Serialization/UnshieldSharp/InstallShieldCabinet.cs b/SabreTools.Serialization/UnshieldSharp/InstallShieldCabinet.cs
index 9b5e6b9e..5bc76c47 100644
--- a/SabreTools.Serialization/UnshieldSharp/InstallShieldCabinet.cs
+++ b/SabreTools.Serialization/UnshieldSharp/InstallShieldCabinet.cs
@@ -13,48 +13,24 @@ namespace UnshieldSharpInternal
///
/// Linked CAB headers
///
- public Header? HeaderList { get; private set; }
+ public Header HeaderList { get; private set; }
///
/// Base filename path for related CAB files
///
- public string? FilenamePattern { get; private set; }
+ public string FilenamePattern { get; private set; }
///
/// Default buffer size
///
private const int BUFFER_SIZE = 64 * 1024;
- ///
- /// Maximum size of the window in bits
- ///
- /// TODO: Remove when Serialization is updated
- private const int MAX_WBITS = 15;
+ #region Constructors
- #region Open Cabinet
-
- ///
- /// Open a file as an InstallShield CAB
- ///
- 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
///
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
///
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;
diff --git a/SabreTools.Serialization/UnshieldSharp/Reader.cs b/SabreTools.Serialization/UnshieldSharp/Reader.cs
index 16f13423..8cfba16e 100644
--- a/SabreTools.Serialization/UnshieldSharp/Reader.cs
+++ b/SabreTools.Serialization/UnshieldSharp/Reader.cs
@@ -13,17 +13,17 @@ namespace UnshieldSharpInternal
///
/// Cabinet file to read from
///
- private InstallShieldCabinet? _cabinet;
+ private readonly InstallShieldCabinet _cabinet;
///
/// Currently selected index
///
- private uint _index;
+ private readonly uint _index;
///
/// File descriptor defining the currently selected index
///
- private FileDescriptor? _fileDescriptor;
+ private readonly FileDescriptor _fileDescriptor;
///
/// 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
+
///
/// Create a new from an existing cabinet, index, and file descriptor
///
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)
diff --git a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
index 089df050..60904b6b 100644
--- a/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
+++ b/SabreTools.Serialization/Wrappers/InstallShieldCabinet.cs
@@ -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
+ public partial class InstallShieldCabinet : WrapperBase, IExtractable
{
#region Descriptive Properties
@@ -353,6 +354,74 @@ namespace SabreTools.Serialization.Wrappers
#region Extraction
+ ///
+ 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;
+ }
+ }
+
///
/// Uncompress a source byte array to a destination
///