Added hashed based checking of updates.

This commit is contained in:
erik 2025-06-22 22:22:10 +02:00
parent e9925096f0
commit 6120966c05
3 changed files with 1709 additions and 20 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Security.Cryptography;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace MosswartMassacre namespace MosswartMassacre
@ -10,20 +11,47 @@ namespace MosswartMassacre
private const string UPDATE_URL = "https://git.snakedesert.se/SawatoMosswartsEnjoyersClub/MosswartMassacre/raw/branch/spawn-detection/MosswartMassacre/bin/Release/MosswartMassacre.dll"; private const string UPDATE_URL = "https://git.snakedesert.se/SawatoMosswartsEnjoyersClub/MosswartMassacre/raw/branch/spawn-detection/MosswartMassacre/bin/Release/MosswartMassacre.dll";
private static bool updateAvailable = false; private static bool updateAvailable = false;
private static long remoteFileSize = 0; private static string remoteFileHash = string.Empty;
private static long localFileSize = 0; private static string localFileHash = string.Empty;
private static DateTime lastCheckTime = DateTime.MinValue; private static DateTime lastCheckTime = DateTime.MinValue;
public static bool IsUpdateAvailable => updateAvailable; public static bool IsUpdateAvailable => updateAvailable;
public static DateTime LastCheckTime => lastCheckTime; public static DateTime LastCheckTime => lastCheckTime;
/// <summary>
/// Calculate SHA256 hash of a file
/// </summary>
private static string CalculateFileHash(string filePath)
{
using (var sha256 = SHA256.Create())
{
using (var stream = File.OpenRead(filePath))
{
byte[] hashBytes = sha256.ComputeHash(stream);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
}
}
}
/// <summary>
/// Calculate SHA256 hash of byte array
/// </summary>
private static string CalculateHash(byte[] data)
{
using (var sha256 = SHA256.Create())
{
byte[] hashBytes = sha256.ComputeHash(data);
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
}
}
public static async Task<bool> CheckForUpdateAsync() public static async Task<bool> CheckForUpdateAsync()
{ {
try try
{ {
PluginCore.WriteToChat("[Update] Checking for updates..."); PluginCore.WriteToChat("[Update] Checking for updates...");
// Get local file size // Get local file hash
string localPath = GetLocalDllPath(); string localPath = GetLocalDllPath();
if (!File.Exists(localPath)) if (!File.Exists(localPath))
{ {
@ -31,36 +59,40 @@ namespace MosswartMassacre
return false; return false;
} }
localFileSize = new FileInfo(localPath).Length; PluginCore.WriteToChat("[Update] Calculating local file hash...");
localFileHash = CalculateFileHash(localPath);
// Check remote file size // Download remote file and calculate hash
using (var client = new HttpClient()) using (var client = new HttpClient())
{ {
client.Timeout = TimeSpan.FromSeconds(10); client.Timeout = TimeSpan.FromSeconds(30);
var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Head, UPDATE_URL)); PluginCore.WriteToChat("[Update] Downloading remote file for comparison...");
response.EnsureSuccessStatusCode(); var remoteData = await client.GetByteArrayAsync(UPDATE_URL);
remoteFileSize = response.Content.Headers.ContentLength ?? 0; if (remoteData == null || remoteData.Length == 0)
if (remoteFileSize == 0)
{ {
PluginCore.WriteToChat("[Update] Error: Could not determine remote file size"); PluginCore.WriteToChat("[Update] Error: Could not download remote file");
return false; return false;
} }
PluginCore.WriteToChat("[Update] Calculating remote file hash...");
remoteFileHash = CalculateHash(remoteData);
} }
// Compare sizes // Compare hashes
updateAvailable = (remoteFileSize != localFileSize); updateAvailable = !string.Equals(localFileHash, remoteFileHash, StringComparison.OrdinalIgnoreCase);
lastCheckTime = DateTime.Now; lastCheckTime = DateTime.Now;
if (updateAvailable) if (updateAvailable)
{ {
PluginCore.WriteToChat($"[Update] Update available! Local: {localFileSize} bytes, Remote: {remoteFileSize} bytes"); PluginCore.WriteToChat($"[Update] Update available!");
PluginCore.WriteToChat($"[Update] Local hash: {localFileHash}");
PluginCore.WriteToChat($"[Update] Remote hash: {remoteFileHash}");
} }
else else
{ {
PluginCore.WriteToChat("[Update] Up to date"); PluginCore.WriteToChat("[Update] Up to date - hashes match");
} }
return true; return true;
@ -112,12 +144,15 @@ namespace MosswartMassacre
} }
} }
// Validate downloaded file // Validate downloaded file by hash
var downloadedSize = new FileInfo(tempPath).Length; PluginCore.WriteToChat("[Update] Validating downloaded file...");
if (downloadedSize != remoteFileSize) var downloadedHash = CalculateFileHash(tempPath);
if (!string.Equals(downloadedHash, remoteFileHash, StringComparison.OrdinalIgnoreCase))
{ {
File.Delete(tempPath); File.Delete(tempPath);
PluginCore.WriteToChat($"[Update] Download validation failed. Expected {remoteFileSize} bytes, got {downloadedSize} bytes"); PluginCore.WriteToChat($"[Update] Download validation failed. Hash mismatch!");
PluginCore.WriteToChat($"[Update] Expected: {remoteFileHash}");
PluginCore.WriteToChat($"[Update] Got: {downloadedHash}");
return false; return false;
} }