2020-08-01 09:51:59 +00:00
|
|
|
|
using System.Collections.Generic;
|
2020-09-04 21:00:29 +00:00
|
|
|
|
using System.IO;
|
2020-07-15 04:20:56 +00:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
2021-09-27 12:42:46 +00:00
|
|
|
|
using Wabbajack.Paths;
|
|
|
|
|
using Wabbajack.Paths.IO;
|
2020-07-15 04:20:56 +00:00
|
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
|
namespace Wabbajack.Common.FileSignatures;
|
|
|
|
|
|
|
|
|
|
public class SignatureChecker
|
2020-07-15 04:20:56 +00:00
|
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
|
private readonly int _maxLength;
|
|
|
|
|
private readonly (FileType, byte[])[] _signatures;
|
|
|
|
|
|
|
|
|
|
public SignatureChecker(params FileType[] types)
|
|
|
|
|
{
|
|
|
|
|
HashSet<FileType> types1 = new(types);
|
|
|
|
|
_signatures = Definitions.Signatures.Where(row => types1.Contains(row.Item1))
|
|
|
|
|
.OrderByDescending(x => x.Item2.Length).ToArray();
|
|
|
|
|
_maxLength = _signatures.First().Item2.Length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async ValueTask<FileType?> MatchesAsync(AbsolutePath path)
|
|
|
|
|
{
|
|
|
|
|
await using var fs = path.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
|
|
|
|
|
return await MatchesAsync(fs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async ValueTask<FileType?> MatchesAsync(Stream stream)
|
|
|
|
|
{
|
|
|
|
|
var buffer = new byte[_maxLength];
|
|
|
|
|
stream.Position = 0;
|
|
|
|
|
await stream.ReadAsync(buffer);
|
|
|
|
|
stream.Position = 0;
|
|
|
|
|
|
|
|
|
|
foreach (var (fileType, signature) in _signatures)
|
|
|
|
|
if (AreEqual(buffer, signature))
|
|
|
|
|
return fileType;
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool AreEqual(IReadOnlyList<byte> a, IEnumerable<byte> b)
|
2020-07-15 04:20:56 +00:00
|
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
|
return !b.Where((t, i) => a[i] != t).Any();
|
2020-07-15 04:20:56 +00:00
|
|
|
|
}
|
2021-09-27 12:42:46 +00:00
|
|
|
|
}
|