From d3157e4d4805337742d8d70a67a25e0e04182f47 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Wed, 6 Aug 2025 12:31:19 +0200 Subject: [PATCH] ElwigData: Check zip file integrity --- Elwig/App.xaml.cs | 4 ++-- Elwig/Elwig.csproj | 1 + Elwig/Helpers/Export/ElwigData.cs | 4 +++- Elwig/Helpers/Extensions.cs | 13 +++++++++++++ Elwig/Windows/MainWindow.xaml.cs | 4 ++-- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Elwig/App.xaml.cs b/Elwig/App.xaml.cs index df7f047..c08cec3 100644 --- a/Elwig/App.xaml.cs +++ b/Elwig/App.xaml.cs @@ -240,9 +240,9 @@ namespace Elwig { } } - public static void ReplaceDatabase(string filename) { + public static async Task ReplaceDatabase(string filename) { try { - ElwigData.ImportDatabase(filename); + await ElwigData.ImportDatabase(filename); MessageBox.Show("Das Ersetzen war erfolgreich!\n\nBitte starten Sie Elwig neu!", "Datenbank ersetzen", MessageBoxButton.OK, MessageBoxImage.Information); ForceShutdown = true; Current.Shutdown(); diff --git a/Elwig/Elwig.csproj b/Elwig/Elwig.csproj index 3e0aaf0..31f09d0 100644 --- a/Elwig/Elwig.csproj +++ b/Elwig/Elwig.csproj @@ -35,6 +35,7 @@ + diff --git a/Elwig/Helpers/Export/ElwigData.cs b/Elwig/Helpers/Export/ElwigData.cs index c196c43..3868be4 100644 --- a/Elwig/Helpers/Export/ElwigData.cs +++ b/Elwig/Helpers/Export/ElwigData.cs @@ -75,6 +75,7 @@ namespace Elwig.Helpers.Export { foreach (var filename in filenames) { // TODO read encrypted files using var zip = ZipFile.Open(filename, ZipArchiveMode.Read); + await zip.CheckIntegrity(); var version = zip.GetEntry("version"); using (var reader = new StreamReader(version!.Open(), Utils.UTF8)) { @@ -370,11 +371,12 @@ namespace Elwig.Helpers.Export { }.Export(filename); } - public static void ImportDatabase(string filename) { + public static async Task ImportDatabase(string filename) { var oldName = Path.ChangeExtension(App.Config.DatabaseFile, ".old.sqlite3"); var newName = Path.ChangeExtension(App.Config.DatabaseFile, ".new.sqlite3"); try { using (var zip = ZipFile.Open(filename, ZipArchiveMode.Read)) { + await zip.CheckIntegrity(); var db = zip.GetEntry("database.sqlite3")!; db.ExtractToFile(newName, true); } diff --git a/Elwig/Helpers/Extensions.cs b/Elwig/Helpers/Extensions.cs index bae2d8c..d616225 100644 --- a/Elwig/Helpers/Extensions.cs +++ b/Elwig/Helpers/Extensions.cs @@ -1,5 +1,7 @@ using System; using System.IO; +using System.IO.Compression; +using System.IO.Hashing; using System.Net.Http; using System.Runtime.InteropServices; using System.Threading; @@ -95,5 +97,16 @@ namespace Elwig.Helpers { await download.CopyToAsync(destination, 81920, relativeProgress, cancellationToken); progress.Report(100.0); } + + public static async Task CheckIntegrity(this ZipArchive zip) { + var crc = new Crc32(); + foreach (var entry in zip.Entries) { + crc.Reset(); + using var stream = entry.Open(); + await crc.AppendAsync(stream); + if (crc.GetCurrentHashAsUInt32() != entry.Crc32) + throw new InvalidDataException($"CRC-32 mismatch in '{entry.FullName}'"); + } + } } } diff --git a/Elwig/Windows/MainWindow.xaml.cs b/Elwig/Windows/MainWindow.xaml.cs index e5f8351..a7fef8e 100644 --- a/Elwig/Windows/MainWindow.xaml.cs +++ b/Elwig/Windows/MainWindow.xaml.cs @@ -266,8 +266,8 @@ namespace Elwig.Windows { if (res != MessageBoxResult.OK) return; - await App.MainDispatcher.BeginInvoke(() => { - App.ReplaceDatabase(filename); + await App.MainDispatcher.BeginInvoke(async () => { + await App.ReplaceDatabase(filename); }); } catch (HttpRequestException exc) { MessageBox.Show("Eventuell Internetverbindung prüfen!\n\n" + exc.Message, "Datenbank herunterladen", MessageBoxButton.OK, MessageBoxImage.Error);