From c7cbdc6d197b846540e993dcc63ce4e1df78c14a Mon Sep 17 00:00:00 2001 From: Filippo Ferrario <102259289+ferrariofilippo@users.noreply.github.com> Date: Thu, 24 Jul 2025 13:20:19 +0200 Subject: [PATCH 01/10] Feature: Add "Digital Signatures" tab to the properties window --- .../Enums/PropertiesNavigationViewItemType.cs | 7 +- .../PropertiesNavigationViewItemFactory.cs | 28 ++- .../Data/Models/SignatureInfoItem.cs | 77 +++++++ .../Helpers/Win32/Win32PInvoke.Methods.cs | 39 +++- src/Files.App/Strings/en-US/Resources.resw | 18 ++ .../Utils/Signatures/DigitalSignaturesUtil.cs | 15 ++ .../Properties/MainPropertiesViewModel.cs | 3 +- .../Properties/SignaturesViewModel.cs | 28 +++ .../Views/Properties/SignaturesPage.xaml | 193 ++++++++++++++++++ .../Views/Properties/SignaturesPage.xaml.cs | 40 ++++ 10 files changed, 435 insertions(+), 13 deletions(-) create mode 100644 src/Files.App/Data/Models/SignatureInfoItem.cs create mode 100644 src/Files.App/Utils/Signatures/DigitalSignaturesUtil.cs create mode 100644 src/Files.App/ViewModels/Properties/SignaturesViewModel.cs create mode 100644 src/Files.App/Views/Properties/SignaturesPage.xaml create mode 100644 src/Files.App/Views/Properties/SignaturesPage.xaml.cs diff --git a/src/Files.App/Data/Enums/PropertiesNavigationViewItemType.cs b/src/Files.App/Data/Enums/PropertiesNavigationViewItemType.cs index 4b33779e6c1d..766bb13cc863 100644 --- a/src/Files.App/Data/Enums/PropertiesNavigationViewItemType.cs +++ b/src/Files.App/Data/Enums/PropertiesNavigationViewItemType.cs @@ -47,5 +47,10 @@ public enum PropertiesNavigationViewItemType /// Shortcut page type /// Shortcut, - } + + /// + /// Signatures page type + /// + Signatures, + } } diff --git a/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs b/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs index f546301858e4..44b0c569740d 100644 --- a/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs +++ b/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs @@ -61,9 +61,16 @@ public static ObservableCollection Initialize ItemType = PropertiesNavigationViewItemType.Compatibility, ThemedIconStyle = (Style)Application.Current.Resources["App.ThemedIcons.Properties.Compatability"], }; - - PropertiesNavigationViewItems.Add(generalItem); - PropertiesNavigationViewItems.Add(securityItem); + var signaturesItem = new NavigationViewItemButtonStyleItem() + { + Name = Strings.Signatures.GetLocalizedResource(), + ItemType = PropertiesNavigationViewItemType.Signatures, + ThemedIconStyle = (Style)Application.Current.Resources["App.ThemedIcons.Properties.Signatures"], + }; + + PropertiesNavigationViewItems.Add(generalItem); + PropertiesNavigationViewItems.Add(signaturesItem); + PropertiesNavigationViewItems.Add(securityItem); PropertiesNavigationViewItems.Add(hashesItem); PropertiesNavigationViewItems.Add(shortcutItem); PropertiesNavigationViewItems.Add(libraryItem); @@ -89,7 +96,8 @@ public static ObservableCollection Initialize PropertiesNavigationViewItems.Remove(securityItem); PropertiesNavigationViewItems.Remove(customizationItem); PropertiesNavigationViewItems.Remove(hashesItem); - } + PropertiesNavigationViewItems.Remove(signaturesItem); + } else if (item is ListedItem listedItem) { var isShortcut = listedItem.IsShortcut; @@ -106,10 +114,13 @@ public static ObservableCollection Initialize if (!securityItemEnabled) PropertiesNavigationViewItems.Remove(securityItem); - if (!hashItemEnabled) - PropertiesNavigationViewItems.Remove(hashesItem); + if (!hashItemEnabled) + { + PropertiesNavigationViewItems.Remove(hashesItem); + PropertiesNavigationViewItems.Remove(signaturesItem); + } - if (!isShortcut) + if (!isShortcut) PropertiesNavigationViewItems.Remove(shortcutItem); if (!isLibrary) @@ -132,7 +143,8 @@ public static ObservableCollection Initialize PropertiesNavigationViewItems.Remove(detailsItem); PropertiesNavigationViewItems.Remove(customizationItem); PropertiesNavigationViewItems.Remove(compatibilityItem); - } + PropertiesNavigationViewItems.Remove(signaturesItem); + } return PropertiesNavigationViewItems; } diff --git a/src/Files.App/Data/Models/SignatureInfoItem.cs b/src/Files.App/Data/Models/SignatureInfoItem.cs new file mode 100644 index 000000000000..5a3593bb93f6 --- /dev/null +++ b/src/Files.App/Data/Models/SignatureInfoItem.cs @@ -0,0 +1,77 @@ +// Copyright (c) Files Community +// Licensed under the MIT License. + +using System.Windows.Input; + +namespace Files.App.Data.Models +{ + public sealed partial class SignatureInfoItem : ObservableObject + { + private string _Version = string.Empty; + public string Version + { + get => _Version; + set => SetProperty(ref _Version, value); + } + + private string _IssuedBy = string.Empty; + public string IssuedBy + { + get => _IssuedBy; + set => SetProperty(ref _IssuedBy, value); + } + + private string _IssuedTo = string.Empty; + public string IssuedTo + { + get => _IssuedTo; + set => SetProperty(ref _IssuedTo, value); + } + + private string _ValidFromTimestamp = string.Empty; + public string ValidFromTimestamp + { + get => _ValidFromTimestamp; + set => SetProperty(ref _ValidFromTimestamp, value); + } + + private string _ValidToTimestamp = string.Empty; + public string ValidToTimestamp + { + get => _ValidToTimestamp; + set => SetProperty(ref _ValidToTimestamp, value); + } + + private string _VerifiedTimestamp = string.Empty; + public string VerifiedTimestamp + { + get => _VerifiedTimestamp; + set => SetProperty(ref _VerifiedTimestamp, value); + } + + private bool _Verified = false; + public bool Verified + { + get => _Verified; + set + { + if (SetProperty(ref _Verified, value)) + OnPropertyChanged(nameof(Glyph)); + } + } + + public string Glyph => Verified ? "\uE930" : "\uEA39"; + + public ICommand OpenDetailsCommand { get; } + + public SignatureInfoItem() + { + OpenDetailsCommand = new AsyncRelayCommand(DoOpenDetails); + } + + private Task DoOpenDetails() + { + return Task.CompletedTask; + } + } +} diff --git a/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs b/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs index 5d700736a2fa..06c875be2e25 100644 --- a/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs +++ b/src/Files.App/Helpers/Win32/Win32PInvoke.Methods.cs @@ -1,5 +1,5 @@ -// Copyright (c) 2024 Files Community -// Licensed under the MIT License. See the LICENSE. +// Copyright (c) Files Community +// Licensed under the MIT License. using System.IO; using System.Runtime.InteropServices; @@ -347,5 +347,38 @@ public static extern int SHGetKnownFolderPath( IntPtr hToken, out IntPtr pszPath ); - } + + [DllImport("wintrust.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern uint WinVerifyTrust( + IntPtr hwnd, + [MarshalAs(UnmanagedType.LPStruct)] Guid pgActionID, + IntPtr pWVTData + ); + + [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern bool CryptQueryObject( + uint dwObjectType, + IntPtr pvObject, + uint dwExpectedContentTypeFlags, + uint dwExpectedFormatTypeFlags, + uint dwFlags, + out uint pdwMsgAndCertEncodingType, + out uint pdwContentType, + out uint pdwFormatType, + out IntPtr phCertStore, + out IntPtr phMsg, + out IntPtr ppvContext + ); + + [DllImport("crypt32.dll", SetLastError = true)] + private static extern bool CertCloseStore( + IntPtr hCertStore, + uint dwFlags + ); + + [DllImport("crypt32.dll", SetLastError = true)] + private static extern bool CryptMsgClose( + IntPtr hCryptMsg + ); + } } diff --git a/src/Files.App/Strings/en-US/Resources.resw b/src/Files.App/Strings/en-US/Resources.resw index fb30d3afa016..66db6101b1ef 100644 --- a/src/Files.App/Strings/en-US/Resources.resw +++ b/src/Files.App/Strings/en-US/Resources.resw @@ -4273,4 +4273,22 @@ Filename + + Signatures + + + Signature list + + + Issued by: + + + Issued to: + + + Valid from: + + + Valid to: + diff --git a/src/Files.App/Utils/Signatures/DigitalSignaturesUtil.cs b/src/Files.App/Utils/Signatures/DigitalSignaturesUtil.cs new file mode 100644 index 000000000000..97707cab1fb3 --- /dev/null +++ b/src/Files.App/Utils/Signatures/DigitalSignaturesUtil.cs @@ -0,0 +1,15 @@ +// Copyright (c) Files Community +// Licensed under the MIT License. + +namespace Files.App.Utils.Signatures +{ + public static class DigitalSignaturesUtil + { + public static List GetSignaturesOfItem(string filePath) + { + var signatures = new List(); + + return signatures; + } + } +} diff --git a/src/Files.App/ViewModels/Properties/MainPropertiesViewModel.cs b/src/Files.App/ViewModels/Properties/MainPropertiesViewModel.cs index 14a7922e0115..b3029eb9c41e 100644 --- a/src/Files.App/ViewModels/Properties/MainPropertiesViewModel.cs +++ b/src/Files.App/ViewModels/Properties/MainPropertiesViewModel.cs @@ -41,7 +41,8 @@ public NavigationViewItemButtonStyleItem SelectedNavigationViewItem PropertiesNavigationViewItemType.Customization => typeof(CustomizationPage), PropertiesNavigationViewItemType.Compatibility => typeof(CompatibilityPage), PropertiesNavigationViewItemType.Hashes => typeof(HashesPage), - _ => typeof(GeneralPage), + PropertiesNavigationViewItemType.Signatures => typeof(SignaturesPage), + _ => typeof(GeneralPage), }; _mainFrame?.Navigate(page, parameter, new EntranceNavigationTransitionInfo()); diff --git a/src/Files.App/ViewModels/Properties/SignaturesViewModel.cs b/src/Files.App/ViewModels/Properties/SignaturesViewModel.cs new file mode 100644 index 000000000000..7b83c4c0e90c --- /dev/null +++ b/src/Files.App/ViewModels/Properties/SignaturesViewModel.cs @@ -0,0 +1,28 @@ +// Copyright (c) Files Community +// Licensed under the MIT License. + +using Files.App.Utils.Signatures; + +namespace Files.App.ViewModels.Properties +{ + public sealed partial class SignaturesViewModel : ObservableObject, IDisposable + { + private CancellationTokenSource _cancellationTokenSource; + + public ObservableCollection Signatures { get; set; } + + public SignaturesViewModel(ListedItem item) + { + _cancellationTokenSource = new(); + Signatures = new(); + + var signatures = DigitalSignaturesUtil.GetSignaturesOfItem(item.ItemPath); + signatures.ForEach(s => Signatures.Add(s)); + } + + public void Dispose() + { + _cancellationTokenSource.Cancel(); + } + } +} diff --git a/src/Files.App/Views/Properties/SignaturesPage.xaml b/src/Files.App/Views/Properties/SignaturesPage.xaml new file mode 100644 index 000000000000..edeec6562dcd --- /dev/null +++ b/src/Files.App/Views/Properties/SignaturesPage.xaml @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +