-
Notifications
You must be signed in to change notification settings - Fork 1
/
Program.cs
executable file
·107 lines (79 loc) · 3.2 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Xml;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace ModlinksShaVerifier
{
internal static class Program
{
private static readonly HttpClient _Client = new();
private static string ShaToString(byte[] hash)
=> BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
private static async Task<bool> CheckLink(Manifest m, Link link)
{
using var sha = SHA256.Create();
Stream stream;
try
{
stream = await _Client.GetStreamAsync(link.URL);
}
catch (HttpRequestException e)
{
WriteError("Check", $"Request failed for {m.Name} - {link.URL}! {e.StatusCode}");
return false;
}
string shasum = ShaToString(await sha.ComputeHashAsync(stream));
if (shasum == link.SHA256.ToLowerInvariant())
return true;
WriteError("Check", $"Hash mismatch of {m.Name} in link {link.URL}. Expected value from modlinks: {link.SHA256}, Actual value: {shasum}");
return false;
}
private static async Task<bool> CheckSingleSha(Manifest m)
{
Console.WriteLine($"Checking '{m.Name}'");
var res = await Task.WhenAll(m.Links.AsEnumerable().Select(x => CheckLink(m, x)));
return res.All(x => x);
}
internal static async Task<int> Main(string[] args)
{
var sw = new Stopwatch();
sw.Start();
if (args.Length != 1)
{
await Console.Error.WriteLineAsync("Usage: ModlinksShaVerifier [FILE]");
return 1;
}
var path = args[0];
if (!File.Exists(path))
{
await Console.Error.WriteLineAsync($"Unable to access {path}! Does it exist?");
return 1;
}
var reader = XmlReader.Create(path, new XmlReaderSettings {Async = true});
var serializer = new XmlSerializer(typeof(Manifest));
List<Task<bool>> checks = new();
while (await reader.ReadAsync())
{
if (reader.NodeType != XmlNodeType.Element)
continue;
if (reader.Name != "Manifest")
continue;
var manifest = (Manifest?) serializer.Deserialize(reader) ?? throw new InvalidDataException();
checks.Add(CheckSingleSha(manifest));
}
var res = await Task.WhenAll(checks);
sw.Stop();
Console.WriteLine($"Completed in {sw.ElapsedMilliseconds}ms.");
// If they're not all correct, error.
return !res.All(x => x) ? 1 : 0;
}
private static void WriteError(string title, string message) =>
Console.WriteLine($"::error title={title}::{message}");
}
}