Browse Source

Fix update datetime formatting to be culture invariant

pull/109/head
Ionite 1 year ago
parent
commit
46db84f092
No known key found for this signature in database
  1. 104
      StabilityMatrix.Core/Updater/UpdateHelper.cs

104
StabilityMatrix.Core/Updater/UpdateHelper.cs

@ -1,4 +1,5 @@
using System.Text.Json; using System.Globalization;
using System.Text.Json;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using StabilityMatrix.Core.Extensions; using StabilityMatrix.Core.Extensions;
@ -18,24 +19,31 @@ public class UpdateHelper : IUpdateHelper
private readonly IDownloadService downloadService; private readonly IDownloadService downloadService;
private readonly DebugOptions debugOptions; private readonly DebugOptions debugOptions;
private readonly System.Timers.Timer timer = new(TimeSpan.FromMinutes(5)); private readonly System.Timers.Timer timer = new(TimeSpan.FromMinutes(5));
private string UpdateManifestUrl => debugOptions.UpdateManifestUrl ?? private string UpdateManifestUrl =>
"https://cdn.lykos.ai/update-v2.json"; debugOptions.UpdateManifestUrl ?? "https://cdn.lykos.ai/update-v2.json";
public const string UpdateFolderName = ".StabilityMatrixUpdate"; public const string UpdateFolderName = ".StabilityMatrixUpdate";
public static DirectoryPath UpdateFolder => Compat.AppCurrentDir.JoinDir(UpdateFolderName); public static DirectoryPath UpdateFolder => Compat.AppCurrentDir.JoinDir(UpdateFolderName);
public static FilePath ExecutablePath => UpdateFolder.JoinFile(Compat.GetExecutableName()); public static FilePath ExecutablePath => UpdateFolder.JoinFile(Compat.GetExecutableName());
public UpdateHelper(ILogger<UpdateHelper> logger, IHttpClientFactory httpClientFactory, public UpdateHelper(
IDownloadService downloadService, IOptions<DebugOptions> debugOptions) ILogger<UpdateHelper> logger,
IHttpClientFactory httpClientFactory,
IDownloadService downloadService,
IOptions<DebugOptions> debugOptions
)
{ {
this.logger = logger; this.logger = logger;
this.httpClientFactory = httpClientFactory; this.httpClientFactory = httpClientFactory;
this.downloadService = downloadService; this.downloadService = downloadService;
this.debugOptions = debugOptions.Value; this.debugOptions = debugOptions.Value;
timer.Elapsed += async (_, _) => { await CheckForUpdate().ConfigureAwait(false); }; timer.Elapsed += async (_, _) =>
{
await CheckForUpdate().ConfigureAwait(false);
};
} }
public async Task StartCheckingForUpdates() public async Task StartCheckingForUpdates()
@ -45,18 +53,33 @@ public class UpdateHelper : IUpdateHelper
await CheckForUpdate().ConfigureAwait(false); await CheckForUpdate().ConfigureAwait(false);
} }
public async Task DownloadUpdate(UpdateInfo updateInfo, public async Task DownloadUpdate(UpdateInfo updateInfo, IProgress<ProgressReport> progress)
IProgress<ProgressReport> progress)
{ {
var downloadUrl = updateInfo.DownloadUrl; var downloadUrl = updateInfo.DownloadUrl;
Directory.CreateDirectory(UpdateFolder); Directory.CreateDirectory(UpdateFolder);
// download the file from URL // download the file from URL
await downloadService.DownloadToFileAsync(downloadUrl, ExecutablePath, progress: progress, await downloadService
httpClientName: "UpdateClient").ConfigureAwait(false); .DownloadToFileAsync(
downloadUrl,
ExecutablePath,
progress: progress,
httpClientName: "UpdateClient"
)
.ConfigureAwait(false);
} }
/// <summary>
/// Format a DatetimeOffset to a culture invariant string for use in signature verification.
/// </summary>
private static string FormatDateTimeOffsetInvariant(DateTimeOffset dateTimeOffset)
{
return dateTimeOffset.ToString(
@"yyyy-MM-ddTHH\:mm\:ss.ffffffzzz",
CultureInfo.InvariantCulture
);
}
/// <summary> /// <summary>
/// Data for use in signature verification. /// Data for use in signature verification.
@ -66,10 +89,10 @@ public class UpdateHelper : IUpdateHelper
private static string GetUpdateInfoSignedData(UpdateInfo updateInfo) private static string GetUpdateInfoSignedData(UpdateInfo updateInfo)
{ {
var channel = updateInfo.Channel.GetStringValue().ToLowerInvariant(); var channel = updateInfo.Channel.GetStringValue().ToLowerInvariant();
var date = updateInfo.ReleaseDate.ToString("yyyy-MM-ddTHH:mm:ss.ffffffzzz"); var date = FormatDateTimeOffsetInvariant(updateInfo.ReleaseDate);
return $"{updateInfo.Version};{date};{channel};" + return $"{updateInfo.Version};{date};{channel};"
$"{(int) updateInfo.Type};{updateInfo.DownloadUrl};{updateInfo.ChangelogUrl};" + + $"{(int)updateInfo.Type};{updateInfo.DownloadUrl};{updateInfo.ChangelogUrl};"
$"{updateInfo.HashBlake3}"; + $"{updateInfo.HashBlake3}";
} }
private async Task CheckForUpdate() private async Task CheckForUpdate()
@ -80,22 +103,26 @@ public class UpdateHelper : IUpdateHelper
var response = await httpClient.GetAsync(UpdateManifestUrl).ConfigureAwait(false); var response = await httpClient.GetAsync(UpdateManifestUrl).ConfigureAwait(false);
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
{ {
logger.LogWarning("Error while checking for update {StatusCode} - {Content}", logger.LogWarning(
response.StatusCode, await response.Content.ReadAsStringAsync().ConfigureAwait(false)); "Error while checking for update {StatusCode} - {Content}",
response.StatusCode,
await response.Content.ReadAsStringAsync().ConfigureAwait(false)
);
return; return;
} }
var updateCollection = var updateCollection = await JsonSerializer
await JsonSerializer.DeserializeAsync<UpdateCollection>( .DeserializeAsync<UpdateCollection>(
await response.Content.ReadAsStreamAsync() await response.Content.ReadAsStreamAsync().ConfigureAwait(false)
.ConfigureAwait(false)).ConfigureAwait(false); )
.ConfigureAwait(false);
if (updateCollection is null) if (updateCollection is null)
{ {
logger.LogError("UpdateCollection is null"); logger.LogError("UpdateCollection is null");
return; return;
} }
// Get the update info for our platform // Get the update info for our platform
var updateInfo = updateCollection switch var updateInfo = updateCollection switch
{ {
@ -106,15 +133,18 @@ public class UpdateHelper : IUpdateHelper
if (updateInfo is null) if (updateInfo is null)
{ {
logger.LogWarning("Could not find compatible update info for the platform {Platform}", Compat.Platform); logger.LogWarning(
"Could not find compatible update info for the platform {Platform}",
Compat.Platform
);
return; return;
} }
logger.LogInformation("UpdateInfo signature: {Signature}", updateInfo.Signature); logger.LogInformation("UpdateInfo signature: {Signature}", updateInfo.Signature);
var updateInfoSignData = GetUpdateInfoSignedData(updateInfo); var updateInfoSignData = GetUpdateInfoSignedData(updateInfo);
logger.LogInformation("UpdateInfo signed data: {SignData}", updateInfoSignData); logger.LogInformation("UpdateInfo signed data: {SignData}", updateInfoSignData);
// Verify signature // Verify signature
var checker = new SignatureChecker(); var checker = new SignatureChecker();
if (!checker.Verify(updateInfoSignData, updateInfo.Signature)) if (!checker.Verify(updateInfoSignData, updateInfo.Signature))
@ -129,8 +159,11 @@ public class UpdateHelper : IUpdateHelper
if (order > 0) if (order > 0)
{ {
// Newer version available // Newer version available
logger.LogInformation("Update available {AppVer} -> {UpdateVer}", logger.LogInformation(
Compat.AppVersion, updateInfo.Version); "Update available {AppVer} -> {UpdateVer}",
Compat.AppVersion,
updateInfo.Version
);
EventManager.Instance.OnUpdateAvailable(updateInfo); EventManager.Instance.OnUpdateAvailable(updateInfo);
return; return;
} }
@ -142,13 +175,16 @@ public class UpdateHelper : IUpdateHelper
// If different, we can update // If different, we can update
if (updateHash != appHash) if (updateHash != appHash)
{ {
logger.LogInformation("Update available {AppVer} -> {UpdateVer}", logger.LogInformation(
Compat.AppVersion, updateInfo.Version); "Update available {AppVer} -> {UpdateVer}",
Compat.AppVersion,
updateInfo.Version
);
EventManager.Instance.OnUpdateAvailable(updateInfo); EventManager.Instance.OnUpdateAvailable(updateInfo);
return; return;
} }
} }
logger.LogInformation("No update available"); logger.LogInformation("No update available");
} }
catch (Exception e) catch (Exception e)

Loading…
Cancel
Save