Files
SabreTools.Serialization/SabreTools.Serialization.Readers/Hashfile.cs
Matt Nadareski 8f49e190d8 Fix everything
2026-03-24 19:17:25 -04:00

564 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using SabreTools.Data.Models.Hashfile;
using SabreTools.Hashing;
#pragma warning disable CA1822 // Mark members as static
namespace SabreTools.Serialization.Readers
{
public class Hashfile : BaseBinaryReader<Data.Models.Hashfile.Hashfile>
{
#region IByteReader
/// <inheritdoc/>
public override Data.Models.Hashfile.Hashfile? Deserialize(byte[]? data, int offset)
=> Deserialize(data, offset, HashType.CRC32);
/// <inheritdoc cref="Deserialize(byte[], int)"/>
public Data.Models.Hashfile.Hashfile? Deserialize(byte[]? data, int offset, HashType hash)
{
// If the data is invalid
if (data is null || data.Length == 0)
return null;
// If the offset is out of bounds
if (offset < 0 || offset >= data.Length)
return null;
// Create a memory stream and parse that
var dataStream = new MemoryStream(data, offset, data.Length - offset);
return Deserialize(dataStream, hash);
}
#endregion
#region IFileReader
/// <inheritdoc/>
public override Data.Models.Hashfile.Hashfile? Deserialize(string? path)
=> Deserialize(path, HashType.CRC32);
/// <inheritdoc cref="Deserialize(string?)"/>
public Data.Models.Hashfile.Hashfile? Deserialize(string? path, HashType hash)
{
try
{
// If we don't have a file
if (string.IsNullOrEmpty(path) || !File.Exists(path))
return default;
// Open the file for deserialization
using var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
return Deserialize(stream, hash);
}
catch
{
// TODO: Handle logging the exception
return default;
}
}
#endregion
#region IStreamReader
public override Data.Models.Hashfile.Hashfile? Deserialize(Stream? data)
=> Deserialize(data, HashType.CRC32);
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? Deserialize(Stream? data, HashType hash)
{
if (hash == HashType.CRC32)
return DeserializeSFV(data);
else if (hash == HashType.MD2)
return DeserializeMD2(data);
else if (hash == HashType.MD4)
return DeserializeMD4(data);
else if (hash == HashType.MD5)
return DeserializeMD5(data);
else if (hash == HashType.RIPEMD128)
return DeserializeRIPEMD128(data);
else if (hash == HashType.RIPEMD160)
return DeserializeRIPEMD160(data);
else if (hash == HashType.SHA1)
return DeserializeSHA1(data);
else if (hash == HashType.SHA256)
return DeserializeSHA256(data);
else if (hash == HashType.SHA384)
return DeserializeSHA384(data);
else if (hash == HashType.SHA512)
return DeserializeSHA512(data);
else if (hash == HashType.SpamSum)
return DeserializeSpamSum(data);
else
return null;
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeSFV(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Setup the reader and output
var reader = new StreamReader(data);
var sfvList = new List<SFV>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
var sfv = new SFV
{
File = string.Join(" ", lineParts, 0, lineParts.Length - 1),
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
Hash = lineParts[^1],
#else
Hash = lineParts[lineParts.Length - 1],
#endif
};
sfvList.Add(sfv);
}
// Assign the hashes to the hashfile and return
if (sfvList.Count > 0)
return new Data.Models.Hashfile.Hashfile { SFV = [.. sfvList] };
return null;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeMD2(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Setup the reader and output
var reader = new StreamReader(data);
var md2List = new List<MD2>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
// Parse the line into a hash
var md2 = new MD2
{
Hash = lineParts[0],
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
};
md2List.Add(md2);
}
// Assign the hashes to the hashfile and return
if (md2List.Count > 0)
return new Data.Models.Hashfile.Hashfile { MD2 = [.. md2List] };
return null;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeMD4(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Setup the reader and output
var reader = new StreamReader(data);
var md4List = new List<MD4>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
// Parse the line into a hash
var md4 = new MD4
{
Hash = lineParts[0],
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
};
md4List.Add(md4);
}
// Assign the hashes to the hashfile and return
if (md4List.Count > 0)
return new Data.Models.Hashfile.Hashfile { MD4 = [.. md4List] };
return null;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeMD5(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
// Setup the reader and output
var reader = new StreamReader(data);
var md5List = new List<MD5>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
// Parse the line into a hash
var md5 = new MD5
{
Hash = lineParts[0],
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
};
md5List.Add(md5);
}
// Assign the hashes to the hashfile and return
if (md5List.Count > 0)
return new Data.Models.Hashfile.Hashfile { MD5 = [.. md5List] };
return null;
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeRIPEMD128(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
// Setup the reader and output
var reader = new StreamReader(data);
var ripemd128List = new List<RIPEMD128>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
// Parse the line into a hash
var ripemd128 = new RIPEMD128
{
Hash = lineParts[0],
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
};
ripemd128List.Add(ripemd128);
}
// Assign the hashes to the hashfile and return
if (ripemd128List.Count > 0)
return new Data.Models.Hashfile.Hashfile { RIPEMD128 = [.. ripemd128List] };
return null;
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeRIPEMD160(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
// Setup the reader and output
var reader = new StreamReader(data);
var ripemd160List = new List<RIPEMD160>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
// Parse the line into a hash
var ripemd160 = new RIPEMD160
{
Hash = lineParts[0],
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
};
ripemd160List.Add(ripemd160);
}
// Assign the hashes to the hashfile and return
if (ripemd160List.Count > 0)
return new Data.Models.Hashfile.Hashfile { RIPEMD160 = [.. ripemd160List] };
return null;
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeSHA1(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Setup the reader and output
var reader = new StreamReader(data);
var sha1List = new List<SHA1>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
// Parse the line into a hash
var sha1 = new SHA1
{
Hash = lineParts[0],
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
};
sha1List.Add(sha1);
}
// Assign the hashes to the hashfile and return
if (sha1List.Count > 0)
return new Data.Models.Hashfile.Hashfile { SHA1 = [.. sha1List] };
return null;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeSHA256(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Setup the reader and output
var reader = new StreamReader(data);
var sha256List = new List<SHA256>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
// Parse the line into a hash
var sha256 = new SHA256
{
Hash = lineParts[0],
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
};
sha256List.Add(sha256);
}
// Assign the hashes to the hashfile and return
if (sha256List.Count > 0)
return new Data.Models.Hashfile.Hashfile { SHA256 = [.. sha256List] };
return null;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeSHA384(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Setup the reader and output
var reader = new StreamReader(data);
var sha384List = new List<SHA384>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
// Parse the line into a hash
var sha384 = new SHA384
{
Hash = lineParts[0],
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
};
sha384List.Add(sha384);
}
// Assign the hashes to the hashfile and return
if (sha384List.Count > 0)
return new Data.Models.Hashfile.Hashfile { SHA384 = [.. sha384List] };
return null;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeSHA512(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return null;
try
{
// Setup the reader and output
var reader = new StreamReader(data);
var sha512List = new List<SHA512>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
// Parse the line into a hash
var sha512 = new SHA512
{
Hash = lineParts[0],
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
};
sha512List.Add(sha512);
}
// Assign the hashes to the hashfile and return
if (sha512List.Count > 0)
return new Data.Models.Hashfile.Hashfile { SHA512 = [.. sha512List] };
return null;
}
catch
{
// Ignore the actual error
return null;
}
}
/// <inheritdoc cref="Deserialize(Stream)"/>
public Data.Models.Hashfile.Hashfile? DeserializeSpamSum(Stream? data)
{
// If the data is invalid
if (data is null || !data.CanRead)
return default;
try
{
// Setup the reader and output
var reader = new StreamReader(data);
var spamsumList = new List<SpamSum>();
// Loop through the rows and parse out values
while (!reader.EndOfStream)
{
// Read and split the line
string? line = reader.ReadLine();
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
if (lineParts is null || lineParts.Length < 2)
continue;
// Parse the line into a hash
var spamSum = new SpamSum
{
Hash = lineParts[0],
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
};
spamsumList.Add(spamSum);
}
// Assign the hashes to the hashfile and return
if (spamsumList.Count > 0)
return new Data.Models.Hashfile.Hashfile { SpamSum = [.. spamsumList] };
return null;
}
catch
{
// Ignore the actual error
return null;
}
}
#endregion
}
}