23 Commits
V1.11 ... V1.13

Author SHA1 Message Date
BONNEVILLE Geoffroy
4aefbcb8b9 RecycleBin now uses resources
RecycleBin bugs correction
2018-03-12 17:30:03 +01:00
BONNEVILLE Geoffroy
56129253d9 Use ModernKeePass Lib 2.38.2
Changed suspension save errors handling
2018-03-12 12:45:12 +01:00
BONNEVILLE Geoffroy
7613629d87 Deactivation of buggy Splat custom icon implementation 2018-03-12 12:40:07 +01:00
BONNEVILLE Geoffroy
fb0eab00c2 Create group and delete current group hidden in Recycle Bin 2018-03-12 11:27:15 +01:00
BONNEVILLE Geoffroy
5b8c3b9b11 Typo in restore button 2018-03-12 11:18:42 +01:00
BONNEVILLE Geoffroy
700f76679a Corrected RecycleBin group bug
Database Settings page now has radio button for recycle bin
2018-03-12 10:21:36 +01:00
BONNEVILLE Geoffroy
e7d731bb04 KeepassLib version 2.38
Added a new settings page to allow auto-save or not
App now resumes correctly from suspend
Settings service now allows getting default values
Removed french special characters from metadata
Code cleanup
2018-03-09 18:06:06 +01:00
BONNEVILLE Geoffroy
49637fcc3b KeepassLib version update to 2.38 2018-03-09 17:49:47 +01:00
BONNEVILLE Geoffroy
fc25d7ea93 Update some packages 2018-03-07 18:39:56 +01:00
BONNEVILLE Geoffroy
cca6579274 Removed useless code in Donate page 2018-02-23 18:13:44 +01:00
BONNEVILLE Geoffroy
7dbf93fe7b Changed most services to singletons
Refactor the Database Service (no more enum, ...)
Restored the Donate page with Paypal web page
Added (but not working) MS App Center integration
Corrected tests accordingly
WIP AOP to detect database changes
2018-02-23 18:09:21 +01:00
BONNEVILLE Geoffroy
b46ab8db51 Code cleanup
Popup discard action now works
2018-01-09 18:40:11 +01:00
BONNEVILLE Geoffroy
a19519fa73 Removed database status in favor of much cleaner code
Implemented (but deactivated) anti corruption mechanism
WIP detect changes and save them if opening another database
2018-01-08 18:52:03 +01:00
BONNEVILLE Geoffroy
4a3f36d38b Version bump to 1.13
New group button is now at the bottom of the listview
2018-01-08 11:02:53 +01:00
BONNEVILLE Geoffroy
4ae02fc07b Corrected test case to reflect page removal 2018-01-03 11:37:09 +01:00
BONNEVILLE Geoffroy
047fca32bf Hid donations pages (need to implement 3rd party API) 2018-01-03 11:29:51 +01:00
BONNEVILLE Geoffroy
abbff449c0 Removed User Account from composite key (probably never going to work as intended)
Changed copy URL to navigate to URL in entry quick menu
2017-12-26 17:54:13 +01:00
BONNEVILLE Geoffroy
fba668860b WIP user accounts - not working at all 2017-12-21 18:24:01 +01:00
BONNEVILLE Geoffroy
acb196d9c2 WIP Windows User Accounts Composite Key integration 2017-12-20 18:49:11 +01:00
BONNEVILLE Geoffroy
dfa3a21e6b Removed an useless converter
Groups in menu now use instead a Template selector (depending on IIsSelected)
2017-12-19 18:44:35 +01:00
BONNEVILLE Geoffroy
7ff6bccbc4 Added some tests
Removed false first group, replaced it a button in the header
Code refactor
2017-12-18 18:53:42 +01:00
BONNEVILLE Geoffroy
88e5b80778 Version bump to 1.12
Added small menu on entries list to copy login, password and URL
2017-12-18 14:09:04 +01:00
BONNEVILLE Geoffroy
d127431396 Third try on store special character escaping 2017-12-18 11:52:49 +01:00
181 changed files with 1415 additions and 782 deletions

View File

@@ -0,0 +1,33 @@
using System;
using Windows.UI.Xaml;
using Microsoft.Xaml.Interactivity;
using ModernKeePass.Common;
namespace ModernKeePass.Actions
{
public class NavigateToUrlAction : DependencyObject, IAction
{
public string Url
{
get { return (string)GetValue(UrlProperty); }
set { SetValue(UrlProperty, value); }
}
public static readonly DependencyProperty UrlProperty =
DependencyProperty.Register("Url", typeof(string), typeof(NavigateToUrlAction), new PropertyMetadata(string.Empty));
public object Execute(object sender, object parameter)
{
try
{
var uri = new Uri(Url);
return Windows.System.Launcher.LaunchUriAsync(uri).GetAwaiter().GetResult();
}
catch (Exception ex)
{
MessageDialogHelper.ShowErrorDialog(ex);
return false;
}
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using ModernKeePass.Services;
namespace ModernKeePass.Attributes
{
[AttributeUsage(AttributeTargets.All)]
public class DatabaseChangedAttribute: Attribute
{
public DatabaseChangedAttribute()
{
DatabaseService.Instance.HasChanged = true;
}
}
}

View File

@@ -0,0 +1,26 @@
using System.Reflection;
using ModernKeePass.Interfaces;
namespace ModernKeePass.Aop
{
public class DatabaseChangedProxy<T>: IProxyInvocationHandler
{
private readonly T _decorated;
private readonly IDatabaseService _databaseService;
public DatabaseChangedProxy(T decorated, IDatabaseService databaseService)
{
_decorated = decorated;
_databaseService = databaseService;
}
public object Invoke(object proxy, MethodInfo method, object[] parameters)
{
object retVal = null;
retVal = method.Invoke(proxy, parameters);
_databaseService.HasChanged = true;
return retVal;
}
}
}

View File

@@ -6,6 +6,9 @@ using Windows.Storage;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Push;
using ModernKeePass.Common;
using ModernKeePass.Exceptions;
using ModernKeePass.Services;
@@ -20,20 +23,20 @@ namespace ModernKeePass
/// </summary>
sealed partial class App
{
public DatabaseService Database { get; private set; }
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
AppCenter.Start("79d23520-a486-4f63-af81-8d90bf4e1bea", typeof(Analytics), typeof(Push));
InitializeComponent();
Suspending += OnSuspending;
Resuming += OnResuming;
UnhandledException += OnUnhandledException;
Database = new DatabaseService();
}
#region Event Handlers
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs unhandledExceptionEventArgs)
@@ -46,9 +49,16 @@ namespace ModernKeePass
? exception.InnerException
: exception;
if (!(realException is SaveException)) return;
unhandledExceptionEventArgs.Handled = true;
MessageDialogHelper.SaveErrorDialog(realException as SaveException, Database);
if (realException is SaveException)
{
unhandledExceptionEventArgs.Handled = true;
MessageDialogHelper.SaveErrorDialog(realException as SaveException, DatabaseService.Instance);
}
else if (realException is DatabaseOpenedException)
{
unhandledExceptionEventArgs.Handled = true;
MessageDialogHelper.SaveUnchangedDialog(realException as DatabaseOpenedException, DatabaseService.Instance);
}
}
/// <summary>
@@ -90,7 +100,10 @@ namespace ModernKeePass
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
//TODO: Load state from previously terminated application
#if DEBUG
MessageDialogHelper.ShowNotificationDialog("App terminated", "Windows or an error made the app terminate");
#endif
}
// Place the frame in the current Window
@@ -125,6 +138,31 @@ namespace ModernKeePass
Window.Current.Activate();
}
private async void OnResuming(object sender, object e)
{
var currentFrame = Window.Current.Content as Frame;
var database = DatabaseService.Instance;
if (database.DatabaseFile == null)
{
#if DEBUG
ToastNotificationHelper.ShowGenericToast("App suspended", "Nothing to do, no previous database opened");
#endif
return;
}
try
{
if (database.CompositeKey != null) await database.ReOpen();
}
catch (Exception ex)
{
currentFrame?.Navigate(typeof(MainPage));
#if DEBUG
MessageDialogHelper.ShowErrorDialog(ex);
#endif
ToastNotificationHelper.ShowGenericToast("App suspended", "Database was closed (changes were saved)");
}
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
@@ -142,11 +180,21 @@ namespace ModernKeePass
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
UnhandledException -= OnUnhandledException;
Database.Save();
var database = DatabaseService.Instance;
try
{
if (SettingsService.Instance.GetSetting("SaveSuspend", true)) database.Save();
await database.Close(false);
}
catch (Exception exception)
{
#if DEBUG
ToastNotificationHelper.ShowErrorToast(exception);
#endif
}
deferral.Complete();
}
@@ -158,7 +206,7 @@ namespace ModernKeePass
{
base.OnFileActivated(args);
var rootFrame = new Frame();
Database.DatabaseFile = args.Files[0] as StorageFile;
DatabaseService.Instance.DatabaseFile = args.Files[0] as StorageFile;
rootFrame.Navigate(typeof(MainPage), args);
Window.Current.Content = rootFrame;
Window.Current.Activate();

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using Windows.Storage.Pickers;
using Windows.UI.Popups;
using Windows.UI.Xaml.Media.Animation;
using ModernKeePass.Exceptions;
using ModernKeePass.Interfaces;
@@ -10,19 +9,20 @@ namespace ModernKeePass.Common
{
public static class MessageDialogHelper
{
public static async void ShowActionDialog(string title, string contentText, string actionButtonText, string cancelButtonText, UICommandInvokedHandler action)
// TODO: include resources
public static async void ShowActionDialog(string title, string contentText, string actionButtonText, string cancelButtonText, UICommandInvokedHandler actionCommand, UICommandInvokedHandler cancelCommand)
{
// Create the message dialog and set its content
var messageDialog = CreateBasicDialog(title, contentText, cancelButtonText);
var messageDialog = CreateBasicDialog(title, contentText, cancelButtonText, cancelCommand);
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
messageDialog.Commands.Add(new UICommand(actionButtonText, action));
messageDialog.Commands.Add(new UICommand(actionButtonText, actionCommand));
// Show the message dialog
await messageDialog.ShowAsync();
}
public static void SaveErrorDialog(SaveException exception, IDatabase database)
public static void SaveErrorDialog(SaveException exception, IDatabaseService database)
{
ShowActionDialog("Save error", exception.InnerException.Message, "Save as", "Discard", async command =>
{
@@ -35,6 +35,19 @@ namespace ModernKeePass.Common
var file = await savePicker.PickSaveFileAsync();
if (file != null) database.Save(file);
}, null);
}
public static void SaveUnchangedDialog(DatabaseOpenedException exception, IDatabaseService database)
{
ShowActionDialog("Opened database", $"Database {database.Name} is currently opened. What to you wish to do?", "Save changes", "Discard", command =>
{
database.Save();
database.Close();
},
command =>
{
database.Close();
});
}
@@ -42,7 +55,7 @@ namespace ModernKeePass.Common
{
if (exception == null) return;
// Create the message dialog and set its content
var messageDialog = CreateBasicDialog("Error occured", exception.Message, "OK");
var messageDialog = CreateBasicDialog(exception.Message, exception.StackTrace, "OK");
// Show the message dialog
await messageDialog.ShowAsync();
@@ -56,13 +69,13 @@ namespace ModernKeePass.Common
await dialog.ShowAsync();
}
private static MessageDialog CreateBasicDialog(string title, string message, string dismissActionText)
private static MessageDialog CreateBasicDialog(string title, string message, string dismissActionText, UICommandInvokedHandler cancelCommand = null)
{
// Create the message dialog and set its content
var messageDialog = new MessageDialog(message, title);
// Add commands and set their callbacks;
messageDialog.Commands.Add(new UICommand(dismissActionText));
messageDialog.Commands.Add(new UICommand(dismissActionText, cancelCommand));
// Set the command that will be invoked by default
messageDialog.DefaultCommandIndex = 1;

View File

@@ -45,5 +45,10 @@ namespace ModernKeePass.Common
};
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
public static void ShowErrorToast(Exception exception)
{
ShowGenericToast(exception.Source, exception.Message);
}
}
}

View File

@@ -1,20 +0,0 @@
using System;
using Windows.UI.Text;
using Windows.UI.Xaml.Data;
namespace ModernKeePass.Converters
{
public class BooleanToFontStyleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var boolean = value is bool ? (bool)value : false;
return boolean ? FontStyle.Italic : FontStyle.Normal;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,9 @@
using System;
namespace ModernKeePass.Exceptions
{
public class DatabaseOpenedException: Exception
{
}
}

View File

@@ -1,4 +1,5 @@
using Windows.Storage;
using System.Threading.Tasks;
using Windows.Storage;
using ModernKeePass.ViewModels;
using ModernKeePassLib;
using ModernKeePassLib.Cryptography.KeyDerivation;
@@ -6,24 +7,29 @@ using ModernKeePassLib.Keys;
namespace ModernKeePass.Interfaces
{
public interface IDatabase
public interface IDatabaseService
{
string Name { get; }
bool RecycleBinEnabled { get; set; }
int Status { get; set; }
//int Status { get; set; }
GroupVm RootGroup { get; set; }
GroupVm RecycleBin { get; set; }
StorageFile DatabaseFile { get; set; }
CompositeKey CompositeKey { get; set; }
PwUuid DataCipher { get; set; }
PwCompressionAlgorithm CompressionAlgorithm { get; set; }
KdfParameters KeyDerivation { get; set; }
bool IsOpen { get; }
bool IsFileOpen { get; }
bool IsClosed { get; }
bool HasChanged { get; set; }
void Open(CompositeKey key, bool createNew);
void UpdateCompositeKey(CompositeKey key);
Task Open(CompositeKey key, bool createNew = false);
Task ReOpen();
void Save();
void Save(StorageFile file);
void CreateRecycleBin();
void CreateRecycleBin(string title);
void AddDeletedItem(PwUuid id);
void Close();
Task Close(bool releaseFile = true);
}
}

View File

@@ -0,0 +1,9 @@
using System.Reflection;
namespace ModernKeePass.Interfaces
{
public interface IProxyInvocationHandler
{
object Invoke(object proxy, MethodInfo method, object[] parameters);
}
}

View File

@@ -34,6 +34,6 @@ namespace ModernKeePass.Interfaces
/// <summary>
/// Delete from ViewModel
/// </summary>
void MarkForDelete();
void MarkForDelete(string recycleBinTitle);
}
}

View File

@@ -4,7 +4,7 @@ using Windows.Storage;
namespace ModernKeePass.Interfaces
{
public interface IRecent
public interface IRecentService
{
int EntryCount { get; }
Task<IStorageItem> GetFileAsync(string token);

View File

@@ -1,6 +1,6 @@
namespace ModernKeePass.Interfaces
{
public interface IResource
public interface IResourceService
{
string GetResourceValue(string key);
}

View File

@@ -1,8 +0,0 @@
namespace ModernKeePass.Interfaces
{
public interface ISettings
{
T GetSetting<T>(string property);
void PutSetting<T>(string property, T value);
}
}

View File

@@ -0,0 +1,8 @@
namespace ModernKeePass.Interfaces
{
public interface ISettingsService
{
T GetSetting<T>(string property, T defaultValue = default(T));
void PutSetting<T>(string property, T value);
}
}

View File

@@ -109,20 +109,27 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="Actions\ClipboardAction.cs" />
<Compile Include="Actions\NavigateToUrlAction.cs" />
<Compile Include="Actions\SetupFocusAction.cs" />
<Compile Include="Aop\DatabaseChangedProxy.cs" />
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="Aop\DatabaseChanged.cs" />
<Compile Include="Exceptions\DatabaseOpenedException.cs" />
<Compile Include="Interfaces\ILicenseService.cs" />
<Compile Include="Interfaces\IRecent.cs" />
<Compile Include="Interfaces\IProxyInvocationHandler.cs" />
<Compile Include="Interfaces\IRecentService.cs" />
<Compile Include="Interfaces\IRecentItem.cs" />
<Compile Include="Interfaces\IResource.cs" />
<Compile Include="ViewModels\DonateVm.cs" />
<Compile Include="Interfaces\IResourceService.cs" />
<Compile Include="Services\SingletonServiceBase.cs" />
<Compile Include="TemplateSelectors\SelectableDataTemplateSelector.cs" />
<Compile Include="ViewModels\Items\SettingsSaveVm.cs" />
<Compile Include="Views\MainPageFrames\DonatePage.xaml.cs">
<DependentUpon>DonatePage.xaml</DependentUpon>
</Compile>
<Compile Include="Services\DatabaseService.cs" />
<Compile Include="Interfaces\ISettings.cs" />
<Compile Include="Interfaces\ISettingsService.cs" />
<Compile Include="Common\MessageDialogHelper.cs" />
<Compile Include="Common\NavigationHelper.cs" />
<Compile Include="Common\NotifyPropertyChangedBase.cs" />
@@ -139,7 +146,7 @@
<Compile Include="Converters\NullToBooleanConverter.cs" />
<Compile Include="Exceptions\SaveException.cs" />
<Compile Include="Extensions\DispatcherTaskExtensions.cs" />
<Compile Include="Interfaces\IDatabase.cs" />
<Compile Include="Interfaces\IDatabaseService.cs" />
<Compile Include="Interfaces\IHasSelectableObject.cs" />
<Compile Include="Interfaces\ISelectableModel.cs" />
<Compile Include="Views\BasePages\LayoutAwarePageBase.cs" />
@@ -149,6 +156,9 @@
<Compile Include="Views\SettingsPageFrames\SettingsNewDatabasePage.xaml.cs">
<DependentUpon>SettingsNewDatabasePage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPageFrames\SettingsSavePage.xaml.cs">
<DependentUpon>SettingsSavePage.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SettingsPageFrames\SettingsSecurityPage.xaml.cs">
<DependentUpon>SettingsSecurityPage.xaml</DependentUpon>
</Compile>
@@ -165,7 +175,6 @@
<Compile Include="Converters\ColorToBrushConverter.cs" />
<Compile Include="Converters\DoubleToSolidColorBrushConverter.cs" />
<Compile Include="Converters\InverseBooleanToVisibilityConverter.cs" />
<Compile Include="Converters\BooleanToFontStyleConverter.cs" />
<Compile Include="Converters\PluralizationConverter.cs" />
<Compile Include="Converters\ProgressBarLegalValuesConverter.cs" />
<Compile Include="Converters\TextToWidthConverter.cs" />
@@ -240,6 +249,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="Views\SettingsPageFrames\SettingsSavePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\UserControls\CompositeKeyUserControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -335,12 +348,24 @@
<HintPath>..\packages\Portable.BouncyCastle.1.8.1.3\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AppCenter, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.1.5.0\lib\portable-net45+win8+wpa81+wp8\Microsoft.AppCenter.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AppCenter.Analytics, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.Analytics.1.5.0\lib\portable-net45+win8+wpa81+wp8\Microsoft.AppCenter.Analytics.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AppCenter.Push, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.Push.1.5.0\lib\portable-net45+win8+wpa81+wp8\Microsoft.AppCenter.Push.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Toolkit.Uwp.Notifications, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Toolkit.Uwp.Notifications.2.0.0\lib\dotnet\Microsoft.Toolkit.Uwp.Notifications.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="ModernKeePassLib, Version=2.37.0.2000, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ModernKeePassLib.2.37.8000\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
<HintPath>..\packages\ModernKeePassLib.2.38.2\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
@@ -434,9 +459,6 @@
<Content Include="Assets\Wide310x150Logo.scale-140.png" />
<Content Include="Assets\Wide310x150Logo.scale-180.png" />
<Content Include="Assets\Wide310x150Logo.scale-80.png" />
<Content Include="Data\WindowsStoreProxy.xml">
<SubType>Designer</SubType>
</Content>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '12.0' ">
<VisualStudioVersion>12.0</VisualStudioVersion>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest">
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.11.0.31" />
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.13.0.32" />
<Properties>
<DisplayName>ModernKeePass</DisplayName>
<PublisherDisplayName>wismna</PublisherDisplayName>

View File

@@ -24,6 +24,6 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.11.0.0")]
[assembly: AssemblyFileVersion("1.11.0.0")]
[assembly: AssemblyVersion("1.13.0.0")]
[assembly: AssemblyFileVersion("1.13.0.0")]
[assembly: ComVisible(false)]

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Exceptions;
@@ -14,22 +15,14 @@ using ModernKeePassLib.Serialization;
namespace ModernKeePass.Services
{
public class DatabaseService: IDatabase
public class DatabaseService: SingletonServiceBase<DatabaseService>, IDatabaseService
{
public enum DatabaseStatus
{
Error = -3,
NoCompositeKey = -2,
CompositeKeyError = -1,
Closed = 0,
Opening = 1,
Opened = 2
}
private readonly PwDatabase _pwDatabase = new PwDatabase();
private readonly ISettings _settings;
private readonly IResource _resource;
private readonly ISettingsService _settings;
private StorageFile _realDatabaseFile;
private StorageFile _databaseFile;
private GroupVm _recycleBin;
private CompositeKey _compositeKey;
public GroupVm RootGroup { get; set; }
@@ -39,11 +32,10 @@ namespace ModernKeePass.Services
set
{
_recycleBin = value;
_pwDatabase.RecycleBinUuid = _recycleBin.IdUuid;
_pwDatabase.RecycleBinUuid = _recycleBin?.IdUuid;
}
}
public int Status { get; set; } = (int)DatabaseStatus.Closed;
public string Name => DatabaseFile?.Name;
public bool RecycleBinEnabled
@@ -57,11 +49,20 @@ namespace ModernKeePass.Services
get { return _databaseFile; }
set
{
if (IsOpen && HasChanged)
{
throw new DatabaseOpenedException();
}
_databaseFile = value;
Status = (int)DatabaseStatus.Opening;
}
}
public CompositeKey CompositeKey
{
get { return _compositeKey; }
set { _compositeKey = value; }
}
public PwUuid DataCipher
{
get { return _pwDatabase.DataCipherUuid; }
@@ -80,13 +81,20 @@ namespace ModernKeePass.Services
set { _pwDatabase.KdfParameters = value; }
}
public DatabaseService() : this(new SettingsService())
{ }
public bool IsOpen => _pwDatabase.IsOpen;
public bool IsFileOpen => !_pwDatabase.IsOpen && _databaseFile != null;
public bool IsClosed => _databaseFile == null;
public bool HasChanged { get; set; }
public DatabaseService() : this(SettingsService.Instance)
{
}
public DatabaseService(ISettings settings)
public DatabaseService(ISettingsService settings)
{
_settings = settings;
}
/// <summary>
/// Open a KeePass database
@@ -94,15 +102,17 @@ namespace ModernKeePass.Services
/// <param name="key">The database composite key</param>
/// <param name="createNew">True to create a new database before opening it</param>
/// <returns>An error message, if any</returns>
public void Open(CompositeKey key, bool createNew = false)
public async Task Open(CompositeKey key, bool createNew = false)
{
// TODO: Check if there is an existing backup file
try
{
if (key == null)
{
Status = (int)DatabaseStatus.NoCompositeKey;
return;
throw new ArgumentNullException(nameof(key));
}
_compositeKey = key;
var ioConnection = IOConnectionInfo.FromFile(DatabaseFile);
if (createNew)
{
@@ -120,18 +130,50 @@ namespace ModernKeePass.Services
}
else _pwDatabase.Open(ioConnection, key, new NullStatusLogger());
if (!_pwDatabase.IsOpen) return;
Status = (int)DatabaseStatus.Opened;
//if (!_pwDatabase.IsOpen) return;
// Copy database in temp directory and use this file for operations
if (_settings.GetSetting<bool>("AntiCorruption"))
{
_realDatabaseFile = _databaseFile;
var backupFile =
await ApplicationData.Current.RoamingFolder.CreateFileAsync(Name,
CreationCollisionOption.FailIfExists);
Save(backupFile);
}
RootGroup = new GroupVm(_pwDatabase.RootGroup, null, RecycleBinEnabled ? _pwDatabase.RecycleBinUuid : null);
}
catch (InvalidCompositeKeyException)
catch (InvalidCompositeKeyException ex)
{
Status = (int)DatabaseStatus.CompositeKeyError;
throw new ArgumentException(ex.Message, ex);
}
catch (Exception)
}
public async Task ReOpen()
{
await Open(_compositeKey);
}
/// <summary>
/// Commit the changes to the currently opened database to file
/// </summary>
public void Save()
{
if (!IsOpen) return;
try
{
Status = (int)DatabaseStatus.Error;
throw;
_pwDatabase.Save(new NullStatusLogger());
// Test if save worked correctly
if (_settings.GetSetting<bool>("AntiCorruption"))
{
_pwDatabase.Open(_pwDatabase.IOConnectionInfo, _pwDatabase.MasterKey, new NullStatusLogger());
}
}
catch (Exception e)
{
throw new SaveException(e);
}
}
@@ -152,35 +194,23 @@ namespace ModernKeePass.Services
DatabaseFile = oldFile;
throw;
}
finally
{
Status = (int)DatabaseStatus.Opened;
}
}
/// <summary>
/// Commit the changes to the currently opened database to file
/// </summary>
public void Save()
{
if (_pwDatabase == null || !_pwDatabase.IsOpen) return;
try
{
_pwDatabase.Save(new NullStatusLogger());
}
catch (Exception e)
{
throw new SaveException(e);
}
}
/// <summary>
/// Close the currently opened database
/// </summary>
public void Close()
public async Task Close(bool releaseFile = true)
{
_pwDatabase?.Close();
Status = (int)DatabaseStatus.Closed;
// Restore the backup DB to the original one
if (_settings.GetSetting<bool>("AntiCorruption"))
{
if (_pwDatabase != null && _pwDatabase.Modified)
Save(_realDatabaseFile);
await DatabaseFile.DeleteAsync();
}
if (releaseFile) DatabaseFile = null;
}
public void AddDeletedItem(PwUuid id)
@@ -188,18 +218,13 @@ namespace ModernKeePass.Services
_pwDatabase.DeletedObjects.Add(new PwDeletedObject(id, DateTime.UtcNow));
}
public void CreateRecycleBin()
public void CreateRecycleBin(string title)
{
RecycleBin = RootGroup.AddNewGroup("Recycle bin");
RecycleBin = RootGroup.AddNewGroup(title);
RecycleBin.IsSelected = true;
RecycleBin.IconSymbol = Symbol.Delete;
}
public void UpdateCompositeKey(CompositeKey key)
{
_pwDatabase.MasterKey = key;
}
private void CreateSampleData()
{
_pwDatabase.RootGroup.AddGroup(new PwGroup(true, true, "Banking", PwIcon.Count), true);

View File

@@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Store;
using ModernKeePass.Interfaces;
namespace ModernKeePass.Services
{
public class LicenseService : ILicenseService
public class LicenseService : SingletonServiceBase<LicenseService>, ILicenseService
{
public enum PurchaseResult
{
@@ -27,34 +26,13 @@ namespace ModernKeePass.Services
public LicenseService()
{
// Initialize the license info for use in the app that is uploaded to the Store.
// Uncomment the following line in the release version of your app.
//_licenseInformation = CurrentApp.LicenseInformation;
// Initialize the license info for testing.
// Comment the following line in the release version of your app.
//_licenseInformation = CurrentAppSimulator.LicenseInformation;
#if DEBUG
try
{
var proxyFile = Package.Current.InstalledLocation.GetFileAsync("data\\WindowsStoreProxy.xml").GetAwaiter().GetResult();
CurrentAppSimulator.ReloadSimulatorAsync(proxyFile).GetAwaiter().GetResult();
}
catch { }
var listing = CurrentAppSimulator.LoadListingInformationAsync().GetAwaiter().GetResult();
#else
var listing = CurrentApp.LoadListingInformationAsync().GetAwaiter().GetResult();
#endif
Products = listing.ProductListings;
}
public async Task<int> Purchase(string addOn)
{
#if DEBUG
var purchaseResults = await CurrentAppSimulator.RequestProductPurchaseAsync(addOn);
#else
var purchaseResults = await CurrentApp.RequestProductPurchaseAsync(addOn);
#endif
switch (purchaseResults.Status)
{
case ProductPurchaseStatus.Succeeded:
@@ -79,11 +57,7 @@ namespace ModernKeePass.Services
private async Task<PurchaseResult> ReportFulfillmentAsync(Guid transactionId, string productName)
{
#if DEBUG
var result = await CurrentAppSimulator.ReportConsumableFulfillmentAsync(productName, transactionId);
#else
var result = await CurrentApp.ReportConsumableFulfillmentAsync(productName, transactionId);
#endif
return (PurchaseResult) result;
}

View File

@@ -8,10 +8,10 @@ using ModernKeePass.ViewModels;
namespace ModernKeePass.Services
{
public class RecentService : IRecent
public class RecentService : SingletonServiceBase<RecentService>, IRecentService
{
private readonly StorageItemMostRecentlyUsedList _mru = StorageApplicationPermissions.MostRecentlyUsedList;
public int EntryCount => _mru.Entries.Count;
public ObservableCollection<IRecentItem> GetAllFiles(bool removeIfNonExistant = true)

View File

@@ -3,7 +3,7 @@ using ModernKeePass.Interfaces;
namespace ModernKeePass.Services
{
public class ResourcesService: IResource
public class ResourcesService: IResourceService
{
private const string ResourceFileName = "CodeBehind";
private readonly ResourceLoader _resourceLoader = ResourceLoader.GetForCurrentView();

View File

@@ -5,11 +5,11 @@ using ModernKeePass.Interfaces;
namespace ModernKeePass.Services
{
public class SettingsService : ISettings
public class SettingsService : SingletonServiceBase<SettingsService>, ISettingsService
{
private readonly IPropertySet _values = ApplicationData.Current.LocalSettings.Values;
public T GetSetting<T>(string property)
public T GetSetting<T>(string property, T defaultValue = default(T))
{
try
{
@@ -17,7 +17,7 @@ namespace ModernKeePass.Services
}
catch (InvalidCastException)
{
return default(T);
return defaultValue;
}
}

View File

@@ -0,0 +1,12 @@
using System;
namespace ModernKeePass.Services
{
public abstract class SingletonServiceBase<T> where T : new()
{
private static readonly Lazy<T> LazyInstance =
new Lazy<T>(() => new T());
public static T Instance => LazyInstance.Value;
}
}

View File

@@ -204,9 +204,6 @@
<data name="EntryDeletingConfirmation" xml:space="preserve">
<value>Are you sure you want to delete this entry?</value>
</data>
<data name="EntryNew" xml:space="preserve">
<value>&lt; New entry &gt;</value>
</data>
<data name="EntryRecycled" xml:space="preserve">
<value>Entry moved to the Recycle bin</value>
</data>
@@ -222,9 +219,6 @@
<data name="GroupDeletingConfirmation" xml:space="preserve">
<value>Are you sure you want to delete the whole group and all its entries?</value>
</data>
<data name="GroupNew" xml:space="preserve">
<value>&lt; New group &gt;</value>
</data>
<data name="GroupRecycled" xml:space="preserve">
<value>Group moved to the Recycle bin</value>
</data>
@@ -270,4 +264,13 @@
<data name="SettingsMenuItemSecurity" xml:space="preserve">
<value>Security</value>
</data>
<data name="CompositeKeyErrorUserAccount" xml:space="preserve">
<value>user account</value>
</data>
<data name="SettingsMenuItemSave" xml:space="preserve">
<value>Saving</value>
</data>
<data name="RecycleBinTitle" xml:space="preserve">
<value>Recycle Bin</value>
</data>
</root>

View File

@@ -171,11 +171,14 @@
<data name="CompositeKeyPassword.PlaceholderText" xml:space="preserve">
<value>Password</value>
</data>
<data name="CompositeKeyUserAccount.Text" xml:space="preserve">
<value>Windows User Account</value>
</data>
<data name="DonateButton.Content" xml:space="preserve">
<value>Donate</value>
</data>
<data name="DonateDesc.Text" xml:space="preserve">
<value>Like this app? Why not make a small donation to support my work and help this app stay ad-free :) ?</value>
<value>Like this app? Why not make a small donation to support my work and help me keep it ad-free :) ?</value>
</data>
<data name="EntryExpirationDate.Content" xml:space="preserve">
<value>Expiration date</value>
@@ -183,6 +186,15 @@
<data name="EntryExpirationTooltip.Content" xml:space="preserve">
<value>Password has expired</value>
</data>
<data name="EntryItemCopyLogin.Text" xml:space="preserve">
<value>Copy login</value>
</data>
<data name="EntryItemCopyPassword.Text" xml:space="preserve">
<value>Copy password</value>
</data>
<data name="EntryItemCopyUrl.Text" xml:space="preserve">
<value>Navigate to URL</value>
</data>
<data name="EntryLogin.Text" xml:space="preserve">
<value>User name or login</value>
</data>
@@ -202,10 +214,10 @@
<value>Filter...</value>
</data>
<data name="GroupNewItemTextBox.Text" xml:space="preserve">
<value>&lt; New group &gt;</value>
<value>New group</value>
</data>
<data name="GroupNewItemTooltip.Content" xml:space="preserve">
<value>&lt; New group &gt;</value>
<value>New group</value>
</data>
<data name="GroupSearch.PlaceholderText" xml:space="preserve">
<value>Search...</value>
@@ -303,6 +315,12 @@
<data name="SettingsDatabaseRecycleBin.OnContent" xml:space="preserve">
<value>Enabled</value>
</data>
<data name="SettingsDatabaseRecycleBinCreate.Content" xml:space="preserve">
<value>Create a new group</value>
</data>
<data name="SettingsDatabaseRecycleBinExisting.Content" xml:space="preserve">
<value>Use an existing group</value>
</data>
<data name="SettingsNewDatabaseDesc.Text" xml:space="preserve">
<value>Here, you can change some default options when creating a database.</value>
</data>
@@ -321,6 +339,18 @@
<data name="SettingsNewDatabaseSample.OnContent" xml:space="preserve">
<value>Yes</value>
</data>
<data name="SettingsSaveDatabaseSuspend.OffContent" xml:space="preserve">
<value>Don't save</value>
</data>
<data name="SettingsSaveDatabaseSuspend.OnContent" xml:space="preserve">
<value>Save</value>
</data>
<data name="SettingsSaveDatabaseSuspendDesc.Text" xml:space="preserve">
<value>This settings is generally recommended. If you enable it, database will automatically be saved on application suspension and closing. However, if your database is huge, saving may be deemed too long by Windows, which will then forcibly kill the app.</value>
</data>
<data name="SettingsSaveDatabaseSuspendTitle.Text" xml:space="preserve">
<value>Auto-save on suspend?</value>
</data>
<data name="SettingsSecurityDesc1.Text" xml:space="preserve">
<value>Here, you may change your database password, key file, or both. Just click on on</value>
</data>

View File

@@ -204,10 +204,6 @@
<data name="EntryDeletingConfirmation" xml:space="preserve">
<value>Êtes-vous sûr de vouloir supprimer cette entrée ?</value>
</data>
<data name="EntryNew" xml:space="preserve">
<value>&lt; Nouvelle entrée &gt;</value>
<comment>Unused</comment>
</data>
<data name="EntryRecycled" xml:space="preserve">
<value>Entrée placée dans la Corbeille</value>
</data>
@@ -223,9 +219,6 @@
<data name="GroupDeletingConfirmation" xml:space="preserve">
<value>Êtes-vous sûr de vouloir supprimer ce group et toutes ses entrées ?</value>
</data>
<data name="GroupNew" xml:space="preserve">
<value>&lt; Nouveau groupe &gt;</value>
</data>
<data name="GroupRecycled" xml:space="preserve">
<value>Groupe placé dans la Corbeille</value>
</data>
@@ -271,4 +264,13 @@
<data name="SettingsMenuItemSecurity" xml:space="preserve">
<value>Sécurité</value>
</data>
<data name="CompositeKeyErrorUserAccount" xml:space="preserve">
<value>compte utilisateur</value>
</data>
<data name="SettingsMenuItemSave" xml:space="preserve">
<value>Sauvegardes</value>
</data>
<data name="RecycleBinTitle" xml:space="preserve">
<value>Corbeille</value>
</data>
</root>

View File

@@ -142,7 +142,7 @@
<value>Accueil</value>
</data>
<data name="AppBarRestore.Label" xml:space="preserve">
<value>Restorer</value>
<value>Restaurer</value>
</data>
<data name="AppBarSave.Label" xml:space="preserve">
<value>Sauvegarder</value>
@@ -171,6 +171,9 @@
<data name="CompositeKeyPassword.PlaceholderText" xml:space="preserve">
<value>Mot de passe</value>
</data>
<data name="CompositeKeyUserAccount.Text" xml:space="preserve">
<value>Compte Utilisateur Windows</value>
</data>
<data name="DonateButton.Content" xml:space="preserve">
<value>Donner</value>
</data>
@@ -183,6 +186,15 @@
<data name="EntryExpirationTooltip.Content" xml:space="preserve">
<value>Le mot de passe a expiré</value>
</data>
<data name="EntryItemCopyLogin.Text" xml:space="preserve">
<value>Copier le login</value>
</data>
<data name="EntryItemCopyPassword.Text" xml:space="preserve">
<value>Copier le mot de passe</value>
</data>
<data name="EntryItemCopyUrl.Text" xml:space="preserve">
<value>Naviguer vers l'URL</value>
</data>
<data name="EntryLogin.Text" xml:space="preserve">
<value>Nom d'utilisateur ou login</value>
</data>
@@ -202,10 +214,10 @@
<value>Filtrer...</value>
</data>
<data name="GroupNewItemTextBox.Text" xml:space="preserve">
<value>&lt; Nouveau groupe &gt;</value>
<value>Nouveau groupe</value>
</data>
<data name="GroupNewItemTooltip.Content" xml:space="preserve">
<value>&lt; Nouveau groupe &gt;</value>
<value>Nouveau groupe</value>
</data>
<data name="GroupSearch.PlaceholderText" xml:space="preserve">
<value>Rechercher...</value>
@@ -303,6 +315,12 @@
<data name="SettingsDatabaseRecycleBin.OnContent" xml:space="preserve">
<value>Activé</value>
</data>
<data name="SettingsDatabaseRecycleBinCreate.Content" xml:space="preserve">
<value>Créer un nouveau groupe</value>
</data>
<data name="SettingsDatabaseRecycleBinExisting.Content" xml:space="preserve">
<value>Utiliser un groupe existant</value>
</data>
<data name="SettingsNewDatabaseDesc.Text" xml:space="preserve">
<value>Ici, vous pouvez changer certains options lors de la création d'une nouvelle base de données</value>
</data>
@@ -321,6 +339,18 @@
<data name="SettingsNewDatabaseSample.OnContent" xml:space="preserve">
<value>Oui</value>
</data>
<data name="SettingsSaveDatabaseSuspend.OffContent" xml:space="preserve">
<value>Ne pas sauvegarder</value>
</data>
<data name="SettingsSaveDatabaseSuspend.OnContent" xml:space="preserve">
<value>Sauvegarder</value>
</data>
<data name="SettingsSaveDatabaseSuspendDesc.Text" xml:space="preserve">
<value>Ce paramètre est généralement recommandé. Si vous l'activez, la base de données sera sauvegardée automatiquement lors de la suspension et de la fermeture. Cependant, si votre base de données est très volumineuse, il se peut que Windows estime que cela prend trop de temps et tue l'application.</value>
</data>
<data name="SettingsSaveDatabaseSuspendTitle.Text" xml:space="preserve">
<value>Sauvegarder automatiquement lors de la suspension ?</value>
</data>
<data name="SettingsSecurityDesc1.Text" xml:space="preserve">
<value>Ici, vous pouvez changer le mot de passe maître, le fichier de clé, ou les deux. Cliquez simplement sur</value>
</data>

View File

@@ -0,0 +1,18 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Interfaces;
namespace ModernKeePass.TemplateSelectors
{
public class SelectableDataTemplateSelector: DataTemplateSelector
{
public DataTemplate TrueItem { get; set; }
public DataTemplate FalseItem { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
var isSelectableItem = item as ISelectableModel;
return isSelectableItem != null && isSelectableItem.IsSelected ? TrueItem : FalseItem;
}
}
}

View File

@@ -2,7 +2,6 @@
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.UI.Xaml;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Services;
@@ -22,7 +21,7 @@ namespace ModernKeePass.ViewModels
Success = 5
}
public IDatabase Database { get; set; }
public IDatabaseService Database { get; set; }
public bool HasPassword
{
@@ -44,7 +43,17 @@ namespace ModernKeePass.ViewModels
}
}
public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFile != null);
public bool HasUserAccount
{
get { return _hasUserAccount; }
set
{
SetProperty(ref _hasUserAccount, value);
OnPropertyChanged("IsValid");
}
}
public bool IsValid => !_isOpening && (HasPassword || HasKeyFile && KeyFile != null || HasUserAccount);
public string Status
{
@@ -91,19 +100,21 @@ namespace ModernKeePass.ViewModels
public double PasswordComplexityIndicator => QualityEstimation.EstimatePasswordBits(Password?.ToCharArray());
private bool _hasPassword;
private bool _hasKeyFile;
private bool _hasUserAccount;
private bool _isOpening;
private string _password = string.Empty;
private string _status;
private StatusTypes _statusType;
private StorageFile _keyFile;
private string _keyFileText;
private readonly IResource _resource;
private readonly IResourceService _resource;
public CompositeKeyVm() : this((Application.Current as App)?.Database, new ResourcesService()) { }
public CompositeKeyVm() : this(DatabaseService.Instance, new ResourcesService()) { }
public CompositeKeyVm(IDatabase database, IResource resource)
public CompositeKeyVm(IDatabaseService database, IResourceService resource)
{
_resource = resource;
_keyFileText = _resource.GetResourceValue("CompositeKeyDefaultKeyFile");
@@ -112,42 +123,37 @@ namespace ModernKeePass.ViewModels
public async Task<bool> OpenDatabase(bool createNew)
{
var error = string.Empty;
try
{
_isOpening = true;
Database.Open(CreateCompositeKey(), createNew);
await Database.Open(CreateCompositeKey(), createNew);
await Task.Run(() => RootGroup = Database.RootGroup);
return true;
}
catch (ArgumentException)
{
var errorMessage = new StringBuilder(_resource.GetResourceValue("CompositeKeyErrorUserStart"));
if (HasPassword) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserPassword"));
if (HasPassword && HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserOr"));
if (HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserKeyFile"));
if (HasUserAccount) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserAccount"));
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
}
catch (Exception e)
{
error = $"{_resource.GetResourceValue("CompositeKeyErrorOpen")}: {e.Message}";
var error = $"{_resource.GetResourceValue("CompositeKeyErrorOpen")}: {e.Message}";
UpdateStatus(error, StatusTypes.Error);
}
finally
{
_isOpening = false;
}
switch ((DatabaseService.DatabaseStatus)Database.Status)
{
case DatabaseService.DatabaseStatus.Opened:
await Task.Run(() => RootGroup = Database.RootGroup);
return true;
case DatabaseService.DatabaseStatus.CompositeKeyError:
var errorMessage = new StringBuilder(_resource.GetResourceValue("CompositeKeyErrorUserStart"));
if (HasPassword) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserPassword"));
if (HasPassword && HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserOr"));
if (HasKeyFile) errorMessage.Append(_resource.GetResourceValue("CompositeKeyErrorUserKeyFile"));
UpdateStatus(errorMessage.ToString(), StatusTypes.Error);
break;
case DatabaseService.DatabaseStatus.Error:
UpdateStatus(error, StatusTypes.Error);
break;
}
return false;
}
public void UpdateKey()
{
Database.UpdateCompositeKey(CreateCompositeKey());
Database.CompositeKey = CreateCompositeKey();
UpdateStatus(_resource.GetResourceValue("CompositeKeyUpdated"), StatusTypes.Success);
}
@@ -169,6 +175,7 @@ namespace ModernKeePass.ViewModels
var compositeKey = new CompositeKey();
if (HasPassword) compositeKey.AddUserKey(new KcpPassword(Password));
if (HasKeyFile && KeyFile != null) compositeKey.AddUserKey(new KcpKeyFile(IOConnectionInfo.FromFile(KeyFile)));
if (HasUserAccount) compositeKey.AddUserKey(new KcpUserAccount());
return compositeKey;
}
}

View File

@@ -1,44 +0,0 @@
using System;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel.Store;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Services;
namespace ModernKeePass.ViewModels
{
public class DonateVm: NotifyPropertyChangedBase
{
public ObservableCollection<ProductListing> Donations { get; }
public ProductListing SelectedItem
{
get { return _selectedItem; }
set { SetProperty(ref _selectedItem, value); }
}
private readonly ILicenseService _license;
private ProductListing _selectedItem;
public DonateVm() : this (new LicenseService()) { }
public DonateVm(ILicenseService license)
{
// TODO: find a nice way to order products
_license = license;
Donations = new ObservableCollection<ProductListing>(
_license.Products.Values
/*.OrderBy(p => decimal.Parse(p.FormattedPrice.Replace('\u00A0', ' '), NumberStyles.Currency,
CultureInfo.CurrentCulture.NumberFormat))*/
);
}
public async Task<int> Purchase()
{
return await _license.Purchase(SelectedItem.ProductId);
}
}
}

View File

@@ -1,10 +1,11 @@
using System;
using System.ComponentModel;
using System.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Attributes;
using ModernKeePass.Interfaces;
using ModernKeePass.Mappings;
using ModernKeePass.Services;
using ModernKeePassLib;
using ModernKeePassLib.Cryptography.PasswordGenerator;
using ModernKeePassLib.Security;
@@ -46,12 +47,7 @@ namespace ModernKeePass.ViewModels
public string Name
{
get
{
/*var title = GetEntryValue(PwDefs.TitleField);
return title == null ? _resource.GetResourceValue("EntryNew") : title;*/
return GetEntryValue(PwDefs.TitleField);
}
get { return GetEntryValue(PwDefs.TitleField); }
set { SetEntryValue(PwDefs.TitleField, value); }
}
@@ -72,6 +68,7 @@ namespace ModernKeePass.ViewModels
NotifyPropertyChanged("PasswordComplexityIndicator");
}
}
public string Url
{
get { return GetEntryValue(PwDefs.UrlField); }
@@ -160,7 +157,7 @@ namespace ModernKeePass.ViewModels
public event PropertyChangedEventHandler PropertyChanged;
private readonly PwEntry _pwEntry;
private readonly IDatabase _database;
private readonly IDatabaseService _database;
private bool _isEditMode;
private bool _isRevealPassword;
private double _passwordLength = 25;
@@ -173,9 +170,9 @@ namespace ModernKeePass.ViewModels
public EntryVm() { }
internal EntryVm(PwEntry entry, GroupVm parent) : this(entry, parent, (Application.Current as App)?.Database) { }
internal EntryVm(PwEntry entry, GroupVm parent) : this(entry, parent, DatabaseService.Instance) { }
public EntryVm(PwEntry entry, GroupVm parent, IDatabase database)
public EntryVm(PwEntry entry, GroupVm parent, IDatabaseService database)
{
_database = database;
_pwEntry = entry;
@@ -216,15 +213,16 @@ namespace ModernKeePass.ViewModels
return _pwEntry?.Strings.GetSafe(key).ReadString();
}
[DatabaseChanged]
private void SetEntryValue(string key, string newValue)
{
_pwEntry?.Strings.Set(key, new ProtectedString(true, newValue));
}
public void MarkForDelete()
public void MarkForDelete(string recycleBinTitle)
{
if (_database.RecycleBinEnabled && _database.RecycleBin?.IdUuid == null)
_database.CreateRecycleBin();
_database.CreateRecycleBin(recycleBinTitle);
Move(_database.RecycleBinEnabled && !ParentGroup.IsSelected ? _database.RecycleBin : null);
}

View File

@@ -3,11 +3,12 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Attributes;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Mappings;
using ModernKeePass.Services;
using ModernKeePassLib;
namespace ModernKeePass.ViewModels
@@ -54,6 +55,7 @@ namespace ModernKeePass.ViewModels
public string Name
{
get { return _pwGroup == null ? string.Empty : _pwGroup.Name; }
[DatabaseChanged]
set { _pwGroup.Name = value; }
}
@@ -61,7 +63,6 @@ namespace ModernKeePass.ViewModels
{
get
{
if (_pwGroup == null) return Symbol.Add;
var result = PwIconToSegoeMapping.GetSymbolFromIcon(_pwGroup.IconId);
return result == Symbol.More ? Symbol.Folder : result;
}
@@ -92,20 +93,19 @@ namespace ModernKeePass.ViewModels
}
private readonly PwGroup _pwGroup;
private readonly IDatabase _database;
private readonly IDatabaseService _database;
private bool _isEditMode;
private PwEntry _reorderedEntry;
private ObservableCollection<EntryVm> _entries = new ObservableCollection<EntryVm>();
private string _filter = string.Empty;
private bool _isMenuClosed = true;
public GroupVm() {}
internal GroupVm(PwGroup pwGroup, GroupVm parent, PwUuid recycleBinId = null) : this(pwGroup, parent,
(Application.Current as App)?.Database, recycleBinId)
DatabaseService.Instance, recycleBinId)
{ }
public GroupVm(PwGroup pwGroup, GroupVm parent, IDatabase database, PwUuid recycleBinId = null)
public GroupVm(PwGroup pwGroup, GroupVm parent, IDatabaseService database, PwUuid recycleBinId = null)
{
_pwGroup = pwGroup;
_database = database;
@@ -115,9 +115,9 @@ namespace ModernKeePass.ViewModels
Entries = new ObservableCollection<EntryVm>(pwGroup.Entries.Select(e => new EntryVm(e, this)));
Entries.CollectionChanged += Entries_CollectionChanged;
Groups = new ObservableCollection<GroupVm>(pwGroup.Groups.Select(g => new GroupVm(g, this, recycleBinId)));
Groups.Insert(0, new GroupVm());
}
[DatabaseChanged]
private void Entries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
@@ -133,7 +133,8 @@ namespace ModernKeePass.ViewModels
break;
}
}
[DatabaseChanged]
public GroupVm AddNewGroup(string name = "")
{
var pwGroup = new PwGroup(true, true, name, PwIcon.Folder);
@@ -152,10 +153,10 @@ namespace ModernKeePass.ViewModels
return newEntry;
}
public void MarkForDelete()
public void MarkForDelete(string recycleBinTitle)
{
if (_database.RecycleBinEnabled && _database.RecycleBin?.IdUuid == null)
_database.CreateRecycleBin();
_database.CreateRecycleBin(recycleBinTitle);
Move(_database.RecycleBinEnabled && !IsSelected ? _database.RecycleBin : null);
}
@@ -164,6 +165,7 @@ namespace ModernKeePass.ViewModels
Move(PreviousGroup);
}
[DatabaseChanged]
public void Move(GroupVm destination)
{
PreviousGroup = ParentGroup;
@@ -191,6 +193,7 @@ namespace ModernKeePass.ViewModels
_database.Save();
}
[DatabaseChanged]
public void SortEntries()
{
var comparer = new PwEntryComparer(PwDefs.TitleField, true, false);
@@ -205,6 +208,7 @@ namespace ModernKeePass.ViewModels
}
}
[DatabaseChanged]
public void SortGroups()
{
try

View File

@@ -1,6 +1,5 @@
using Windows.Storage;
using ModernKeePass.Common;
using Windows.UI.Xaml;
using ModernKeePass.Interfaces;
using ModernKeePass.Services;
@@ -31,20 +30,20 @@ namespace ModernKeePass.ViewModels
public void OpenDatabaseFile()
{
OpenDatabaseFile((Application.Current as App)?.Database);
OpenDatabaseFile(DatabaseService.Instance);
}
public void OpenDatabaseFile(IDatabase database)
public void OpenDatabaseFile(IDatabaseService database)
{
database.DatabaseFile = DatabaseFile;
}
public void UpdateAccessTime()
{
UpdateAccessTime(new RecentService());
UpdateAccessTime(RecentService.Instance);
}
public async void UpdateAccessTime(IRecent recent)
public async void UpdateAccessTime(IRecentService recent)
{
await recent.GetFileAsync(Token);
}

View File

@@ -2,9 +2,9 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Windows.UI.Xaml;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Services;
using ModernKeePassLib;
using ModernKeePassLib.Cryptography.Cipher;
using ModernKeePassLib.Cryptography.KeyDerivation;
@@ -14,7 +14,7 @@ namespace ModernKeePass.ViewModels
// TODO: implement Kdf settings
public class SettingsDatabaseVm: NotifyPropertyChangedBase, IHasSelectableObject
{
private readonly IDatabase _database;
private readonly IDatabaseService _database;
private GroupVm _selectedItem;
public bool HasRecycleBin
@@ -27,6 +27,15 @@ namespace ModernKeePass.ViewModels
}
}
public bool IsNewRecycleBin
{
get { return _database.RecycleBin == null; }
set
{
if (value) _database.RecycleBin = null;
}
}
public ObservableCollection<GroupVm> Groups { get; set; }
public IEnumerable<string> Ciphers
@@ -73,7 +82,7 @@ namespace ModernKeePass.ViewModels
get { return Groups.FirstOrDefault(g => g.IsSelected); }
set
{
if (_selectedItem == value) return;
if (_selectedItem == value || IsNewRecycleBin) return;
if (_selectedItem != null)
{
_selectedItem.IsSelected = false;
@@ -88,9 +97,9 @@ namespace ModernKeePass.ViewModels
}
}
public SettingsDatabaseVm() : this((Application.Current as App)?.Database) { }
public SettingsDatabaseVm() : this(DatabaseService.Instance) { }
public SettingsDatabaseVm(IDatabase database)
public SettingsDatabaseVm(IDatabaseService database)
{
_database = database;
Groups = _database?.RootGroup.Groups;

View File

@@ -6,12 +6,12 @@ namespace ModernKeePass.ViewModels
{
public class SettingsNewVm
{
private ISettings _settings;
private readonly ISettingsService _settings;
public SettingsNewVm() : this(new SettingsService())
public SettingsNewVm() : this(SettingsService.Instance)
{ }
public SettingsNewVm(ISettings settings)
public SettingsNewVm(ISettingsService settings)
{
_settings = settings;
}

View File

@@ -0,0 +1,24 @@
using ModernKeePass.Interfaces;
using ModernKeePass.Services;
namespace ModernKeePass.ViewModels
{
public class SettingsSaveVm
{
private readonly ISettingsService _settings;
public SettingsSaveVm() : this(SettingsService.Instance)
{ }
public SettingsSaveVm(ISettingsService settings)
{
_settings = settings;
}
public bool IsSaveSuspend
{
get { return _settings.GetSetting("SaveSuspend", true); }
set { _settings.PutSetting("SaveSuspend", value); }
}
}
}

View File

@@ -1,7 +1,6 @@
using System.Collections.ObjectModel;
using System.Linq;
using Windows.ApplicationModel;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
@@ -46,12 +45,12 @@ namespace ModernKeePass.ViewModels
public MainVm() {}
internal MainVm(Frame referenceFrame, Frame destinationFrame) : this(referenceFrame, destinationFrame,
(Application.Current as App)?.Database, new ResourcesService(), new RecentService())
DatabaseService.Instance, new ResourcesService(), RecentService.Instance)
{ }
public MainVm(Frame referenceFrame, Frame destinationFrame, IDatabase database, IResource resource, IRecent recent)
public MainVm(Frame referenceFrame, Frame destinationFrame, IDatabaseService database, IResourceService resource, IRecentService recent)
{
var isDatabaseOpen = database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opened;
var isDatabaseOpen = database != null && database.IsOpen;
var mainMenuItems = new ObservableCollection<MainMenuItemVm>
{
@@ -62,7 +61,7 @@ namespace ModernKeePass.ViewModels
Destination = destinationFrame,
Parameter = referenceFrame,
SymbolIcon = Symbol.Page2,
IsSelected = database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opening
IsSelected = database != null && database.IsFileOpen && !database.IsOpen
},
new MainMenuItemVm
{
@@ -90,7 +89,7 @@ namespace ModernKeePass.ViewModels
Parameter = referenceFrame,
SymbolIcon = Symbol.Copy,
IsSelected =
(database == null || database.Status == (int) DatabaseService.DatabaseStatus.Closed) &&
(database == null || database.IsClosed) &&
recent.EntryCount > 0,
IsEnabled = recent.EntryCount > 0
},
@@ -120,7 +119,7 @@ namespace ModernKeePass.ViewModels
SelectedItem = mainMenuItems.FirstOrDefault(m => m.IsSelected);
// Add currently opened database to the menu
if (database != null && database.Status == (int) DatabaseService.DatabaseStatus.Opened)
if (database != null && database.IsOpen)
mainMenuItems.Add(new MainMenuItemVm
{
Title = database.Name,

View File

@@ -1,5 +1,4 @@
using Windows.Storage;
using Windows.UI.Xaml;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
using ModernKeePass.Services;
@@ -8,27 +7,27 @@ namespace ModernKeePass.ViewModels
{
public class OpenVm: NotifyPropertyChangedBase
{
public bool ShowPasswordBox => _database?.Status == (int) DatabaseService.DatabaseStatus.Opening;
public bool ShowPasswordBox => _database.IsFileOpen;
public string Name => _database?.Name;
private readonly IDatabase _database;
private readonly IDatabaseService _database;
public OpenVm() : this((Application.Current as App)?.Database) { }
public OpenVm() : this(DatabaseService.Instance) { }
public OpenVm(IDatabase database)
public OpenVm(IDatabaseService database)
{
_database = database;
if (database == null || database.Status != (int) DatabaseService.DatabaseStatus.Opening) return;
if (database == null || !database.IsFileOpen) return;
OpenFile(database.DatabaseFile);
}
public void OpenFile(StorageFile file)
{
OpenFile(file, new RecentService());
OpenFile(file, RecentService.Instance);
}
public void OpenFile(StorageFile file, IRecent recent)
public void OpenFile(StorageFile file, IRecentService recent)
{
_database.DatabaseFile = file;
OnPropertyChanged("Name");
@@ -36,7 +35,7 @@ namespace ModernKeePass.ViewModels
AddToRecentList(file, recent);
}
private void AddToRecentList(StorageFile file, IRecent recent)
private void AddToRecentList(StorageFile file, IRecentService recent)
{
recent.Add(file, file.DisplayName);
}

View File

@@ -7,7 +7,7 @@ namespace ModernKeePass.ViewModels
{
public class RecentVm : NotifyPropertyChangedBase, IHasSelectableObject
{
private readonly IRecent _recent;
private readonly IRecentService _recent;
private ISelectableModel _selectedItem;
private ObservableCollection<IRecentItem> _recentItems = new ObservableCollection<IRecentItem>();
@@ -35,10 +35,10 @@ namespace ModernKeePass.ViewModels
}
}
public RecentVm() : this (new RecentService())
public RecentVm() : this (RecentService.Instance)
{ }
public RecentVm(IRecent recent)
public RecentVm(IRecentService recent)
{
_recent = recent;
RecentItems = _recent.GetAllFiles();

View File

@@ -1,23 +1,25 @@
using Windows.Storage;
using Windows.UI.Xaml;
using System.Threading.Tasks;
using Windows.Storage;
using ModernKeePass.Interfaces;
using ModernKeePass.Services;
namespace ModernKeePass.ViewModels
{
public class SaveVm
{
private readonly IDatabase _database;
public SaveVm() : this((Application.Current as App)?.Database) { }
private readonly IDatabaseService _database;
public SaveVm() : this(DatabaseService.Instance) { }
public SaveVm(IDatabase database)
public SaveVm(IDatabaseService database)
{
_database = database;
}
public void Save(bool close = true)
public async Task Save(bool close = true)
{
_database.Save();
if (close) _database.Close();
if (close)
await _database.Close();
}
public void Save(StorageFile file)

View File

@@ -1,6 +1,5 @@
using System.Collections.ObjectModel;
using System.Linq;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Common;
using ModernKeePass.Interfaces;
@@ -41,9 +40,9 @@ namespace ModernKeePass.ViewModels
}
}
public SettingsVm() : this((Application.Current as App)?.Database, new ResourcesService()) { }
public SettingsVm() : this(DatabaseService.Instance, new ResourcesService()) { }
public SettingsVm(IDatabase database, IResource resource)
public SettingsVm(IDatabaseService database, IResourceService resource)
{
var menuItems = new ObservableCollection<ListMenuItemVm>
{
@@ -56,12 +55,19 @@ namespace ModernKeePass.ViewModels
IsSelected = true
},
new ListMenuItemVm
{
Title = resource.GetResourceValue("SettingsMenuItemSave"),
Group = resource.GetResourceValue("SettingsMenuGroupApplication"),
SymbolIcon = Symbol.Save,
PageType = typeof(SettingsSavePage)
},
new ListMenuItemVm
{
Title = resource.GetResourceValue("SettingsMenuItemGeneral"),
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
SymbolIcon = Symbol.Setting,
PageType = typeof(SettingsDatabasePage),
IsEnabled = database?.Status == 2
IsEnabled = database.IsOpen
},
new ListMenuItemVm
{
@@ -69,7 +75,7 @@ namespace ModernKeePass.ViewModels
Group = resource.GetResourceValue("SettingsMenuGroupDatabase"),
SymbolIcon = Symbol.Permissions,
PageType = typeof(SettingsSecurityPage),
IsEnabled = database?.Status == 2
IsEnabled = database.IsOpen
}
};
SelectedItem = menuItems.FirstOrDefault(m => m.IsSelected);

View File

@@ -458,7 +458,13 @@
<ProgressBar Value="{Binding PasswordComplexityIndicator, ConverterParameter=0\,128, Converter={StaticResource ProgressBarLegalValuesConverter}}" Maximum="128" Width="350" HorizontalAlignment="Left" Foreground="{Binding PasswordComplexityIndicator, ConverterParameter=128, Converter={StaticResource DoubleToForegroungBrushComplexityConverter}}" />
<CheckBox x:Uid="EntryShowPassword" HorizontalAlignment="Left" Margin="-3,0,0,0" IsChecked="{Binding IsRevealPassword, Mode=TwoWay}" IsEnabled="{Binding IsRevealPasswordEnabled}" />
<TextBlock TextWrapping="Wrap" Text="URL" FontSize="18"/>
<local:TextBoxWithButton x:Name="UrlTextBox" HorizontalAlignment="Left" Text="{Binding Url, Mode=TwoWay}" Height="32" Width="350" MaxLength="256" Style="{StaticResource TextBoxWithButtonStyle}" ButtonClick="UrlButton_Click" ButtonSymbol="&#xE111;" ButtonTooltip="Navigate to URL" />
<local:TextBoxWithButton x:Name="UrlTextBox" HorizontalAlignment="Left" Text="{Binding Url, Mode=TwoWay}" Height="32" Width="350" MaxLength="256" Style="{StaticResource TextBoxWithButtonStyle}" ButtonSymbol="&#xE111;" ButtonTooltip="Navigate to URL">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="ButtonClick">
<actions:NavigateToUrlAction Url="{Binding Url}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</local:TextBoxWithButton>
<TextBlock x:Uid="EntryNotes" TextWrapping="Wrap" FontSize="18" />
<TextBox HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Notes, Mode=TwoWay}" Width="350" Height="200" AcceptsReturn="True" IsSpellCheckEnabled="True" />
<CheckBox x:Uid="EntryExpirationDate" FontSize="18" IsChecked="{Binding HasExpirationDate, Mode=TwoWay}" />

View File

@@ -81,9 +81,9 @@ namespace ModernKeePass.Views
resource.GetResourceValue("EntityDeleteCancelButton"), a =>
{
ToastNotificationHelper.ShowMovedToast(Model, resource.GetResourceValue("EntityDeleting"), text);
Model.MarkForDelete();
Model.MarkForDelete(resource.GetResourceValue("RecycleBinTitle"));
if (Frame.CanGoBack) Frame.GoBack();
});
}, null);
}
private void RestoreButton_Click(object sender, RoutedEventArgs e)
@@ -92,20 +92,7 @@ namespace ModernKeePass.Views
ToastNotificationHelper.ShowMovedToast(Model, resource.GetResourceValue("EntityRestoredTitle"), resource.GetResourceValue("EntryRestored"));
if (Frame.CanGoBack) Frame.GoBack();
}
private async void UrlButton_Click(object sender, RoutedEventArgs e)
{
try
{
var uri = new Uri(UrlTextBox.Text);
await Windows.System.Launcher.LaunchUriAsync(uri);
}
catch (Exception ex)
{
MessageDialogHelper.ShowErrorDialog(ex);
}
}
private void EntryDetailPage_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
VisualStateManager.GoToState(this, e.NewSize.Width < 700 ? "Small" : "Large", true);

View File

@@ -8,7 +8,6 @@
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:actions="using:ModernKeePass.Actions"
xmlns:controls="using:ModernKeePass.Controls"
xmlns:templateSelectors="using:ModernKeePass.TemplateSelectors"
x:Name="PageRoot"
x:Class="ModernKeePass.Views.GroupDetailPage"
@@ -16,7 +15,6 @@
SizeChanged="GroupDetailPage_OnSizeChanged">
<Page.Resources>
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
<converters:BooleanToFontStyleConverter x:Key="BooleanToFontStyleConverter"/>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
<converters:NullToBooleanConverter x:Key="NullToBooleanConverter"/>
@@ -84,7 +82,7 @@
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</AppBarButton>
<AppBarButton Icon="Delete" x:Uid="AppBarDelete" IsEnabled="{Binding IsNotRoot}" Click="DeleteButton_Click" />
<AppBarButton Icon="Delete" x:Uid="AppBarDelete" IsEnabled="{Binding IsNotRoot}" Visibility="{Binding IsSelected, Converter={StaticResource InverseBooleanToVisibilityConverter}}" Click="DeleteButton_Click" />
</CommandBar>
</Page.BottomAppBar>
<Grid>
@@ -127,27 +125,30 @@
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}">
<ListView.Resources>
<DataTemplate x:Name="GroupOtherItem">
<DataTemplate x:Name="IsRecycleBin">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="{Binding IconSymbol}" Margin="8,0,0,0">
<ToolTipService.ToolTip>
<ToolTip Content="{Binding Name}" />
</ToolTipService.ToolTip>
</SymbolIcon>
<TextBlock Text="{Binding Name}" x:Name="GroupTextBlock" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="30,0,20,0" FontStyle="{Binding IsSelected, Converter={StaticResource BooleanToFontStyleConverter}}" />
<TextBlock Text="{Binding Name}" x:Name="GroupTextBlock" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="30,0,20,0" FontStyle="Italic" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Name="GroupFirstItem">
<DataTemplate x:Name="IsNotRecycleBin">
<StackPanel Orientation="Horizontal">
<SymbolIcon Symbol="{Binding IconSymbol}" Margin="8,0,0,0">
<ToolTipService.ToolTip>
<ToolTip x:Uid="GroupNewItemTooltip" />
<ToolTip Content="{Binding Name}" />
</ToolTipService.ToolTip>
</SymbolIcon>
<TextBlock x:Name="GroupTextBlock" x:Uid="GroupNewItemTextBox" FontWeight="SemiBold" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="30,0,20,0" />
</SymbolIcon>
<TextBlock Text="{Binding Name}" x:Name="GroupTextBlock" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="30,0,20,0" />
</StackPanel>
</DataTemplate>
</ListView.Resources>
<ListView.ItemTemplateSelector>
<templateSelectors:SelectableDataTemplateSelector FalseItem="{StaticResource IsNotRecycleBin}" TrueItem="{StaticResource IsRecycleBin}" />
</ListView.ItemTemplateSelector>
<ListView.ItemsSource>
<Binding Source="{StaticResource GroupsViewSource}"/>
</ListView.ItemsSource>
@@ -161,23 +162,35 @@
</ListView.ItemContainerStyle>
<ListView.HeaderTemplate>
<DataTemplate>
<ToggleButton Style="{StaticResource HamburgerToggleButton}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Checked">
<core:ChangePropertyAction PropertyName="Width" Value="Auto" TargetObject="{Binding ElementName=LeftListViewColumn}"/>
</core:EventTriggerBehavior>
<core:EventTriggerBehavior EventName="Unchecked">
<core:ChangePropertyAction PropertyName="Width" Value="50" TargetObject="{Binding ElementName=LeftListViewColumn}"/>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ToggleButton>
<ToggleButton Style="{StaticResource HamburgerToggleButton}">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Checked">
<core:ChangePropertyAction PropertyName="Width" Value="Auto" TargetObject="{Binding ElementName=LeftListViewColumn}"/>
</core:EventTriggerBehavior>
<core:EventTriggerBehavior EventName="Unchecked">
<core:ChangePropertyAction PropertyName="Width" Value="50" TargetObject="{Binding ElementName=LeftListViewColumn}"/>
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ToggleButton>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemTemplateSelector>
<templateSelectors:FirstItemDataTemplateSelector
FirstItem="{StaticResource GroupFirstItem}"
OtherItem="{StaticResource GroupOtherItem}" />
</ListView.ItemTemplateSelector>
<ListView.FooterTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Visibility="{Binding IsSelected, Converter={StaticResource InverseBooleanToVisibilityConverter}}">
<Border BorderBrush="White" BorderThickness="0,0,0,1" />
<Button Padding="0" Height="50" Margin="0" Style="{StaticResource NoBorderButtonStyle}" Background="Transparent" BorderThickness="0" Click="CreateGroup_ButtonClick">
<StackPanel Orientation="Horizontal" Margin="13,0,5,0">
<SymbolIcon Symbol="Add">
<ToolTipService.ToolTip>
<ToolTip x:Uid="GroupNewItemTooltip" />
</ToolTipService.ToolTip>
</SymbolIcon>
<TextBlock x:Uid="GroupNewItemTextBox" FontWeight="SemiBold" TextWrapping="NoWrap" FontSize="16" VerticalAlignment="Center" Margin="30,0,20,0" />
</StackPanel>
</Button>
</StackPanel>
</DataTemplate>
</ListView.FooterTemplate>
</ListView>
<TextBlock Grid.Column="1" x:Uid="ReorderEntriesLabel" Margin="20,20,0,0" Visibility="{Binding IsEditMode, Converter={StaticResource BooleanToVisibilityConverter}}" Style="{StaticResource BodyTextBlockStyle}" />
<HyperlinkButton Grid.Column="1" VerticalAlignment="Top" Margin="40,10,0,0" Click="CreateEntry_ButtonClick" Visibility="{Binding IsSelected, Converter={StaticResource InverseBooleanToVisibilityConverter}}" HorizontalAlignment="Right">
@@ -212,6 +225,7 @@
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<SymbolIcon Grid.Column="0" Symbol="{Binding IconSymbol}" Width="100" Height="100" RenderTransformOrigin="0.5,0.5" >
<SymbolIcon.RenderTransform>
@@ -224,6 +238,34 @@
<TextBlock Text="{Binding UserName}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
<TextBlock Text="{Binding Url}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
</StackPanel>
<Button Grid.Column="2" Style="{StaticResource NoBorderButtonStyle}" VerticalAlignment="Bottom">
<SymbolIcon Symbol="More" />
<Button.Flyout>
<MenuFlyout>
<MenuFlyoutItem x:Uid="EntryItemCopyLogin">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<actions:ClipboardAction Text="{Binding UserName}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</MenuFlyoutItem>
<MenuFlyoutItem x:Uid="EntryItemCopyPassword">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<actions:ClipboardAction Text="{Binding Password}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</MenuFlyoutItem>
<MenuFlyoutItem x:Uid="EntryItemCopyUrl">
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Click">
<actions:NavigateToUrlAction Url="{Binding Url}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</MenuFlyoutItem>
</MenuFlyout>
</Button.Flyout>
</Button>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
@@ -341,13 +383,18 @@
<SymbolIcon Symbol="Find" />
<Button.Flyout>
<Flyout>
<Flyout.FlyoutPresenterStyle>
<Style TargetType="FlyoutPresenter">
<Setter Property="Padding" Value="0" />
</Style>
</Flyout.FlyoutPresenterStyle>
<!--<controls:TextBoxWithButton x:Uid="GroupFilter" ButtonSymbol="&#xE16E;" Text="{Binding Filter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="18" VerticalContentAlignment="Center" Width="400" Style="{StaticResource TextBoxWithButtonStyle}" IsButtonEnabled="False" />-->
<SearchBox x:Uid="GroupSearch" Width="350" Background="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" BorderThickness="0" FontSize="18" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" VerticalContentAlignment="Center" />
<SearchBox x:Uid="GroupSearch" Width="350" Padding="12" Background="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" BorderThickness="0" FontSize="18" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" />
</Flyout>
</Button.Flyout>
</Button>
<!--<controls:TextBoxWithButton Grid.Column="2" x:Name="FilterBox" x:Uid="GroupFilter" ButtonSymbol="&#xE16E;" Text="{Binding Filter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="18" VerticalContentAlignment="Center" Width="400" Style="{StaticResource TextBoxWithButtonStyle}" IsButtonEnabled="False" />-->
<SearchBox Grid.Column="2" x:Uid="GroupSearch" x:Name="SearchBox" Width="350" Background="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" BorderThickness="0" FontSize="18" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" VerticalContentAlignment="Center" />
<SearchBox Grid.Column="2" x:Uid="GroupSearch" x:Name="SearchBox" Padding="12" Width="350" Background="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" BorderThickness="0" FontSize="18" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="DragDropGroup">

View File

@@ -84,9 +84,6 @@ namespace ModernKeePass.Views
{
case -1:
return;
case 0:
group = Model.AddNewGroup();
break;
default:
group = LeftListView.SelectedItem as GroupVm;
break;
@@ -120,9 +117,9 @@ namespace ModernKeePass.Views
resource.GetResourceValue("EntityDeleteCancelButton"), a =>
{
ToastNotificationHelper.ShowMovedToast(Model, resource.GetResourceValue("EntityDeleting"), text);
Model.MarkForDelete();
Model.MarkForDelete(resource.GetResourceValue("RecycleBinTitle"));
if (Frame.CanGoBack) Frame.GoBack();
});
}, null);
}
private void RestoreButton_Click(object sender, RoutedEventArgs e)
@@ -145,6 +142,10 @@ namespace ModernKeePass.Views
{
Frame.Navigate(typeof(EntryDetailPage), Model.AddNewEntry());
}
private void CreateGroup_ButtonClick(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(GroupDetailPage), Model.AddNewGroup());
}
private void GridView_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
@@ -168,7 +169,6 @@ namespace ModernKeePass.Views
Frame.Navigate(typeof(EntryDetailPage), entry);
}
private void GroupDetailPage_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
VisualStateManager.GoToState(this, e.NewSize.Width < 700 ? "Small" : "Large", true);

View File

@@ -4,27 +4,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="using:ModernKeePass.ViewModels"
xmlns:converters="using:ModernKeePass.Converters"
mc:Ignorable="d">
<Page.DataContext>
<viewModels:DonateVm />
</Page.DataContext>
<Page.Resources>
<converters:NullToBooleanConverter x:Key="NullToBooleanConverter"/>
<CollectionViewSource
x:Name="DonateItemsSource"
Source="{Binding Donations}" />
</Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="10,0,0,0">
<TextBlock x:Uid="DonateDesc" Style="{StaticResource BodyTextBlockStyle}" />
<ItemsControl ItemsSource="{Binding Source={StaticResource DonateItemsSource}}" Margin="0,10,0,10">
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton GroupName="DonateOptions" Content="{Binding FormattedPrice}" Checked="ToggleButton_OnChecked" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button x:Uid="DonateButton" Click="ButtonBase_OnClick" IsEnabled="{Binding SelectedItem, Converter={StaticResource NullToBooleanConverter}}" />
</StackPanel>
<WebView Source="https://PayPal.Me/wismna"></WebView>
</Page>

View File

@@ -1,12 +1,4 @@
using System;
using Windows.ApplicationModel.Store;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using ModernKeePass.Common;
using ModernKeePass.Services;
using ModernKeePass.ViewModels;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
@@ -15,57 +7,9 @@ namespace ModernKeePass.Views
/// </summary>
public sealed partial class DonatePage
{
public DonateVm Model => DataContext as DonateVm;
public DonatePage()
{
InitializeComponent();
}
private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
{
var source = sender as RadioButton;
Model.SelectedItem = source?.DataContext as ProductListing;
}
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var resource = new ResourcesService();
try
{
var result = await Model.Purchase();
switch ((LicenseService.PurchaseResult)result)
{
case LicenseService.PurchaseResult.Succeeded:
MessageDialogHelper.ShowNotificationDialog(resource.GetResourceValue("DonateSucceededTitle"), resource.GetResourceValue("DonateSucceededMessage"));
break;
case LicenseService.PurchaseResult.NothingToFulfill:
MessageDialogHelper.ShowNotificationDialog(resource.GetResourceValue("DonateNothingToFulfillTitle"), resource.GetResourceValue("DonateNothingToFulfillMessage"));
break;
case LicenseService.PurchaseResult.PurchasePending:
MessageDialogHelper.ShowNotificationDialog(resource.GetResourceValue("DonatePurchasePendingTitle"), resource.GetResourceValue("DonatePurchasePendingMessage"));
break;
case LicenseService.PurchaseResult.PurchaseReverted:
MessageDialogHelper.ShowNotificationDialog(resource.GetResourceValue("DonatePurchaseRevertedTitle"), resource.GetResourceValue("DonatePurchaseRevertedMessage"));
break;
case LicenseService.PurchaseResult.ServerError:
MessageDialogHelper.ShowNotificationDialog(resource.GetResourceValue("DonateServerErrorTitle"), resource.GetResourceValue("DonateServerErrorMessage"));
break;
case LicenseService.PurchaseResult.NotPurchased:
MessageDialogHelper.ShowNotificationDialog(resource.GetResourceValue("DonateNotPurchasedTitle"), resource.GetResourceValue("DonateNotPurchasedMessage"));
break;
// Should never happen because these are consumables
case LicenseService.PurchaseResult.AlreadyPurchased:
MessageDialogHelper.ShowNotificationDialog(resource.GetResourceValue("DonateAlreadyPurchasedTitle"), resource.GetResourceValue("DonateAlreadyPurchasedMessage"));
break;
default:
throw new ArgumentOutOfRangeException();
}
}
catch (Exception exception)
{
MessageDialogHelper.ShowErrorDialog(exception);
}
}
}
}

View File

@@ -28,10 +28,10 @@ namespace ModernKeePass.Views
_mainFrame = e.Parameter as Frame;
}
private void SaveButton_OnClick(object sender, RoutedEventArgs e)
private async void SaveButton_OnClick(object sender, RoutedEventArgs e)
{
Model.Save();
_mainFrame.Navigate(typeof(Views.MainPage));
await Model.Save();
_mainFrame.Navigate(typeof(MainPage));
}
private async void SaveAsButton_OnClick(object sender, RoutedEventArgs e)
@@ -47,7 +47,7 @@ namespace ModernKeePass.Views
if (file == null) return;
Model.Save(file);
_mainFrame.Navigate(typeof(Views.MainPage));
_mainFrame.Navigate(typeof(MainPage));
}
}
}

View File

@@ -5,35 +5,27 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="using:ModernKeePass.ViewModels"
xmlns:templateSelectors="using:ModernKeePass.TemplateSelectors"
xmlns:converters="using:ModernKeePass.Converters"
mc:Ignorable="d">
<Page.Resources>
<CollectionViewSource x:Name="RecycleBinGroups" Source="{Binding Groups}" />
<CollectionViewSource x:Name="Ciphers" Source="{Binding Ciphers}" />
<CollectionViewSource x:Name="Compressions" Source="{Binding Compressions}" />
<CollectionViewSource x:Name="KeyDerivations" Source="{Binding KeyDerivations}" />
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<converters:NullToBooleanConverter x:Key="NullToBooleanConverter"/>
</Page.Resources>
<Page.DataContext>
<viewModels:SettingsDatabaseVm />
</Page.DataContext>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ToggleSwitch x:Uid="SettingsDatabaseRecycleBin" IsOn="{Binding HasRecycleBin, Mode=TwoWay}" />
<ComboBox ItemsSource="{Binding Source={StaticResource RecycleBinGroups}}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" IsEnabled="{Binding HasRecycleBin}">
<ComboBox.Resources>
<DataTemplate x:Name="GroupFirstItem">
<TextBlock x:Uid="GroupNewItemTextBox" />
</DataTemplate>
<DataTemplate x:Name="GroupOtherItem">
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.Resources>
<ComboBox.ItemTemplateSelector>
<templateSelectors:FirstItemDataTemplateSelector
FirstItem="{StaticResource GroupFirstItem}"
OtherItem="{StaticResource GroupOtherItem}" />
</ComboBox.ItemTemplateSelector>
</ComboBox>
<StackPanel Visibility="{Binding HasRecycleBin, Converter={StaticResource BooleanToVisibilityConverter}}">
<RadioButton x:Uid="SettingsDatabaseRecycleBinCreate" GroupName="Recycle" IsChecked="{Binding IsNewRecycleBin, Mode=TwoWay}" />
<RadioButton x:Name="RadioButton" x:Uid="SettingsDatabaseRecycleBinExisting" GroupName="Recycle" IsChecked="{Binding SelectedItem, Converter={StaticResource NullToBooleanConverter}}" />
<ComboBox ItemsSource="{Binding Source={StaticResource RecycleBinGroups}}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" IsEnabled="{Binding IsChecked, ElementName=RadioButton}" />
</StackPanel>
<TextBlock x:Uid="SettingsDatabaseEncryption" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" />
<ComboBox ItemsSource="{Binding Source={StaticResource Ciphers}}" SelectedIndex="{Binding CipherIndex, Mode=TwoWay}" />
<TextBlock x:Uid="SettingsDatabaseCompression" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,20,0,10" />

View File

@@ -0,0 +1,18 @@
<Page
x:Class="ModernKeePass.Views.SettingsSavePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="using:ModernKeePass.ViewModels"
mc:Ignorable="d">
<Page.DataContext>
<viewModels:SettingsSaveVm />
</Page.DataContext>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Uid="SettingsSaveDatabaseSuspendTitle" Style="{StaticResource TextBlockSettingsHeaderStyle}" Margin="5,0,0,10"/>
<TextBlock x:Uid="SettingsSaveDatabaseSuspendDesc" TextWrapping="WrapWholeWords" Margin="5,0,0,10"/>
<ToggleSwitch x:Uid="SettingsSaveDatabaseSuspend" IsOn="{Binding IsSaveSuspend, Mode=TwoWay}" />
</StackPanel>
</Page>

View File

@@ -0,0 +1,15 @@
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace ModernKeePass.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class SettingsSavePage
{
public SettingsSavePage()
{
InitializeComponent();
}
}
}

View File

@@ -2,7 +2,6 @@
x:Class="ModernKeePass.Views.SettingsSecurityPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ModernKeePass.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:userControls="using:ModernKeePass.Views.UserControls"

View File

@@ -11,7 +11,6 @@
xmlns:viewModels="using:ModernKeePass.ViewModels"
mc:Ignorable="d" >
<UserControl.Resources>
<SolidColorBrush x:Key="ErrorColorBrush" Color="Red"/>
<converters:ProgressBarLegalValuesConverter x:Key="ProgressBarLegalValuesConverter"/>
<converters:DoubleToSolidColorBrushConverter x:Key="DoubleToForegroungBrushConverter"/>
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
@@ -55,7 +54,7 @@
</ToolTipService.ToolTip>
</SymbolIcon>
</HyperlinkButton>
<TextBlock Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3" Height="28" FontSize="14" FontWeight="Light" Text="{Binding Status}" Foreground="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}" Visibility="{Binding Status, Converter={StaticResource EmptyStringToVisibilityConverter}}" />
<Button Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" Content="{Binding ButtonLabel, ElementName=UserControl}" Click="OpenButton_OnClick" Background="{ThemeResource ListViewItemSelectedPointerOverBorderThemeBrush}" Foreground="{ThemeResource TextBoxBackgroundThemeBrush}" IsEnabled="{Binding IsValid}" />
<TextBlock Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="3" Height="28" FontSize="14" FontWeight="Light" Text="{Binding Status}" Foreground="{Binding StatusType, Converter={StaticResource DiscreteIntToSolidColorBrushConverter}}" Visibility="{Binding Status, Converter={StaticResource EmptyStringToVisibilityConverter}}" />
</Grid>
</UserControl>

View File

@@ -90,7 +90,12 @@ namespace ModernKeePass.Views.UserControls
private void PasswordBox_KeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key == VirtualKey.Enter && Model.IsValid) OpenButton_OnClick(null, null);
if (e.Key == VirtualKey.Enter && Model.IsValid)
{
OpenButton_OnClick(sender, e);
// Stop the event from triggering twice
e.Handled = true;
}
}
private async void KeyFileButton_Click(object sender, RoutedEventArgs e)

View File

@@ -1,2 +1,4 @@
Error when opening file from Explorer corrected
Filter entries reverted to search entries because of regressions
Application now correctly resumes from suspend
Code enhancements
Return of the Donate page, with Paypal
KeePassLib version bump to 2.38

View File

@@ -1,6 +1,6 @@
En avez-vous assez d'essayer de retenir des quantit&eacute;s de mots de passe ? Etes-vous soucieux que le fait d'utiliser le m&ecirc;me mot de passe partout vous rend vuln&eacute;rable ?
ModernKeePass est un gestionnaire de mots de passe gratuit, libre, facile &agrave; utiliser mais n&eacute;anmoins s<EFBFBD>r, bas&eacute; sur la technologie certifi&eacute;e et r&eacute;pandue KeePass 2.x et compatible avec celui-ci.
Vous pouvez stocker ou g&eacute;n&eacute;rer vos mots de passe dans une base de donn&eacute;es chiffr&eacute;e, qui peut &ecirc;tre plac&eacute;e n'importe o<EFBFBD> (ordinateur personnel/tablette, cloud, cl&eacute; USB...)
En avez-vous assez d'essayer de retenir des quantites de mots de passe ? Etes-vous soucieux que le fait d'utiliser le meme mot de passe partout vous rend vulnerable ?
ModernKeePass est un gestionnaire de mots de passe gratuit, libre, facile a utiliser mais neanmoins sur, base sur la technologie certifiee et repandue KeePass 2.x et compatible avec celui-ci.
Vous pouvez stocker ou generer vos mots de passe dans une base de donnees chiffree, qui peut etre placee n'importe ou (ordinateur personnel/tablette, cloud, cle USB...)
Bien que la s&eacute;curit&eacute; informatique soit tr&egrave;s importante, cette application essaie de rester simple &agrave; utiliser et &agrave; comprendre. Vos suggestions sont les bienvenues !
Bien que la securite informatique soit tres importante, cette application essaie de rester simple a utiliser et a comprendre. Vos suggestions sont les bienvenues !
Fonctionne sur Windows 10, 8.1 et RT.

View File

@@ -1 +1 @@
Page d'entr<EFBFBD>e avec g<EFBFBD>n<EFBFBD>rateur de mot de passe
Page d'entree avec generateur de mot de passe

View File

@@ -1 +1 @@
Filtrez vos entr<EFBFBD>es pour rapidement trouver celle qui vous int<EFBFBD>resse
Filtrez vos entrees pour rapidement trouver celle qui vous interesse

View File

@@ -1 +1 @@
Vue d'un groupe, avec ses sous-groupes et ses entr<EFBFBD>es
Vue d'un groupe, avec ses sous-groupes et ses entrees

View File

@@ -1 +1 @@
Cr<EFBFBD>ez de nouvelles bases de donn<EFBFBD>es, en d<EFBFBD>finissant un mot de passe et/ou un fichier de cl<EFBFBD> existant ou nouveau
Creez de nouvelles bases de donnees, en definissant un mot de passe et/ou un fichier de cle existant ou nouveau

View File

@@ -1 +1 @@
Ouvrez une base de donn<EFBFBD>es avec mot de passe et/ou fichier de cl<EFBFBD>
Ouvrez une base de donnees avec mot de passe et/ou fichier de cle

View File

@@ -1 +1 @@
Ouvrez les fichiers r<EFBFBD>cents
Ouvrez les fichiers recents

View File

@@ -1 +1 @@
Vue d'ensemble avec le zoom s<EFBFBD>mantique
Vue d'ensemble avec le zoom semantique

View File

@@ -1 +1 @@
Param<EFBFBD>tres de l'application
Parametres de l'application

View File

@@ -1,2 +1,4 @@
Correction d'un bug lors de l'ouverture d'un fichier par Explorer
R&eacute;tablissement de la recherche d'entr&eacute;es &agrave; la place du filtre &agrave; cause de r&eacute;gressions multiples
L'application recupere correctement d'une suspension
Ameliorations de code
Retour de la page de donation, avec Paypal
Version de la KeePassLib montee a 2.38

View File

@@ -1,10 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AppCenter" version="1.5.0" targetFramework="win81" />
<package id="Microsoft.AppCenter.Analytics" version="1.5.0" targetFramework="win81" />
<package id="Microsoft.AppCenter.Push" version="1.5.0" targetFramework="win81" />
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="win81" />
<package id="Microsoft.NETCore.Platforms" version="2.0.1" targetFramework="win81" />
<package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.2" targetFramework="win81" />
<package id="Microsoft.Toolkit.Uwp.Notifications" version="2.0.0" targetFramework="win81" />
<package id="ModernKeePassLib" version="2.37.8000" targetFramework="win81" />
<package id="ModernKeePassLib" version="2.38.2" targetFramework="win81" />
<package id="NETStandard.Library" version="2.0.1" targetFramework="win81" />
<package id="Portable.BouncyCastle" version="1.8.1.3" targetFramework="win81" />
<package id="Splat" version="2.0.0" targetFramework="win81" />

View File

@@ -16,20 +16,20 @@ namespace ModernKeePassApp.Test
[TestMethod]
public void TestCreate()
{
Assert.AreEqual((int) DatabaseService.DatabaseStatus.Closed, _database.Status);
Assert.IsTrue(_database.IsClosed);
_database.DatabaseFile = ApplicationData.Current.TemporaryFolder.CreateFileAsync("NewDatabase.kdbx").GetAwaiter().GetResult();
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opening, _database.Status);
Assert.IsTrue(_database.IsFileOpen);
OpenOrCreateDatabase(true);
_database.Close();
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Closed, _database.Status);
_database.Close().GetAwaiter().GetResult();
Assert.IsTrue(_database.IsClosed);
}
[TestMethod]
public void TestOpen()
{
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Closed, _database.Status);
_database.DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Databases\TestDatabase.kdbx").GetAwaiter().GetResult();
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opening, _database.Status);
Assert.IsTrue(_database.IsClosed);
_database.DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx").GetAwaiter().GetResult();
Assert.IsTrue(_database.IsFileOpen);
OpenOrCreateDatabase(false);
}
@@ -38,23 +38,23 @@ namespace ModernKeePassApp.Test
{
TestOpen();
_database.Save(ApplicationData.Current.TemporaryFolder.CreateFileAsync("SaveDatabase.kdbx").GetAwaiter().GetResult());
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opened, _database.Status);
_database.Close();
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Closed, _database.Status);
Assert.IsTrue(_database.IsOpen);
_database.Close().GetAwaiter().GetResult();
Assert.IsTrue(_database.IsClosed);
TestOpen();
}
private void OpenOrCreateDatabase(bool createNew)
{
_database.Open(null, createNew);
Assert.AreEqual((int)DatabaseService.DatabaseStatus.NoCompositeKey, _database.Status);
Assert.ThrowsException<ArgumentNullException>(
() => _database.Open(null, createNew).GetAwaiter().GetResult());
var compositeKey = new CompositeKeyVm(_database, new ResourceServiceMock())
{
HasPassword = true,
Password = "test"
};
compositeKey.OpenDatabase(createNew).GetAwaiter().GetResult();
Assert.AreEqual((int)DatabaseService.DatabaseStatus.Opened, _database.Status);
Assert.IsTrue(_database.IsOpen);
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using ModernKeePass.Interfaces;
using ModernKeePass.ViewModels;
using ModernKeePassLib;
@@ -8,16 +9,34 @@ using Windows.Storage;
namespace ModernKeePassApp.Test.Mock
{
public class DatabaseServiceMock : IDatabase
public class DatabaseServiceMock : IDatabaseService
{
private bool _isOpen;
private bool _isClosed;
private CompositeKey _compositeKey;
public PwCompressionAlgorithm CompressionAlgorithm { get; set; }
public StorageFile DatabaseFile { get; set; }
public CompositeKey CompositeKey
{
get { return _compositeKey; }
set { _compositeKey = value; }
}
public PwUuid DataCipher { get; set; }
public KdfParameters KeyDerivation { get; set; }
public bool IsOpen => _isOpen;
public bool IsFileOpen => DatabaseFile != null;
public bool IsClosed => _isClosed;
public bool HasChanged { get; set; }
public string Name => "MockDatabase";
public GroupVm RecycleBin { get; set; }
@@ -25,42 +44,49 @@ namespace ModernKeePassApp.Test.Mock
public bool RecycleBinEnabled { get; set; }
public GroupVm RootGroup { get; set; }
public int Status { get; set; }
public void AddDeletedItem(PwUuid id)
{
throw new NotImplementedException();
}
public void Close()
public Task Close(bool releaseFile = true)
{
Status = 0;
return Task.Run(() =>
{
_isClosed = true;
_isOpen = false;
});
}
public void CreateRecycleBin()
public void CreateRecycleBin(string title)
{
throw new NotImplementedException();
}
public void Open(CompositeKey key, bool createNew)
public Task Open(CompositeKey key, bool createNew = false)
{
Status = 2;
_compositeKey = key;
return Task.Run(() =>
{
_isOpen = true;
_isClosed = false;
});
}
public async Task ReOpen()
{
await Open(_compositeKey);
}
public void Save()
{
throw new NotImplementedException();
// Do Nothing
}
public void Save(StorageFile file)
{
throw new NotImplementedException();
}
public void UpdateCompositeKey(CompositeKey key)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Store;
using ModernKeePass.Interfaces;
namespace ModernKeePassApp.Test.Mock
{
public class LicenseServiceMock: ILicenseService
{
public IReadOnlyDictionary<string, ProductListing> Products { get; }
public LicenseServiceMock()
{
try
{
var proxyFile = Package.Current.InstalledLocation.GetFileAsync("data\\WindowsStoreProxy.xml").GetAwaiter().GetResult();
CurrentAppSimulator.ReloadSimulatorAsync(proxyFile).GetAwaiter().GetResult();
}
catch { }
var listing = CurrentAppSimulator.LoadListingInformationAsync().GetAwaiter().GetResult();
Products = listing.ProductListings;
}
public Task<int> Purchase(string addOn)
{
throw new System.NotImplementedException();
}
}
}

View File

@@ -6,7 +6,7 @@ using Windows.Storage;
namespace ModernKeePassApp.Test.Mock
{
class RecentServiceMock : IRecent
class RecentServiceMock : IRecentService
{
public int EntryCount => 0;

View File

@@ -1,9 +1,8 @@
using System;
using ModernKeePass.Interfaces;
using ModernKeePass.Interfaces;
namespace ModernKeePassApp.Test.Mock
{
class ResourceServiceMock : IResource
class ResourceServiceMock : IResourceService
{
public string GetResourceValue(string key)
{

View File

@@ -3,11 +3,11 @@ using ModernKeePass.Interfaces;
namespace ModernKeePassApp.Test.Mock
{
public class SettingsServiceMock : ISettings
public class SettingsServiceMock : ISettingsService
{
public T GetSetting<T>(string property)
public T GetSetting<T>(string property, T defaultValue = default(T))
{
return default(T);
return defaultValue;
}
public void PutSetting<T>(string property, T value)

View File

@@ -121,6 +121,7 @@
<ItemGroup>
<Compile Include="DatabaseTests.cs" />
<Compile Include="Mock\DatabaseServiceMock.cs" />
<Compile Include="Mock\LicenseServiceMock.cs" />
<Compile Include="Mock\RecentServiceMock.cs" />
<Compile Include="Mock\ResourceServiceMock.cs" />
<Compile Include="Mock\SettingsServiceMock.cs" />
@@ -131,11 +132,14 @@
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<Content Include="Databases\TestDatabase.kdbx" />
<Content Include="Data\TestDatabase.kdbx" />
<None Include="ModernKeePassApp.Test_TemporaryKey.pfx" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="Data\WindowsStoreProxy.xml">
<SubType>Designer</SubType>
</Content>
<Content Include="Images\UnitTestLogo.scale-100.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>

View File

@@ -6,14 +6,15 @@ using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using ModernKeePass.ViewModels;
using ModernKeePass.Views;
using ModernKeePassApp.Test.Mock;
using ModernKeePassLib;
namespace ModernKeePassApp.Test
{
[TestClass]
public class ViewModelsTests
{
private RecentServiceMock _recent = new RecentServiceMock();
private ResourceServiceMock _resource = new ResourceServiceMock();
private readonly RecentServiceMock _recent = new RecentServiceMock();
private readonly ResourceServiceMock _resource = new ResourceServiceMock();
[TestMethod]
public void TestAboutVm()
@@ -32,12 +33,13 @@ namespace ModernKeePassApp.Test
var firstGroup = mainVm.MainMenuItems.FirstOrDefault();
Assert.AreEqual(7, firstGroup.Count());
database.Status = 1;
database.DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx")
.GetAwaiter().GetResult();
mainVm = new MainVm(null, null, database, _resource, _recent);
Assert.IsNotNull(mainVm.SelectedItem);
Assert.AreEqual(typeof(OpenDatabasePage), ((MainMenuItemVm) mainVm.SelectedItem).PageType);
database.Status = 2;
database.Open(null, false).GetAwaiter().GetResult();
mainVm = new MainVm(null, null, database, _resource, _recent);
Assert.IsNotNull(mainVm.SelectedItem);
Assert.AreEqual(2, mainVm.MainMenuItems.Count());
@@ -61,8 +63,7 @@ namespace ModernKeePassApp.Test
{
var database = new DatabaseServiceMock
{
Status = 1,
DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Databases\TestDatabase.kdbx")
DatabaseFile = Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx")
.GetAwaiter().GetResult()
};
var openVm = new OpenVm(database);
@@ -79,7 +80,7 @@ namespace ModernKeePassApp.Test
public void TestRecentVm()
{
var mru = StorageApplicationPermissions.MostRecentlyUsedList;
mru.Add(Package.Current.InstalledLocation.GetFileAsync(@"Databases\TestDatabase.kdbx")
mru.Add(Package.Current.InstalledLocation.GetFileAsync(@"Data\TestDatabase.kdbx")
.GetAwaiter().GetResult(), "MockDatabase");
var recentVm = new RecentVm();
Assert.IsTrue(recentVm.RecentItems.Count == 1);
@@ -88,10 +89,17 @@ namespace ModernKeePassApp.Test
mru.Clear();
}
/*[TestMethod]
[TestMethod]
public void TestSaveVm()
{
}*/
var database = new DatabaseServiceMock();
var saveVm = new SaveVm(database);
database.Open(null, false).GetAwaiter().GetResult();
saveVm.Save(false).GetAwaiter().GetResult();
Assert.IsTrue(database.IsOpen);
saveVm.Save().GetAwaiter().GetResult();
Assert.IsFalse(database.IsOpen);
}
[TestMethod]
public void TestSettingsVm()
@@ -100,10 +108,32 @@ namespace ModernKeePassApp.Test
Assert.AreEqual(1, settingsVm.MenuItems.Count());
var firstGroup = settingsVm.MenuItems.FirstOrDefault();
// All groups have an empty title, so all settings are put inside the empty group
Assert.AreEqual(3, firstGroup.Count());
Assert.AreEqual(4, firstGroup.Count());
Assert.IsNotNull(settingsVm.SelectedItem);
var selectedItem = (ListMenuItemVm) settingsVm.SelectedItem;
Assert.AreEqual(typeof(SettingsNewDatabasePage), selectedItem.PageType);
}
[TestMethod]
public void TestEntryVm()
{
var database = new DatabaseServiceMock();
var entryVm = new EntryVm(new PwEntry(true, true), new GroupVm(), database)
{
Name = "Test",
UserName = "login",
Password = "password"
};
}
[TestMethod]
public void TestGroupVm()
{
var database = new DatabaseServiceMock();
var entryVm = new GroupVm(new PwGroup(true, true), new GroupVm(), database)
{
Name = "Test"
};
}
}
}

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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
@@ -69,7 +69,7 @@ namespace ModernKeePassLib.Cryptography.Cipher
}
}
public sealed class ChaCha20Stream : Stream
internal sealed class ChaCha20Stream : Stream
{
private Stream m_sBase;
private readonly bool m_bWriting;

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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

View File

@@ -1,6 +1,6 @@
/*
KeePass Password Safe - The Open-Source Password Manager
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
Copyright (C) 2003-2018 Dominik Reichl <dominik.reichl@t-online.de>
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
@@ -22,9 +22,13 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
#if ModernKeePassLib || KeePassUAP
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Parameters;
#else
using System.Security.Cryptography;
#endif
using ModernKeePassLib.Cryptography;
using ModernKeePassLib.Native;
@@ -134,7 +138,7 @@ namespace ModernKeePassLib.Cryptography.KeyDerivation
return null;
}
public static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
internal static bool TransformKeyManaged(byte[] pbNewKey32, byte[] pbKeySeed32,
ulong uNumRounds)
{
#if ModernKeePassLib || KeePassUAP

Some files were not shown because too many files have changed in this diff Show More