28 lines
1.8 KiB
C#
28 lines
1.8 KiB
C#
using System.Security.Cryptography;
|
|
using System.Text.Json;
|
|
|
|
namespace PRecAnnot.Plant3D2026;
|
|
|
|
internal sealed record CompositeAssemblyManifest(string Name, string Sha256, bool Required);
|
|
internal sealed record CompositeManifest(int SchemaVersion, string Package, string Version, IReadOnlyList<string> Modules, IReadOnlyList<CompositeAssemblyManifest> Assemblies);
|
|
|
|
internal static class CompositeModuleManifest
|
|
{
|
|
public static CompositeManifest Validate()
|
|
{
|
|
var assemblyPath = typeof(EntryPoint).Assembly.Location;
|
|
var path = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(assemblyPath)!, "..", "module-manifest.json"));
|
|
if (!File.Exists(path)) throw new InvalidOperationException("COMPOSITE_MODULE_MANIFEST_MISSING");
|
|
var manifest = JsonSerializer.Deserialize<CompositeManifest>(File.ReadAllText(path), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? throw new InvalidOperationException("COMPOSITE_MODULE_MANIFEST_INVALID");
|
|
if (manifest.SchemaVersion != 1 || !string.Equals(manifest.Package, "P_Rec_Annot", StringComparison.Ordinal) || manifest.Modules.Count == 0) throw new InvalidOperationException("COMPOSITE_MODULE_MANIFEST_INVALID");
|
|
foreach (var item in manifest.Assemblies.Where(value => value.Required))
|
|
{
|
|
var file = Path.Combine(Path.GetDirectoryName(assemblyPath)!, item.Name);
|
|
if (!File.Exists(file)) throw new InvalidOperationException($"COMPOSITE_MODULE_ASSEMBLY_MISSING:{item.Name}");
|
|
var hash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(file))).ToLowerInvariant();
|
|
if (!string.Equals(hash, item.Sha256, StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException($"COMPOSITE_MODULE_HASH_MISMATCH:{item.Name}");
|
|
}
|
|
return manifest;
|
|
}
|
|
}
|