mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-09-22 06:45:11 +00:00
Start cleaning up duplicate and unnecessary code
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="ExtractionTool" />
|
||||
<InternalsVisibleTo Include="SabreTools.Serialization.Test" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user