diff --git a/.idea/.idea.Aaru/.idea/contentModel.xml b/.idea/.idea.Aaru/.idea/contentModel.xml
index 926ea8547..bd5718eac 100644
--- a/.idea/.idea.Aaru/.idea/contentModel.xml
+++ b/.idea/.idea.Aaru/.idea/contentModel.xml
@@ -1223,8 +1223,6 @@
-
-
@@ -1242,6 +1240,7 @@
+
@@ -1305,6 +1304,7 @@
+
@@ -1325,6 +1325,8 @@
+
+
diff --git a/Aaru.Core/Checksum.cs b/Aaru.Core/Checksum.cs
index eb93bfe2a..71289a394 100644
--- a/Aaru.Core/Checksum.cs
+++ b/Aaru.Core/Checksum.cs
@@ -316,40 +316,40 @@ namespace Aaru.Core
f16Thread.IsAlive ||
f32Thread.IsAlive) {}
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Adler32))
adlerThread = new Thread(UpdateHash);
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Crc16))
crc16Thread = new Thread(UpdateHash);
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Crc32))
crc32Thread = new Thread(UpdateHash);
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Crc16))
crc64Thread = new Thread(UpdateHash);
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Md5))
md5Thread = new Thread(UpdateHash);
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Sha1))
sha1Thread = new Thread(UpdateHash);
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Sha256))
sha256Thread = new Thread(UpdateHash);
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Sha384))
sha384Thread = new Thread(UpdateHash);
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Sha512))
sha512Thread = new Thread(UpdateHash);
if(enabled.HasFlag(EnableChecksum.SpamSum))
spamsumThread = new Thread(UpdateHash);
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Fletcher16))
f16Thread = new Thread(UpdateHash);
- if(enabled.HasFlag(EnableChecksum.SpamSum))
+ if(enabled.HasFlag(EnableChecksum.Fletcher32))
f32Thread = new Thread(UpdateHash);
}
diff --git a/Aaru.Gui/Forms/frmImageChecksum.xeto b/Aaru.Gui/Forms/frmImageChecksum.xeto
deleted file mode 100644
index 613afcf6c..000000000
--- a/Aaru.Gui/Forms/frmImageChecksum.xeto
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
\ No newline at end of file
diff --git a/Aaru.Gui/Forms/frmImageChecksum.xeto.cs b/Aaru.Gui/Forms/frmImageChecksum.xeto.cs
deleted file mode 100644
index 099be362b..000000000
--- a/Aaru.Gui/Forms/frmImageChecksum.xeto.cs
+++ /dev/null
@@ -1,500 +0,0 @@
-// /***************************************************************************
-// Aaru Data Preservation Suite
-// ----------------------------------------------------------------------------
-//
-// Filename : frmImageChecksum.xeto.cs
-// Author(s) : Natalia Portillo
-//
-// Component : Image checksum calculation window.
-//
-// --[ Description ] ----------------------------------------------------------
-//
-// Implements creating checksums of a media image.
-//
-// --[ License ] --------------------------------------------------------------
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General public License for more details.
-//
-// You should have received a copy of the GNU General public License
-// along with this program. If not, see ;http://www.gnu.org/licenses/>.
-//
-// ----------------------------------------------------------------------------
-// Copyright © 2011-2020 Natalia Portillo
-// ****************************************************************************/
-
-using System;
-using System.Threading;
-using Aaru.CommonTypes.Interfaces;
-using Aaru.CommonTypes.Structs;
-using Aaru.Console;
-using Aaru.Core;
-using Eto.Forms;
-using Eto.Serialization.Xaml;
-using Schemas;
-
-namespace Aaru.Gui.Forms
-{
- public class frmImageChecksum : Form
- {
- // How many sectors to read at once
- const uint SECTORS_TO_READ = 256;
- readonly IMediaImage inputFormat;
- bool cancel;
-
- public frmImageChecksum(IMediaImage inputFormat)
- {
- this.inputFormat = inputFormat;
- XamlReader.Load(this);
- cancel = false;
-
- try
- {
- chkChecksumTracks.Visible = (inputFormat as IOpticalMediaImage)?.Tracks?.Count > 0;
- }
- catch
- {
- chkChecksumTracks.Visible = false;
- }
-
- chkChecksumTracks.Checked = chkChecksumTracks.Visible;
- chkChecksumMedia.Visible = chkChecksumTracks.Visible;
- }
-
- protected void OnBtnStart(object sender, EventArgs e)
- {
- chkAdler32.Enabled = false;
- chkChecksumMedia.Enabled = false;
- chkChecksumTracks.Enabled = false;
- chkCrc16.Enabled = false;
- chkCrc32.Enabled = false;
- chkCrc64.Enabled = false;
- chkFletcher16.Enabled = false;
- chkFletcher32.Enabled = false;
- chkMd5.Enabled = false;
- chkSha1.Enabled = false;
- chkSha256.Enabled = false;
- chkSha384.Enabled = false;
- chkSha512.Enabled = false;
- chkSpamsum.Enabled = false;
- btnClose.Visible = false;
- btnStart.Visible = false;
- btnStop.Visible = true;
- stkProgress.Visible = true;
- lblProgress2.Visible = false;
-
- new Thread(DoWork).Start();
- }
-
- void DoWork()
- {
- var opticalMediaImage = inputFormat as IOpticalMediaImage;
- bool formatHasTracks = false;
-
- if(opticalMediaImage != null)
- try
- {
- formatHasTracks = opticalMediaImage.Tracks?.Count > 0;
- }
- catch
- {
- formatHasTracks = false;
- }
-
- // Setup progress bars
- Application.Instance.Invoke(() =>
- {
- stkProgress.Visible = true;
- prgProgress.MaxValue = 1;
- prgProgress2.MaxValue = (int)(inputFormat.Info.Sectors / SECTORS_TO_READ);
-
- if(formatHasTracks &&
- chkChecksumTracks.Checked == true &&
- opticalMediaImage != null)
- prgProgress.MaxValue += opticalMediaImage.Tracks.Count;
- else
- {
- prgProgress.MaxValue = 2;
- prgProgress2.Visible = false;
- lblProgress2.Visible = false;
- }
- });
-
- var enabledChecksums = new EnableChecksum();
-
- if(chkAdler32.Checked == true)
- enabledChecksums |= EnableChecksum.Adler32;
-
- if(chkCrc16.Checked == true)
- enabledChecksums |= EnableChecksum.Crc16;
-
- if(chkCrc32.Checked == true)
- enabledChecksums |= EnableChecksum.Crc32;
-
- if(chkCrc64.Checked == true)
- enabledChecksums |= EnableChecksum.Crc64;
-
- if(chkMd5.Checked == true)
- enabledChecksums |= EnableChecksum.Md5;
-
- if(chkSha1.Checked == true)
- enabledChecksums |= EnableChecksum.Sha1;
-
- if(chkSha256.Checked == true)
- enabledChecksums |= EnableChecksum.Sha256;
-
- if(chkSha384.Checked == true)
- enabledChecksums |= EnableChecksum.Sha384;
-
- if(chkSha512.Checked == true)
- enabledChecksums |= EnableChecksum.Sha512;
-
- if(chkSpamsum.Checked == true)
- enabledChecksums |= EnableChecksum.SpamSum;
-
- if(chkFletcher16.Checked == true)
- enabledChecksums |= EnableChecksum.Fletcher16;
-
- if(chkFletcher32.Checked == true)
- enabledChecksums |= EnableChecksum.Fletcher32;
-
- Checksum mediaChecksum = null;
-
- var trackHashes = new TreeGridItemCollection();
- var mediaHashes = new TreeGridItemCollection();
-
- if(opticalMediaImage != null)
- try
- {
- Checksum trackChecksum = null;
-
- if(chkChecksumMedia.Checked == true)
- mediaChecksum = new Checksum(enabledChecksums);
-
- ulong previousTrackEnd = 0;
-
- foreach(Track currentTrack in opticalMediaImage.Tracks)
- {
- Application.Instance.Invoke(() =>
- {
- lblProgress.Text =
- $"Hashing track {currentTrack.TrackSequence} of {opticalMediaImage.Tracks.Count}";
-
- prgProgress.Value++;
- });
-
- if(currentTrack.TrackStartSector - previousTrackEnd != 0 &&
- chkChecksumMedia.Checked == true)
- for(ulong i = previousTrackEnd + 1; i < currentTrack.TrackStartSector; i++)
- {
- ulong sector = i;
-
- Application.Instance.Invoke(() =>
- {
- prgProgress2.Value = (int)(sector / SECTORS_TO_READ);
- lblProgress2.Text = $"Hashing track-less sector {sector}";
- });
-
- byte[] hiddenSector = opticalMediaImage.ReadSector(i);
-
- mediaChecksum?.Update(hiddenSector);
- }
-
- AaruConsole.DebugWriteLine("Checksum command",
- "Track {0} starts at sector {1} and ends at sector {2}",
- currentTrack.TrackSequence, currentTrack.TrackStartSector,
- currentTrack.TrackEndSector);
-
- if(chkChecksumTracks.Checked == true)
- trackChecksum = new Checksum(enabledChecksums);
-
- ulong sectors = (currentTrack.TrackEndSector - currentTrack.TrackStartSector) + 1;
- ulong doneSectors = 0;
-
- while(doneSectors < sectors)
- {
- if(cancel)
- {
- Application.Instance.Invoke(() =>
- {
- btnClose.Visible = true;
- btnStart.Visible = false;
- btnStop.Visible = false;
- });
-
- return;
- }
-
- byte[] sector;
-
- if(sectors - doneSectors >= SECTORS_TO_READ)
- {
- sector = opticalMediaImage.ReadSectors(doneSectors, SECTORS_TO_READ,
- currentTrack.TrackSequence);
-
- ulong doneSectorsToInvoke = doneSectors;
-
- Application.Instance.Invoke(() =>
- {
- prgProgress2.Value = (int)(doneSectorsToInvoke / SECTORS_TO_READ);
-
- lblProgress2.Text =
- $"Hashings sectors {doneSectorsToInvoke} to {doneSectorsToInvoke + SECTORS_TO_READ} of track {currentTrack.TrackSequence}";
- });
-
- doneSectors += SECTORS_TO_READ;
- }
- else
- {
- sector = opticalMediaImage.ReadSectors(doneSectors, (uint)(sectors - doneSectors),
- currentTrack.TrackSequence);
-
- ulong doneSectorsToInvoke = doneSectors;
-
- Application.Instance.Invoke(() =>
- {
- prgProgress2.Value = (int)(doneSectorsToInvoke / SECTORS_TO_READ);
-
- lblProgress2.Text =
- $"Hashings sectors {doneSectorsToInvoke} to {doneSectorsToInvoke + (sectors - doneSectorsToInvoke)} of track {currentTrack.TrackSequence}";
- });
-
- doneSectors += sectors - doneSectors;
- }
-
- if(chkChecksumMedia.Checked == true)
- mediaChecksum?.Update(sector);
-
- if(chkChecksumTracks.Checked == true)
- trackChecksum?.Update(sector);
- }
-
- if(chkChecksumTracks.Checked == true)
- if(trackChecksum != null)
- foreach(ChecksumType chk in trackChecksum.End())
- trackHashes.Add(new TreeGridItem
- {
- Values = new object[]
- {
- currentTrack.TrackSequence, chk.type, chk.Value
- }
- });
-
- previousTrackEnd = currentTrack.TrackEndSector;
- }
-
- if(opticalMediaImage.Info.Sectors - previousTrackEnd != 0 &&
- chkChecksumMedia.Checked == true)
- for(ulong i = previousTrackEnd + 1; i < opticalMediaImage.Info.Sectors; i++)
- {
- ulong sector = i;
-
- Application.Instance.Invoke(() =>
- {
- prgProgress2.Value = (int)(sector / SECTORS_TO_READ);
- lblProgress2.Text = $"Hashing track-less sector {sector}";
- });
-
- byte[] hiddenSector = opticalMediaImage.ReadSector(i);
- mediaChecksum?.Update(hiddenSector);
- }
-
- if(chkChecksumMedia.Checked == true)
- if(mediaChecksum != null)
- foreach(ChecksumType chk in mediaChecksum.End())
- mediaHashes.Add(new TreeGridItem
- {
- Values = new object[]
- {
- chk.type, chk.Value
- }
- });
- }
- catch(Exception ex)
- {
- AaruConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message);
- AaruConsole.WriteLine("Unable to get separate tracks, not checksumming them");
- }
- else
- {
- Application.Instance.Invoke(() =>
- {
- stkProgress1.Visible = false;
- });
-
- mediaChecksum = new Checksum(enabledChecksums);
-
- ulong doneSectors = 0;
-
- while(doneSectors < inputFormat.Info.Sectors)
- {
- if(cancel)
- {
- Application.Instance.Invoke(() =>
- {
- btnClose.Visible = true;
- btnStart.Visible = false;
- btnStop.Visible = false;
- });
-
- return;
- }
-
- byte[] sector;
-
- if(inputFormat.Info.Sectors - doneSectors >= SECTORS_TO_READ)
- {
- sector = inputFormat.ReadSectors(doneSectors, SECTORS_TO_READ);
-
- ulong doneSectorsToInvoke = doneSectors;
-
- Application.Instance.Invoke(() =>
- {
- prgProgress2.Value = (int)(doneSectorsToInvoke / SECTORS_TO_READ);
-
- lblProgress2.Text =
- $"Hashings sectors {doneSectorsToInvoke} to {doneSectorsToInvoke + SECTORS_TO_READ}";
- });
-
- doneSectors += SECTORS_TO_READ;
- }
- else
- {
- sector = inputFormat.ReadSectors(doneSectors, (uint)(inputFormat.Info.Sectors - doneSectors));
- ulong doneSectorsToInvoke = doneSectors;
-
- Application.Instance.Invoke(() =>
- {
- prgProgress2.Value = (int)(doneSectorsToInvoke / SECTORS_TO_READ);
-
- lblProgress2.Text =
- $"Hashings sectors {doneSectorsToInvoke} to {doneSectorsToInvoke + (inputFormat.Info.Sectors - doneSectorsToInvoke)}";
- });
-
- doneSectors += inputFormat.Info.Sectors - doneSectors;
- }
-
- mediaChecksum.Update(sector);
- }
-
- foreach(ChecksumType chk in mediaChecksum.End())
- mediaHashes.Add(new TreeGridItem
- {
- Values = new object[]
- {
- chk.type, chk.Value
- }
- });
- }
-
- if(chkChecksumTracks.Checked == true)
- Application.Instance.Invoke(() =>
- {
- grpTrackChecksums.Text = "Track checksums:";
- stkTrackChecksums.Visible = true;
-
- treeTrackChecksums.Columns.Add(new GridColumn
- {
- HeaderText = "Track", DataCell = new TextBoxCell(0)
- });
-
- treeTrackChecksums.Columns.Add(new GridColumn
- {
- HeaderText = "Algorithm", DataCell = new TextBoxCell(1)
- });
-
- treeTrackChecksums.Columns.Add(new GridColumn
- {
- HeaderText = "Hash", DataCell = new TextBoxCell(2)
- });
-
- treeTrackChecksums.AllowMultipleSelection = false;
- treeTrackChecksums.ShowHeader = true;
- treeTrackChecksums.DataStore = trackHashes;
- });
-
- if(chkChecksumMedia.Checked == true)
- Application.Instance.Invoke(() =>
- {
- grpMediaChecksums.Text = "Media checksums:";
- stkMediaChecksums.Visible = true;
-
- treeMediaChecksums.Columns.Add(new GridColumn
- {
- HeaderText = "Algorithm", DataCell = new TextBoxCell(0)
- });
-
- treeMediaChecksums.Columns.Add(new GridColumn
- {
- HeaderText = "Hash", DataCell = new TextBoxCell(1)
- });
-
- treeMediaChecksums.AllowMultipleSelection = false;
- treeMediaChecksums.ShowHeader = true;
- treeMediaChecksums.DataStore = mediaHashes;
- });
-
- Statistics.AddCommand("checksum");
-
- Application.Instance.Invoke(() =>
- {
- stkOptions.Visible = false;
- stkResults.Visible = true;
- stkProgress.Visible = false;
- btnStart.Visible = false;
- btnStop.Visible = false;
- btnClose.Visible = true;
- });
- }
-
- protected void OnBtnClose(object sender, EventArgs e) => Close();
-
- protected void OnBtnStop(object sender, EventArgs e)
- {
- cancel = true;
- btnStop.Enabled = false;
- }
-
- #region XAML IDs
- StackLayout stkOptions;
- CheckBox chkChecksumMedia;
- CheckBox chkChecksumTracks;
- CheckBox chkAdler32;
- CheckBox chkCrc16;
- CheckBox chkCrc32;
- CheckBox chkCrc64;
- CheckBox chkFletcher16;
- CheckBox chkFletcher32;
- CheckBox chkMd5;
- CheckBox chkSha1;
- CheckBox chkSha256;
- CheckBox chkSha384;
- CheckBox chkSha512;
- CheckBox chkSpamsum;
- StackLayout stkResults;
- StackLayout stkTrackChecksums;
- GroupBox grpTrackChecksums;
- TreeGridView treeTrackChecksums;
- StackLayout stkMediaChecksums;
- GroupBox grpMediaChecksums;
- TreeGridView treeMediaChecksums;
- StackLayout stkProgress;
- StackLayout stkProgress1;
- Label lblProgress;
- ProgressBar prgProgress;
- StackLayout stkProgress2;
- Label lblProgress2;
- ProgressBar prgProgress2;
- Button btnStart;
- Button btnClose;
- Button btnStop;
- #endregion
- }
-}
\ No newline at end of file
diff --git a/Aaru.Gui/Models/ChecksumModel.cs b/Aaru.Gui/Models/ChecksumModel.cs
new file mode 100644
index 000000000..43f93470d
--- /dev/null
+++ b/Aaru.Gui/Models/ChecksumModel.cs
@@ -0,0 +1,9 @@
+namespace Aaru.Gui.Models
+{
+ public class ChecksumModel
+ {
+ public string Track { get; set; }
+ public string Algorithm { get; set; }
+ public string Hash { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Aaru.Gui/ViewModels/ImageChecksumViewModel.cs b/Aaru.Gui/ViewModels/ImageChecksumViewModel.cs
new file mode 100644
index 000000000..1f7d71ec3
--- /dev/null
+++ b/Aaru.Gui/ViewModels/ImageChecksumViewModel.cs
@@ -0,0 +1,665 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Reactive;
+using System.Threading;
+using Aaru.CommonTypes.Interfaces;
+using Aaru.CommonTypes.Structs;
+using Aaru.Console;
+using Aaru.Core;
+using Aaru.Gui.Models;
+using Avalonia.Controls;
+using Avalonia.Threading;
+using ReactiveUI;
+using Schemas;
+
+namespace Aaru.Gui.ViewModels
+{
+ public class ImageChecksumViewModel : ViewModelBase
+ {
+ // How many sectors to read at once
+ const uint SECTORS_TO_READ = 256;
+ readonly IMediaImage _inputFormat;
+ readonly Window _view;
+ bool _adler32Checked;
+ bool _cancel;
+ bool _checksumMediaChecked;
+ bool _checksumTracksChecked;
+ bool _checksumTracksVisible;
+ bool _closeCommandEnabled;
+ bool _closeCommandVisible;
+ bool _crc16Checked;
+ bool _crc32Checked;
+ bool _crc64Checked;
+ bool _fletcher16Checked;
+ bool _fletcher32Checked;
+ bool _md5Checked;
+ bool _mediaChecksumsVisible;
+ bool _optionsEnabled;
+ bool _progress1Visible;
+ double _progress2Max;
+ string _progress2Text;
+ double _progress2Value;
+ bool _progress2Visible;
+ double _progressMax;
+ string _progressText;
+ double _progressValue;
+ bool _progressVisible;
+ bool _resultsVisible;
+ bool _sha1Checked;
+ bool _sha256Checked;
+ bool _sha384Checked;
+ bool _sha512Checked;
+ bool _spamsumChecked;
+ bool _startCommandEnabled;
+ bool _startCommandVisible;
+ bool _stopCommandEnabled;
+ bool _stopCommandVisible;
+ string _title;
+ bool _trackChecksumsVisible;
+
+ public ImageChecksumViewModel(IMediaImage inputFormat, Window view)
+ {
+ _view = view;
+ _cancel = false;
+ _inputFormat = inputFormat;
+ ChecksumTracksChecked = ChecksumTracksVisible;
+ OptionsEnabled = true;
+ ChecksumMediaChecked = true;
+ ChecksumTracksChecked = true;
+ Adler32Checked = true;
+ Crc16Checked = true;
+ Crc32Checked = true;
+ Md5Checked = true;
+ Sha1Checked = true;
+ SpamsumChecked = true;
+ TrackChecksums = new ObservableCollection();
+ MediaChecksums = new ObservableCollection();
+ StartCommand = ReactiveCommand.Create(ExecuteStartCommand);
+ CloseCommand = ReactiveCommand.Create(ExecuteCloseCommand);
+ StopCommand = ReactiveCommand.Create(ExecuteStopCommand);
+ StopCommandVisible = false;
+ StartCommandVisible = true;
+ CloseCommandVisible = true;
+ StopCommandEnabled = true;
+ StartCommandEnabled = true;
+ CloseCommandEnabled = true;
+
+ try
+ {
+ ChecksumTracksVisible = (inputFormat as IOpticalMediaImage)?.Tracks?.Count > 0;
+ }
+ catch
+ {
+ ChecksumTracksVisible = false;
+ }
+ }
+
+ public string Title
+ {
+ get => _title;
+ set => this.RaiseAndSetIfChanged(ref _title, value);
+ }
+
+ public bool OptionsEnabled
+ {
+ get => _optionsEnabled;
+ set => this.RaiseAndSetIfChanged(ref _optionsEnabled, value);
+ }
+
+ public bool ChecksumMediaChecked
+ {
+ get => _checksumMediaChecked;
+ set => this.RaiseAndSetIfChanged(ref _checksumMediaChecked, value);
+ }
+
+ public bool ChecksumTracksChecked
+ {
+ get => _checksumTracksChecked;
+ set => this.RaiseAndSetIfChanged(ref _checksumTracksChecked, value);
+ }
+
+ public bool Adler32Checked
+ {
+ get => _adler32Checked;
+ set => this.RaiseAndSetIfChanged(ref _adler32Checked, value);
+ }
+
+ public bool Crc16Checked
+ {
+ get => _crc16Checked;
+ set => this.RaiseAndSetIfChanged(ref _crc16Checked, value);
+ }
+
+ public bool Crc32Checked
+ {
+ get => _crc32Checked;
+ set => this.RaiseAndSetIfChanged(ref _crc32Checked, value);
+ }
+
+ public bool Crc64Checked
+ {
+ get => _crc64Checked;
+ set => this.RaiseAndSetIfChanged(ref _crc64Checked, value);
+ }
+
+ public bool Fletcher16Checked
+ {
+ get => _fletcher16Checked;
+ set => this.RaiseAndSetIfChanged(ref _fletcher16Checked, value);
+ }
+
+ public bool Fletcher32Checked
+ {
+ get => _fletcher32Checked;
+ set => this.RaiseAndSetIfChanged(ref _fletcher32Checked, value);
+ }
+
+ public bool Md5Checked
+ {
+ get => _md5Checked;
+ set => this.RaiseAndSetIfChanged(ref _md5Checked, value);
+ }
+
+ public bool Sha1Checked
+ {
+ get => _sha1Checked;
+ set => this.RaiseAndSetIfChanged(ref _sha1Checked, value);
+ }
+
+ public bool Sha256Checked
+ {
+ get => _sha256Checked;
+ set => this.RaiseAndSetIfChanged(ref _sha256Checked, value);
+ }
+
+ public bool Sha384Checked
+ {
+ get => _sha384Checked;
+ set => this.RaiseAndSetIfChanged(ref _sha384Checked, value);
+ }
+
+ public bool Sha512Checked
+ {
+ get => _sha512Checked;
+ set => this.RaiseAndSetIfChanged(ref _sha512Checked, value);
+ }
+
+ public bool SpamsumChecked
+ {
+ get => _spamsumChecked;
+ set => this.RaiseAndSetIfChanged(ref _spamsumChecked, value);
+ }
+
+ public bool ResultsVisible
+ {
+ get => _resultsVisible;
+ set => this.RaiseAndSetIfChanged(ref _resultsVisible, value);
+ }
+
+ public bool TrackChecksumsVisible
+ {
+ get => _trackChecksumsVisible;
+ set => this.RaiseAndSetIfChanged(ref _trackChecksumsVisible, value);
+ }
+
+ public bool MediaChecksumsVisible
+ {
+ get => _mediaChecksumsVisible;
+ set => this.RaiseAndSetIfChanged(ref _mediaChecksumsVisible, value);
+ }
+
+ public bool ProgressVisible
+ {
+ get => _progressVisible;
+ set => this.RaiseAndSetIfChanged(ref _progressVisible, value);
+ }
+
+ public bool Progress1Visible
+ {
+ get => _progress1Visible;
+ set => this.RaiseAndSetIfChanged(ref _progress1Visible, value);
+ }
+
+ public string ProgressText
+ {
+ get => _progressText;
+ set => this.RaiseAndSetIfChanged(ref _progressText, value);
+ }
+
+ public double ProgressMax
+ {
+ get => _progressMax;
+ set => this.RaiseAndSetIfChanged(ref _progressMax, value);
+ }
+
+ public double ProgressValue
+ {
+ get => _progressValue;
+ set => this.RaiseAndSetIfChanged(ref _progressValue, value);
+ }
+
+ public bool Progress2Visible
+ {
+ get => _progress2Visible;
+ set => this.RaiseAndSetIfChanged(ref _progress2Visible, value);
+ }
+
+ public string Progress2Text
+ {
+ get => _progress2Text;
+ set => this.RaiseAndSetIfChanged(ref _progress2Text, value);
+ }
+
+ public double Progress2Max
+ {
+ get => _progress2Max;
+ set => this.RaiseAndSetIfChanged(ref _progress2Max, value);
+ }
+
+ public double Progress2Value
+ {
+ get => _progress2Value;
+ set => this.RaiseAndSetIfChanged(ref _progress2Value, value);
+ }
+
+ public bool StartCommandEnabled
+ {
+ get => _startCommandEnabled;
+ set => this.RaiseAndSetIfChanged(ref _startCommandEnabled, value);
+ }
+
+ public bool StartCommandVisible
+ {
+ get => _startCommandVisible;
+ set => this.RaiseAndSetIfChanged(ref _startCommandVisible, value);
+ }
+
+ public bool CloseCommandEnabled
+ {
+ get => _closeCommandEnabled;
+ set => this.RaiseAndSetIfChanged(ref _closeCommandEnabled, value);
+ }
+
+ public bool CloseCommandVisible
+ {
+ get => _closeCommandVisible;
+ set => this.RaiseAndSetIfChanged(ref _closeCommandVisible, value);
+ }
+
+ public bool StopCommandEnabled
+ {
+ get => _stopCommandEnabled;
+ set => this.RaiseAndSetIfChanged(ref _stopCommandEnabled, value);
+ }
+
+ public bool StopCommandVisible
+ {
+ get => _stopCommandVisible;
+ set => this.RaiseAndSetIfChanged(ref _stopCommandVisible, value);
+ }
+
+ public bool ChecksumTracksVisible
+ {
+ get => _checksumTracksVisible;
+ set => this.RaiseAndSetIfChanged(ref _stopCommandVisible, value);
+ }
+
+ public ObservableCollection TrackChecksums { get; }
+ public ObservableCollection MediaChecksums { get; }
+ public ReactiveCommand StartCommand { get; }
+ public ReactiveCommand CloseCommand { get; }
+ public ReactiveCommand StopCommand { get; }
+
+ void ExecuteStartCommand()
+ {
+ OptionsEnabled = false;
+ CloseCommandVisible = false;
+ StartCommandVisible = false;
+ StopCommandVisible = true;
+ ProgressVisible = true;
+ Progress1Visible = true;
+ Progress2Visible = false;
+
+ new Thread(DoWork)
+ {
+ Priority = ThreadPriority.BelowNormal
+ }.Start();
+ }
+
+ void ExecuteCloseCommand() => _view.Close();
+
+ internal void ExecuteStopCommand()
+ {
+ _cancel = true;
+ StopCommandEnabled = false;
+ }
+
+ async void DoWork()
+ {
+ var opticalMediaImage = _inputFormat as IOpticalMediaImage;
+ bool formatHasTracks = false;
+
+ if(opticalMediaImage != null)
+ try
+ {
+ formatHasTracks = opticalMediaImage.Tracks?.Count > 0;
+ }
+ catch
+ {
+ formatHasTracks = false;
+ }
+
+ // Setup progress bars
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ ProgressVisible = true;
+ Progress1Visible = true;
+ Progress2Visible = true;
+ ProgressMax = 1;
+ Progress2Max = (int)(_inputFormat.Info.Sectors / SECTORS_TO_READ);
+
+ if(formatHasTracks &&
+ ChecksumTracksChecked &&
+ opticalMediaImage != null)
+ ProgressMax += opticalMediaImage.Tracks.Count;
+ else
+ {
+ ProgressMax = 2;
+ Progress2Visible = false;
+ }
+ });
+
+ var enabledChecksums = new EnableChecksum();
+
+ if(Adler32Checked)
+ enabledChecksums |= EnableChecksum.Adler32;
+
+ if(Crc16Checked)
+ enabledChecksums |= EnableChecksum.Crc16;
+
+ if(Crc32Checked)
+ enabledChecksums |= EnableChecksum.Crc32;
+
+ if(Crc64Checked)
+ enabledChecksums |= EnableChecksum.Crc64;
+
+ if(Md5Checked)
+ enabledChecksums |= EnableChecksum.Md5;
+
+ if(Sha1Checked)
+ enabledChecksums |= EnableChecksum.Sha1;
+
+ if(Sha256Checked)
+ enabledChecksums |= EnableChecksum.Sha256;
+
+ if(Sha384Checked)
+ enabledChecksums |= EnableChecksum.Sha384;
+
+ if(Sha512Checked)
+ enabledChecksums |= EnableChecksum.Sha512;
+
+ if(SpamsumChecked)
+ enabledChecksums |= EnableChecksum.SpamSum;
+
+ if(Fletcher16Checked)
+ enabledChecksums |= EnableChecksum.Fletcher16;
+
+ if(Fletcher32Checked)
+ enabledChecksums |= EnableChecksum.Fletcher32;
+
+ Checksum mediaChecksum = null;
+
+ if(opticalMediaImage?.Tracks != null)
+ try
+ {
+ Checksum trackChecksum = null;
+
+ if(ChecksumMediaChecked)
+ mediaChecksum = new Checksum(enabledChecksums);
+
+ ulong previousTrackEnd = 0;
+
+ foreach(Track currentTrack in opticalMediaImage.Tracks)
+ {
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ ProgressText =
+ $"Hashing track {currentTrack.TrackSequence} of {opticalMediaImage.Tracks.Count}";
+
+ ProgressValue++;
+ });
+
+ if(currentTrack.TrackStartSector - previousTrackEnd != 0 && ChecksumMediaChecked)
+ for(ulong i = previousTrackEnd + 1; i < currentTrack.TrackStartSector; i++)
+ {
+ ulong sector = i;
+
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress2Value = (int)(sector / SECTORS_TO_READ);
+ Progress2Text = $"Hashing track-less sector {sector}";
+ });
+
+ byte[] hiddenSector = opticalMediaImage.ReadSector(i);
+
+ mediaChecksum?.Update(hiddenSector);
+ }
+
+ AaruConsole.DebugWriteLine("Checksum command",
+ "Track {0} starts at sector {1} and ends at sector {2}",
+ currentTrack.TrackSequence, currentTrack.TrackStartSector,
+ currentTrack.TrackEndSector);
+
+ if(ChecksumTracksChecked)
+ trackChecksum = new Checksum(enabledChecksums);
+
+ ulong sectors = (currentTrack.TrackEndSector - currentTrack.TrackStartSector) + 1;
+ ulong doneSectors = 0;
+
+ while(doneSectors < sectors)
+ {
+ if(_cancel)
+ {
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ CloseCommandVisible = true;
+ StartCommandVisible = false;
+ StopCommandVisible = false;
+ });
+
+ return;
+ }
+
+ byte[] sector;
+
+ if(sectors - doneSectors >= SECTORS_TO_READ)
+ {
+ sector = opticalMediaImage.ReadSectors(doneSectors, SECTORS_TO_READ,
+ currentTrack.TrackSequence);
+
+ ulong doneSectorsToInvoke = doneSectors;
+
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress2Value = (int)(doneSectorsToInvoke / SECTORS_TO_READ);
+
+ Progress2Text =
+ $"Hashing sectors {doneSectorsToInvoke} to {doneSectorsToInvoke + SECTORS_TO_READ} of track {currentTrack.TrackSequence}";
+ });
+
+ doneSectors += SECTORS_TO_READ;
+ }
+ else
+ {
+ sector = opticalMediaImage.ReadSectors(doneSectors, (uint)(sectors - doneSectors),
+ currentTrack.TrackSequence);
+
+ ulong doneSectorsToInvoke = doneSectors;
+
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress2Value = (int)(doneSectorsToInvoke / SECTORS_TO_READ);
+
+ Progress2Text =
+ $"Hashing sectors {doneSectorsToInvoke} to {doneSectorsToInvoke + (sectors - doneSectorsToInvoke)} of track {currentTrack.TrackSequence}";
+ });
+
+ doneSectors += sectors - doneSectors;
+ }
+
+ if(ChecksumMediaChecked)
+ mediaChecksum?.Update(sector);
+
+ if(ChecksumTracksChecked)
+ trackChecksum?.Update(sector);
+ }
+
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ if(ChecksumTracksChecked != true)
+ return;
+
+ if(trackChecksum == null)
+ return;
+
+ foreach(ChecksumType chk in trackChecksum.End())
+ TrackChecksums.Add(new ChecksumModel
+ {
+ Track = currentTrack.TrackSequence.ToString(), Algorithm = chk.type.ToString(),
+ Hash = chk.Value
+ });
+ });
+
+ previousTrackEnd = currentTrack.TrackEndSector;
+ }
+
+ if(opticalMediaImage.Info.Sectors - previousTrackEnd != 0 && ChecksumMediaChecked)
+ for(ulong i = previousTrackEnd + 1; i < opticalMediaImage.Info.Sectors; i++)
+ {
+ ulong sector = i;
+
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress2Value = (int)(sector / SECTORS_TO_READ);
+ Progress2Text = $"Hashing track-less sector {sector}";
+ });
+
+ byte[] hiddenSector = opticalMediaImage.ReadSector(i);
+ mediaChecksum?.Update(hiddenSector);
+ }
+
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ if(mediaChecksum == null)
+ return;
+
+ foreach(ChecksumType chk in mediaChecksum.End())
+ MediaChecksums.Add(new ChecksumModel
+ {
+ Algorithm = chk.type.ToString(), Hash = chk.Value
+ });
+ });
+ }
+ catch(Exception ex)
+ {
+ AaruConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message);
+ AaruConsole.WriteLine("Unable to get separate tracks, not checksumming them");
+ }
+ else
+ {
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress1Visible = false;
+ });
+
+ mediaChecksum = new Checksum(enabledChecksums);
+
+ ulong doneSectors = 0;
+
+ while(doneSectors < _inputFormat.Info.Sectors)
+ {
+ if(_cancel)
+ {
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ CloseCommandVisible = true;
+ StartCommandVisible = false;
+ StopCommandVisible = false;
+ });
+
+ return;
+ }
+
+ byte[] sector;
+
+ if(_inputFormat.Info.Sectors - doneSectors >= SECTORS_TO_READ)
+ {
+ sector = _inputFormat.ReadSectors(doneSectors, SECTORS_TO_READ);
+
+ ulong doneSectorsToInvoke = doneSectors;
+
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress2Value = (int)(doneSectorsToInvoke / SECTORS_TO_READ);
+
+ Progress2Text =
+ $"Hashing sectors {doneSectorsToInvoke} to {doneSectorsToInvoke + SECTORS_TO_READ}";
+ });
+
+ doneSectors += SECTORS_TO_READ;
+ }
+ else
+ {
+ sector = _inputFormat.ReadSectors(doneSectors, (uint)(_inputFormat.Info.Sectors - doneSectors));
+ ulong doneSectorsToInvoke = doneSectors;
+
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ Progress2Value = (int)(doneSectorsToInvoke / SECTORS_TO_READ);
+
+ Progress2Text =
+ $"Hashing sectors {doneSectorsToInvoke} to {doneSectorsToInvoke + (_inputFormat.Info.Sectors - doneSectorsToInvoke)}";
+ });
+
+ doneSectors += _inputFormat.Info.Sectors - doneSectors;
+ }
+
+ mediaChecksum.Update(sector);
+ }
+
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ foreach(ChecksumType chk in mediaChecksum.End())
+ MediaChecksums.Add(new ChecksumModel
+ {
+ Algorithm = chk.type.ToString(), Hash = chk.Value
+ });
+ });
+ }
+
+ if(ChecksumTracksChecked)
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ TrackChecksumsVisible = true;
+ });
+
+ if(ChecksumMediaChecked)
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ MediaChecksumsVisible = true;
+ });
+
+ Statistics.AddCommand("checksum");
+
+ await Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ OptionsEnabled = false;
+ ResultsVisible = true;
+ ProgressVisible = false;
+ StartCommandVisible = false;
+ StopCommandVisible = false;
+ CloseCommandVisible = true;
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/Aaru.Gui/ViewModels/ImageInfoViewModel.cs b/Aaru.Gui/ViewModels/ImageInfoViewModel.cs
index a109da403..284fd43a2 100644
--- a/Aaru.Gui/ViewModels/ImageInfoViewModel.cs
+++ b/Aaru.Gui/ViewModels/ImageInfoViewModel.cs
@@ -13,6 +13,7 @@ using Aaru.Decoders.SCSI;
using Aaru.Decoders.Xbox;
using Aaru.Gui.Models;
using Aaru.Gui.Tabs;
+using Aaru.Gui.Views;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media.Imaging;
@@ -29,7 +30,9 @@ namespace Aaru.Gui.ViewModels
readonly IMediaImage _imageFormat;
readonly Window _view;
IFilter _filter;
- string _imagePath;
+
+ ImageChecksumWindow _imageChecksumWindow;
+ string _imagePath;
public ImageInfoViewModel(string imagePath, IFilter filter, IMediaImage imageFormat, Window view)
@@ -744,23 +747,22 @@ namespace Aaru.Gui.ViewModels
protected void ExecuteChecksumCommand()
{
- /* TODO: frmImageChecksum
- if(frmImageChecksum != null)
+ if(_imageChecksumWindow != null)
{
- frmImageChecksum.Show();
+ _imageChecksumWindow.Show();
return;
}
- frmImageChecksum = new frmImageChecksum(imageFormat);
+ _imageChecksumWindow = new ImageChecksumWindow();
+ _imageChecksumWindow.DataContext = new ImageChecksumViewModel(_imageFormat, _imageChecksumWindow);
- frmImageChecksum.Closed += (s, ea) =>
+ _imageChecksumWindow.Closed += (sender, args) =>
{
- frmImageChecksum = null;
+ _imageChecksumWindow = null;
};
- frmImageChecksum.Show();
- */
+ _imageChecksumWindow.Show();
}
protected void ExecuteConvertCommand()
diff --git a/Aaru.Gui/Views/ImageChecksumWindow.xaml b/Aaru.Gui/Views/ImageChecksumWindow.xaml
new file mode 100644
index 000000000..212457fa9
--- /dev/null
+++ b/Aaru.Gui/Views/ImageChecksumWindow.xaml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Aaru.Gui/Views/ImageChecksumWindow.xaml.cs b/Aaru.Gui/Views/ImageChecksumWindow.xaml.cs
new file mode 100644
index 000000000..db0d64528
--- /dev/null
+++ b/Aaru.Gui/Views/ImageChecksumWindow.xaml.cs
@@ -0,0 +1,27 @@
+using System.ComponentModel;
+using Aaru.Gui.ViewModels;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Aaru.Gui.Views
+{
+ public class ImageChecksumWindow : Window
+ {
+ public ImageChecksumWindow()
+ {
+ InitializeComponent();
+ #if DEBUG
+ this.AttachDevTools();
+ #endif
+ }
+
+ void InitializeComponent() => AvaloniaXamlLoader.Load(this);
+
+ protected override void OnClosing(CancelEventArgs e)
+ {
+ (DataContext as ImageChecksumViewModel)?.ExecuteStopCommand();
+ base.OnClosing(e);
+ }
+ }
+}
\ No newline at end of file