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

Loading…
Cancel
Save