Files

101 lines
3.3 KiB
C#
Raw Permalink Normal View History

using System.Collections.Generic;
using System.IO;
using SabreTools.Data.Models.InstallShieldExecutable;
using SabreTools.IO.Extensions;
2026-03-24 19:17:25 -04:00
using SabreTools.Text.Extensions;
using static SabreTools.Data.Models.InstallShieldExecutable.Constants;
2026-01-27 12:03:01 -05:00
#pragma warning disable IDE0017 // Simplify object initialization
namespace SabreTools.Serialization.Readers
{
public class InstallShieldExecutable : BaseBinaryReader<SFX>
{
public override SFX? Deserialize(Stream? data)
{
// If the data is invalid
2026-01-25 14:30:18 -05:00
if (data is null || !data.CanRead)
return null;
try
{
var sfx = new SFX();
2026-01-25 13:38:52 -05:00
// Cache the initial offset
long initialOffset = data.Position;
var sfxList = new List<FileEntry>();
2026-01-25 13:38:52 -05:00
while (data.Position < data.Length)
{
// Try to parse the entry
var fileEntry = ParseFileEntry(data, initialOffset);
2026-01-25 14:30:18 -05:00
if (fileEntry is null)
break;
// Get the length, and make sure it won't EOF
long length = (long)fileEntry.Length;
if (length > data.Length - data.Position)
break;
data.SeekIfPossible(length, SeekOrigin.Current);
sfxList.Add(fileEntry);
}
2026-01-25 13:38:52 -05:00
if (sfxList.Count == 0)
return null;
2026-01-25 13:38:52 -05:00
sfx.Entries = [.. sfxList];
return sfx;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <summary>
/// Parse a Stream into a FileEntry
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled FileEntry on success, null on error</returns>
public static FileEntry? ParseFileEntry(Stream data, long initialOffset)
{
string? name = data.ReadNullTerminatedAnsiString();
2026-01-25 14:30:18 -05:00
if (name is null)
return null;
2026-01-25 13:38:52 -05:00
// Both of these strings indicate that this is a different kind of encrypted and/or compressed format of
2026-01-25 13:38:52 -05:00
// ISEXE that is not yet supported, but will be in the future.
// They return early because no extraction can be performed, like how MsCab currently returns if a folder
// is LZX or Quantum.
if (name == ISSignatureString)
return null;
2026-01-25 13:38:52 -05:00
if (name == ISSetupSignatureString)
return null;
string? path = data.ReadNullTerminatedAnsiString();
2026-01-25 14:30:18 -05:00
if (path is null)
return null;
string? version = data.ReadNullTerminatedAnsiString();
2026-01-25 14:30:18 -05:00
if (version is null)
return null;
var lengthString = data.ReadNullTerminatedAnsiString();
2026-01-25 14:30:18 -05:00
if (lengthString is null || !ulong.TryParse(lengthString, out var lengthValue))
return null;
var obj = new FileEntry();
obj.Name = name;
obj.Path = path;
obj.Version = version;
obj.Length = lengthValue;
obj.Offset = data.Position - initialOffset;
2026-01-25 13:38:52 -05:00
return obj;
}
}
}