mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-09-23 07:14:57 +00:00
Libraries
This change looks dramatic, but it's just separating out the already-split namespaces into separate top-level folders. In theory, every single one could be built into their own Nuget package. `SabreTools.Serialization` still builds the normal Nuget package that is used by all other projects and includes all namespaces.
This commit is contained in:
99
SabreTools.Serialization.Readers/InstallShieldExecutable.cs
Normal file
99
SabreTools.Serialization.Readers/InstallShieldExecutable.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SabreTools.Data.Models.InstallShieldExecutable;
|
||||
using SabreTools.IO.Extensions;
|
||||
using static SabreTools.Data.Models.InstallShieldExecutable.Constants;
|
||||
|
||||
#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
|
||||
if (data is null || !data.CanRead)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
var sfx = new SFX();
|
||||
|
||||
// Cache the initial offset
|
||||
long initialOffset = data.Position;
|
||||
|
||||
var sfxList = new List<FileEntry>();
|
||||
|
||||
while (data.Position < data.Length)
|
||||
{
|
||||
// Try to parse the entry
|
||||
var fileEntry = ParseFileEntry(data, initialOffset);
|
||||
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);
|
||||
}
|
||||
|
||||
if (sfxList.Count == 0)
|
||||
return null;
|
||||
|
||||
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();
|
||||
if (name is null)
|
||||
return null;
|
||||
|
||||
// Both of these strings indicate that this is a different kind of encrypted and/or compressed format of
|
||||
// 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;
|
||||
|
||||
if (name == ISSetupSignatureString)
|
||||
return null;
|
||||
|
||||
string? path = data.ReadNullTerminatedAnsiString();
|
||||
if (path is null)
|
||||
return null;
|
||||
|
||||
string? version = data.ReadNullTerminatedAnsiString();
|
||||
if (version is null)
|
||||
return null;
|
||||
|
||||
var lengthString = data.ReadNullTerminatedAnsiString();
|
||||
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;
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user