mirror of
https://github.com/wismna/ModernKeePass.git
synced 2025-10-04 16:10:16 -04:00
Compare commits
61 Commits
Author | SHA1 | Date | |
---|---|---|---|
cddda7adcd | |||
69a63f4b2e | |||
10b6330ac6 | |||
676365460c | |||
acb5bcc230 | |||
![]() |
f1737ca9f7 | ||
2f1355104e | |||
97b1475100 | |||
454e074c44 | |||
951172e36f | |||
f5fd3effaf | |||
ec4f2e7d88 | |||
98ecb0b8a1 | |||
![]() |
f2794f8055 | ||
![]() |
dfb5ec9683 | ||
3d033417ad | |||
f22ca4c46f | |||
11fb82573b | |||
4aa3b17398 | |||
c611f5a8a2 | |||
013108f2ec | |||
616d922145 | |||
![]() |
95771878fc | ||
267d9f25c2 | |||
2bcc4fde60 | |||
30838d0e00 | |||
![]() |
6d69dd4d15 | ||
![]() |
324553c58c | ||
![]() |
1ca3f29da0 | ||
817f25e8a8 | |||
![]() |
056e1624be | ||
b5c04d524d | |||
1582060466 | |||
caaf34918e | |||
![]() |
3a045dbb16 | ||
40256be135 | |||
26e9b78b3b | |||
a76b0ff350 | |||
7e0f21f88f | |||
d78e75f449 | |||
93be4cf01c | |||
ec037b97fd | |||
2b469d764d | |||
cfd61a87e8 | |||
1faa26473d | |||
27aaa8023a | |||
22ea657885 | |||
34996da19d | |||
![]() |
3bf8015280 | ||
![]() |
32e629231c | ||
![]() |
9d78d59a15 | ||
668afbe817 | |||
a43bc20eb3 | |||
![]() |
baba70e56d | ||
c4ac244270 | |||
668ffcb107 | |||
a7cdd248c9 | |||
f976a2cc86 | |||
![]() |
5d271d4133 | ||
![]() |
25d1564a8d | ||
00897307a4 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -33,4 +33,7 @@ _ReSharper*/
|
|||||||
Translation/TrlUtil.vshost.exe.manifest
|
Translation/TrlUtil.vshost.exe.manifest
|
||||||
*.nupkg
|
*.nupkg
|
||||||
.vs/
|
.vs/
|
||||||
/UpgradeLog.htm
|
/UpgradeLog*.htm
|
||||||
|
packages/
|
||||||
|
project.lock.json
|
||||||
|
AppPackages/
|
@@ -5,7 +5,12 @@ VisualStudioVersion = 14.0.25420.1
|
|||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePass", "ModernKeePass\ModernKeePass.csproj", "{A0CFC681-769B-405A-8482-0CDEE595A91F}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePass", "ModernKeePass\ModernKeePass.csproj", "{A0CFC681-769B-405A-8482-0CDEE595A91F}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLib", "ModernKeePassLib\ModernKeePassLib.csproj", "{A207789D-9020-401B-9D0A-D0D2CFF721BD}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLib", "ModernKeePassLib\ModernKeePassLib.csproj", "{2E710089-9559-4967-846C-E763DD1F3ACB}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModernKeePassLib.Test", "ModernKeePassLib.Test\ModernKeePassLib.Test.csproj", "{067456C0-086C-46A8-B37F-1405717B7BFC}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{2E710089-9559-4967-846C-E763DD1F3ACB} = {2E710089-9559-4967-846C-E763DD1F3ACB}
|
||||||
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -43,22 +48,38 @@ Global
|
|||||||
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.ActiveCfg = Release|x86
|
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.ActiveCfg = Release|x86
|
||||||
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.Build.0 = Release|x86
|
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.Build.0 = Release|x86
|
||||||
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.Deploy.0 = Release|x86
|
{A0CFC681-769B-405A-8482-0CDEE595A91F}.Release|x86.Deploy.0 = Release|x86
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|ARM.ActiveCfg = Debug|ARM
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|ARM.Build.0 = Debug|ARM
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|x64.ActiveCfg = Debug|x64
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|x64.Build.0 = Debug|x64
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|x86.ActiveCfg = Debug|x86
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Debug|x86.Build.0 = Debug|x86
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|ARM.ActiveCfg = Release|ARM
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|ARM.Build.0 = Release|ARM
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|x64.ActiveCfg = Release|x64
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|x64.Build.0 = Release|x64
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|x86.ActiveCfg = Release|x86
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{A207789D-9020-401B-9D0A-D0D2CFF721BD}.Release|x86.Build.0 = Release|x86
|
{2E710089-9559-4967-846C-E763DD1F3ACB}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|ARM.Build.0 = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{067456C0-086C-46A8-B37F-1405717B7BFC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
23
ModernKeePass/Actions/SetupFocusAction.cs
Normal file
23
ModernKeePass/Actions/SetupFocusAction.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Microsoft.Xaml.Interactivity;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Actions
|
||||||
|
{
|
||||||
|
public class SetupFocusAction : DependencyObject, IAction
|
||||||
|
{
|
||||||
|
public Control TargetObject
|
||||||
|
{
|
||||||
|
get { return (Control)GetValue(TargetObjectProperty); }
|
||||||
|
set { SetValue(TargetObjectProperty, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DependencyProperty TargetObjectProperty =
|
||||||
|
DependencyProperty.Register("TargetObject", typeof(Control), typeof(SetupFocusAction), new PropertyMetadata(0));
|
||||||
|
|
||||||
|
public object Execute(object sender, object parameter)
|
||||||
|
{
|
||||||
|
return TargetObject?.Focus(FocusState.Programmatic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -2,6 +2,14 @@
|
|||||||
x:Class="ModernKeePass.App"
|
x:Class="ModernKeePass.App"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="using:ModernKeePass">
|
RequestedTheme="Light">
|
||||||
|
<Application.Resources>
|
||||||
|
<ResourceDictionary>
|
||||||
|
<ResourceDictionary.MergedDictionaries>
|
||||||
|
<ResourceDictionary Source="Styles/TextBoxWithButtonStyle.xaml" />
|
||||||
|
<ResourceDictionary Source="Styles/HamburgerButtonStyle.xaml" />
|
||||||
|
</ResourceDictionary.MergedDictionaries>
|
||||||
|
</ResourceDictionary>
|
||||||
|
</Application.Resources>
|
||||||
|
|
||||||
</Application>
|
</Application>
|
||||||
|
@@ -1,20 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using Windows.ApplicationModel;
|
using Windows.ApplicationModel;
|
||||||
using Windows.ApplicationModel.Activation;
|
using Windows.ApplicationModel.Activation;
|
||||||
|
using Windows.ApplicationModel.Search;
|
||||||
using Windows.Foundation;
|
using Windows.Foundation;
|
||||||
using Windows.Foundation.Collections;
|
using Windows.Storage;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Controls.Primitives;
|
|
||||||
using Windows.UI.Xaml.Data;
|
|
||||||
using Windows.UI.Xaml.Input;
|
|
||||||
using Windows.UI.Xaml.Media;
|
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
|
||||||
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
|
// The Blank Application template is documented at http://go.microsoft.com/fwlink/?LinkId=234227
|
||||||
|
|
||||||
namespace ModernKeePass
|
namespace ModernKeePass
|
||||||
@@ -24,14 +19,16 @@ namespace ModernKeePass
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
sealed partial class App : Application
|
sealed partial class App : Application
|
||||||
{
|
{
|
||||||
|
public DatabaseHelper Database { get; set; } = new DatabaseHelper();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes the singleton application object. This is the first line of authored code
|
/// 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().
|
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public App()
|
public App()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
this.Suspending += OnSuspending;
|
Suspending += OnSuspending;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -45,11 +42,11 @@ namespace ModernKeePass
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
if (System.Diagnostics.Debugger.IsAttached)
|
if (System.Diagnostics.Debugger.IsAttached)
|
||||||
{
|
{
|
||||||
this.DebugSettings.EnableFrameRateCounter = true;
|
DebugSettings.EnableFrameRateCounter = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Frame rootFrame = Window.Current.Content as Frame;
|
var rootFrame = Window.Current.Content as Frame;
|
||||||
|
|
||||||
// Do not repeat app initialization when the Window already has content,
|
// Do not repeat app initialization when the Window already has content,
|
||||||
// just ensure that the window is active
|
// just ensure that the window is active
|
||||||
@@ -103,7 +100,18 @@ namespace ModernKeePass
|
|||||||
{
|
{
|
||||||
var deferral = e.SuspendingOperation.GetDeferral();
|
var deferral = e.SuspendingOperation.GetDeferral();
|
||||||
//TODO: Save application state and stop any background activity
|
//TODO: Save application state and stop any background activity
|
||||||
|
//Database.Save();
|
||||||
deferral.Complete();
|
deferral.Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnFileActivated(FileActivatedEventArgs args)
|
||||||
|
{
|
||||||
|
base.OnFileActivated(args);
|
||||||
|
var rootFrame = new Frame();
|
||||||
|
Database.DatabaseFile = args.Files[0] as StorageFile;
|
||||||
|
rootFrame.Navigate(typeof(MainPage), args);
|
||||||
|
Window.Current.Content = rootFrame;
|
||||||
|
Window.Current.Activate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4
ModernKeePass/BundleArtifacts/neutral.txt
Normal file
4
ModernKeePass/BundleArtifacts/neutral.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
MainPackage=C:\Users\GBE\Source\Repos\ModernKeePass\ModernKeePass\bin\Release\ModernKeePass_1.2.0.14_AnyCPU.appx
|
||||||
|
SymbolPackage=C:\Users\GBE\Source\Repos\ModernKeePass\ModernKeePass\AppPackages\ModernKeePass_1.2.0.14_Test\ModernKeePass_1.2.0.14_AnyCPU.appxsym
|
||||||
|
ResourcePack=C:\Users\GBE\Source\Repos\ModernKeePass\ModernKeePass\bin\Release\ModernKeePass_1.2.0.14_scale-140.appx
|
||||||
|
ResourcePack=C:\Users\GBE\Source\Repos\ModernKeePass\ModernKeePass\bin\Release\ModernKeePass_1.2.0.14_scale-180.appx
|
86
ModernKeePass/Common/DatabaseHelper.cs
Normal file
86
ModernKeePass/Common/DatabaseHelper.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.Storage;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
using ModernKeePassLib;
|
||||||
|
using ModernKeePassLib.Interfaces;
|
||||||
|
using ModernKeePassLib.Keys;
|
||||||
|
using ModernKeePassLib.Serialization;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Common
|
||||||
|
{
|
||||||
|
public class DatabaseHelper
|
||||||
|
{
|
||||||
|
public enum DatabaseStatus
|
||||||
|
{
|
||||||
|
Closed = 0,
|
||||||
|
Opening = 1,
|
||||||
|
Opened = 2
|
||||||
|
}
|
||||||
|
private PwDatabase _pwDatabase = new PwDatabase();
|
||||||
|
private StorageFile _databaseFile;
|
||||||
|
|
||||||
|
public GroupVm RootGroup { get; set; }
|
||||||
|
public DatabaseStatus Status { get; private set; } = DatabaseStatus.Closed;
|
||||||
|
public string Name => DatabaseFile?.Name;
|
||||||
|
|
||||||
|
public StorageFile DatabaseFile
|
||||||
|
{
|
||||||
|
get { return _databaseFile; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_databaseFile = value;
|
||||||
|
Status = DatabaseStatus.Opening;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Open(string password, bool createNew = false)
|
||||||
|
{
|
||||||
|
var key = new CompositeKey();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
key.AddUserKey(new KcpPassword(password));
|
||||||
|
var ioConnection = IOConnectionInfo.FromFile(DatabaseFile);
|
||||||
|
if (createNew) _pwDatabase.New(ioConnection, key);
|
||||||
|
else _pwDatabase.Open(ioConnection, key, new NullStatusLogger());
|
||||||
|
|
||||||
|
if (_pwDatabase.IsOpen)
|
||||||
|
{
|
||||||
|
Status = DatabaseStatus.Opened;
|
||||||
|
RootGroup = new GroupVm(_pwDatabase.RootGroup, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ArgumentNullException)
|
||||||
|
{
|
||||||
|
return "Password cannot be empty";
|
||||||
|
}
|
||||||
|
catch (InvalidCompositeKeyException)
|
||||||
|
{
|
||||||
|
return "Wrong password";
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ex.Message;
|
||||||
|
}
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Save(StorageFile file)
|
||||||
|
{
|
||||||
|
DatabaseFile = file;
|
||||||
|
_pwDatabase.SaveAs(IOConnectionInfo.FromFile(DatabaseFile), true, new NullStatusLogger());
|
||||||
|
Status = DatabaseStatus.Opened;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
if (_pwDatabase != null && _pwDatabase.IsOpen)
|
||||||
|
_pwDatabase.Save(new NullStatusLogger());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
_pwDatabase?.Close();
|
||||||
|
Status = DatabaseStatus.Closed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
ModernKeePass/Common/NotifyPropertyChangedBase.cs
Normal file
28
ModernKeePass/Common/NotifyPropertyChangedBase.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Common
|
||||||
|
{
|
||||||
|
public class NotifyPropertyChangedBase : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool SetProperty<T>(ref T property, T value, [CallerMemberName] string propertyName = "")
|
||||||
|
{
|
||||||
|
if (EqualityComparer<T>.Default.Equals(property, value))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
property = value;
|
||||||
|
OnPropertyChanged(propertyName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -46,6 +46,14 @@ namespace ModernKeePass.Common
|
|||||||
this.Add(item.Key, item.Value);
|
this.Add(item.Key, item.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddRange(IEnumerable<KeyValuePair<string, object>> values)
|
||||||
|
{
|
||||||
|
foreach (var value in values)
|
||||||
|
{
|
||||||
|
Add(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool Remove(string key)
|
public bool Remove(string key)
|
||||||
{
|
{
|
||||||
if (this._dictionary.Remove(key))
|
if (this._dictionary.Remove(key))
|
||||||
|
18
ModernKeePass/Controls/FirstItemDataTemplateSelector.cs
Normal file
18
ModernKeePass/Controls/FirstItemDataTemplateSelector.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Controls
|
||||||
|
{
|
||||||
|
public class FirstItemDataTemplateSelector: DataTemplateSelector
|
||||||
|
{
|
||||||
|
public DataTemplate FirstItem { get; set; }
|
||||||
|
public DataTemplate OtherItem { get; set; }
|
||||||
|
|
||||||
|
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
|
||||||
|
{
|
||||||
|
var itemsControl = ItemsControl.ItemsControlFromItemContainer(container);
|
||||||
|
var returnTemplate = itemsControl.IndexFromContainer(container) == 0 ? FirstItem : OtherItem;
|
||||||
|
return returnTemplate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
ModernKeePass/Controls/ListViewWithDisable.cs
Normal file
20
ModernKeePass/Controls/ListViewWithDisable.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Controls
|
||||||
|
{
|
||||||
|
public class ListViewWithDisable: ListView
|
||||||
|
{
|
||||||
|
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
|
||||||
|
{
|
||||||
|
base.PrepareContainerForItemOverride(element, item);
|
||||||
|
|
||||||
|
var container = element as ListViewItem;
|
||||||
|
var binaryItem = item as IIsEnabled;
|
||||||
|
if (container == null || binaryItem == null) return;
|
||||||
|
container.IsEnabled = binaryItem.IsEnabled;
|
||||||
|
container.IsHitTestVisible = binaryItem.IsEnabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
344
ModernKeePass/Controls/OpenDatabaseUserControl.xaml
Normal file
344
ModernKeePass/Controls/OpenDatabaseUserControl.xaml
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
<UserControl
|
||||||
|
x:Class="ModernKeePass.Controls.OpenDatabaseUserControl"
|
||||||
|
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"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="65"
|
||||||
|
d:DesignWidth="335" Loaded="UserControl_Loaded">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<Style TargetType="PasswordBox" x:Name="PasswordBoxWithButtonStyle">
|
||||||
|
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
|
||||||
|
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
|
||||||
|
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
|
||||||
|
<Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
|
||||||
|
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}" />
|
||||||
|
<Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}" />
|
||||||
|
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
|
||||||
|
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||||
|
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||||
|
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
|
||||||
|
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
|
||||||
|
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="PasswordBox">
|
||||||
|
<Grid>
|
||||||
|
<Grid.Resources>
|
||||||
|
<Style x:Name="RevealButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"/>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}">
|
||||||
|
<TextBlock x:Name="GlyphElement"
|
||||||
|
Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontStyle="Normal"
|
||||||
|
Text=""
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style x:Name="GotoButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" >
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"/>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}">
|
||||||
|
<TextBlock x:Name="GlyphElement"
|
||||||
|
Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontStyle="Normal"
|
||||||
|
Text=""
|
||||||
|
Padding="4,0,4,0"
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Grid.Resources>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Normal">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlBackgroundThemeOpacity}" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlBorderThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Focused" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="ButtonStates">
|
||||||
|
<VisualState x:Name="ButtonVisible">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RevealButton"
|
||||||
|
Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0">
|
||||||
|
<DiscreteObjectKeyFrame.Value>
|
||||||
|
<Visibility>Visible</Visibility>
|
||||||
|
</DiscreteObjectKeyFrame.Value>
|
||||||
|
</DiscreteObjectKeyFrame>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="ButtonCollapsed" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Grid.RowSpan="1"/>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Grid.RowSpan="1"/>
|
||||||
|
<ContentPresenter x:Name="HeaderContentPresenter"
|
||||||
|
Grid.Row="0"
|
||||||
|
Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
|
||||||
|
Margin="0,4,0,4"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Content="{TemplateBinding Header}"
|
||||||
|
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||||
|
FontWeight="Semilight" />
|
||||||
|
<ScrollViewer x:Name="ContentElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
|
||||||
|
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
|
||||||
|
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
|
||||||
|
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
|
||||||
|
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
|
||||||
|
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
IsTabStop="False"
|
||||||
|
ZoomMode="Disabled"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
<ContentControl x:Name="PlaceholderTextContentPresenter"
|
||||||
|
Grid.Row="1"
|
||||||
|
Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.ColumnSpan="3"
|
||||||
|
Content="{TemplateBinding PlaceholderText}"
|
||||||
|
IsHitTestVisible="False"/>
|
||||||
|
<Button x:Name="RevealButton"
|
||||||
|
Grid.Row="1"
|
||||||
|
Style="{StaticResource RevealButtonStyle}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.Column="1"
|
||||||
|
Visibility="Collapsed"
|
||||||
|
FontSize="{TemplateBinding FontSize}"
|
||||||
|
VerticalAlignment="Stretch"/>
|
||||||
|
<Button x:Name="GotoButton"
|
||||||
|
Grid.Row="1"
|
||||||
|
Style="{StaticResource GotoButtonStyle}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.Column="2"
|
||||||
|
Visibility="Visible"
|
||||||
|
FontSize="{TemplateBinding FontSize}"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Click="OpenButton_OnClick" />
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</UserControl.Resources>
|
||||||
|
<StackPanel>
|
||||||
|
<PasswordBox x:Name="PasswordBox" Width="300" IsPasswordRevealButtonEnabled="True" KeyDown="PasswordBox_KeyDown" PlaceholderText="Password" Style="{StaticResource PasswordBoxWithButtonStyle}"/>
|
||||||
|
<!--<StackPanel Orientation="Horizontal" Margin="0,-1,0,-1" >
|
||||||
|
<Button Click="OpenButton_OnClick" Width="auto" Padding="2,0">
|
||||||
|
<SymbolIcon Symbol="Forward" />
|
||||||
|
</Button>
|
||||||
|
</StackPanel>-->
|
||||||
|
<TextBlock x:Name="StatusTextBlock" Height="32" Width="auto" Foreground="#FFBF6969" FontSize="16" FontWeight="Bold" />
|
||||||
|
</StackPanel>
|
||||||
|
</UserControl>
|
60
ModernKeePass/Controls/OpenDatabaseUserControl.xaml.cs
Normal file
60
ModernKeePass/Controls/OpenDatabaseUserControl.xaml.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Windows.System;
|
||||||
|
using Windows.UI.Core;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Input;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Events;
|
||||||
|
|
||||||
|
// Pour en savoir plus sur le modèle d'élément Contrôle utilisateur, consultez la page http://go.microsoft.com/fwlink/?LinkId=234236
|
||||||
|
|
||||||
|
namespace ModernKeePass.Controls
|
||||||
|
{
|
||||||
|
public sealed partial class OpenDatabaseUserControl : UserControl
|
||||||
|
{
|
||||||
|
public bool CreateNew
|
||||||
|
{
|
||||||
|
get { return (bool)GetValue(CreateNewProperty); }
|
||||||
|
set { SetValue(CreateNewProperty, value); }
|
||||||
|
}
|
||||||
|
public static readonly DependencyProperty CreateNewProperty =
|
||||||
|
DependencyProperty.Register(
|
||||||
|
"CreateNew",
|
||||||
|
typeof(bool),
|
||||||
|
typeof(OpenDatabaseUserControl),
|
||||||
|
new PropertyMetadata(null, (o, args) => { }));
|
||||||
|
|
||||||
|
public OpenDatabaseUserControl()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PasswordCheckingEventHandler ValidationChecking;
|
||||||
|
public delegate void PasswordCheckingEventHandler(object sender, EventArgs e);
|
||||||
|
public event PasswordCheckedEventHandler ValidationChecked;
|
||||||
|
public delegate void PasswordCheckedEventHandler(object sender, PasswordEventArgs e);
|
||||||
|
|
||||||
|
private void OpenButton_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
ValidationChecking?.Invoke(this, new EventArgs());
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
StatusTextBlock.Text = app.Database.Open(PasswordBox.Password, CreateNew);
|
||||||
|
if (app.Database.Status == DatabaseHelper.DatabaseStatus.Opened)
|
||||||
|
ValidationChecked?.Invoke(this, new PasswordEventArgs(app.Database.RootGroup));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PasswordBox_KeyDown(object sender, KeyRoutedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key == VirtualKey.Enter) OpenButton_OnClick(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UserControl_Loaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Task.Factory.StartNew(
|
||||||
|
() => Dispatcher.RunAsync(CoreDispatcherPriority.Low,
|
||||||
|
() => PasswordBox.Focus(FocusState.Programmatic)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
ModernKeePass/Controls/TextBoxWithButton.cs
Normal file
21
ModernKeePass/Controls/TextBoxWithButton.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Controls
|
||||||
|
{
|
||||||
|
public class TextBoxWithButton : TextBox
|
||||||
|
{
|
||||||
|
public event EventHandler<RoutedEventArgs> GotoClick;
|
||||||
|
|
||||||
|
protected override void OnApplyTemplate()
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate();
|
||||||
|
var extraButton = GetTemplateChild("GotoButton") as Button;
|
||||||
|
if (extraButton != null)
|
||||||
|
{
|
||||||
|
extraButton.Click += (sender, e) => GotoClick?.Invoke(sender, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
ModernKeePass/Converters/BooleanToVisibilityConverter.cs
Normal file
28
ModernKeePass/Converters/BooleanToVisibilityConverter.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class BooleanToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var boolean = value is bool ? (bool) value : false;
|
||||||
|
return boolean ? Visibility.Visible : Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to implement this
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var visibility = value is Visibility ? (Visibility) value : Visibility.Visible;
|
||||||
|
switch (visibility)
|
||||||
|
{
|
||||||
|
case Visibility.Visible: return true;
|
||||||
|
case Visibility.Collapsed: return false;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
ModernKeePass/Converters/ColorToBrushConverter.cs
Normal file
26
ModernKeePass/Converters/ColorToBrushConverter.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class ColorToBrushConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var color = value is Color ? (Color?) value : Color.Empty;
|
||||||
|
if (color == Color.Empty && parameter is SolidColorBrush) return (SolidColorBrush) parameter;
|
||||||
|
return new SolidColorBrush(Windows.UI.Color.FromArgb(
|
||||||
|
color.Value.A,
|
||||||
|
color.Value.R,
|
||||||
|
color.Value.G,
|
||||||
|
color.Value.B));
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class InverseBooleanToVisibilityConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var boolean = value is bool ? (bool)value : false;
|
||||||
|
return boolean ? Visibility.Collapsed : Visibility.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to implement this
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var visibility = value is Visibility ? (Visibility)value : Visibility.Visible;
|
||||||
|
switch (visibility)
|
||||||
|
{
|
||||||
|
case Visibility.Visible: return false;
|
||||||
|
case Visibility.Collapsed: return true;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
ModernKeePass/Converters/PluralizationConverter.cs
Normal file
24
ModernKeePass/Converters/PluralizationConverter.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Converters
|
||||||
|
{
|
||||||
|
public class PluralizationConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
var pluralizationOptionString = parameter as string;
|
||||||
|
var pluralizationOptions = pluralizationOptionString?.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (pluralizationOptions == null || pluralizationOptions.Length != 2) return string.Empty;
|
||||||
|
var count = value is int ? (int) value : 0;
|
||||||
|
var text = count == 1 ? pluralizationOptions[0] : pluralizationOptions[1];
|
||||||
|
return $"{count} {text}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to implement this
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
ModernKeePass/Events/PasswordEventArgs.cs
Normal file
15
ModernKeePass/Events/PasswordEventArgs.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Events
|
||||||
|
{
|
||||||
|
public class PasswordEventArgs: EventArgs
|
||||||
|
{
|
||||||
|
public GroupVm RootGroup { get; set; }
|
||||||
|
|
||||||
|
public PasswordEventArgs(GroupVm groupVm)
|
||||||
|
{
|
||||||
|
RootGroup = groupVm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
ModernKeePass/Interfaces/IIsEnabled.cs
Normal file
7
ModernKeePass/Interfaces/IIsEnabled.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace ModernKeePass.Interfaces
|
||||||
|
{
|
||||||
|
public interface IIsEnabled
|
||||||
|
{
|
||||||
|
bool IsEnabled { get; }
|
||||||
|
}
|
||||||
|
}
|
@@ -1,41 +1,66 @@
|
|||||||
<Page
|
<Page
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="using:ModernKeePass"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:ViewModels="using:ModernKeePass.ViewModels"
|
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||||
|
xmlns:controls="using:ModernKeePass.Controls"
|
||||||
x:Class="ModernKeePass.MainPage"
|
x:Class="ModernKeePass.MainPage"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
|
Background="{StaticResource ApplicationPageBackgroundThemeBrush}" >
|
||||||
<Page.DataContext>
|
<Page.DataContext>
|
||||||
<ViewModels:DatabaseVm/>
|
<viewModels:MainVm />
|
||||||
</Page.DataContext>
|
</Page.DataContext>
|
||||||
|
<Page.Resources>
|
||||||
|
<CollectionViewSource
|
||||||
|
x:Name="MenuItemsSource"
|
||||||
|
Source="{Binding MainMenuItems}"
|
||||||
|
IsSourceGrouped="True" />
|
||||||
|
</Page.Resources>
|
||||||
|
|
||||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
|
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" >
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="250" />
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="50" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Grid.RowDefinitions>
|
<controls:ListViewWithDisable Grid.Column="0"
|
||||||
<RowDefinition Height="Auto" />
|
x:Name="MenuListView"
|
||||||
<RowDefinition Height="50" />
|
RequestedTheme="Dark"
|
||||||
<RowDefinition Height="*" />
|
SelectionChanged="ListView_SelectionChanged"
|
||||||
</Grid.RowDefinitions>
|
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||||
<Button Grid.Column="0" Grid.Row="0" x:Name="selectButton" Content="Select password database" Click="Button_Click" HorizontalAlignment="Center" />
|
ItemsSource="{Binding Source={StaticResource MenuItemsSource}}"
|
||||||
<Grid Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" Height="auto" VerticalAlignment="Top" Width="auto" Visibility="{Binding Visibility}" >
|
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
|
||||||
<Grid.ColumnDefinitions>
|
IsSynchronizedWithCurrentItem="False">
|
||||||
<ColumnDefinition Width="100" />
|
<ListView.Header>
|
||||||
<ColumnDefinition Width="150" />
|
<TextBlock Text="ModernKeePass" FontWeight="Bold" FontSize="36" Margin="20" />
|
||||||
</Grid.ColumnDefinitions>
|
</ListView.Header>
|
||||||
<Grid.RowDefinitions>
|
<ListView.ItemTemplate>
|
||||||
<RowDefinition Height="Auto" />
|
<DataTemplate >
|
||||||
<RowDefinition Height="*" />
|
<StackPanel Orientation="Horizontal">
|
||||||
<RowDefinition Height="*" />
|
<SymbolIcon Symbol="{Binding SymbolIcon}" />
|
||||||
</Grid.RowDefinitions>
|
<TextBlock Text="{Binding Title}" Margin="10,5,0,0" />
|
||||||
<TextBlock Grid.Column="0" Grid.Row="0" x:Name="passwordTextBlock" HorizontalAlignment="Left" TextWrapping="Wrap" Text="Password" VerticalAlignment="Center" Height="auto" Width="auto" FontSize="16" Margin="10,7,0,6" />
|
</StackPanel>
|
||||||
<PasswordBox Grid.Column="1" Grid.Row="0" x:Name="passwordBox" VerticalAlignment="Top" HorizontalAlignment="Right" Width="130" Password="{Binding Password, Mode=TwoWay}" IsPasswordRevealButtonEnabled="True" Margin="0,0,10,0"/>
|
</DataTemplate>
|
||||||
<Button Grid.Column="1" Grid.Row="1" x:Name="openBbutton" Content="Open" HorizontalAlignment="Right" VerticalAlignment="Top" Click="openBbutton_Click" Margin="0,0,7,0" Width="auto"/>
|
</ListView.ItemTemplate>
|
||||||
<TextBlock Grid.Column="1" Grid.Row="2" x:Name="errorTextBlock" TextWrapping="Wrap" Text="{Binding ErrorMessage}" HorizontalAlignment="Right" Height="auto" Width="auto" Foreground="#FF9E0909" Margin="0,0,10,0"/>
|
<ListView.ItemContainerStyle>
|
||||||
</Grid>
|
<Style TargetType="ListViewItem">
|
||||||
|
<Setter Property="Padding" Value="20,5,0,0" />
|
||||||
|
<Setter Property="Margin" Value="0" />
|
||||||
|
</Style>
|
||||||
|
</ListView.ItemContainerStyle>
|
||||||
|
<ListView.GroupStyle>
|
||||||
|
<GroupStyle HidesIfEmpty="True">
|
||||||
|
<GroupStyle.HeaderTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Background="DarkGray" Margin="20,0,0,0">
|
||||||
|
<Border Height="1" Width="240" HorizontalAlignment="Stretch"/>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</GroupStyle.HeaderTemplate>
|
||||||
|
</GroupStyle>
|
||||||
|
</ListView.GroupStyle>
|
||||||
|
</controls:ListViewWithDisable>
|
||||||
|
<Frame Grid.Column="2" Name="MenuFrame" Width="auto" Margin="0,60,0,0" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
@@ -1,8 +1,5 @@
|
|||||||
using System;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Navigation;
|
||||||
using Windows.UI.Xaml.Input;
|
|
||||||
|
|
||||||
using ModernKeePass.Pages;
|
|
||||||
using ModernKeePass.ViewModels;
|
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
|
||||||
@@ -16,34 +13,19 @@ namespace ModernKeePass
|
|||||||
{
|
{
|
||||||
public MainPage()
|
public MainPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Button_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
var picker = new Windows.Storage.Pickers.FileOpenPicker();
|
|
||||||
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.List;
|
|
||||||
picker.SuggestedStartLocation =
|
|
||||||
Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
|
|
||||||
picker.FileTypeFilter.Add(".kdbx");
|
|
||||||
|
|
||||||
var file = await picker.PickSingleFileAsync();
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
if (file != null)
|
|
||||||
{
|
|
||||||
// Application now has read/write access to the picked file
|
|
||||||
DataContext = new DatabaseVm(file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openBbutton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
|
||||||
{
|
{
|
||||||
var database = DataContext as DatabaseVm;
|
base.OnNavigatedTo(e);
|
||||||
database.Open();
|
DataContext = new MainVm(Frame, MenuFrame);
|
||||||
if (database.IsOpen)
|
}
|
||||||
Frame.Navigate(typeof(GroupDetailPage), database.RootGroup);
|
|
||||||
|
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var mainVm = DataContext as MainVm;
|
||||||
|
mainVm.SelectedItem?.Destination.Navigate(mainVm.SelectedItem.PageType, mainVm.SelectedItem.Parameter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
82
ModernKeePass/Mappings/PwIconToSegoeMapping.cs
Normal file
82
ModernKeePass/Mappings/PwIconToSegoeMapping.cs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePassLib;
|
||||||
|
|
||||||
|
namespace ModernKeePass.Mappings
|
||||||
|
{
|
||||||
|
public static class PwIconToSegoeMapping
|
||||||
|
{
|
||||||
|
public static Symbol GetSymbolFromIcon(PwIcon icon)
|
||||||
|
{
|
||||||
|
switch (icon)
|
||||||
|
{
|
||||||
|
case PwIcon.Key: return Symbol.Permissions;
|
||||||
|
case PwIcon.World: return Symbol.World;
|
||||||
|
case PwIcon.Warning: return Symbol.Important;
|
||||||
|
case PwIcon.WorldComputer:
|
||||||
|
case PwIcon.DriveWindows:
|
||||||
|
case PwIcon.NetworkServer: return Symbol.MapDrive;
|
||||||
|
//case PwIcon.MarkedDirectory: return Symbol.;
|
||||||
|
case PwIcon.UserCommunication: return Symbol.ContactInfo;
|
||||||
|
//case PwIcon.Parts: return Symbol.;
|
||||||
|
case PwIcon.Notepad: return Symbol.Document;
|
||||||
|
//case PwIcon.WorldScoket: return Symbol.;
|
||||||
|
case PwIcon.Identity: return Symbol.Contact2;
|
||||||
|
//case PwIcon.PaperReady: return Symbol.;
|
||||||
|
case PwIcon.Digicam: return Symbol.Camera;
|
||||||
|
case PwIcon.IRCommunication: return Symbol.View;
|
||||||
|
case PwIcon.Energy: return Symbol.ZeroBars;
|
||||||
|
case PwIcon.Scanner: return Symbol.Scan;
|
||||||
|
case PwIcon.CDRom: return Symbol.Rotate;
|
||||||
|
case PwIcon.Monitor: return Symbol.Caption;
|
||||||
|
case PwIcon.EMailBox:
|
||||||
|
case PwIcon.EMail: return Symbol.Mail;
|
||||||
|
case PwIcon.Configuration: return Symbol.Setting;
|
||||||
|
case PwIcon.ClipboardReady: return Symbol.Paste;
|
||||||
|
case PwIcon.PaperNew: return Symbol.Page2;
|
||||||
|
case PwIcon.Screen: return Symbol.GoToStart;
|
||||||
|
case PwIcon.EnergyCareful: return Symbol.FourBars;
|
||||||
|
case PwIcon.Disk: return Symbol.Save;
|
||||||
|
//case PwIcon.Drive: return Symbol.;
|
||||||
|
//case PwIcon.PaperQ: return Symbol.;
|
||||||
|
//case PwIcon.TerminalEncrypted: return Symbol.;
|
||||||
|
//case PwIcon.Console: return Symbol.;
|
||||||
|
//case PwIcon.Printer: return Symbol.;
|
||||||
|
case PwIcon.ProgramIcons: return Symbol.GoToStart;
|
||||||
|
//case PwIcon.Run: return Symbol.;
|
||||||
|
case PwIcon.Settings:
|
||||||
|
case PwIcon.Tool: return Symbol.Repair;
|
||||||
|
//case PwIcon.Archive: return Symbol.;
|
||||||
|
case PwIcon.Count: return Symbol.MapDrive;
|
||||||
|
case PwIcon.Clock: return Symbol.Clock;
|
||||||
|
case PwIcon.EMailSearch: return Symbol.Find;
|
||||||
|
case PwIcon.PaperFlag: return Symbol.Flag;
|
||||||
|
//case PwIcon.Memory: return Symbol.;
|
||||||
|
case PwIcon.TrashBin: return Symbol.Delete;
|
||||||
|
case PwIcon.Expired: return Symbol.Cancel;
|
||||||
|
case PwIcon.Info: return Symbol.Help;
|
||||||
|
//case PwIcon.Package: return Symbol.;
|
||||||
|
case PwIcon.Folder:
|
||||||
|
case PwIcon.FolderOpen:
|
||||||
|
case PwIcon.FolderPackage: return Symbol.Folder;
|
||||||
|
//case PwIcon.LockOpen: return Symbol.;
|
||||||
|
case PwIcon.PaperLocked: return Symbol.ProtectedDocument;
|
||||||
|
case PwIcon.Checked: return Symbol.Accept;
|
||||||
|
case PwIcon.Pen: return Symbol.Edit;
|
||||||
|
case PwIcon.Thumbnail: return Symbol.BrowsePhotos;
|
||||||
|
case PwIcon.Book: return Symbol.Library;
|
||||||
|
case PwIcon.List: return Symbol.List;
|
||||||
|
case PwIcon.UserKey: return Symbol.ContactPresence;
|
||||||
|
case PwIcon.Home: return Symbol.Home;
|
||||||
|
case PwIcon.Star: return Symbol.OutlineStar;
|
||||||
|
//case PwIcon.Tux: return Symbol.;
|
||||||
|
//case PwIcon.Feather: return Symbol.;
|
||||||
|
//case PwIcon.Apple: return Symbol.;
|
||||||
|
//case PwIcon.Wiki: return Symbol.;
|
||||||
|
//case PwIcon.Money: return Symbol.;
|
||||||
|
case PwIcon.Certificate: return Symbol.PreviewLink;
|
||||||
|
case PwIcon.BlackBerry: return Symbol.CellPhone;
|
||||||
|
default: return Symbol.More;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -107,26 +107,59 @@
|
|||||||
<Prefer32Bit>true</Prefer32Bit>
|
<Prefer32Bit>true</Prefer32Bit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="Actions\SetupFocusAction.cs" />
|
||||||
<Compile Include="App.xaml.cs">
|
<Compile Include="App.xaml.cs">
|
||||||
<DependentUpon>App.xaml</DependentUpon>
|
<DependentUpon>App.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Common\DatabaseHelper.cs" />
|
||||||
<Compile Include="Common\NavigationHelper.cs" />
|
<Compile Include="Common\NavigationHelper.cs" />
|
||||||
|
<Compile Include="Common\NotifyPropertyChangedBase.cs" />
|
||||||
<Compile Include="Common\ObservableDictionary.cs" />
|
<Compile Include="Common\ObservableDictionary.cs" />
|
||||||
<Compile Include="Common\RelayCommand.cs" />
|
<Compile Include="Common\RelayCommand.cs" />
|
||||||
<Compile Include="Common\SuspensionManager.cs" />
|
<Compile Include="Common\SuspensionManager.cs" />
|
||||||
|
<Compile Include="Controls\FirstItemDataTemplateSelector.cs" />
|
||||||
|
<Compile Include="Controls\ListViewWithDisable.cs" />
|
||||||
|
<Compile Include="Controls\OpenDatabaseUserControl.xaml.cs">
|
||||||
|
<DependentUpon>OpenDatabaseUserControl.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Controls\TextBoxWithButton.cs" />
|
||||||
|
<Compile Include="Converters\BooleanToVisibilityConverter.cs" />
|
||||||
|
<Compile Include="Converters\ColorToBrushConverter.cs" />
|
||||||
|
<Compile Include="Converters\InverseBooleanToVisibilityConverter.cs" />
|
||||||
|
<Compile Include="Converters\PluralizationConverter.cs" />
|
||||||
|
<Compile Include="Events\PasswordEventArgs.cs" />
|
||||||
|
<Compile Include="Interfaces\IIsEnabled.cs" />
|
||||||
<Compile Include="MainPage.xaml.cs">
|
<Compile Include="MainPage.xaml.cs">
|
||||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Mappings\PwIconToSegoeMapping.cs" />
|
||||||
|
<Compile Include="Pages\NewDatabasePage.xaml.cs">
|
||||||
|
<DependentUpon>NewDatabasePage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="ViewModels\Items\MainMenuItemVm.cs" />
|
||||||
|
<Compile Include="ViewModels\Items\RecentItemVm.cs" />
|
||||||
<Compile Include="Pages\EntryDetailPage.xaml.cs">
|
<Compile Include="Pages\EntryDetailPage.xaml.cs">
|
||||||
<DependentUpon>EntryDetailPage.xaml</DependentUpon>
|
<DependentUpon>EntryDetailPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Pages\GroupDetailPage.xaml.cs">
|
<Compile Include="Pages\GroupDetailPage.xaml.cs">
|
||||||
<DependentUpon>GroupDetailPage.xaml</DependentUpon>
|
<DependentUpon>GroupDetailPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Pages\OpenDatabasePage.xaml.cs">
|
||||||
|
<DependentUpon>OpenDatabasePage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Pages\RecentDatabasesPage.xaml.cs">
|
||||||
|
<DependentUpon>RecentDatabasesPage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Pages\SaveDatabasePage.xaml.cs">
|
||||||
|
<DependentUpon>SaveDatabasePage.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ViewModels\DatabaseVm.cs" />
|
|
||||||
<Compile Include="ViewModels\EntryVm.cs" />
|
<Compile Include="ViewModels\EntryVm.cs" />
|
||||||
<Compile Include="ViewModels\GroupVm.cs" />
|
<Compile Include="ViewModels\GroupVm.cs" />
|
||||||
|
<Compile Include="ViewModels\MainVm.cs" />
|
||||||
|
<Compile Include="ViewModels\OpenVm.cs" />
|
||||||
|
<Compile Include="ViewModels\RecentVm.cs" />
|
||||||
|
<Compile Include="ViewModels\SaveVm.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AppxManifest Include="Package.appxmanifest">
|
<AppxManifest Include="Package.appxmanifest">
|
||||||
@@ -134,7 +167,9 @@
|
|||||||
</AppxManifest>
|
</AppxManifest>
|
||||||
<None Include="ModernKeePass_StoreKey.pfx" />
|
<None Include="ModernKeePass_StoreKey.pfx" />
|
||||||
<None Include="ModernKeePass_TemporaryKey.pfx" />
|
<None Include="ModernKeePass_TemporaryKey.pfx" />
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Package.StoreAssociation.xml" />
|
<None Include="Package.StoreAssociation.xml" />
|
||||||
@@ -144,6 +179,10 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</ApplicationDefinition>
|
</ApplicationDefinition>
|
||||||
|
<Page Include="Controls\OpenDatabaseUserControl.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="MainPage.xaml">
|
<Page Include="MainPage.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
@@ -156,18 +195,60 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Pages\NewDatabasePage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Pages\OpenDatabasePage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Pages\RecentDatabasesPage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Pages\SaveDatabasePage.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Styles\HamburgerButtonStyle.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Page>
|
||||||
|
<Page Include="Styles\TextBoxWithButtonStyle.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="ModernKeePassLib, Version=2.19.0.15913, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="BouncyCastle.Crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\ModernKeePassLib.2.19.2950\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
|
<HintPath>..\packages\Portable.BouncyCastle.1.8.1.3\lib\netstandard1.0\BouncyCastle.Crypto.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="ModernKeePassLib, Version=2.28.1.4000, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\ModernKeePassLib.2.28.4000\lib\netstandard1.2\ModernKeePassLib.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Splat.2.0.0\lib\Portable-Win81+Wpa81\Splat.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.Runtime.InteropServices.RuntimeInformation, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\win8\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
|
<HintPath>..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\win8\System.Runtime.InteropServices.RuntimeInformation.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Validation, Version=2.4.0.0, Culture=neutral, PublicKeyToken=2fc06f0d701809a7, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Validation.2.4.15\lib\portable-net45+win8+wp8+wpa81\Validation.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<SDKReference Include="BehaviorsXamlSDKManaged, Version=12.0">
|
||||||
|
<Name>BehaviorsXamlSDKManaged</Name>
|
||||||
|
</SDKReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Assets\Logo.scale-100.png" />
|
<Content Include="Assets\Logo.scale-100.png" />
|
||||||
<Content Include="Assets\Logo.scale-140.png" />
|
<Content Include="Assets\Logo.scale-140.png" />
|
||||||
@@ -220,7 +301,9 @@
|
|||||||
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Error Condition="!Exists('..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets'))" />
|
<Error Condition="!Exists('..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\NETStandard.Library.2.0.0\build\NETStandard.Library.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
|
||||||
</Target>
|
</Target>
|
||||||
|
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
<Target Name="BeforeBuild">
|
<Target Name="BeforeBuild">
|
||||||
|
3
ModernKeePass/ModernKeePass.csproj.DotSettings
Normal file
3
ModernKeePass/ModernKeePass.csproj.DotSettings
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp70</s:String>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=viewmodels_005Citems/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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">
|
<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.1.0.2" />
|
<Identity Name="wismna.ModernKeePass" Publisher="CN=0719A91A-C322-4EE0-A257-E60733EECF06" Version="1.2.0.14" />
|
||||||
<Properties>
|
<Properties>
|
||||||
<DisplayName>ModernKeePass</DisplayName>
|
<DisplayName>ModernKeePass</DisplayName>
|
||||||
<PublisherDisplayName>wismna</PublisherDisplayName>
|
<PublisherDisplayName>wismna</PublisherDisplayName>
|
||||||
@@ -28,6 +28,22 @@
|
|||||||
</SupportedFileTypes>
|
</SupportedFileTypes>
|
||||||
</FileOpenPicker>
|
</FileOpenPicker>
|
||||||
</Extension>
|
</Extension>
|
||||||
|
<Extension Category="windows.fileTypeAssociation">
|
||||||
|
<FileTypeAssociation Name="kdbx">
|
||||||
|
<DisplayName>KeePass 2.x database</DisplayName>
|
||||||
|
<EditFlags OpenIsSafe="true" />
|
||||||
|
<SupportedFileTypes>
|
||||||
|
<FileType ContentType="application/xml">.kdbx</FileType>
|
||||||
|
</SupportedFileTypes>
|
||||||
|
</FileTypeAssociation>
|
||||||
|
</Extension>
|
||||||
|
<Extension Category="windows.fileSavePicker">
|
||||||
|
<FileSavePicker>
|
||||||
|
<SupportedFileTypes>
|
||||||
|
<FileType>.kdbx</FileType>
|
||||||
|
</SupportedFileTypes>
|
||||||
|
</FileSavePicker>
|
||||||
|
</Extension>
|
||||||
</Extensions>
|
</Extensions>
|
||||||
</Application>
|
</Application>
|
||||||
</Applications>
|
</Applications>
|
||||||
|
@@ -1,19 +1,24 @@
|
|||||||
<Page
|
<Page
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="using:ModernKeePass.Pages"
|
|
||||||
xmlns:common="using:ModernKeePass.Common"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:ViewModels="using:ModernKeePass.ViewModels"
|
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||||
x:Name="pageRoot"
|
xmlns:converters="using:ModernKeePass.Converters"
|
||||||
|
xmlns:local="using:ModernKeePass.Controls"
|
||||||
|
x:Name="PageRoot"
|
||||||
x:Class="ModernKeePass.Pages.EntryDetailPage"
|
x:Class="ModernKeePass.Pages.EntryDetailPage"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
|
<Page.Resources>
|
||||||
|
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
|
<converters:InverseBooleanToVisibilityConverter x:Key="InverseBooleanToVisibilityConverter"/>
|
||||||
|
</Page.Resources>
|
||||||
|
|
||||||
<Page.DataContext>
|
<Page.DataContext>
|
||||||
<ViewModels:EntryVm/>
|
<viewModels:EntryVm/>
|
||||||
</Page.DataContext>
|
</Page.DataContext>
|
||||||
|
|
||||||
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<Grid.ChildrenTransitions>
|
<Grid.ChildrenTransitions>
|
||||||
<TransitionCollection>
|
<TransitionCollection>
|
||||||
@@ -25,44 +30,56 @@
|
|||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid Grid.Row="1" x:Name="contentRegion">
|
<StackPanel Grid.Row="1" Margin="20,0,0,0" >
|
||||||
<Grid.RowDefinitions>
|
<StackPanel.Resources>
|
||||||
<RowDefinition Height="Auto"/>
|
<Style TargetType="TextBlock">
|
||||||
<RowDefinition Height="*"/>
|
<Setter Property="Margin" Value="0,20,0,0"/>
|
||||||
<RowDefinition Height="Auto"/>
|
</Style>
|
||||||
<RowDefinition Height="Auto"/>
|
</StackPanel.Resources>
|
||||||
<RowDefinition Height="*"/>
|
<TextBlock x:Name="userTextBlock" TextWrapping="Wrap" Text="User name or login" FontSize="18"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<TextBox x:Name="userTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding UserName, Mode=TwoWay}" Width="350" Height="32" />
|
||||||
<RowDefinition Height="*"/>
|
<TextBlock x:Name="passwordTextBlock" TextWrapping="Wrap" Text="Password" FontSize="18"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<PasswordBox x:Name="passwordBox" HorizontalAlignment="Left" Password="{Binding Password, Mode=TwoWay}" Width="350" Height="32" IsPasswordRevealButtonEnabled="True" Visibility="{Binding IsRevealPassword, Converter={StaticResource InverseBooleanToVisibilityConverter}}" />
|
||||||
<RowDefinition Height="*"/>
|
<TextBox x:Name="passwordTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Password, Mode=TwoWay}" Width="350" Height="32" Visibility="{Binding IsRevealPassword, Converter={StaticResource BooleanToVisibilityConverter}}" />
|
||||||
</Grid.RowDefinitions>
|
<CheckBox x:Name="checkBox" HorizontalAlignment="Left" Margin="-3,0,0,0" Content="Show password" IsChecked="{Binding IsRevealPassword, Mode=TwoWay}"/>
|
||||||
<TextBlock x:Name="userTextBlock" Grid.Row="0" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="User name or login" VerticalAlignment="Top" FontSize="18"/>
|
<TextBlock x:Name="urlTextBlock" TextWrapping="Wrap" Text="URL" FontSize="18"/>
|
||||||
<TextBox x:Name="userTextBox" Grid.Row="1" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding UserName, Mode=TwoWay}" VerticalAlignment="Top" Width="250" AllowDrop="True"/>
|
<!--<StackPanel Orientation="Horizontal" Margin="0,-1,0,-1" Width="350" HorizontalAlignment="Left">
|
||||||
<TextBlock x:Name="passwordTextBlock" Grid.Row="2" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Password" VerticalAlignment="Top" FontSize="18"/>
|
<TextBox x:Name="urlTextBox" TextWrapping="Wrap" Text="{Binding Url, Mode=TwoWay}" Height="32" Width="350" MaxLength="256" Padding="0,0,34,0" />
|
||||||
<PasswordBox x:Name="passwordBox" Grid.Row="3" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Password="{Binding Password, Mode=TwoWay}" IsPasswordRevealButtonEnabled="True" Width="250" AllowDrop="True"/>
|
<Button Click="UrlButton_Click" Height="34" Margin="-34,0,0,0" Background="Transparent" Padding="2,0" >
|
||||||
<TextBox x:Name="passwordTextBox" Grid.Row="3" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding Password, Mode=TwoWay}" VerticalAlignment="Top" Width="250" FontSize="14,667" MaxLength="256" AllowDrop="True" Visibility="Collapsed"/>
|
<SymbolIcon Symbol="Forward" VerticalAlignment="Center" />
|
||||||
<CheckBox x:Name="checkBox" Grid.Row="4" Content="Show password" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Checked="checkBox_Checked" Unchecked="checkBox_Unchecked"/>
|
</Button>
|
||||||
<TextBlock x:Name="urlTextBlock" Grid.Row="5" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="URL" VerticalAlignment="Top" FontSize="18"/>
|
</StackPanel>-->
|
||||||
<TextBox x:Name="urlTextBox" Grid.Row="6" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding URL, Mode=TwoWay}" VerticalAlignment="Top" Width="250" FontSize="14,667" MaxLength="256" AllowDrop="True"/>
|
<local:TextBoxWithButton x:Name="urlTextBox" HorizontalAlignment="Left" Text="{Binding Url, Mode=TwoWay}" Height="32" Width="350" MaxLength="256" Style="{StaticResource TextBoxWithButtonStyle}" GotoClick="UrlButton_Click" />
|
||||||
<TextBlock x:Name="notesTextBlock" Grid.Row="7" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Notes" VerticalAlignment="Top" FontSize="18"/>
|
<TextBlock x:Name="notesTextBlock" TextWrapping="Wrap" Text="Notes" FontSize="18"/>
|
||||||
<TextBox x:Name="notesTextBox" Grid.Row="8" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="{Binding Notes, Mode=TwoWay}" VerticalAlignment="Top" Width="250" Height="32" IsSpellCheckEnabled="True" AllowDrop="True"/>
|
<TextBox x:Name="notesTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" Text="{Binding Notes, Mode=TwoWay}" Width="350" Height="200" AcceptsReturn="True" IsSpellCheckEnabled="True" />
|
||||||
</Grid>
|
</StackPanel>
|
||||||
|
|
||||||
<!-- Bouton Précédent et titre de la page -->
|
<!-- Bouton Précédent et titre de la page -->
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="120"/>
|
<ColumnDefinition Width="120"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="200"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
|
<Button Margin="39,0,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}"
|
||||||
Style="{StaticResource NavigationBackButtonNormalStyle}"
|
Style="{StaticResource NavigationBackButtonNormalStyle}"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Center"
|
||||||
AutomationProperties.Name="Back"
|
AutomationProperties.Name="Back"
|
||||||
AutomationProperties.AutomationId="BackButton"
|
AutomationProperties.AutomationId="BackButton"
|
||||||
AutomationProperties.ItemType="Navigation Button"/>
|
AutomationProperties.ItemType="Navigation Button"/>
|
||||||
<TextBlock x:Name="pageTitle" Text="{Binding Title}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
|
<TextBox
|
||||||
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
|
Grid.Column="1"
|
||||||
|
Text="{Binding Title, Mode=TwoWay}"
|
||||||
|
Style="{StaticResource HeaderTextBoxStyle}"
|
||||||
|
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}"
|
||||||
|
IsHitTestVisible="{Binding IsEditMode}"
|
||||||
|
TextWrapping="NoWrap"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="0,0,30,0"/>
|
||||||
|
<CommandBar Grid.Column="2" Background="Transparent" IsOpen="True" VerticalAlignment="Center" Margin="0,20,0,0">
|
||||||
|
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}" />
|
||||||
|
<AppBarButton Icon="Delete" Label="Delete" Click="AppBarButton_Click" />
|
||||||
|
</CommandBar>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
||||||
|
@@ -1,17 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using Windows.UI.Popups;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.WindowsRuntime;
|
|
||||||
using ModernKeePass.Common;
|
using ModernKeePass.Common;
|
||||||
using Windows.Foundation;
|
|
||||||
using Windows.Foundation.Collections;
|
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Controls.Primitives;
|
|
||||||
using Windows.UI.Xaml.Data;
|
|
||||||
using Windows.UI.Xaml.Input;
|
|
||||||
using Windows.UI.Xaml.Media;
|
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
using ModernKeePass.ViewModels;
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
@@ -31,16 +22,13 @@ namespace ModernKeePass.Pages
|
|||||||
/// NavigationHelper est utilisé sur chaque page pour faciliter la navigation et
|
/// NavigationHelper est utilisé sur chaque page pour faciliter la navigation et
|
||||||
/// gestion de la durée de vie des processus
|
/// gestion de la durée de vie des processus
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NavigationHelper NavigationHelper
|
public NavigationHelper NavigationHelper => navigationHelper;
|
||||||
{
|
|
||||||
get { return this.navigationHelper; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntryDetailPage()
|
public EntryDetailPage()
|
||||||
{
|
{
|
||||||
this.InitializeComponent();
|
InitializeComponent();
|
||||||
this.navigationHelper = new NavigationHelper(this);
|
navigationHelper = new NavigationHelper(this);
|
||||||
this.navigationHelper.LoadState += navigationHelper_LoadState;
|
navigationHelper.LoadState += navigationHelper_LoadState;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -51,17 +39,10 @@ namespace ModernKeePass.Pages
|
|||||||
/// Source de l'événement ; en général <see cref="Common.NavigationHelper"/>
|
/// Source de l'événement ; en général <see cref="Common.NavigationHelper"/>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="e">Données d'événement qui fournissent le paramètre de navigation transmis à
|
/// <param name="e">Données d'événement qui fournissent le paramètre de navigation transmis à
|
||||||
/// <see cref="Frame.Navigate(Type, Object)"/> lors de la requête initiale de cette page et
|
/// <see cref="Frame.Navigate(Type, object)"/> lors de la requête initiale de cette page et
|
||||||
/// un dictionnaire d'état conservé par cette page durant une session
|
/// un dictionnaire d'état conservé par cette page durant une session
|
||||||
/// antérieure. L'état n'aura pas la valeur Null lors de la première visite de la page.</param>
|
/// antérieure. L'état n'aura pas la valeur Null lors de la première visite de la page.</param>
|
||||||
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
|
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e) {}
|
||||||
{
|
|
||||||
object navigationParameter;
|
|
||||||
if (e.PageState != null && e.PageState.ContainsKey("SelectedItem"))
|
|
||||||
{
|
|
||||||
navigationParameter = e.PageState["SelectedItem"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Inscription de NavigationHelper
|
#region Inscription de NavigationHelper
|
||||||
|
|
||||||
@@ -89,17 +70,42 @@ namespace ModernKeePass.Pages
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void checkBox_Checked(object sender, RoutedEventArgs e)
|
private async void AppBarButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
passwordBox.Visibility = Visibility.Collapsed;
|
// Create the message dialog and set its content
|
||||||
passwordTextBox.Visibility = Visibility.Visible;
|
var messageDialog = new MessageDialog("Are you sure you want to delete this entry?");
|
||||||
|
|
||||||
|
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
|
||||||
|
messageDialog.Commands.Add(new UICommand("Delete", delete =>
|
||||||
|
{
|
||||||
|
var entry = DataContext as EntryVm;
|
||||||
|
entry?.RemoveEntry();
|
||||||
|
if (Frame.CanGoBack) Frame.GoBack();
|
||||||
|
}));
|
||||||
|
messageDialog.Commands.Add(new UICommand("Cancel"));
|
||||||
|
|
||||||
|
// Set the command that will be invoked by default
|
||||||
|
messageDialog.DefaultCommandIndex = 1;
|
||||||
|
|
||||||
|
// Set the command to be invoked when escape is pressed
|
||||||
|
messageDialog.CancelCommandIndex = 1;
|
||||||
|
|
||||||
|
// Show the message dialog
|
||||||
|
await messageDialog.ShowAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBox_Unchecked(object sender, RoutedEventArgs e)
|
private async void UrlButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
passwordBox.Visibility = Visibility.Visible;
|
try
|
||||||
passwordTextBox.Visibility = Visibility.Collapsed;
|
{
|
||||||
|
var uri = new Uri(urlTextBox.Text);
|
||||||
|
await Windows.System.Launcher.LaunchUriAsync(uri);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// TODO: Show some error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,19 +1,37 @@
|
|||||||
<Page
|
<Page
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="using:ModernKeePass.Pages"
|
|
||||||
xmlns:common="using:ModernKeePass.Common"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:ViewModels="using:ModernKeePass.ViewModels"
|
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||||
x:Name="pageRoot"
|
xmlns:converters="using:ModernKeePass.Converters"
|
||||||
|
xmlns:local="using:ModernKeePass.Controls"
|
||||||
|
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||||
|
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
|
||||||
|
x:Name="PageRoot"
|
||||||
x:Class="ModernKeePass.Pages.GroupDetailPage"
|
x:Class="ModernKeePass.Pages.GroupDetailPage"
|
||||||
mc:Ignorable="d" >
|
mc:Ignorable="d" >
|
||||||
|
<Page.Resources>
|
||||||
|
<SolidColorBrush x:Key="Transparent" Color="Transparent"/>
|
||||||
|
<SolidColorBrush x:Key="SystemColor" Color="{StaticResource SystemColorButtonFaceColor}" />
|
||||||
|
<converters:ColorToBrushConverter x:Key="ColorToBrushConverter"/>
|
||||||
|
<converters:PluralizationConverter x:Key="PluralizationConverter"/>
|
||||||
|
</Page.Resources>
|
||||||
<Page.DataContext>
|
<Page.DataContext>
|
||||||
<ViewModels:GroupVm />
|
<viewModels:GroupVm />
|
||||||
</Page.DataContext>
|
</Page.DataContext>
|
||||||
|
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
|
||||||
<Grid>
|
<Grid.Resources>
|
||||||
|
<CollectionViewSource
|
||||||
|
x:Name="GroupsViewSource"
|
||||||
|
Source="{Binding Groups}" />
|
||||||
|
<CollectionViewSource
|
||||||
|
x:Name="EntriesViewSource"
|
||||||
|
Source="{Binding Entries}" />
|
||||||
|
<CollectionViewSource
|
||||||
|
x:Name="EntriesZoomedOutViewSource"
|
||||||
|
Source="{Binding EntriesZoomedOut}" IsSourceGrouped="True"/>
|
||||||
|
</Grid.Resources>
|
||||||
<Grid.ChildrenTransitions>
|
<Grid.ChildrenTransitions>
|
||||||
<TransitionCollection>
|
<TransitionCollection>
|
||||||
<EntranceThemeTransition/>
|
<EntranceThemeTransition/>
|
||||||
@@ -23,83 +41,203 @@
|
|||||||
<RowDefinition Height="140"/>
|
<RowDefinition Height="140"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid.Resources>
|
|
||||||
<CollectionViewSource
|
|
||||||
x:Name="groupsViewSource"
|
|
||||||
Source="{Binding Groups}"/>
|
|
||||||
<CollectionViewSource
|
|
||||||
x:Name="entriesViewSource"
|
|
||||||
Source="{Binding Entries}"/>
|
|
||||||
</Grid.Resources>
|
|
||||||
<!-- Horizontal scrolling grid -->
|
<!-- Horizontal scrolling grid -->
|
||||||
<GridView
|
<SemanticZoom Grid.Row="1" ViewChangeStarted="SemanticZoom_ViewChangeStarted" >
|
||||||
x:Name="groupsGridView"
|
<SemanticZoom.ZoomedInView>
|
||||||
AutomationProperties.AutomationId="ItemGridView"
|
<GridView
|
||||||
AutomationProperties.Name="Groups"
|
x:Name="GridView"
|
||||||
TabIndex="1"
|
AutomationProperties.AutomationId="ItemGridView"
|
||||||
Grid.RowSpan="2"
|
AutomationProperties.Name="Entries"
|
||||||
Padding="120,126,120,50"
|
TabIndex="1"
|
||||||
ItemsSource="{Binding Source={StaticResource groupsViewSource}}"
|
IsSwipeEnabled="false"
|
||||||
IsSwipeEnabled="false"
|
SelectionChanged="entries_SelectionChanged"
|
||||||
SelectionChanged="groupsGridView_SelectionChanged"
|
IsSynchronizedWithCurrentItem="False">
|
||||||
SelectedIndex="-1" >
|
<GridView.Resources>
|
||||||
<GridView.ItemTemplate>
|
<DataTemplate x:Name="GroupFirstItem">
|
||||||
<DataTemplate>
|
<Border
|
||||||
<Grid Height="110" Width="480" Margin="10">
|
BorderThickness="2"
|
||||||
<Grid.ColumnDefinitions>
|
BorderBrush="{StaticResource SystemColor}"
|
||||||
<ColumnDefinition Width="Auto"/>
|
Background="{StaticResource HubSectionHeaderPressedForegroundThemeBrush}">
|
||||||
<ColumnDefinition Width="*"/>
|
<Grid Height="110" Width="480">
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" Width="110" Height="110">
|
|
||||||
<Image Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
|
|
||||||
</Border>
|
|
||||||
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,0,0,0">
|
|
||||||
<TextBlock Text="{Binding Name}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
|
|
||||||
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
|
|
||||||
<TextBlock Text="{Binding EntryCount}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/>
|
|
||||||
<TextBlock Text="{Binding GroupCount}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Grid>
|
|
||||||
</DataTemplate>
|
|
||||||
</GridView.ItemTemplate>
|
|
||||||
<GridView.Header>
|
|
||||||
<StackPanel Width="480" Margin="0,4,14,0">
|
|
||||||
<ListView x:Name="entriesListView" Height="100" ItemsSource="{Binding Source={StaticResource entriesViewSource}}" Margin="10,0,0,0" SelectionChanged="entriesListView_SelectionChanged">
|
|
||||||
<ListView.ItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<Grid>
|
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="10,0,0,0"/>
|
<SymbolIcon Grid.Column="0" Symbol="{Binding IconSymbol}" Width="100" Height="100" RenderTransformOrigin="0.5,0.5" >
|
||||||
|
<SymbolIcon.RenderTransform>
|
||||||
|
<CompositeTransform ScaleX="2" TranslateX="0" TranslateY="0" ScaleY="2"/>
|
||||||
|
</SymbolIcon.RenderTransform>
|
||||||
|
</SymbolIcon>
|
||||||
|
<TextBlock Grid.Column="1" Text="{Binding Title}" FontWeight="Bold" Style="{ThemeResource TitleTextBlockStyle}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="13,0,0,5"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</Border>
|
||||||
</ListView.ItemTemplate>
|
</DataTemplate>
|
||||||
</ListView>
|
<DataTemplate x:Name="GroupOtherItem">
|
||||||
</StackPanel>
|
<Grid Height="110" Width="480" >
|
||||||
</GridView.Header>
|
<Grid.ColumnDefinitions>
|
||||||
<GridView.ItemContainerStyle>
|
<ColumnDefinition Width="Auto"/>
|
||||||
<Style TargetType="FrameworkElement">
|
<ColumnDefinition Width="*"/>
|
||||||
<Setter Property="Margin" Value="52,0,0,2"/>
|
</Grid.ColumnDefinitions>
|
||||||
</Style>
|
<Border
|
||||||
</GridView.ItemContainerStyle>
|
Grid.Column="0"
|
||||||
</GridView>
|
BorderThickness="2"
|
||||||
|
BorderBrush="{StaticResource SystemColor}"
|
||||||
|
Background="{Binding BackgroundColor, ConverterParameter={StaticResource Transparent}, Converter={StaticResource ColorToBrushConverter}}">
|
||||||
|
<SymbolIcon Symbol="{Binding IconSymbol}" Width="100" Height="100" RenderTransformOrigin="0.5,0.5" >
|
||||||
|
<SymbolIcon.RenderTransform>
|
||||||
|
<CompositeTransform ScaleX="2" TranslateX="0" TranslateY="0" ScaleY="2"/>
|
||||||
|
</SymbolIcon.RenderTransform>
|
||||||
|
</SymbolIcon>
|
||||||
|
</Border>
|
||||||
|
<StackPanel Grid.Column="1" VerticalAlignment="Top" Margin="10,10,0,0" >
|
||||||
|
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap" Foreground="{Binding ForegroundColor, ConverterParameter={StaticResource TextBoxForegroundThemeBrush}, Converter={StaticResource ColorToBrushConverter}}"/>
|
||||||
|
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
|
||||||
|
<!--<TextBlock Text="{Binding EntryCount, ConverterParameter=entry\,entries, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
|
||||||
|
<TextBlock Text="{Binding GroupCount, ConverterParameter=group\,groups, Converter={StaticResource PluralizationConverter}}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />-->
|
||||||
|
<TextBlock Text="{Binding UserName}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
|
||||||
|
<TextBlock Text="{Binding Url}" Style="{StaticResource BodyTextBlockStyle}" MaxHeight="60" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</GridView.Resources>
|
||||||
|
<GridView.ItemsSource>
|
||||||
|
<Binding Source="{StaticResource EntriesViewSource}"/>
|
||||||
|
</GridView.ItemsSource>
|
||||||
|
<GridView.DataContext>
|
||||||
|
<viewModels:EntryVm/>
|
||||||
|
</GridView.DataContext>
|
||||||
|
<GridView.ItemTemplateSelector>
|
||||||
|
<local:FirstItemDataTemplateSelector
|
||||||
|
FirstItem="{StaticResource GroupFirstItem}"
|
||||||
|
OtherItem="{StaticResource GroupOtherItem}" />
|
||||||
|
</GridView.ItemTemplateSelector>
|
||||||
|
<GridView.ItemContainerStyle>
|
||||||
|
<Style TargetType="FrameworkElement">
|
||||||
|
<Setter Property="Margin" Value="52,0,0,2"/>
|
||||||
|
</Style>
|
||||||
|
</GridView.ItemContainerStyle>
|
||||||
|
<GridView.Header>
|
||||||
|
<ListView
|
||||||
|
x:Name="LeftListView"
|
||||||
|
SelectionChanged="groups_SelectionChanged"
|
||||||
|
IsSwipeEnabled="false"
|
||||||
|
IsSynchronizedWithCurrentItem="False"
|
||||||
|
DataContext="{Binding DataContext, ElementName=PageRoot}"
|
||||||
|
RequestedTheme="Dark"
|
||||||
|
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||||
|
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}">
|
||||||
|
<ListView.Resources>
|
||||||
|
<DataTemplate x:Name="Collapsed">
|
||||||
|
<SymbolIcon Symbol="{Binding IconSymbol}">
|
||||||
|
<ToolTipService.ToolTip>
|
||||||
|
<ToolTip Content="{Binding Name}" />
|
||||||
|
</ToolTipService.ToolTip>
|
||||||
|
</SymbolIcon>
|
||||||
|
</DataTemplate>
|
||||||
|
<DataTemplate x:Name="Expanded">
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<SymbolIcon Symbol="{Binding IconSymbol}" />
|
||||||
|
<TextBlock Text="{Binding Name}" FontWeight="{Binding FontWeight}" TextWrapping="NoWrap" VerticalAlignment="Center" Margin="30,0,20,0" />
|
||||||
|
<!--<TextBlock Text="{Binding EntryCount}" HorizontalAlignment="Right" VerticalAlignment="Center" />-->
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.Resources>
|
||||||
|
<ListView.ItemsSource>
|
||||||
|
<Binding Source="{StaticResource GroupsViewSource}"/>
|
||||||
|
</ListView.ItemsSource>
|
||||||
|
<ListView.ItemContainerStyle>
|
||||||
|
<Style TargetType="ListViewItem">
|
||||||
|
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||||
|
<Setter Property="Padding" Value="20,0,0,0"/>
|
||||||
|
<Setter Property="Margin" Value="0"/>
|
||||||
|
</Style>
|
||||||
|
</ListView.ItemContainerStyle>
|
||||||
|
<ListView.HeaderTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<ToggleButton IsChecked="{Binding IsLeftPaneOpen, Mode=TwoWay}" Style="{StaticResource HamburgerToggleButton}" Margin="0" />
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.HeaderTemplate>
|
||||||
|
<interactivity:Interaction.Behaviors>
|
||||||
|
<core:DataTriggerBehavior Binding="{Binding IsLeftPaneOpen}" Value="True">
|
||||||
|
<core:ChangePropertyAction PropertyName="ItemTemplate" Value="{StaticResource Expanded}"/>
|
||||||
|
</core:DataTriggerBehavior>
|
||||||
|
<core:DataTriggerBehavior Binding="{Binding IsLeftPaneOpen}" Value="False">
|
||||||
|
<core:ChangePropertyAction PropertyName="ItemTemplate" Value="{StaticResource Collapsed}"/>
|
||||||
|
</core:DataTriggerBehavior>
|
||||||
|
</interactivity:Interaction.Behaviors>
|
||||||
|
</ListView>
|
||||||
|
</GridView.Header>
|
||||||
|
</GridView>
|
||||||
|
</SemanticZoom.ZoomedInView>
|
||||||
|
|
||||||
|
<SemanticZoom.ZoomedOutView>
|
||||||
|
<ListView
|
||||||
|
x:Name="SemanticListView"
|
||||||
|
ItemsSource="{Binding Source={StaticResource EntriesZoomedOutViewSource}}"
|
||||||
|
IsSwipeEnabled="false"
|
||||||
|
SelectionChanged="groups_SelectionChanged"
|
||||||
|
IsSynchronizedWithCurrentItem="False">
|
||||||
|
<ListView.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ListView.ItemsPanel>
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Orientation="Vertical">
|
||||||
|
<TextBlock Text="{Binding Title}" Style="{StaticResource TitleTextBlockStyle}" TextWrapping="NoWrap"/>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
<ListView.GroupStyle>
|
||||||
|
<GroupStyle HidesIfEmpty="True">
|
||||||
|
<GroupStyle.HeaderTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<Grid Background="LightGray" Margin="0,0,10,0" HorizontalAlignment="Left">
|
||||||
|
<TextBlock Text="{Binding Key}" Foreground="Black" Margin="30" Style="{StaticResource HeaderTextBlockStyle}"/>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</GroupStyle.HeaderTemplate>
|
||||||
|
</GroupStyle>
|
||||||
|
</ListView.GroupStyle>
|
||||||
|
</ListView>
|
||||||
|
</SemanticZoom.ZoomedOutView>
|
||||||
|
</SemanticZoom>
|
||||||
|
|
||||||
<!-- Back button and page title -->
|
<!-- Back button and page title -->
|
||||||
<Grid>
|
<Grid Grid.Row="0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="120"/>
|
<ColumnDefinition Width="120"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="300"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
|
<Button Margin="39,0,39,0"
|
||||||
Style="{StaticResource NavigationBackButtonNormalStyle}"
|
Command="{Binding NavigationHelper.GoBackCommand, ElementName=PageRoot}"
|
||||||
VerticalAlignment="Top"
|
Style="{StaticResource NavigationBackButtonNormalStyle}"
|
||||||
AutomationProperties.Name="Back"
|
VerticalAlignment="Center"
|
||||||
AutomationProperties.AutomationId="BackButton"
|
AutomationProperties.Name="Back"
|
||||||
AutomationProperties.ItemType="Navigation Button"/>
|
AutomationProperties.AutomationId="BackButton"
|
||||||
<TextBlock x:Name="pageTitle" Text="{Binding Path=Name}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
|
AutomationProperties.ItemType="Navigation Button"/>
|
||||||
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
|
<TextBox
|
||||||
|
Grid.Column="1"
|
||||||
|
Text="{Binding Name, Mode=TwoWay}"
|
||||||
|
Style="{StaticResource HeaderTextBoxStyle}"
|
||||||
|
Foreground="{ThemeResource DefaultTextForegroundThemeBrush}"
|
||||||
|
IsHitTestVisible="{Binding IsEditMode}"
|
||||||
|
TextWrapping="NoWrap"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="0,0,30,0"/>
|
||||||
|
<CommandBar Grid.Column="2" Background="Transparent" IsOpen="True" VerticalAlignment="Center" Margin="0,20,0,0">
|
||||||
|
<AppBarButton Icon="Find" Label="Search">
|
||||||
|
<AppBarButton.Flyout>
|
||||||
|
<Flyout>
|
||||||
|
<SearchBox PlaceholderText="Search..." Width="350" SuggestionsRequested="SearchBox_OnSuggestionsRequested" SearchHistoryEnabled="False" ResultSuggestionChosen="SearchBox_OnResultSuggestionChosen" />
|
||||||
|
</Flyout>
|
||||||
|
</AppBarButton.Flyout>
|
||||||
|
</AppBarButton>
|
||||||
|
<AppBarToggleButton Icon="Edit" Label="Edit" IsChecked="{Binding IsEditMode, Mode=TwoWay}" />
|
||||||
|
<AppBarButton Icon="Delete" Label="Delete" IsEnabled="{Binding IsNotRoot}" Click="DeleteButton_Click" />
|
||||||
|
</CommandBar>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Page>
|
</Page>
|
@@ -1,4 +1,8 @@
|
|||||||
using ModernKeePass.Common;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Windows.Storage.Streams;
|
||||||
|
using Windows.UI.Popups;
|
||||||
|
using ModernKeePass.Common;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Windows.UI.Xaml.Navigation;
|
using Windows.UI.Xaml.Navigation;
|
||||||
using ModernKeePass.ViewModels;
|
using ModernKeePass.ViewModels;
|
||||||
@@ -13,23 +17,17 @@ namespace ModernKeePass.Pages
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed partial class GroupDetailPage : Page
|
public sealed partial class GroupDetailPage : Page
|
||||||
{
|
{
|
||||||
private NavigationHelper navigationHelper;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NavigationHelper is used on each page to aid in navigation and
|
/// NavigationHelper is used on each page to aid in navigation and
|
||||||
/// process lifetime management
|
/// process lifetime management
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public NavigationHelper NavigationHelper
|
public NavigationHelper NavigationHelper { get; }
|
||||||
{
|
|
||||||
get { return navigationHelper; }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public GroupDetailPage()
|
public GroupDetailPage()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
navigationHelper = new NavigationHelper(this);
|
NavigationHelper = new NavigationHelper(this);
|
||||||
navigationHelper.LoadState += navigationHelper_LoadState;
|
NavigationHelper.LoadState += navigationHelper_LoadState;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -40,12 +38,10 @@ namespace ModernKeePass.Pages
|
|||||||
/// The source of the event; typically <see cref="Common.NavigationHelper"/>
|
/// The source of the event; typically <see cref="Common.NavigationHelper"/>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="e">Event data that provides both the navigation parameter passed to
|
/// <param name="e">Event data that provides both the navigation parameter passed to
|
||||||
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested and
|
/// <see cref="Frame.Navigate(Type, object)"/> when this page was initially requested and
|
||||||
/// a dictionary of state preserved by this page during an earlier
|
/// a dictionary of state preserved by this page during an earlier
|
||||||
/// session. The state will be null the first time a page is visited.</param>
|
/// session. The state will be null the first time a page is visited.</param>
|
||||||
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
|
private void navigationHelper_LoadState(object sender, LoadStateEventArgs e) {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#region NavigationHelper registration
|
#region NavigationHelper registration
|
||||||
|
|
||||||
@@ -60,34 +56,104 @@ namespace ModernKeePass.Pages
|
|||||||
///
|
///
|
||||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
navigationHelper.OnNavigatedTo(e);
|
NavigationHelper.OnNavigatedTo(e);
|
||||||
|
|
||||||
if (e.Parameter is GroupVm)
|
if (!(e.Parameter is GroupVm)) return;
|
||||||
{
|
DataContext = (GroupVm) e.Parameter;
|
||||||
DataContext = e.Parameter as GroupVm;
|
|
||||||
groupsGridView.SelectedIndex = -1;
|
|
||||||
entriesListView.SelectedIndex = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
protected override void OnNavigatedFrom(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
navigationHelper.OnNavigatedFrom(e);
|
NavigationHelper.OnNavigatedFrom(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private void groupsGridView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
||||||
|
#region Event Handlers
|
||||||
|
|
||||||
|
private void groups_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
var gridView = sender as GridView;
|
if (LeftListView.SelectedIndex == 0)
|
||||||
Frame.Navigate(typeof(GroupDetailPage), gridView.SelectedItem as GroupVm);
|
{
|
||||||
|
var currentGroup = DataContext as GroupVm;
|
||||||
|
currentGroup?.CreateNewGroup();
|
||||||
|
LeftListView.SelectedIndex = -1;
|
||||||
|
// TODO: Navigate to new group?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var selectedItem = LeftListView.SelectedItem as GroupVm;
|
||||||
|
if (selectedItem == null) return;
|
||||||
|
Frame.Navigate(typeof(GroupDetailPage), selectedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void entries_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||||
private void entriesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
||||||
{
|
{
|
||||||
var listView = sender as ListView;
|
switch (GridView.SelectedIndex)
|
||||||
Frame.Navigate(typeof(EntryDetailPage), listView.SelectedItem as EntryVm);
|
{
|
||||||
|
case -1:
|
||||||
|
return;
|
||||||
|
case 0:
|
||||||
|
var currentGroup = DataContext as GroupVm;
|
||||||
|
currentGroup?.CreateNewEntry();
|
||||||
|
GridView.SelectedIndex = -1;
|
||||||
|
// TODO: Navigate to new entry?
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Frame.Navigate(typeof(EntryDetailPage), GridView.SelectedItem as EntryVm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void DeleteButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
// Create the message dialog and set its content
|
||||||
|
var messageDialog = new MessageDialog("Are you sure you want to delete the whole group and all its entries?");
|
||||||
|
|
||||||
|
// Add commands and set their callbacks; both buttons use the same callback function instead of inline event handlers
|
||||||
|
messageDialog.Commands.Add(new UICommand("Delete", delete =>
|
||||||
|
{
|
||||||
|
var group = DataContext as GroupVm;
|
||||||
|
group?.RemoveGroup();
|
||||||
|
if (Frame.CanGoBack) Frame.GoBack();
|
||||||
|
}));
|
||||||
|
messageDialog.Commands.Add(new UICommand("Cancel"));
|
||||||
|
|
||||||
|
// Set the command that will be invoked by default
|
||||||
|
messageDialog.DefaultCommandIndex = 1;
|
||||||
|
|
||||||
|
// Set the command to be invoked when escape is pressed
|
||||||
|
messageDialog.CancelCommandIndex = 1;
|
||||||
|
|
||||||
|
// Show the message dialog
|
||||||
|
await messageDialog.ShowAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SemanticZoom_ViewChangeStarted(object sender, SemanticZoomViewChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.IsSourceZoomedInView == false)
|
||||||
|
{
|
||||||
|
e.DestinationItem.Item = e.SourceItem.Item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SearchBox_OnSuggestionsRequested(SearchBox sender, SearchBoxSuggestionsRequestedEventArgs args)
|
||||||
|
{
|
||||||
|
var viewModel = DataContext as GroupVm;
|
||||||
|
var imageUri = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx://Assets/Logo.scale-80.png"));
|
||||||
|
var results = viewModel.Entries.Skip(1).Where(e => e.Title.IndexOf(args.QueryText, StringComparison.OrdinalIgnoreCase) >= 0).Take(5);
|
||||||
|
foreach (var result in results)
|
||||||
|
{
|
||||||
|
args.Request.SearchSuggestionCollection.AppendResultSuggestion(result.Title, result.ParentGroup.Name, result.Id, imageUri, string.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SearchBox_OnResultSuggestionChosen(SearchBox sender, SearchBoxResultSuggestionChosenEventArgs args)
|
||||||
|
{
|
||||||
|
var viewModel = DataContext as GroupVm;
|
||||||
|
var entry = viewModel.Entries.Skip(1).FirstOrDefault(e => e.Id == args.Tag);
|
||||||
|
Frame.Navigate(typeof(EntryDetailPage), entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
ModernKeePass/Pages/NewDatabasePage.xaml
Normal file
23
ModernKeePass/Pages/NewDatabasePage.xaml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<Page
|
||||||
|
x:Class="ModernKeePass.Pages.NewDatabasePage"
|
||||||
|
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:controls="using:ModernKeePass.Controls"
|
||||||
|
xmlns:converters="using:ModernKeePass.Converters"
|
||||||
|
xmlns:viewModels="using:ModernKeePass.ViewModels"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<Page.Resources>
|
||||||
|
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
|
</Page.Resources>
|
||||||
|
<Page.DataContext>
|
||||||
|
<viewModels:OpenVm />
|
||||||
|
</Page.DataContext>
|
||||||
|
|
||||||
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<HyperlinkButton Content="Create new..." Click="ButtonBase_OnClick" />
|
||||||
|
<TextBlock TextWrapping="Wrap" Text="{Binding Name}" Height="auto" Width="auto" FontSize="16" Margin="10,7,0,6" />
|
||||||
|
<controls:OpenDatabaseUserControl CreateNew="True" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}" ValidationChecked="PasswordUserControl_PasswordChecked" />
|
||||||
|
</StackPanel>
|
||||||
|
</Page>
|
52
ModernKeePass/Pages/NewDatabasePage.xaml.cs
Normal file
52
ModernKeePass/Pages/NewDatabasePage.xaml.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Windows.Storage.Pickers;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.Events;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
|
namespace ModernKeePass.Pages
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class NewDatabasePage : Page
|
||||||
|
{
|
||||||
|
private Frame _mainFrame;
|
||||||
|
|
||||||
|
public NewDatabasePage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
_mainFrame = e.Parameter as Frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var savePicker = new FileSavePicker
|
||||||
|
{
|
||||||
|
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
|
||||||
|
SuggestedFileName = "New Database"
|
||||||
|
};
|
||||||
|
savePicker.FileTypeChoices.Add("KeePass 2.x database", new List<string> { ".kdbx" });
|
||||||
|
|
||||||
|
var file = await savePicker.PickSaveFileAsync();
|
||||||
|
if (file == null) return;
|
||||||
|
var viewModel = DataContext as OpenVm;
|
||||||
|
viewModel.OpenFile(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PasswordUserControl_PasswordChecked(object sender, PasswordEventArgs e)
|
||||||
|
{
|
||||||
|
_mainFrame.Navigate(typeof(GroupDetailPage), e.RootGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
ModernKeePass/Pages/OpenDatabasePage.xaml
Normal file
24
ModernKeePass/Pages/OpenDatabasePage.xaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<Page
|
||||||
|
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"
|
||||||
|
xmlns:local="using:ModernKeePass.Controls"
|
||||||
|
xmlns:converters="using:ModernKeePass.Converters"
|
||||||
|
x:Class="ModernKeePass.Pages.OpenDatabasePage"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<Page.Resources>
|
||||||
|
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
|
</Page.Resources>
|
||||||
|
<Page.DataContext>
|
||||||
|
<viewModels:OpenVm/>
|
||||||
|
</Page.DataContext>
|
||||||
|
|
||||||
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<HyperlinkButton Content="Browse files..." Click="ButtonBase_OnClick" />
|
||||||
|
<HyperlinkButton Content="From Url..." IsEnabled="False" />
|
||||||
|
<TextBlock TextWrapping="Wrap" Text="{Binding Name}" Height="auto" Width="auto" FontSize="16" Margin="10,7,0,6" />
|
||||||
|
<local:OpenDatabaseUserControl HorizontalAlignment="Left" Visibility="{Binding ShowPasswordBox, Converter={StaticResource BooleanToVisibilityConverter}}" ValidationChecked="PasswordUserControl_PasswordChecked" />
|
||||||
|
</StackPanel>
|
||||||
|
</Page>
|
54
ModernKeePass/Pages/OpenDatabasePage.xaml.cs
Normal file
54
ModernKeePass/Pages/OpenDatabasePage.xaml.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.Storage.Pickers;
|
||||||
|
using Windows.System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Input;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Events;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
|
namespace ModernKeePass.Pages
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class OpenDatabasePage : Page
|
||||||
|
{
|
||||||
|
private Frame _mainFrame;
|
||||||
|
|
||||||
|
public OpenDatabasePage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
_mainFrame = e.Parameter as Frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var picker =
|
||||||
|
new FileOpenPicker
|
||||||
|
{
|
||||||
|
ViewMode = PickerViewMode.List,
|
||||||
|
SuggestedStartLocation = PickerLocationId.DocumentsLibrary
|
||||||
|
};
|
||||||
|
picker.FileTypeFilter.Add(".kdbx");
|
||||||
|
|
||||||
|
var viewModel = DataContext as OpenVm;
|
||||||
|
// Application now has read/write access to the picked file
|
||||||
|
viewModel.OpenFile(await picker.PickSingleFileAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PasswordUserControl_PasswordChecked(object sender, PasswordEventArgs e)
|
||||||
|
{
|
||||||
|
_mainFrame.Navigate(typeof(GroupDetailPage), e.RootGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
ModernKeePass/Pages/RecentDatabasesPage.xaml
Normal file
38
ModernKeePass/Pages/RecentDatabasesPage.xaml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<Page
|
||||||
|
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"
|
||||||
|
xmlns:local="using:ModernKeePass.Controls"
|
||||||
|
xmlns:converters="using:ModernKeePass.Converters"
|
||||||
|
x:Class="ModernKeePass.Pages.RecentDatabasesPage"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<Page.Resources>
|
||||||
|
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
|
||||||
|
<CollectionViewSource x:Name="RecentItemsSource" Source="{Binding RecentItems}" />
|
||||||
|
</Page.Resources>
|
||||||
|
<Page.DataContext>
|
||||||
|
<viewModels:RecentVm/>
|
||||||
|
</Page.DataContext>
|
||||||
|
<ListView
|
||||||
|
Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
|
||||||
|
ItemsSource="{Binding Source={StaticResource RecentItemsSource}}"
|
||||||
|
SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
|
||||||
|
<ListView.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Margin="10,0,10,0">
|
||||||
|
<TextBlock Text="{Binding Name}" Width="350" Padding="5,0,0,0" />
|
||||||
|
<TextBlock Text="{Binding Path}" Width="350" Padding="5,0,0,0" FontSize="10" />
|
||||||
|
<local:OpenDatabaseUserControl Margin="0,10,0,0" Visibility="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}" ValidationChecking="OpenDatabaseUserControl_OnValidationChecking" ValidationChecked="PasswordUserControl_PasswordChecked" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
<ListView.ItemContainerStyle>
|
||||||
|
<Style TargetType="ListViewItem">
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||||
|
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
||||||
|
</Style>
|
||||||
|
</ListView.ItemContainerStyle>
|
||||||
|
</ListView>
|
||||||
|
</Page>
|
43
ModernKeePass/Pages/RecentDatabasesPage.xaml.cs
Normal file
43
ModernKeePass/Pages/RecentDatabasesPage.xaml.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.Events;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
// Pour en savoir plus sur le modèle d'élément Page vierge, consultez la page http://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
|
namespace ModernKeePass.Pages
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Une page vide peut être utilisée seule ou constituer une page de destination au sein d'un frame.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class RecentDatabasesPage : Page
|
||||||
|
{
|
||||||
|
private Frame _mainFrame;
|
||||||
|
|
||||||
|
public RecentDatabasesPage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
_mainFrame = e.Parameter as Frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PasswordUserControl_PasswordChecked(object sender, PasswordEventArgs e)
|
||||||
|
{
|
||||||
|
_mainFrame.Navigate(typeof(GroupDetailPage), e.RootGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenDatabaseUserControl_OnValidationChecking(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
//throw new NotImplementedException();
|
||||||
|
var viewModel = DataContext as RecentVm;
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
app.Database.DatabaseFile = viewModel.SelectedItem.DatabaseFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
ModernKeePass/Pages/SaveDatabasePage.xaml
Normal file
17
ModernKeePass/Pages/SaveDatabasePage.xaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<Page
|
||||||
|
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"
|
||||||
|
x:Class="ModernKeePass.Pages.SaveDatabasePage"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<Page.DataContext>
|
||||||
|
<viewModels:SaveVm/>
|
||||||
|
</Page.DataContext>
|
||||||
|
|
||||||
|
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
<HyperlinkButton x:Name="SaveButton" Content="Save and close" Click="SaveButton_OnClick" VerticalAlignment="Top" IsEnabled="{Binding IsSaveEnabled}" />
|
||||||
|
<HyperlinkButton x:Name="SaveAsButton" Content="Save as..." Click="SaveAsButton_OnClick" VerticalAlignment="Top" IsEnabled="{Binding IsSaveEnabled}" />
|
||||||
|
</StackPanel>
|
||||||
|
</Page>
|
54
ModernKeePass/Pages/SaveDatabasePage.xaml.cs
Normal file
54
ModernKeePass/Pages/SaveDatabasePage.xaml.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Windows.Storage.Pickers;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Navigation;
|
||||||
|
using ModernKeePass.ViewModels;
|
||||||
|
|
||||||
|
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
|
||||||
|
|
||||||
|
namespace ModernKeePass.Pages
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class SaveDatabasePage : Page
|
||||||
|
{
|
||||||
|
private Frame _mainFrame;
|
||||||
|
public SaveDatabasePage()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnNavigatedTo(e);
|
||||||
|
_mainFrame = e.Parameter as Frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveButton_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var viewModel = DataContext as SaveVm;
|
||||||
|
viewModel.Save();
|
||||||
|
_mainFrame.Navigate(typeof(MainPage));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void SaveAsButton_OnClick(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var savePicker = new FileSavePicker
|
||||||
|
{
|
||||||
|
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
|
||||||
|
SuggestedFileName = "New Database"
|
||||||
|
};
|
||||||
|
savePicker.FileTypeChoices.Add("KeePass 2.x database", new List<string> { ".kdbx" });
|
||||||
|
|
||||||
|
var file = await savePicker.PickSaveFileAsync();
|
||||||
|
if (file == null) return;
|
||||||
|
var viewModel = DataContext as SaveVm;
|
||||||
|
viewModel.Save(file);
|
||||||
|
|
||||||
|
_mainFrame.Navigate(typeof(MainPage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -6,9 +6,9 @@ using System.Runtime.InteropServices;
|
|||||||
// set of attributes. Change these attribute values to modify the information
|
// set of attributes. Change these attribute values to modify the information
|
||||||
// associated with an assembly.
|
// associated with an assembly.
|
||||||
[assembly: AssemblyTitle("ModernKeePass")]
|
[assembly: AssemblyTitle("ModernKeePass")]
|
||||||
[assembly: AssemblyDescription("")]
|
[assembly: AssemblyDescription("A port of KeePass 2.x to Modern UI as a Windows Store application")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("")]
|
[assembly: AssemblyCompany("wismna")]
|
||||||
[assembly: AssemblyProduct("ModernKeePass")]
|
[assembly: AssemblyProduct("ModernKeePass")]
|
||||||
[assembly: AssemblyCopyright("Copyright © 2017")]
|
[assembly: AssemblyCopyright("Copyright © 2017")]
|
||||||
[assembly: AssemblyTrademark("")]
|
[assembly: AssemblyTrademark("")]
|
||||||
@@ -24,6 +24,6 @@ using System.Runtime.InteropServices;
|
|||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
[assembly: AssemblyVersion("1.2.0.0")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
[assembly: AssemblyFileVersion("1.2.0.0")]
|
||||||
[assembly: ComVisible(false)]
|
[assembly: ComVisible(false)]
|
48
ModernKeePass/Styles/HamburgerButtonStyle.xaml
Normal file
48
ModernKeePass/Styles/HamburgerButtonStyle.xaml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
|
||||||
|
<Style TargetType="ToggleButton" x:Name="HamburgerToggleButton">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="ToggleButton">
|
||||||
|
<ContentControl>
|
||||||
|
<Grid Background="Transparent" Margin="0" Width="77" Height="77">
|
||||||
|
<Canvas x:Name="hampurger_menu" HorizontalAlignment="Center" Height="17" UseLayoutRounding="False" VerticalAlignment="Center" Width="28">
|
||||||
|
<Canvas x:Name="Layer_1" Height="17" Canvas.Left="0" Width="28" Margin="0" RenderTransformOrigin="0.5,0.5">
|
||||||
|
<Canvas.RenderTransform>
|
||||||
|
<CompositeTransform/>
|
||||||
|
</Canvas.RenderTransform>
|
||||||
|
<Canvas.Projection>
|
||||||
|
<PlaneProjection/>
|
||||||
|
</Canvas.Projection>
|
||||||
|
<Path x:Name="path" Data="M0,12.997 L30,12.997" Height="3" Stretch="Fill" StrokeThickness="3" Width="28" Stroke="{ThemeResource DefaultTextForegroundThemeBrush}" StrokeStartLineCap="Square" StrokeEndLineCap="Square" RenderTransformOrigin="0.5,0.5">
|
||||||
|
<Path.RenderTransform>
|
||||||
|
<CompositeTransform/>
|
||||||
|
</Path.RenderTransform>
|
||||||
|
</Path>
|
||||||
|
<Path Data="M0,12.997 L30,12.997" Height="3" Stretch="Fill" StrokeThickness="3" Width="28" Stroke="{ThemeResource DefaultTextForegroundThemeBrush}" StrokeStartLineCap="Square" StrokeEndLineCap="Square" Canvas.Top="7"/>
|
||||||
|
<Path x:Name="path1" Data="M0,12.997 L30,12.997" Height="3" Stretch="Fill" StrokeThickness="3" Width="28" Stroke="{ThemeResource DefaultTextForegroundThemeBrush}" StrokeStartLineCap="Square" StrokeEndLineCap="Square" Canvas.Top="14" RenderTransformOrigin="0.5,0.5">
|
||||||
|
<Path.RenderTransform>
|
||||||
|
<CompositeTransform/>
|
||||||
|
</Path.RenderTransform>
|
||||||
|
</Path>
|
||||||
|
</Canvas>
|
||||||
|
</Canvas>
|
||||||
|
</Grid>
|
||||||
|
</ContentControl>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
<Setter Property="VerticalAlignment" Value="Top" />
|
||||||
|
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||||
|
<Setter Property="Margin" Value="20" />
|
||||||
|
</Style>
|
||||||
|
<Style x:Key="HeaderTextBoxStyle" TargetType="TextBox">
|
||||||
|
<Setter Property="FontSize" Value="56"/>
|
||||||
|
<Setter Property="FontWeight" Value="Light"/>
|
||||||
|
<Setter Property="BorderBrush" Value="Transparent" />
|
||||||
|
<Setter Property="Background" Value="Transparent" />
|
||||||
|
<!--<Setter Property="LineHeight" Value="40"/>-->
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
229
ModernKeePass/Styles/TextBoxWithButtonStyle.xaml
Normal file
229
ModernKeePass/Styles/TextBoxWithButtonStyle.xaml
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
|
||||||
|
<Style TargetType="TextBox" x:Name="TextBoxWithButtonStyle">
|
||||||
|
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
|
||||||
|
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
|
||||||
|
<Setter Property="Foreground" Value="{ThemeResource TextBoxForegroundThemeBrush}" />
|
||||||
|
<Setter Property="Background" Value="{ThemeResource TextBoxBackgroundThemeBrush}" />
|
||||||
|
<Setter Property="BorderBrush" Value="{ThemeResource TextBoxBorderThemeBrush}" />
|
||||||
|
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextSelectionHighlightColorThemeBrush}" />
|
||||||
|
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
|
||||||
|
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||||
|
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||||
|
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
|
||||||
|
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
|
||||||
|
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
|
||||||
|
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}"/>
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="TextBox">
|
||||||
|
<Grid>
|
||||||
|
<Grid.Resources>
|
||||||
|
<Style x:Name="GotoButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPointerOverForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxButtonPressedForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
To="0"
|
||||||
|
Duration="0" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
BorderBrush="{ThemeResource TextBoxButtonBorderThemeBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"/>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Background="{ThemeResource TextBoxButtonBackgroundThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}">
|
||||||
|
<TextBlock x:Name="GlyphElement"
|
||||||
|
Foreground="{ThemeResource TextBoxButtonForegroundThemeBrush}"
|
||||||
|
Padding="4,0,4,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
FontStyle="Normal"
|
||||||
|
Text=""
|
||||||
|
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Grid.Resources>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBackgroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="BorderBrush">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledBorderThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter"
|
||||||
|
Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextBoxDisabledForegroundThemeBrush}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Normal">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlBackgroundThemeOpacity}" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlBorderThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BackgroundElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlPointerOverBackgroundThemeOpacity}" />
|
||||||
|
<DoubleAnimation Storyboard.TargetName="BorderElement"
|
||||||
|
Storyboard.TargetProperty="Opacity"
|
||||||
|
Duration="0"
|
||||||
|
To="{ThemeResource TextControlPointerOverBorderThemeOpacity}" />
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="Focused" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="ButtonStates">
|
||||||
|
<VisualState x:Name="ButtonVisible">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GotoButton"
|
||||||
|
Storyboard.TargetProperty="Visibility">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0">
|
||||||
|
<DiscreteObjectKeyFrame.Value>
|
||||||
|
<Visibility>Visible</Visibility>
|
||||||
|
</DiscreteObjectKeyFrame.Value>
|
||||||
|
</DiscreteObjectKeyFrame>
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
<VisualState x:Name="ButtonCollapsed" />
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto" />
|
||||||
|
<RowDefinition Height="*" />
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Border x:Name="BackgroundElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Grid.RowSpan="1"/>
|
||||||
|
<Border x:Name="BorderElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Grid.RowSpan="1"/>
|
||||||
|
<ContentPresenter x:Name="HeaderContentPresenter"
|
||||||
|
Grid.Row="0"
|
||||||
|
Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}"
|
||||||
|
Margin="0,4,0,4"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Content="{TemplateBinding Header}"
|
||||||
|
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||||
|
FontWeight="Semilight" />
|
||||||
|
<ScrollViewer x:Name="ContentElement"
|
||||||
|
Grid.Row="1"
|
||||||
|
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
|
||||||
|
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
|
||||||
|
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
|
||||||
|
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
|
||||||
|
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
|
||||||
|
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
|
||||||
|
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
IsTabStop="False"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"
|
||||||
|
ZoomMode="Disabled" />
|
||||||
|
<ContentControl x:Name="PlaceholderTextContentPresenter"
|
||||||
|
Grid.Row="1"
|
||||||
|
Foreground="{ThemeResource TextBoxPlaceholderTextThemeBrush}"
|
||||||
|
Margin="{TemplateBinding BorderThickness}"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.ColumnSpan="2"
|
||||||
|
Content="{TemplateBinding PlaceholderText}"
|
||||||
|
IsHitTestVisible="False"/>
|
||||||
|
<Button x:Name="GotoButton"
|
||||||
|
Grid.Row="1"
|
||||||
|
Style="{StaticResource GotoButtonStyle}"
|
||||||
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
|
IsTabStop="False"
|
||||||
|
Grid.Column="1"
|
||||||
|
Visibility="Collapsed"
|
||||||
|
FontSize="{TemplateBinding FontSize}"
|
||||||
|
VerticalAlignment="Stretch"/>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
@@ -1,69 +0,0 @@
|
|||||||
using System.ComponentModel;
|
|
||||||
using Windows.Storage;
|
|
||||||
|
|
||||||
using ModernKeePassLib;
|
|
||||||
using ModernKeePassLib.Keys;
|
|
||||||
using ModernKeePassLib.Serialization;
|
|
||||||
using ModernKeePassLib.Interfaces;
|
|
||||||
using Windows.UI.Xaml;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace ModernKeePass.ViewModels
|
|
||||||
{
|
|
||||||
public class DatabaseVm : INotifyPropertyChanged
|
|
||||||
{
|
|
||||||
private PwDatabase database = new PwDatabase();
|
|
||||||
private StorageFile databaseFile;
|
|
||||||
|
|
||||||
public string Password { get; set; }
|
|
||||||
public bool IsOpen { get; set; }
|
|
||||||
public Visibility Visibility { get; private set; }
|
|
||||||
public string ErrorMessage { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public GroupVm RootGroup { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public DatabaseVm()
|
|
||||||
{
|
|
||||||
Visibility = Visibility.Collapsed;
|
|
||||||
}
|
|
||||||
public DatabaseVm(StorageFile databaseFile)
|
|
||||||
{
|
|
||||||
this.databaseFile = databaseFile;
|
|
||||||
Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
public async void Open()
|
|
||||||
{
|
|
||||||
var key = new CompositeKey();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
key.AddUserKey(new KcpPassword(Password));
|
|
||||||
await database.Open(IOConnectionInfo.FromFile(databaseFile), key, new NullStatusLogger());
|
|
||||||
IsOpen = database.IsOpen;
|
|
||||||
Name = databaseFile.DisplayName;
|
|
||||||
RootGroup = new GroupVm (database.RootGroup);
|
|
||||||
}
|
|
||||||
catch (ArgumentNullException)
|
|
||||||
{
|
|
||||||
ErrorMessage = "Password cannot be empty";
|
|
||||||
NotifyPropertyChanged("ErrorMessage");
|
|
||||||
}
|
|
||||||
catch (InvalidCompositeKeyException)
|
|
||||||
{
|
|
||||||
ErrorMessage = "Wrong password";
|
|
||||||
NotifyPropertyChanged("ErrorMessage");
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// TODO: move this when implementing write mode
|
|
||||||
database.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
public void NotifyPropertyChanged(string propertyName)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,26 +1,98 @@
|
|||||||
using System.ComponentModel;
|
using Windows.UI.Text;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Mappings;
|
||||||
using ModernKeePassLib;
|
using ModernKeePassLib;
|
||||||
|
using ModernKeePassLib.Security;
|
||||||
|
|
||||||
namespace ModernKeePass.ViewModels
|
namespace ModernKeePass.ViewModels
|
||||||
{
|
{
|
||||||
public class EntryVm : INotifyPropertyChanged
|
public class EntryVm: NotifyPropertyChangedBase
|
||||||
{
|
{
|
||||||
public string Title { get; private set; }
|
public GroupVm ParentGroup { get; }
|
||||||
public string UserName { get; private set; }
|
public PwEntry Entry { get; }
|
||||||
public string Password { get; private set; }
|
|
||||||
public string URL { get; private set; }
|
|
||||||
public string Notes { get; private set; }
|
|
||||||
|
|
||||||
public EntryVm() { }
|
public System.Drawing.Color? BackgroundColor => Entry?.BackgroundColor;
|
||||||
public EntryVm(PwEntry entry)
|
public System.Drawing.Color? ForegroundColor => Entry?.ForegroundColor;
|
||||||
|
|
||||||
|
public string Title
|
||||||
{
|
{
|
||||||
Title = entry.Strings.GetSafe(PwDefs.TitleField).ReadString();
|
get
|
||||||
UserName = entry.Strings.GetSafe(PwDefs.UserNameField).ReadString();
|
{
|
||||||
Password = entry.Strings.GetSafe(PwDefs.PasswordField).ReadString();
|
var title = GetEntryValue(PwDefs.TitleField);
|
||||||
URL = entry.Strings.GetSafe(PwDefs.UrlField).ReadString();
|
return title == null ? "New entry" : title;
|
||||||
Notes = entry.Strings.GetSafe(PwDefs.NotesField).ReadString();
|
}
|
||||||
|
set { SetEntryValue(PwDefs.TitleField, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public string Id => Entry.Uuid.ToHexString();
|
||||||
|
|
||||||
|
public string UserName
|
||||||
|
{
|
||||||
|
get { return GetEntryValue(PwDefs.UserNameField); }
|
||||||
|
set { SetEntryValue(PwDefs.UserNameField, value); }
|
||||||
|
}
|
||||||
|
public string Password
|
||||||
|
{
|
||||||
|
get { return GetEntryValue(PwDefs.PasswordField); }
|
||||||
|
set { SetEntryValue(PwDefs.PasswordField, value); }
|
||||||
|
}
|
||||||
|
public string Url
|
||||||
|
{
|
||||||
|
get { return GetEntryValue(PwDefs.UrlField); }
|
||||||
|
set { SetEntryValue(PwDefs.UrlField, value); }
|
||||||
|
}
|
||||||
|
public string Notes
|
||||||
|
{
|
||||||
|
get { return GetEntryValue(PwDefs.NotesField); }
|
||||||
|
set { SetEntryValue(PwDefs.NotesField, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Symbol IconSymbol
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Entry == null) return Symbol.Add;
|
||||||
|
var result = PwIconToSegoeMapping.GetSymbolFromIcon(Entry.IconId);
|
||||||
|
return result == Symbol.More ? Symbol.Permissions : result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEditMode
|
||||||
|
{
|
||||||
|
get { return _isEditMode; }
|
||||||
|
set { SetProperty(ref _isEditMode, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRevealPassword
|
||||||
|
{
|
||||||
|
get { return _isRevealPassword; }
|
||||||
|
set { SetProperty(ref _isRevealPassword, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _isEditMode;
|
||||||
|
private bool _isRevealPassword;
|
||||||
|
|
||||||
|
public EntryVm() { }
|
||||||
|
public EntryVm(PwEntry entry, GroupVm parent)
|
||||||
|
{
|
||||||
|
Entry = entry;
|
||||||
|
ParentGroup = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveEntry()
|
||||||
|
{
|
||||||
|
ParentGroup.RemoveEntry(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetEntryValue(string key)
|
||||||
|
{
|
||||||
|
return Entry?.Strings.GetSafe(key).ReadString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetEntryValue(string key, string newValue)
|
||||||
|
{
|
||||||
|
Entry?.Strings.Set(key, new ProtectedString(true, newValue));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,50 +1,105 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Windows.UI.Text;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Mappings;
|
||||||
using ModernKeePassLib;
|
using ModernKeePassLib;
|
||||||
|
|
||||||
namespace ModernKeePass.ViewModels
|
namespace ModernKeePass.ViewModels
|
||||||
{
|
{
|
||||||
public class GroupVm : INotifyPropertyChanged
|
public class GroupVm : NotifyPropertyChangedBase
|
||||||
{
|
{
|
||||||
public ObservableCollection<EntryVm> Entries { get; set; }
|
public GroupVm ParentGroup { get; }
|
||||||
public ObservableCollection<GroupVm> Groups { get; set; }
|
public ObservableCollection<EntryVm> Entries { get; set; } = new ObservableCollection<EntryVm>();
|
||||||
public string Name { get; set; }
|
|
||||||
|
public ObservableCollection<GroupVm> Groups { get; set; } = new ObservableCollection<GroupVm>();
|
||||||
|
|
||||||
public string EntryCount {
|
public int EntryCount => Entries.Count() - 1;
|
||||||
get
|
public int GroupCount => Groups.Count - 1;
|
||||||
{
|
public bool IsNotRoot => ParentGroup != null;
|
||||||
return $"{Entries?.Count} entries.";
|
public FontWeight FontWeight => _pwGroup == null ? FontWeights.Bold : FontWeights.Normal;
|
||||||
}
|
|
||||||
}
|
public IOrderedEnumerable<IGrouping<char, EntryVm>> EntriesZoomedOut
|
||||||
public string GroupCount
|
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return $"{Groups?.Count} groups.";
|
return from e in Entries
|
||||||
|
where e.Entry != null
|
||||||
|
group e by e.Title.FirstOrDefault() into grp
|
||||||
|
orderby grp.Key
|
||||||
|
select grp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroupVm()
|
public string Name
|
||||||
{
|
{
|
||||||
Name = "GroupName";
|
get { return _pwGroup == null ? "New group" : _pwGroup.Name; }
|
||||||
Entries = new ObservableCollection<EntryVm>();
|
set { _pwGroup.Name = value; }
|
||||||
Groups = new ObservableCollection<GroupVm>();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public GroupVm(PwGroup group)
|
public Symbol IconSymbol
|
||||||
{
|
{
|
||||||
Name = group.Name;
|
get
|
||||||
Entries = new ObservableCollection<EntryVm>(group.Entries.Select(e => new EntryVm(e)));
|
{
|
||||||
Groups = new ObservableCollection<GroupVm>(group.Groups.Select(g => new GroupVm(g)));
|
if (_pwGroup == null) return Symbol.Add;
|
||||||
|
var result = PwIconToSegoeMapping.GetSymbolFromIcon(_pwGroup.IconId);
|
||||||
|
return result == Symbol.More ? Symbol.Folder : result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public bool IsLeftPaneOpen
|
||||||
|
|
||||||
public void NotifyPropertyChanged(string propertyName)
|
|
||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
get { return _isLeftPaneOpen; }
|
||||||
|
set { SetProperty(ref _isLeftPaneOpen, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsEditMode
|
||||||
|
{
|
||||||
|
get { return _isEditMode; }
|
||||||
|
set { SetProperty(ref _isEditMode, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly PwGroup _pwGroup;
|
||||||
|
private bool _isLeftPaneOpen;
|
||||||
|
private bool _isEditMode;
|
||||||
|
|
||||||
|
public GroupVm() {}
|
||||||
|
|
||||||
|
public GroupVm(PwGroup pwGroup, GroupVm parent)
|
||||||
|
{
|
||||||
|
_pwGroup = pwGroup;
|
||||||
|
ParentGroup = parent;
|
||||||
|
Entries = new ObservableCollection<EntryVm>(pwGroup.Entries.Select(e => new EntryVm(e, this)).OrderBy(e => e.Title));
|
||||||
|
Entries.Insert(0, new EntryVm ());
|
||||||
|
Groups = new ObservableCollection<GroupVm>(pwGroup.Groups.Select(g => new GroupVm(g, this)).OrderBy(g => g.Name));
|
||||||
|
Groups.Insert(0, new GroupVm ());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateNewGroup()
|
||||||
|
{
|
||||||
|
var pwGroup = new PwGroup(true, true, "New group", PwIcon.Folder);
|
||||||
|
_pwGroup.AddGroup(pwGroup, true);
|
||||||
|
Groups.Add(new GroupVm(pwGroup, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateNewEntry()
|
||||||
|
{
|
||||||
|
var pwEntry = new PwEntry(true, true);
|
||||||
|
_pwGroup.AddEntry(pwEntry, true);
|
||||||
|
Entries.Add(new EntryVm(pwEntry, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveGroup()
|
||||||
|
{
|
||||||
|
_pwGroup.ParentGroup.Groups.Remove(_pwGroup);
|
||||||
|
ParentGroup.Groups.Remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveEntry(EntryVm entry)
|
||||||
|
{
|
||||||
|
_pwGroup.Entries.Remove(entry.Entry);
|
||||||
|
Entries.Remove(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
37
ModernKeePass/ViewModels/Items/MainMenuItemVm.cs
Normal file
37
ModernKeePass/ViewModels/Items/MainMenuItemVm.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Interfaces;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class MainMenuItemVm: NotifyPropertyChangedBase, IIsEnabled
|
||||||
|
{
|
||||||
|
private string _title;
|
||||||
|
private bool _isSelected;
|
||||||
|
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get { return IsEnabled ? _title : _title + " - Coming soon"; }
|
||||||
|
set { _title = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type PageType { get; set; }
|
||||||
|
public object Parameter { get; set; }
|
||||||
|
public Frame Destination { get; set; }
|
||||||
|
public int Group { get; set; } = 0;
|
||||||
|
public Symbol SymbolIcon { get; set; }
|
||||||
|
public bool IsEnabled => PageType != null;
|
||||||
|
|
||||||
|
public bool IsSelected
|
||||||
|
{
|
||||||
|
get { return _isSelected; }
|
||||||
|
set { SetProperty(ref _isSelected, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
ModernKeePass/ViewModels/Items/RecentItemVm.cs
Normal file
30
ModernKeePass/ViewModels/Items/RecentItemVm.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using Windows.Storage;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using Windows.Storage.AccessCache;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class RecentItemVm: NotifyPropertyChangedBase
|
||||||
|
{
|
||||||
|
private bool _isSelected;
|
||||||
|
|
||||||
|
public RecentItemVm(AccessListEntry entry, StorageFile file)
|
||||||
|
{
|
||||||
|
Token = entry.Token;
|
||||||
|
Name = entry.Metadata;
|
||||||
|
DatabaseFile = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StorageFile DatabaseFile { get; private set; }
|
||||||
|
public string Token { get; private set; }
|
||||||
|
public string Name { get; private set; }
|
||||||
|
public string Path => DatabaseFile.Path;
|
||||||
|
|
||||||
|
public bool IsSelected
|
||||||
|
{
|
||||||
|
get { return _isSelected; }
|
||||||
|
internal set { SetProperty(ref _isSelected, value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
ModernKeePass/ViewModels/MainVm.cs
Normal file
86
ModernKeePass/ViewModels/MainVm.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using Windows.Storage.AccessCache;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
using ModernKeePass.Pages;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class MainVm : NotifyPropertyChangedBase
|
||||||
|
{
|
||||||
|
private IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> _mainMenuItems;
|
||||||
|
private MainMenuItemVm _selectedItem;
|
||||||
|
|
||||||
|
public IOrderedEnumerable<IGrouping<int, MainMenuItemVm>> MainMenuItems
|
||||||
|
{
|
||||||
|
get { return _mainMenuItems; }
|
||||||
|
set { SetProperty(ref _mainMenuItems, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public MainMenuItemVm SelectedItem
|
||||||
|
{
|
||||||
|
get { return _selectedItem; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_selectedItem == value) return;
|
||||||
|
if (_selectedItem != null)
|
||||||
|
{
|
||||||
|
_selectedItem.IsSelected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetProperty(ref _selectedItem, value);
|
||||||
|
|
||||||
|
if (_selectedItem != null)
|
||||||
|
{
|
||||||
|
_selectedItem.IsSelected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MainVm() {}
|
||||||
|
|
||||||
|
public MainVm(Frame referenceFrame, Frame destinationFrame)
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
var mru = StorageApplicationPermissions.MostRecentlyUsedList;
|
||||||
|
|
||||||
|
var mainMenuItems = new ObservableCollection<MainMenuItemVm>
|
||||||
|
{
|
||||||
|
new MainMenuItemVm
|
||||||
|
{
|
||||||
|
Title = "Open", PageType = typeof(OpenDatabasePage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Page2,
|
||||||
|
IsSelected = app.Database.Status == DatabaseHelper.DatabaseStatus.Opening
|
||||||
|
},
|
||||||
|
new MainMenuItemVm
|
||||||
|
{
|
||||||
|
Title = "New" , PageType = typeof(NewDatabasePage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Add
|
||||||
|
},
|
||||||
|
new MainMenuItemVm
|
||||||
|
{
|
||||||
|
Title = "Save" , PageType = typeof(SaveDatabasePage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Save,
|
||||||
|
IsSelected = app.Database != null && app.Database.Status == DatabaseHelper.DatabaseStatus.Opened
|
||||||
|
},
|
||||||
|
new MainMenuItemVm {
|
||||||
|
Title = "Recent" , PageType = typeof(RecentDatabasesPage), Destination = destinationFrame, Parameter = referenceFrame, SymbolIcon = Symbol.Copy,
|
||||||
|
IsSelected = (app.Database == null || app.Database.Status == DatabaseHelper.DatabaseStatus.Closed) && mru.Entries.Count > 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Auto-select the Recent Items menu item if the conditions are met
|
||||||
|
SelectedItem = mainMenuItems.FirstOrDefault(m => m.IsSelected);
|
||||||
|
if (app.Database != null && app.Database.Status == DatabaseHelper.DatabaseStatus.Opened)
|
||||||
|
mainMenuItems.Add(new MainMenuItemVm
|
||||||
|
{
|
||||||
|
Title = app.Database.Name,
|
||||||
|
PageType = typeof(GroupDetailPage),
|
||||||
|
Destination = referenceFrame,
|
||||||
|
Parameter = app.Database.RootGroup,
|
||||||
|
Group = 1,
|
||||||
|
SymbolIcon = Symbol.ProtectedDocument
|
||||||
|
});
|
||||||
|
|
||||||
|
MainMenuItems = from item in mainMenuItems group item by item.Group into grp orderby grp.Key select grp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
ModernKeePass/ViewModels/OpenVm.cs
Normal file
50
ModernKeePass/ViewModels/OpenVm.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Windows.Storage;
|
||||||
|
using Windows.Storage.AccessCache;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class OpenVm: INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public bool ShowPasswordBox
|
||||||
|
{
|
||||||
|
get { return ((App)Application.Current).Database.Status == DatabaseHelper.DatabaseStatus.Opening; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get { return ((App)Application.Current).Database.Name; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public OpenVm()
|
||||||
|
{
|
||||||
|
var database = ((App)Application.Current).Database;
|
||||||
|
if (database == null || database.Status != DatabaseHelper.DatabaseStatus.Opening) return;
|
||||||
|
OpenFile(database.DatabaseFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
private void NotifyPropertyChanged(string propertyName)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OpenFile(StorageFile file)
|
||||||
|
{
|
||||||
|
var database = ((App)Application.Current).Database;
|
||||||
|
database.DatabaseFile = file;
|
||||||
|
NotifyPropertyChanged("Name");
|
||||||
|
NotifyPropertyChanged("ShowPasswordBox");
|
||||||
|
AddToRecentList(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddToRecentList(StorageFile file)
|
||||||
|
{
|
||||||
|
var mru = StorageApplicationPermissions.MostRecentlyUsedList;
|
||||||
|
mru.Add(file, file.DisplayName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
ModernKeePass/ViewModels/RecentVm.cs
Normal file
57
ModernKeePass/ViewModels/RecentVm.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using Windows.Storage.AccessCache;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class RecentVm : NotifyPropertyChangedBase
|
||||||
|
{
|
||||||
|
private RecentItemVm _selectedItem;
|
||||||
|
private ObservableCollection<RecentItemVm> _recentItems = new ObservableCollection<RecentItemVm>();
|
||||||
|
|
||||||
|
public ObservableCollection<RecentItemVm> RecentItems
|
||||||
|
{
|
||||||
|
get { return _recentItems; }
|
||||||
|
set { SetProperty(ref _recentItems, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecentItemVm SelectedItem
|
||||||
|
{
|
||||||
|
get { return _selectedItem; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_selectedItem == value) return;
|
||||||
|
if (_selectedItem != null)
|
||||||
|
{
|
||||||
|
_selectedItem.IsSelected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetProperty(ref _selectedItem, value);
|
||||||
|
|
||||||
|
if (_selectedItem == null) return;
|
||||||
|
_selectedItem.IsSelected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public RecentVm()
|
||||||
|
{
|
||||||
|
var mru = StorageApplicationPermissions.MostRecentlyUsedList;
|
||||||
|
foreach (var entry in mru.Entries)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var file = mru.GetFileAsync(entry.Token).GetAwaiter().GetResult();
|
||||||
|
RecentItems.Add(new RecentItemVm(entry, file));
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
mru.Remove(entry.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (RecentItems.Count > 0)
|
||||||
|
SelectedItem = RecentItems[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
40
ModernKeePass/ViewModels/SaveVm.cs
Normal file
40
ModernKeePass/ViewModels/SaveVm.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Windows.Storage;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using ModernKeePass.Common;
|
||||||
|
|
||||||
|
namespace ModernKeePass.ViewModels
|
||||||
|
{
|
||||||
|
public class SaveVm: INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public bool IsSaveEnabled
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
return app.Database.Status == DatabaseHelper.DatabaseStatus.Opened;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
private void NotifyPropertyChanged(string propertyName)
|
||||||
|
{
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(bool close = true)
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
app.Database.Save();
|
||||||
|
if (!close) return;
|
||||||
|
app.Database.Close();
|
||||||
|
NotifyPropertyChanged("IsSaveEnabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Save(StorageFile file)
|
||||||
|
{
|
||||||
|
var app = (App)Application.Current;
|
||||||
|
app.Database.Save(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -2,10 +2,26 @@
|
|||||||
<packages>
|
<packages>
|
||||||
<package id="Microsoft.NETCore.Platforms" version="2.0.0" targetFramework="win81" />
|
<package id="Microsoft.NETCore.Platforms" version="2.0.0" targetFramework="win81" />
|
||||||
<package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.2" targetFramework="win81" />
|
<package id="Microsoft.NETCore.Portable.Compatibility" version="1.0.2" targetFramework="win81" />
|
||||||
<package id="ModernKeePassLib" version="2.19.2950" targetFramework="win81" />
|
<package id="ModernKeePassLib" version="2.28.4000" targetFramework="win81" />
|
||||||
<package id="NETStandard.Library" version="2.0.0" targetFramework="win81" />
|
<package id="NETStandard.Library" version="2.0.0" targetFramework="win81" />
|
||||||
|
<package id="Portable.BouncyCastle" version="1.8.1.3" targetFramework="win81" />
|
||||||
|
<package id="Splat" version="2.0.0" targetFramework="win81" />
|
||||||
|
<package id="System.Collections" version="4.0.11" targetFramework="win81" />
|
||||||
|
<package id="System.Diagnostics.Debug" version="4.0.11" targetFramework="win81" />
|
||||||
|
<package id="System.Globalization" version="4.0.11" targetFramework="win81" />
|
||||||
|
<package id="System.IO" version="4.1.0" targetFramework="win81" />
|
||||||
|
<package id="System.Linq" version="4.1.0" targetFramework="win81" />
|
||||||
<package id="System.Net.Requests" version="4.3.0" targetFramework="win81" />
|
<package id="System.Net.Requests" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Reflection" version="4.1.0" targetFramework="win81" />
|
||||||
|
<package id="System.Reflection.Extensions" version="4.0.1" targetFramework="win81" />
|
||||||
|
<package id="System.Runtime" version="4.1.0" targetFramework="win81" />
|
||||||
|
<package id="System.Runtime.Extensions" version="4.3.0" targetFramework="win81" />
|
||||||
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="win81" />
|
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="win81" />
|
||||||
<package id="System.Runtime.WindowsRuntime" version="4.3.0" targetFramework="win81" />
|
<package id="System.Runtime.WindowsRuntime" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="System.Text.Encoding" version="4.0.11" targetFramework="win81" />
|
||||||
|
<package id="System.Threading" version="4.0.11" targetFramework="win81" />
|
||||||
|
<package id="System.Threading.Tasks" version="4.0.11" targetFramework="win81" />
|
||||||
|
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="win81" />
|
||||||
<package id="System.Xml.XmlSerializer" version="4.3.0" targetFramework="win81" />
|
<package id="System.Xml.XmlSerializer" version="4.3.0" targetFramework="win81" />
|
||||||
|
<package id="Validation" version="2.4.15" targetFramework="win81" />
|
||||||
</packages>
|
</packages>
|
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Cryptography.Cipher;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Cryptography.Cipher;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Cryptography.Cipher
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class StandardAesEngineTests
|
||||||
|
{
|
||||||
|
[Test ()]
|
||||||
|
public void TestEncryptStream ()
|
||||||
|
{
|
||||||
|
// Test vector (official ECB test vector #356)
|
||||||
|
var pbIV = new byte[16];
|
||||||
|
var pbTestKey = new byte[32];
|
||||||
|
var pbTestData = new byte[16];
|
||||||
|
var pbReferenceCT = new byte[16] {
|
||||||
|
0x75, 0xD1, 0x1B, 0x0E, 0x3A, 0x68, 0xC4, 0x22,
|
||||||
|
0x3D, 0x88, 0xDB, 0xF0, 0x17, 0x97, 0x7D, 0xD7
|
||||||
|
};
|
||||||
|
|
||||||
|
pbTestData[0] = 0x04;
|
||||||
|
|
||||||
|
var outStream = new MemoryStream (new byte[16]);
|
||||||
|
var aes = new StandardAesEngine ();
|
||||||
|
var inStream = aes.EncryptStream (outStream, pbTestKey, pbIV);
|
||||||
|
new BinaryWriter (inStream).Write (pbTestData);
|
||||||
|
Assert.That (outStream.Position, Is.EqualTo (16));
|
||||||
|
outStream.Position = 0;
|
||||||
|
var outBytes = new BinaryReader (outStream).ReadBytes (16);
|
||||||
|
Assert.That(outBytes, Is.EqualTo (pbReferenceCT));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestDecryptStream ()
|
||||||
|
{
|
||||||
|
// Test vector (official ECB test vector #356)
|
||||||
|
var pbIV = new byte[16];
|
||||||
|
var pbTestKey = new byte[32];
|
||||||
|
var pbTestData = new byte[16];
|
||||||
|
var pbReferenceCT = new byte[16] {
|
||||||
|
0x75, 0xD1, 0x1B, 0x0E, 0x3A, 0x68, 0xC4, 0x22,
|
||||||
|
0x3D, 0x88, 0xDB, 0xF0, 0x17, 0x97, 0x7D, 0xD7
|
||||||
|
};
|
||||||
|
|
||||||
|
pbTestData[0] = 0x04;
|
||||||
|
|
||||||
|
// Possible Mono Bug? This only works with size >= 48
|
||||||
|
var inStream = new MemoryStream (new byte[48]);
|
||||||
|
inStream.Write (pbReferenceCT, 0, pbReferenceCT.Length);
|
||||||
|
inStream.Position = 0;
|
||||||
|
var aes = new StandardAesEngine ();
|
||||||
|
var outStream = aes.DecryptStream (inStream, pbTestKey, pbIV);
|
||||||
|
var outBytes = new BinaryReader (outStream).ReadBytes (16);
|
||||||
|
Assert.That(outBytes, Is.EqualTo (pbTestData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,60 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Cryptography;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Cryptography;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Cryptography
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class CryptoRandomStreamTests
|
||||||
|
{
|
||||||
|
void TestGetRandomBytes(CryptoRandomStream stream)
|
||||||
|
{
|
||||||
|
const uint length = 16;
|
||||||
|
var bytes1 = stream.GetRandomBytes (length);
|
||||||
|
Assert.That (bytes1.Length, Is.EqualTo (length));
|
||||||
|
var bytes2 = stream.GetRandomBytes (length);
|
||||||
|
Assert.That (bytes2, Is.Not.EqualTo (bytes1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGetRandomBytesCrsAlgorithmSalsa20 ()
|
||||||
|
{
|
||||||
|
var stream = new CryptoRandomStream (CrsAlgorithm.Salsa20, new byte[16]);
|
||||||
|
TestGetRandomBytes (stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGetRandomBytesCrsAlgorithmArcFourVariant ()
|
||||||
|
{
|
||||||
|
var stream = new CryptoRandomStream (CrsAlgorithm.ArcFourVariant, new byte[16]);
|
||||||
|
TestGetRandomBytes (stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestGetRandomInt64 (CryptoRandomStream stream)
|
||||||
|
{
|
||||||
|
var value1 = stream.GetRandomUInt64 ();
|
||||||
|
var value2 = stream.GetRandomUInt64 ();
|
||||||
|
Assert.That (value2, Is.Not.EqualTo (value1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGetRandomInt64AlgorithmSalsa20 ()
|
||||||
|
{
|
||||||
|
var stream = new CryptoRandomStream (CrsAlgorithm.Salsa20, new byte[16]);
|
||||||
|
TestGetRandomInt64 (stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGetRandomInt64AlgorithmArcFourVariant ()
|
||||||
|
{
|
||||||
|
var stream = new CryptoRandomStream (CrsAlgorithm.ArcFourVariant, new byte[16]);
|
||||||
|
TestGetRandomInt64 (stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
44
ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs
Normal file
44
ModernKeePassLib.Test/Cryptography/CryptoRandomTests.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Cryptography;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Cryptography;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Cryptography
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class CryptoRandomTests
|
||||||
|
{
|
||||||
|
[Test ()]
|
||||||
|
public void TestAddEntropy ()
|
||||||
|
{
|
||||||
|
// just making sure it does not throw an exception
|
||||||
|
CryptoRandom.Instance.AddEntropy (new byte[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGetRandomBytes ()
|
||||||
|
{
|
||||||
|
const int length = 32;
|
||||||
|
var bytes1 = CryptoRandom.Instance.GetRandomBytes (length);
|
||||||
|
Assert.That (bytes1.Length, Is.EqualTo (length));
|
||||||
|
var bytes2 = CryptoRandom.Instance.GetRandomBytes (length);
|
||||||
|
Assert.That (bytes2, Is.Not.EqualTo (bytes1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGeneratedBytesCount ()
|
||||||
|
{
|
||||||
|
const int length = 1;
|
||||||
|
CryptoRandom.Instance.GetRandomBytes (length);
|
||||||
|
var count1 = CryptoRandom.Instance.GeneratedBytesCount;
|
||||||
|
CryptoRandom.Instance.GetRandomBytes (length);
|
||||||
|
var count2 = CryptoRandom.Instance.GeneratedBytesCount;
|
||||||
|
Assert.That (count2, Is.GreaterThan (count1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
77
ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs
Normal file
77
ModernKeePassLib.Test/Cryptography/HashingStreamExTests.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Cryptography;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Cryptography;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Cryptography
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class HashingStreamExTests
|
||||||
|
{
|
||||||
|
const string data = "test";
|
||||||
|
|
||||||
|
// The expected hash includes the \n added by WriteLine
|
||||||
|
static readonly byte[] sha256HashOfData = {
|
||||||
|
0xf2, 0xca, 0x1b, 0xb6, 0xc7, 0xe9, 0x07, 0xd0,
|
||||||
|
0x6d, 0xaf, 0xe4, 0x68, 0x7e, 0x57, 0x9f, 0xce,
|
||||||
|
0x76, 0xb3, 0x7e, 0x4e, 0x93, 0xb7, 0x60, 0x50,
|
||||||
|
0x22, 0xda, 0x52, 0xe6, 0xcc, 0xc2, 0x6f, 0xd2
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestRead ()
|
||||||
|
{
|
||||||
|
// if we use larger size, StreamReader will read past newline and cause bad hash
|
||||||
|
var bytes = new byte[data.Length + 1];
|
||||||
|
using (var ms = new MemoryStream (bytes)) {
|
||||||
|
using (var sw = new StreamWriter (ms)) {
|
||||||
|
// set NewLine to ensure we don't run into cross-platform issues on Windows
|
||||||
|
sw.NewLine = "\n";
|
||||||
|
sw.WriteLine (data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (var ms = new MemoryStream (bytes)) {
|
||||||
|
using (var hs = new HashingStreamEx (ms, false, null)) {
|
||||||
|
using (var sr = new StreamReader (hs)) {
|
||||||
|
var read = sr.ReadLine ();
|
||||||
|
Assert.That (read, Is.EqualTo (data));
|
||||||
|
}
|
||||||
|
// When the StreamReader is disposed, it calls Dispose on the
|
||||||
|
//HasingStreamEx, which computes the hash.
|
||||||
|
Assert.That (hs.Hash, Is.EqualTo (sha256HashOfData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestWrite ()
|
||||||
|
{
|
||||||
|
var bytes = new byte[16];
|
||||||
|
using (var ms = new MemoryStream (bytes)) {
|
||||||
|
using (var hs = new HashingStreamEx (ms, true, null)) {
|
||||||
|
using (var sw = new StreamWriter (hs)) {
|
||||||
|
// set NewLine to ensure we don't run into cross-platform issues on Windows
|
||||||
|
sw.NewLine = "\n";
|
||||||
|
sw.WriteLine (data);
|
||||||
|
}
|
||||||
|
// When the StreamWriter is disposed, it calls Dispose on the
|
||||||
|
//HasingStreamEx, which computes the hash.
|
||||||
|
Assert.That (hs.Hash, Is.EqualTo (sha256HashOfData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (var ms = new MemoryStream (bytes)) {
|
||||||
|
using (var sr = new StreamReader (ms)) {
|
||||||
|
var read = sr.ReadLine ();
|
||||||
|
Assert.That (read, Is.EqualTo (data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
36
ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs
Normal file
36
ModernKeePassLib.Test/Cryptography/HmacOtpTests.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Cryptography;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Cryptography;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Cryptography
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class HmacOtpTests
|
||||||
|
{
|
||||||
|
// Using the test case from Appendix D of RFC 4226
|
||||||
|
|
||||||
|
const string secret = "12345678901234567890";
|
||||||
|
static readonly string[] expectedHOTP = new string[] {
|
||||||
|
"755224", "287082", "359152", "969429", "338314",
|
||||||
|
"254676", "287922", "162583", "399871", "520489"
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestGenerate ()
|
||||||
|
{
|
||||||
|
var secretBytes = Encoding.UTF8.GetBytes (secret);
|
||||||
|
|
||||||
|
for (ulong i = 0; i < 10; i++) {
|
||||||
|
var hotp = HmacOtp.Generate (secretBytes, i, 6, false, -1);
|
||||||
|
Assert.That (hotp, Is.EqualTo (expectedHOTP[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
34
ModernKeePassLib.Test/Keys/CompositeKeyTests.cs
Normal file
34
ModernKeePassLib.Test/Keys/CompositeKeyTests.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Keys;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Keys;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Keys
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class CompositeKeyTests
|
||||||
|
{
|
||||||
|
[Test ()]
|
||||||
|
public void TestGenerateKey32 ()
|
||||||
|
{
|
||||||
|
var originalKey = new byte[32];
|
||||||
|
var expectedKey = new byte[32] {
|
||||||
|
0xF0, 0xED, 0x57, 0xD5, 0xF0, 0xDA, 0xF3, 0x47,
|
||||||
|
0x90, 0xD0, 0xDB, 0x43, 0x25, 0xC6, 0x81, 0x2C,
|
||||||
|
0x81, 0x6A, 0x0D, 0x94, 0x96, 0xA9, 0x03, 0xE1,
|
||||||
|
0x20, 0xD4, 0x3A, 0x3E, 0x45, 0xAD, 0x02, 0x65
|
||||||
|
};
|
||||||
|
const ulong rounds = 1;
|
||||||
|
|
||||||
|
var composite = new CompositeKey ();
|
||||||
|
var key = composite.GenerateKey32 (originalKey, rounds);
|
||||||
|
Assert.That (key, Is.Not.Null);
|
||||||
|
var keyData = key.ReadData ();
|
||||||
|
Assert.That (keyData, Is.EqualTo (expectedKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs
Normal file
39
ModernKeePassLib.Test/Keys/KcpCustomKeyTests.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Keys;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Keys;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Keys
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class KcpCustomKeyTests
|
||||||
|
{
|
||||||
|
static readonly byte[] testData = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestConstruct ()
|
||||||
|
{
|
||||||
|
var expectedHash = new byte[32] {
|
||||||
|
0xAF, 0x55, 0x70, 0xF5, 0xA1, 0x81, 0x0B, 0x7A,
|
||||||
|
0xF7, 0x8C, 0xAF, 0x4B, 0xC7, 0x0A, 0x66, 0x0F,
|
||||||
|
0x0D, 0xF5, 0x1E, 0x42, 0xBA, 0xF9, 0x1D, 0x4D,
|
||||||
|
0xE5, 0xB2, 0x32, 0x8D, 0xE0, 0xE8, 0x3D, 0xFC
|
||||||
|
};
|
||||||
|
|
||||||
|
var key = new KcpCustomKey ("test1", testData, false);
|
||||||
|
var keyData = key.KeyData.ReadData ();
|
||||||
|
Assert.That (keyData, Is.EqualTo (testData));
|
||||||
|
|
||||||
|
key = new KcpCustomKey ("test2", testData, true);
|
||||||
|
keyData = key.KeyData.ReadData ();
|
||||||
|
Assert.That (keyData, Is.EqualTo (expectedHash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
76
ModernKeePassLib.Test/Keys/KcpKeyFileTests.cs
Normal file
76
ModernKeePassLib.Test/Keys/KcpKeyFileTests.cs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Keys;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Keys;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Keys
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class KcpKeyFileTests
|
||||||
|
{
|
||||||
|
const string testCreateFile = "TestCreate.xml";
|
||||||
|
const string testKey = "0123456789";
|
||||||
|
|
||||||
|
const string expectedFileStart =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
|
||||||
|
"<KeyFile>\r\n" +
|
||||||
|
"\t<Meta>\r\n" +
|
||||||
|
"\t\t<Version>1.00</Version>\r\n" +
|
||||||
|
"\t</Meta>\r\n" +
|
||||||
|
"\t<Key>\r\n" +
|
||||||
|
"\t\t<Data>";
|
||||||
|
|
||||||
|
const string expectedFileEnd = "\t</Key>\r\n" +
|
||||||
|
"</KeyFile>\r\n";
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestConstruct ()
|
||||||
|
{
|
||||||
|
var expectedKeyData = new byte[32] {
|
||||||
|
0xC1, 0xB1, 0x12, 0x77, 0x23, 0xB8, 0x99, 0xB8,
|
||||||
|
0xB9, 0x3B, 0x1B, 0xFF, 0x6C, 0xBE, 0xA1, 0x5B,
|
||||||
|
0x8B, 0x99, 0xAC, 0xBD, 0x99, 0x51, 0x85, 0x95,
|
||||||
|
0x31, 0xAA, 0x14, 0x3D, 0x95, 0xBF, 0x63, 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
var fullPath = Path.Combine(Path.GetTempPath(), testCreateFile);
|
||||||
|
using (var fs = new FileStream(fullPath, FileMode.Create)) {
|
||||||
|
using (var sw = new StreamWriter(fs)) {
|
||||||
|
sw.Write (expectedFileStart);
|
||||||
|
sw.Write (testKey);
|
||||||
|
sw.Write (expectedFileEnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var keyFile = new KcpKeyFile (fullPath);
|
||||||
|
var keyData = keyFile.KeyData.ReadData ();
|
||||||
|
Assert.That (keyData, Is.EqualTo (expectedKeyData));
|
||||||
|
} finally {
|
||||||
|
File.Delete (fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestCreate ()
|
||||||
|
{
|
||||||
|
var fullPath = Path.Combine(Path.GetTempPath(), testCreateFile);
|
||||||
|
File.Create(fullPath).Close();
|
||||||
|
KcpKeyFile.Create (fullPath, null);
|
||||||
|
try {
|
||||||
|
var fileContents = File.ReadAllText (fullPath);
|
||||||
|
Assert.That (fileContents.Length, Is.EqualTo (187));
|
||||||
|
Assert.That (fileContents, Does.StartWith (expectedFileStart));
|
||||||
|
Assert.That (fileContents, Does.EndWith (expectedFileEnd));
|
||||||
|
} finally {
|
||||||
|
File.Delete (fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
33
ModernKeePassLib.Test/Keys/KcpPasswordTests.cs
Normal file
33
ModernKeePassLib.Test/Keys/KcpPasswordTests.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Keys;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Keys;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Keys
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class KcpPasswordTests
|
||||||
|
{
|
||||||
|
const string testPassword = "password";
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestConstruct ()
|
||||||
|
{
|
||||||
|
var expectedHash = new byte[32] {
|
||||||
|
0x5E, 0x88, 0x48, 0x98, 0xDA, 0x28, 0x04, 0x71,
|
||||||
|
0x51, 0xD0, 0xE5, 0x6F, 0x8D, 0xC6, 0x29, 0x27,
|
||||||
|
0x73, 0x60, 0x3D, 0x0D, 0x6A, 0xAB, 0xBD, 0xD6,
|
||||||
|
0x2A, 0x11, 0xEF, 0x72, 0x1D, 0x15, 0x42, 0xD8
|
||||||
|
};
|
||||||
|
|
||||||
|
var key = new KcpPassword (testPassword);
|
||||||
|
var keyData = key.KeyData.ReadData ();
|
||||||
|
Assert.That (keyData, Is.EqualTo (expectedHash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
97
ModernKeePassLib.Test/ModernKeePassLib.Test.csproj
Normal file
97
ModernKeePassLib.Test/ModernKeePassLib.Test.csproj
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{067456C0-086C-46A8-B37F-1405717B7BFC}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>ModernKeePassLib.Test</RootNamespace>
|
||||||
|
<AssemblyName>ModernKeePassLib.Test</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<NuGetPackageImportStamp>
|
||||||
|
</NuGetPackageImportStamp>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="crypto, Version=1.8.1.0, Culture=neutral, PublicKeyToken=0e99375e54769942, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\packages\Portable.BouncyCastle.1.8.1.1\lib\portable-net4+sl5+wp8+win8+wpa81\crypto.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="nunit.framework, Version=3.8.1.0, Culture=neutral, PublicKeyToken=2638cd05610744eb, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Splat, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Splat.2.0.0\lib\Net45\Splat.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.ComponentModel.Composition" />
|
||||||
|
<Reference Include="System.IO.Compression" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Numerics" />
|
||||||
|
<Reference Include="Windows">
|
||||||
|
<HintPath>..\ModernKeePassLib\Libs\Windows.winmd</HintPath>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Cryptography\Cipher\StandardAesEngineTests.cs" />
|
||||||
|
<Compile Include="Cryptography\CryptoRandomStreamTests.cs" />
|
||||||
|
<Compile Include="Cryptography\CryptoRandomTests.cs" />
|
||||||
|
<Compile Include="Cryptography\HashingStreamExTests.cs" />
|
||||||
|
<Compile Include="Cryptography\HmacOtpTests.cs" />
|
||||||
|
<Compile Include="Keys\CompositeKeyTests.cs" />
|
||||||
|
<Compile Include="Keys\KcpCustomKeyTests.cs" />
|
||||||
|
<Compile Include="Keys\KcpKeyFileTests.cs" />
|
||||||
|
<Compile Include="Keys\KcpPasswordTests.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Serialization\HashedBlockStreamTests.cs" />
|
||||||
|
<Compile Include="Serialization\KdbxFileTests.cs" />
|
||||||
|
<Compile Include="Utility\GfxUtilTests.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="app.config" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\ModernKeePassLib\ModernKeePassLib.csproj">
|
||||||
|
<Project>{2e710089-9559-4967-846c-e763dd1f3acb}</Project>
|
||||||
|
<Name>ModernKeePassLib</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" />
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
|
||||||
|
</Target>
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
36
ModernKeePassLib.Test/Properties/AssemblyInfo.cs
Normal file
36
ModernKeePassLib.Test/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("ModernKeePassLib.Test")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("ModernKeePassLib.Test")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("067456c0-086c-46a8-b37f-1405717b7bfc")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// 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.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
@@ -0,0 +1,71 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Serialization;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib.Serialization;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Serialization
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class HashedBlockStreamTests
|
||||||
|
{
|
||||||
|
static readonly byte[] data = new byte[16];
|
||||||
|
|
||||||
|
static readonly byte[] hashStreamData = new byte[] {
|
||||||
|
// The first 4 bytes are an integer indicating the block index
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Then the SHA-256 hash of the data
|
||||||
|
0x37, 0x47, 0x08, 0xFF, 0xF7, 0x71, 0x9D, 0xD5,
|
||||||
|
0x97, 0x9E, 0xC8, 0x75, 0xD5, 0x6C, 0xD2, 0x28,
|
||||||
|
0x6F, 0x6D, 0x3C, 0xF7, 0xEC, 0x31, 0x7A, 0x3B,
|
||||||
|
0x25, 0x63, 0x2A, 0xAB, 0x28, 0xEC, 0x37, 0xBB,
|
||||||
|
// then an integer that is the length of the data
|
||||||
|
0x10, 0x00, 0x00, 0x00,
|
||||||
|
// and finally the data itself
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// Next, a terminating block
|
||||||
|
0x01, 0x00, 0x00, 0x00,
|
||||||
|
// terminating block is indicated by a hash of all 0s...
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
// ...and by a size of 0
|
||||||
|
0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestRead ()
|
||||||
|
{
|
||||||
|
using (var ms = new MemoryStream (hashStreamData)) {
|
||||||
|
using (var hbs = new HashedBlockStream (ms, false)) {
|
||||||
|
using (var br = new BinaryReader(hbs)) {
|
||||||
|
var bytes = br.ReadBytes (data.Length);
|
||||||
|
Assert.That (bytes, Is.EqualTo (data));
|
||||||
|
Assert.That (() => br.ReadByte (), Throws.InstanceOf<EndOfStreamException> ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestWrite ()
|
||||||
|
{
|
||||||
|
var buffer = new byte[hashStreamData.Length];
|
||||||
|
using (var ms = new MemoryStream (buffer)) {
|
||||||
|
using (var hbs = new HashedBlockStream (ms, true)) {
|
||||||
|
using (var bw = new BinaryWriter(hbs)) {
|
||||||
|
bw.Write (data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.That (buffer, Is.EqualTo (hashStreamData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
182
ModernKeePassLib.Test/Serialization/KdbxFileTests.cs
Normal file
182
ModernKeePassLib.Test/Serialization/KdbxFileTests.cs
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Windows.UI;
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib;
|
||||||
|
using KeePassLib.Keys;
|
||||||
|
using KeePassLib.Security;
|
||||||
|
using KeePassLib.Serialization;
|
||||||
|
using KeePassLib.Collections;
|
||||||
|
#else
|
||||||
|
using ModernKeePassLib;
|
||||||
|
using ModernKeePassLib.Keys;
|
||||||
|
using ModernKeePassLib.Security;
|
||||||
|
using ModernKeePassLib.Serialization;
|
||||||
|
using ModernKeePassLib.Collections;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Serialization
|
||||||
|
{
|
||||||
|
[TestFixture()]
|
||||||
|
public class KdbxFileTests
|
||||||
|
{
|
||||||
|
const string testLocalizedAppName = "My Localized App Name";
|
||||||
|
|
||||||
|
const string testDatabaseName = "My Database Name";
|
||||||
|
const string testDatabaseDescription = "My Database Description";
|
||||||
|
const string testDefaultUserName = "My Default User Name";
|
||||||
|
const string testColor = "#FF0000"; // Red
|
||||||
|
|
||||||
|
const string testRootGroupName = "My Root Group Name";
|
||||||
|
const string testRootGroupNotes = "My Root Group Notes";
|
||||||
|
const string testRootGroupDefaultAutoTypeSequence = "My Root Group Default Auto Type Sequence";
|
||||||
|
|
||||||
|
const string testDatabase = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\r\n" +
|
||||||
|
"<KeePassFile>\r\n" +
|
||||||
|
"\t<Meta>\r\n" +
|
||||||
|
"\t\t<Generator>" + testLocalizedAppName + "</Generator>\r\n" +
|
||||||
|
"\t\t<DatabaseName>" + testDatabaseName + "</DatabaseName>\r\n" +
|
||||||
|
"\t\t<DatabaseNameChanged>2015-03-14T03:15:26Z</DatabaseNameChanged>\r\n" +
|
||||||
|
"\t\t<DatabaseDescription>" + testDatabaseDescription + "</DatabaseDescription>\r\n" +
|
||||||
|
"\t\t<DatabaseDescriptionChanged>2015-03-14T03:15:26Z</DatabaseDescriptionChanged>\r\n" +
|
||||||
|
"\t\t<DefaultUserName>" + testDefaultUserName + "</DefaultUserName>\r\n" +
|
||||||
|
"\t\t<DefaultUserNameChanged>2015-03-14T03:15:26Z</DefaultUserNameChanged>\r\n" +
|
||||||
|
"\t\t<MaintenanceHistoryDays>365</MaintenanceHistoryDays>\r\n" +
|
||||||
|
//"\t\t<Color>" + testColor + "</Color>\r\n" +
|
||||||
|
"\t\t<Color></Color>\r\n" +
|
||||||
|
"\t\t<MasterKeyChanged>2015-03-14T03:15:26Z</MasterKeyChanged>\r\n" +
|
||||||
|
"\t\t<MasterKeyChangeRec>-1</MasterKeyChangeRec>\r\n" +
|
||||||
|
"\t\t<MasterKeyChangeForce>-1</MasterKeyChangeForce>\r\n" +
|
||||||
|
"\t\t<MemoryProtection>\r\n" +
|
||||||
|
"\t\t\t<ProtectTitle>False</ProtectTitle>\r\n" +
|
||||||
|
"\t\t\t<ProtectUserName>False</ProtectUserName>\r\n" +
|
||||||
|
"\t\t\t<ProtectPassword>True</ProtectPassword>\r\n" +
|
||||||
|
"\t\t\t<ProtectURL>False</ProtectURL>\r\n" +
|
||||||
|
"\t\t\t<ProtectNotes>False</ProtectNotes>\r\n" +
|
||||||
|
"\t\t</MemoryProtection>\r\n" +
|
||||||
|
"\t\t<RecycleBinEnabled>True</RecycleBinEnabled>\r\n" +
|
||||||
|
"\t\t<RecycleBinUUID>AAAAAAAAAAAAAAAAAAAAAA==</RecycleBinUUID>\r\n" +
|
||||||
|
"\t\t<RecycleBinChanged>2015-03-14T03:15:26Z</RecycleBinChanged>\r\n" +
|
||||||
|
"\t\t<EntryTemplatesGroup>AAAAAAAAAAAAAAAAAAAAAA==</EntryTemplatesGroup>\r\n" +
|
||||||
|
"\t\t<EntryTemplatesGroupChanged>2015-03-14T03:15:26Z</EntryTemplatesGroupChanged>\r\n" +
|
||||||
|
"\t\t<HistoryMaxItems>10</HistoryMaxItems>\r\n" +
|
||||||
|
"\t\t<HistoryMaxSize>6291456</HistoryMaxSize>\r\n" +
|
||||||
|
"\t\t<LastSelectedGroup>AAAAAAAAAAAAAAAAAAAAAA==</LastSelectedGroup>\r\n" +
|
||||||
|
"\t\t<LastTopVisibleGroup>AAAAAAAAAAAAAAAAAAAAAA==</LastTopVisibleGroup>\r\n" +
|
||||||
|
"\t\t<Binaries />\r\n" +
|
||||||
|
"\t\t<CustomData />\r\n" +
|
||||||
|
"\t</Meta>\r\n" +
|
||||||
|
"\t<Root>\r\n" +
|
||||||
|
"\t\t<Group>\r\n" +
|
||||||
|
"\t\t\t<UUID>AAAAAAAAAAAAAAAAAAAAAA==</UUID>\r\n" +
|
||||||
|
"\t\t\t<Name>" + testRootGroupName + "</Name>\r\n" +
|
||||||
|
"\t\t\t<Notes>" + testRootGroupNotes + "</Notes>\r\n" +
|
||||||
|
"\t\t\t<IconID>49</IconID>\r\n" +
|
||||||
|
"\t\t\t<Times>\r\n" +
|
||||||
|
"\t\t\t\t<CreationTime>2015-03-14T03:15:26Z</CreationTime>\r\n" +
|
||||||
|
"\t\t\t\t<LastModificationTime>2015-03-14T03:15:26Z</LastModificationTime>\r\n" +
|
||||||
|
"\t\t\t\t<LastAccessTime>2015-03-14T03:15:26Z</LastAccessTime>\r\n" +
|
||||||
|
"\t\t\t\t<ExpiryTime>2015-03-14T03:15:26Z</ExpiryTime>\r\n" +
|
||||||
|
"\t\t\t\t<Expires>False</Expires>\r\n" +
|
||||||
|
"\t\t\t\t<UsageCount>0</UsageCount>\r\n" +
|
||||||
|
"\t\t\t\t<LocationChanged>2015-03-14T03:15:26Z</LocationChanged>\r\n" +
|
||||||
|
"\t\t\t</Times>\r\n" +
|
||||||
|
"\t\t\t<IsExpanded>True</IsExpanded>\r\n" +
|
||||||
|
"\t\t\t<DefaultAutoTypeSequence>" + testRootGroupDefaultAutoTypeSequence + "</DefaultAutoTypeSequence>\r\n" +
|
||||||
|
"\t\t\t<EnableAutoType>null</EnableAutoType>\r\n" +
|
||||||
|
"\t\t\t<EnableSearching>null</EnableSearching>\r\n" +
|
||||||
|
"\t\t\t<LastTopVisibleEntry>AAAAAAAAAAAAAAAAAAAAAA==</LastTopVisibleEntry>\r\n" +
|
||||||
|
"\t\t</Group>\r\n" +
|
||||||
|
"\t\t<DeletedObjects />\r\n" +
|
||||||
|
"\t</Root>\r\n" +
|
||||||
|
"</KeePassFile>";
|
||||||
|
|
||||||
|
const string testDate = "2015-03-14T03:15:26Z";
|
||||||
|
|
||||||
|
[Test()]
|
||||||
|
public void TestLoad()
|
||||||
|
{
|
||||||
|
var database = new PwDatabase();
|
||||||
|
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(testDatabase)))
|
||||||
|
{
|
||||||
|
var file = new KdbxFile(database);
|
||||||
|
file.Load(ms, KdbxFormat.PlainXml, null);
|
||||||
|
}
|
||||||
|
//Assert.That(database.Color.ToArgb(), Is.EqualTo(Color.Red.ToArgb()));
|
||||||
|
Assert.That(database.Compression, Is.EqualTo(PwCompressionAlgorithm.GZip));
|
||||||
|
//Assert.That (database.CustomData, Is.EqualTo ());
|
||||||
|
Assert.That(database.CustomIcons, Is.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test()]
|
||||||
|
public void TestSave()
|
||||||
|
{
|
||||||
|
var buffer = new byte[4096];
|
||||||
|
using (var ms = new MemoryStream(buffer))
|
||||||
|
{
|
||||||
|
var database = new PwDatabase();
|
||||||
|
database.New(new IOConnectionInfo(), new CompositeKey());
|
||||||
|
var date = DateTime.Parse(testDate);
|
||||||
|
PwDatabase.LocalizedAppName = testLocalizedAppName;
|
||||||
|
database.Name = testDatabaseName;
|
||||||
|
database.NameChanged = date;
|
||||||
|
database.Description = testDatabaseDescription;
|
||||||
|
database.DescriptionChanged = date;
|
||||||
|
database.DefaultUserName = testDefaultUserName;
|
||||||
|
database.DefaultUserNameChanged = date;
|
||||||
|
//database.Color = Color.Red;
|
||||||
|
database.MasterKeyChanged = date;
|
||||||
|
database.RecycleBinChanged = date;
|
||||||
|
database.EntryTemplatesGroupChanged = date;
|
||||||
|
database.RootGroup.Uuid = PwUuid.Zero;
|
||||||
|
database.RootGroup.Name = testRootGroupName;
|
||||||
|
database.RootGroup.Notes = testRootGroupNotes;
|
||||||
|
database.RootGroup.DefaultAutoTypeSequence = testRootGroupDefaultAutoTypeSequence;
|
||||||
|
database.RootGroup.CreationTime = date;
|
||||||
|
database.RootGroup.LastModificationTime = date;
|
||||||
|
database.RootGroup.LastAccessTime = date;
|
||||||
|
database.RootGroup.ExpiryTime = date;
|
||||||
|
database.RootGroup.LocationChanged = date;
|
||||||
|
var file = new KdbxFile(database);
|
||||||
|
file.Save(ms, null, KdbxFormat.PlainXml, null);
|
||||||
|
}
|
||||||
|
var fileContents = Encoding.UTF8.GetString(buffer).Replace("\0", "");
|
||||||
|
if (typeof(KdbxFile).Namespace.StartsWith("KeePassLib.")
|
||||||
|
&& Environment.OSVersion.Platform != PlatformID.Win32NT)
|
||||||
|
{
|
||||||
|
// Upstream KeePassLib does not specify line endings for XmlTextWriter,
|
||||||
|
// so it uses native line endings.
|
||||||
|
fileContents = fileContents.Replace("\n", "\r\n");
|
||||||
|
}
|
||||||
|
Assert.That(fileContents, Is.EqualTo(testDatabase));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSearch()
|
||||||
|
{
|
||||||
|
var database = new PwDatabase();
|
||||||
|
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(testDatabase)))
|
||||||
|
{
|
||||||
|
var file = new KdbxFile(database);
|
||||||
|
file.Load(ms, KdbxFormat.PlainXml, null);
|
||||||
|
}
|
||||||
|
var sp = new SearchParameters()
|
||||||
|
{
|
||||||
|
SearchString = "sfsoiwsefsi"
|
||||||
|
};
|
||||||
|
var listStorage = new PwObjectList<PwEntry>();
|
||||||
|
database.RootGroup.SearchEntries(sp, listStorage);
|
||||||
|
Assert.AreEqual(0U, listStorage.UCount);
|
||||||
|
var entry = new PwEntry(true, true);
|
||||||
|
entry.Strings.Set("Title", new ProtectedString(false, "NaMe"));
|
||||||
|
database.RootGroup.AddEntry(entry, true);
|
||||||
|
sp.SearchString = "name";
|
||||||
|
database.RootGroup.SearchEntries(sp, listStorage);
|
||||||
|
Assert.AreEqual(1U, listStorage.UCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
ModernKeePassLib.Test/Utility/GfxUtilTests.cs
Normal file
32
ModernKeePassLib.Test/Utility/GfxUtilTests.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
#if KeePassLib
|
||||||
|
using KeePassLib.Utility;
|
||||||
|
#else
|
||||||
|
using Splat;
|
||||||
|
using ModernKeePassLib.Utility;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ModernKeePassLib.Test.Shared.Utility
|
||||||
|
{
|
||||||
|
[TestFixture ()]
|
||||||
|
public class GfxUtilTests
|
||||||
|
{
|
||||||
|
// 16x16 all white PNG file, base64 encoded
|
||||||
|
const string testImageData =
|
||||||
|
"iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAA" +
|
||||||
|
"LEwEAmpwYAAAAB3RJTUUH3wMOFgIgmTCUMQAAABl0RVh0Q29tbWVudABDcmVhdG" +
|
||||||
|
"VkIHdpdGggR0lNUFeBDhcAAAAaSURBVCjPY/z//z8DKYCJgUQwqmFUw9DRAABVb" +
|
||||||
|
"QMdny4VogAAAABJRU5ErkJggg==";
|
||||||
|
|
||||||
|
[Test ()]
|
||||||
|
public void TestLoadImage ()
|
||||||
|
{
|
||||||
|
var testData = Convert.FromBase64String (testImageData);
|
||||||
|
var image = GfxUtil.LoadImage (testData);
|
||||||
|
Assert.That (image.Width, Is.EqualTo (16));
|
||||||
|
Assert.That (image.Height, Is.EqualTo (16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
ModernKeePassLib.Test/app.config
Normal file
23
ModernKeePassLib.Test/app.config
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<runtime>
|
||||||
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="PInvoke.BCrypt" publicKeyToken="9e300f9f87f04a7a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-0.5.0.0" newVersion="0.5.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="PInvoke.NCrypt" publicKeyToken="9e300f9f87f04a7a" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-0.5.0.0" newVersion="0.5.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="Validation" publicKeyToken="2fc06f0d701809a7" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-2.4.0.0" newVersion="2.4.0.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
<dependentAssembly>
|
||||||
|
<assemblyIdentity name="System.Runtime.WindowsRuntime" publicKeyToken="b77a5c561934e089" culture="neutral" />
|
||||||
|
<bindingRedirect oldVersion="0.0.0.0-4.0.10.0" newVersion="4.0.10.0" />
|
||||||
|
</dependentAssembly>
|
||||||
|
</assemblyBinding>
|
||||||
|
</runtime>
|
||||||
|
</configuration>
|
6
ModernKeePassLib.Test/packages.config
Normal file
6
ModernKeePassLib.Test/packages.config
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="net462" />
|
||||||
|
<package id="NUnit" version="3.8.1" targetFramework="net452" />
|
||||||
|
<package id="Splat" version="2.0.0" targetFramework="net462" />
|
||||||
|
</packages>
|
36
ModernKeePassLib/.gitignore
vendored
36
ModernKeePassLib/.gitignore
vendored
@@ -1,36 +0,0 @@
|
|||||||
################################################################################
|
|
||||||
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
#ignore thumbnails created by windows
|
|
||||||
Thumbs.db
|
|
||||||
#Ignore files build by Visual Studio
|
|
||||||
*.obj
|
|
||||||
*.exe
|
|
||||||
*.pdb
|
|
||||||
*.user
|
|
||||||
*.aps
|
|
||||||
*.pch
|
|
||||||
*.vspscc
|
|
||||||
*_i.c
|
|
||||||
*_p.c
|
|
||||||
*.ncb
|
|
||||||
*.suo
|
|
||||||
*.tlb
|
|
||||||
*.tlh
|
|
||||||
*.bak
|
|
||||||
*.cache
|
|
||||||
*.ilk
|
|
||||||
*.log
|
|
||||||
[Bb]in
|
|
||||||
[Dd]ebug*/
|
|
||||||
*.lib
|
|
||||||
*.sbr
|
|
||||||
obj/
|
|
||||||
[Rr]elease*/
|
|
||||||
_ReSharper*/
|
|
||||||
[Tt]est[Rr]esult*
|
|
||||||
Translation/TrlUtil.vshost.exe.manifest
|
|
||||||
*.nupkg
|
|
||||||
.vs/
|
|
||||||
/UpgradeLog.htm
|
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -194,13 +194,6 @@ namespace ModernKeePassLib.Collections
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(AutoTypeAssociation a)
|
|
||||||
{
|
|
||||||
Debug.Assert(a != null); if(a == null) throw new ArgumentNullException("a");
|
|
||||||
|
|
||||||
m_lWindowAssocs.Add(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AutoTypeAssociation GetAt(int iIndex)
|
public AutoTypeAssociation GetAt(int iIndex)
|
||||||
{
|
{
|
||||||
if((iIndex < 0) || (iIndex >= m_lWindowAssocs.Count))
|
if((iIndex < 0) || (iIndex >= m_lWindowAssocs.Count))
|
||||||
@@ -209,6 +202,22 @@ namespace ModernKeePassLib.Collections
|
|||||||
return m_lWindowAssocs[iIndex];
|
return m_lWindowAssocs[iIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Add(AutoTypeAssociation a)
|
||||||
|
{
|
||||||
|
if(a == null) { Debug.Assert(false); throw new ArgumentNullException("a"); }
|
||||||
|
|
||||||
|
m_lWindowAssocs.Add(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Insert(int iIndex, AutoTypeAssociation a)
|
||||||
|
{
|
||||||
|
if((iIndex < 0) || (iIndex > m_lWindowAssocs.Count))
|
||||||
|
throw new ArgumentOutOfRangeException("iIndex");
|
||||||
|
if(a == null) { Debug.Assert(false); throw new ArgumentNullException("a"); }
|
||||||
|
|
||||||
|
m_lWindowAssocs.Insert(iIndex, a);
|
||||||
|
}
|
||||||
|
|
||||||
public void RemoveAt(int iIndex)
|
public void RemoveAt(int iIndex)
|
||||||
{
|
{
|
||||||
if((iIndex < 0) || (iIndex >= m_lWindowAssocs.Count))
|
if((iIndex < 0) || (iIndex >= m_lWindowAssocs.Count))
|
||||||
@@ -216,5 +225,20 @@ namespace ModernKeePassLib.Collections
|
|||||||
|
|
||||||
m_lWindowAssocs.RemoveAt(iIndex);
|
m_lWindowAssocs.RemoveAt(iIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public void Sort()
|
||||||
|
// {
|
||||||
|
// m_lWindowAssocs.Sort(AutoTypeConfig.AssocCompareFn);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private static int AssocCompareFn(AutoTypeAssociation x,
|
||||||
|
// AutoTypeAssociation y)
|
||||||
|
// {
|
||||||
|
// if(x == null) { Debug.Assert(false); return ((y == null) ? 0 : -1); }
|
||||||
|
// if(y == null) { Debug.Assert(false); return 1; }
|
||||||
|
// int cn = x.WindowName.CompareTo(y.WindowName);
|
||||||
|
// if(cn != 0) return cn;
|
||||||
|
// return x.Sequence.CompareTo(y.Sequence);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,7 +28,7 @@ using ModernKeePassLib.Security;
|
|||||||
using ModernKeePassLib.Utility;
|
using ModernKeePassLib.Utility;
|
||||||
|
|
||||||
#if KeePassLibSD
|
#if KeePassLibSD
|
||||||
using ModernKeePassLibSD;
|
using KeePassLibSD;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ModernKeePassLib.Collections
|
namespace ModernKeePassLib.Collections
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,7 +28,7 @@ using ModernKeePassLib.Security;
|
|||||||
using ModernKeePassLib.Utility;
|
using ModernKeePassLib.Utility;
|
||||||
|
|
||||||
#if KeePassLibSD
|
#if KeePassLibSD
|
||||||
using ModernKeePassLibSD;
|
using KeePassLibSD;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ModernKeePassLib.Collections
|
namespace ModernKeePassLib.Collections
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -133,6 +133,14 @@ namespace ModernKeePassLib.Collections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Insert(uint uIndex, T pwObject)
|
||||||
|
{
|
||||||
|
Debug.Assert(pwObject != null);
|
||||||
|
if(pwObject == null) throw new ArgumentNullException("pwObject");
|
||||||
|
|
||||||
|
m_vObjects.Insert((int)uIndex, pwObject);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get an object of the list.
|
/// Get an object of the list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -225,7 +233,7 @@ namespace ModernKeePassLib.Collections
|
|||||||
if(nCount <= 1) return;
|
if(nCount <= 1) return;
|
||||||
|
|
||||||
int nIndex = m_vObjects.IndexOf(tObject);
|
int nIndex = m_vObjects.IndexOf(tObject);
|
||||||
Debug.Assert(nIndex >= 0);
|
if(nIndex < 0) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
if(bUp && (nIndex > 0)) // No assert for top item
|
if(bUp && (nIndex > 0)) // No assert for top item
|
||||||
{
|
{
|
||||||
@@ -241,6 +249,68 @@ namespace ModernKeePassLib.Collections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void MoveOne(T[] vObjects, bool bUp)
|
||||||
|
{
|
||||||
|
Debug.Assert(vObjects != null);
|
||||||
|
if(vObjects == null) throw new ArgumentNullException("vObjects");
|
||||||
|
|
||||||
|
List<int> lIndices = new List<int>();
|
||||||
|
foreach(T t in vObjects)
|
||||||
|
{
|
||||||
|
if(t == null) { Debug.Assert(false); continue; }
|
||||||
|
|
||||||
|
int p = IndexOf(t);
|
||||||
|
if(p >= 0) lIndices.Add(p);
|
||||||
|
else { Debug.Assert(false); }
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveOne(lIndices.ToArray(), bUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MoveOne(int[] vIndices, bool bUp)
|
||||||
|
{
|
||||||
|
Debug.Assert(vIndices != null);
|
||||||
|
if(vIndices == null) throw new ArgumentNullException("vIndices");
|
||||||
|
|
||||||
|
int n = m_vObjects.Count;
|
||||||
|
if(n <= 1) return; // No moving possible
|
||||||
|
|
||||||
|
int m = vIndices.Length;
|
||||||
|
if(m == 0) return; // Nothing to move
|
||||||
|
|
||||||
|
int[] v = new int[m];
|
||||||
|
Array.Copy(vIndices, v, m);
|
||||||
|
Array.Sort<int>(v);
|
||||||
|
|
||||||
|
if((bUp && (v[0] <= 0)) || (!bUp && (v[m - 1] >= (n - 1))))
|
||||||
|
return; // Moving as a block is not possible
|
||||||
|
|
||||||
|
int iStart = (bUp ? 0 : (m - 1));
|
||||||
|
int iExcl = (bUp ? m : -1);
|
||||||
|
int iStep = (bUp ? 1 : -1);
|
||||||
|
|
||||||
|
for(int i = iStart; i != iExcl; i += iStep)
|
||||||
|
{
|
||||||
|
int p = v[i];
|
||||||
|
if((p < 0) || (p >= n)) { Debug.Assert(false); continue; }
|
||||||
|
|
||||||
|
T t = m_vObjects[p];
|
||||||
|
|
||||||
|
if(bUp)
|
||||||
|
{
|
||||||
|
Debug.Assert(p > 0);
|
||||||
|
m_vObjects.RemoveAt(p);
|
||||||
|
m_vObjects.Insert(p - 1, t);
|
||||||
|
}
|
||||||
|
else // Down
|
||||||
|
{
|
||||||
|
Debug.Assert(p < (n - 1));
|
||||||
|
m_vObjects.RemoveAt(p);
|
||||||
|
m_vObjects.Insert(p + 1, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Move some of the objects in this list to the top/bottom.
|
/// Move some of the objects in this list to the top/bottom.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,15 +26,15 @@ using ModernKeePassLib.Delegates;
|
|||||||
using ModernKeePassLib.Interfaces;
|
using ModernKeePassLib.Interfaces;
|
||||||
|
|
||||||
#if KeePassLibSD
|
#if KeePassLibSD
|
||||||
using ModernKeePassLibSD;
|
using KeePassLibSD;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ModernKeePassLib.Collections
|
namespace ModernKeePassLib.Collections
|
||||||
{
|
{
|
||||||
public sealed class PwObjectPool
|
public sealed class PwObjectPool
|
||||||
{
|
{
|
||||||
private SortedDictionary<PwUuidComparable, IStructureItem> m_dict =
|
private SortedDictionary<PwUuid, IStructureItem> m_dict =
|
||||||
new SortedDictionary<PwUuidComparable, IStructureItem>();
|
new SortedDictionary<PwUuid, IStructureItem>();
|
||||||
|
|
||||||
public static PwObjectPool FromGroupRecursive(PwGroup pgRoot, bool bEntries)
|
public static PwObjectPool FromGroupRecursive(PwGroup pgRoot, bool bEntries)
|
||||||
{
|
{
|
||||||
@@ -42,16 +42,16 @@ namespace ModernKeePassLib.Collections
|
|||||||
|
|
||||||
PwObjectPool p = new PwObjectPool();
|
PwObjectPool p = new PwObjectPool();
|
||||||
|
|
||||||
if(!bEntries) p.m_dict[new PwUuidComparable(pgRoot.Uuid)] = pgRoot;
|
if(!bEntries) p.m_dict[pgRoot.Uuid] = pgRoot;
|
||||||
GroupHandler gh = delegate(PwGroup pg)
|
GroupHandler gh = delegate(PwGroup pg)
|
||||||
{
|
{
|
||||||
p.m_dict[new PwUuidComparable(pg.Uuid)] = pg;
|
p.m_dict[pg.Uuid] = pg;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
EntryHandler eh = delegate(PwEntry pe)
|
EntryHandler eh = delegate(PwEntry pe)
|
||||||
{
|
{
|
||||||
p.m_dict[new PwUuidComparable(pe.Uuid)] = pe;
|
p.m_dict[pe.Uuid] = pe;
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -63,13 +63,13 @@ namespace ModernKeePassLib.Collections
|
|||||||
public IStructureItem Get(PwUuid pwUuid)
|
public IStructureItem Get(PwUuid pwUuid)
|
||||||
{
|
{
|
||||||
IStructureItem pItem;
|
IStructureItem pItem;
|
||||||
m_dict.TryGetValue(new PwUuidComparable(pwUuid), out pItem);
|
m_dict.TryGetValue(pwUuid, out pItem);
|
||||||
return pItem;
|
return pItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ContainsOnlyType(Type t)
|
public bool ContainsOnlyType(Type t)
|
||||||
{
|
{
|
||||||
foreach(KeyValuePair<PwUuidComparable, IStructureItem> kvp in m_dict)
|
foreach(KeyValuePair<PwUuid, IStructureItem> kvp in m_dict)
|
||||||
{
|
{
|
||||||
if(kvp.Value.GetType() != t) return false;
|
if(kvp.Value.GetType() != t) return false;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,7 +26,7 @@ using System.Diagnostics;
|
|||||||
using ModernKeePassLib.Interfaces;
|
using ModernKeePassLib.Interfaces;
|
||||||
|
|
||||||
#if KeePassLibSD
|
#if KeePassLibSD
|
||||||
using ModernKeePassLibSD;
|
using KeePassLibSD;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ModernKeePassLib.Collections
|
namespace ModernKeePassLib.Collections
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,13 +19,17 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Security;
|
||||||
|
|
||||||
namespace ModernKeePassLib.Cryptography.Cipher
|
namespace ModernKeePassLib.Cryptography.Cipher
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pool of encryption/decryption algorithms (ciphers).
|
/// Pool of encryption/decryption algorithms (ciphers).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class CipherPool
|
public sealed class CipherPool
|
||||||
{
|
{
|
||||||
private List<ICipherEngine> m_vCiphers = new List<ICipherEngine>();
|
private List<ICipherEngine> m_vCiphers = new List<ICipherEngine>();
|
||||||
private static CipherPool m_poolGlobal = null;
|
private static CipherPool m_poolGlobal = null;
|
||||||
@@ -65,7 +69,7 @@ namespace ModernKeePassLib.Cryptography.Cipher
|
|||||||
|
|
||||||
// Return if a cipher with that ID is registered already.
|
// Return if a cipher with that ID is registered already.
|
||||||
for(int i = 0; i < m_vCiphers.Count; ++i)
|
for(int i = 0; i < m_vCiphers.Count; ++i)
|
||||||
if(m_vCiphers[i].CipherUuid.EqualsValue(csEngine.CipherUuid))
|
if(m_vCiphers[i].CipherUuid.Equals(csEngine.CipherUuid))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_vCiphers.Add(csEngine);
|
m_vCiphers.Add(csEngine);
|
||||||
@@ -81,7 +85,7 @@ namespace ModernKeePassLib.Cryptography.Cipher
|
|||||||
{
|
{
|
||||||
foreach(ICipherEngine iEngine in m_vCiphers)
|
foreach(ICipherEngine iEngine in m_vCiphers)
|
||||||
{
|
{
|
||||||
if(iEngine.CipherUuid.EqualsValue(uuidCipher))
|
if(iEngine.CipherUuid.Equals(uuidCipher))
|
||||||
return iEngine;
|
return iEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +103,7 @@ namespace ModernKeePassLib.Cryptography.Cipher
|
|||||||
{
|
{
|
||||||
for(int i = 0; i < m_vCiphers.Count; ++i)
|
for(int i = 0; i < m_vCiphers.Count; ++i)
|
||||||
{
|
{
|
||||||
if(m_vCiphers[i].CipherUuid.EqualsValue(uuidCipher))
|
if(m_vCiphers[i].CipherUuid.Equals(uuidCipher))
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,7 +26,7 @@ using ModernKeePassLib.Utility;
|
|||||||
|
|
||||||
namespace ModernKeePassLib.Cryptography.Cipher
|
namespace ModernKeePassLib.Cryptography.Cipher
|
||||||
{
|
{
|
||||||
public sealed class Salsa20Cipher
|
public sealed class Salsa20Cipher : IDisposable
|
||||||
{
|
{
|
||||||
private uint[] m_state = new uint[16];
|
private uint[] m_state = new uint[16];
|
||||||
private uint[] m_x = new uint[16]; // Working buffer
|
private uint[] m_x = new uint[16]; // Working buffer
|
||||||
@@ -34,7 +34,7 @@ namespace ModernKeePassLib.Cryptography.Cipher
|
|||||||
private byte[] m_output = new byte[64];
|
private byte[] m_output = new byte[64];
|
||||||
private int m_outputPos = 64;
|
private int m_outputPos = 64;
|
||||||
|
|
||||||
private static readonly uint[] m_sigma = new uint[4]{
|
private static readonly uint[] m_sigma = new uint[4] {
|
||||||
0x61707865, 0x3320646E, 0x79622D32, 0x6B206574
|
0x61707865, 0x3320646E, 0x79622D32, 0x6B206574
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -45,6 +45,17 @@ namespace ModernKeePassLib.Cryptography.Cipher
|
|||||||
}
|
}
|
||||||
|
|
||||||
~Salsa20Cipher()
|
~Salsa20Cipher()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Dispose(bool bDisposing)
|
||||||
{
|
{
|
||||||
// Clear sensitive data
|
// Clear sensitive data
|
||||||
Array.Clear(m_state, 0, m_state.Length);
|
Array.Clear(m_state, 0, m_state.Length);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,22 +17,32 @@
|
|||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Diagnostics;
|
||||||
|
#if ModernKeePassLib
|
||||||
using ModernKeePassLib.Resources;
|
using ModernKeePassLib.Resources;
|
||||||
using ModernKeePassLib.Serialization;
|
using Org.BouncyCastle.Crypto;
|
||||||
|
using Org.BouncyCastle.Crypto.Engines;
|
||||||
|
using Org.BouncyCastle.Crypto.IO;
|
||||||
|
using Org.BouncyCastle.Crypto.Modes;
|
||||||
|
using Org.BouncyCastle.Crypto.Paddings;
|
||||||
|
using Org.BouncyCastle.Crypto.Parameters;
|
||||||
|
#else
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ModernKeePassLib.Cryptography.Cipher
|
namespace ModernKeePassLib.Cryptography.Cipher
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Standard AES cipher implementation.
|
/// Standard AES cipher implementation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class StandardAesEngine : ICipherEngine
|
public sealed class StandardAesEngine : ICipherEngine
|
||||||
{
|
{
|
||||||
// private const CipherMode m_rCipherMode = CipherMode.CBC;
|
#if !ModernKeePassLib && !KeePassRT
|
||||||
// private const PaddingMode m_rCipherPadding = PaddingMode.PKCS7;
|
private const CipherMode m_rCipherMode = CipherMode.CBC;
|
||||||
|
private const PaddingMode m_rCipherPadding = PaddingMode.PKCS7;
|
||||||
|
#endif
|
||||||
|
|
||||||
private static PwUuid m_uuidAes = null;
|
private static PwUuid m_uuidAes = null;
|
||||||
|
|
||||||
@@ -54,16 +64,13 @@ namespace ModernKeePassLib.Cryptography.Cipher
|
|||||||
return m_uuidAes;
|
return m_uuidAes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the UUID of this cipher engine as <c>PwUuid</c> object.
|
/// Get the UUID of this cipher engine as <c>PwUuid</c> object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public PwUuid CipherUuid
|
public PwUuid CipherUuid => StandardAesEngine.AesUuid;
|
||||||
{
|
|
||||||
get { return StandardAesEngine.AesUuid; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a displayable name describing this cipher engine.
|
/// Get a displayable name describing this cipher engine.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string DisplayName { get { return KLRes.EncAlgorithmAes; } }
|
public string DisplayName { get { return KLRes.EncAlgorithmAes; } }
|
||||||
@@ -94,30 +101,68 @@ namespace ModernKeePassLib.Cryptography.Cipher
|
|||||||
|
|
||||||
private static Stream CreateStream(Stream s, bool bEncrypt, byte[] pbKey, byte[] pbIV)
|
private static Stream CreateStream(Stream s, bool bEncrypt, byte[] pbKey, byte[] pbIV)
|
||||||
{
|
{
|
||||||
StandardAesEngine.ValidateArguments(s, bEncrypt, pbKey, pbIV);
|
ValidateArguments(s, bEncrypt, pbKey, pbIV);
|
||||||
|
|
||||||
return new CryptoStream( s, "AES_CBC_PKCS7", bEncrypt, pbKey, pbIV);
|
|
||||||
|
|
||||||
}
|
byte[] pbLocalIV = new byte[16];
|
||||||
#if false
|
Array.Copy(pbIV, pbLocalIV, 16);
|
||||||
|
|
||||||
RijndaelManaged r = new RijndaelManaged();
|
|
||||||
|
|
||||||
|
byte[] pbLocalKey = new byte[32];
|
||||||
|
Array.Copy(pbKey, pbLocalKey, 32);
|
||||||
|
#if !ModernKeePassLib
|
||||||
|
//#if ModernKeePassLib
|
||||||
|
/*var provider = WinRTCrypto.SymmetricKeyAlgorithmProvider.
|
||||||
|
OpenAlgorithm(SymmetricAlgorithm.AesCbcPkcs7);
|
||||||
|
var key = provider.CreateSymmetricKey(pbLocalKey);
|
||||||
|
if (bEncrypt)
|
||||||
|
{
|
||||||
|
var encryptor = WinRTCrypto.CryptographicEngine.CreateEncryptor(
|
||||||
|
key, pbLocalIV);
|
||||||
|
return new CryptoStream(s, encryptor, CryptoStreamMode.Write);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
var decryptor = WinRTCrypto.CryptographicEngine.CreateDecryptor(
|
||||||
|
key, pbLocalIV);
|
||||||
|
return new CryptoStream(s, decryptor, CryptoStreamMode.Read);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var provider = SymmetricKeyAlgorithmProvider.
|
||||||
|
OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
|
||||||
|
var key = provider.CreateSymmetricKey(CryptographicBuffer.CreateFromByteArray(pbLocalKey));
|
||||||
|
|
||||||
|
using (var ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
s.CopyTo(ms);
|
||||||
|
var data = CryptographicBuffer.CreateFromByteArray(ms.ToArray());
|
||||||
|
byte[] resultByteArray;
|
||||||
|
if (bEncrypt)
|
||||||
|
{
|
||||||
|
var encrypted = CryptographicEngine.Encrypt(key, data, CryptographicBuffer.CreateFromByteArray(pbLocalIV));
|
||||||
|
CryptographicBuffer.CopyToByteArray(encrypted, out resultByteArray);
|
||||||
|
return new MemoryStream(resultByteArray);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var decrypted = CryptographicEngine.Decrypt(key, data, CryptographicBuffer.CreateFromByteArray(pbLocalIV));
|
||||||
|
CryptographicBuffer.CopyToByteArray(decrypted, out resultByteArray);
|
||||||
|
return new MemoryStream(resultByteArray, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#else
|
||||||
|
|
||||||
|
//#if !KeePassRT
|
||||||
|
//#if !ModernKeePassLib
|
||||||
|
RijndaelManaged r = new RijndaelManaged();
|
||||||
if(r.BlockSize != 128) // AES block size
|
if(r.BlockSize != 128) // AES block size
|
||||||
{
|
{
|
||||||
Debug.Assert(false);
|
Debug.Assert(false);
|
||||||
r.BlockSize = 128;
|
r.BlockSize = 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] pbLocalIV = new byte[16];
|
|
||||||
Array.Copy(pbIV, pbLocalIV, 16);
|
|
||||||
r.IV = pbLocalIV;
|
r.IV = pbLocalIV;
|
||||||
|
|
||||||
byte[] pbLocalKey = new byte[32];
|
|
||||||
Array.Copy(pbKey, pbLocalKey, 32);
|
|
||||||
r.KeySize = 256;
|
r.KeySize = 256;
|
||||||
r.Key = pbLocalKey;
|
r.Key = pbLocalKey;
|
||||||
|
|
||||||
r.Mode = m_rCipherMode;
|
r.Mode = m_rCipherMode;
|
||||||
r.Padding = m_rCipherPadding;
|
r.Padding = m_rCipherPadding;
|
||||||
|
|
||||||
@@ -127,20 +172,32 @@ namespace ModernKeePassLib.Cryptography.Cipher
|
|||||||
|
|
||||||
return new CryptoStream(s, iTransform, bEncrypt ? CryptoStreamMode.Write :
|
return new CryptoStream(s, iTransform, bEncrypt ? CryptoStreamMode.Write :
|
||||||
CryptoStreamMode.Read);
|
CryptoStreamMode.Read);
|
||||||
}
|
#else
|
||||||
|
|
||||||
|
AesEngine aes = new AesEngine();
|
||||||
|
CbcBlockCipher cbc = new CbcBlockCipher(aes);
|
||||||
|
PaddedBufferedBlockCipher bc = new PaddedBufferedBlockCipher(cbc,
|
||||||
|
new Pkcs7Padding());
|
||||||
|
KeyParameter kp = new KeyParameter(pbLocalKey);
|
||||||
|
ParametersWithIV prmIV = new ParametersWithIV(kp, pbLocalIV);
|
||||||
|
bc.Init(bEncrypt, prmIV);
|
||||||
|
|
||||||
|
IBufferedCipher cpRead = (bEncrypt ? null : bc);
|
||||||
|
IBufferedCipher cpWrite = (bEncrypt ? bc : null);
|
||||||
|
return new CipherStream(s, cpRead, cpWrite);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//#endif
|
||||||
|
}
|
||||||
|
|
||||||
public Stream EncryptStream(Stream sPlainText, byte[] pbKey, byte[] pbIV)
|
public Stream EncryptStream(Stream sPlainText, byte[] pbKey, byte[] pbIV)
|
||||||
{
|
{
|
||||||
return StandardAesEngine.CreateStream(sPlainText, true, pbKey, pbIV);
|
return CreateStream(sPlainText, true, pbKey, pbIV);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream DecryptStream(Stream sEncrypted, byte[] pbKey, byte[] pbIV)
|
public Stream DecryptStream(Stream sEncrypted, byte[] pbKey, byte[] pbIV)
|
||||||
{
|
{
|
||||||
return StandardAesEngine.CreateStream(sEncrypted, false, pbKey, pbIV);
|
return CreateStream(sEncrypted, false, pbKey, pbIV);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -18,26 +18,36 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
#if ModernKeePassLib
|
||||||
using Windows.Security.Cryptography;
|
using Windows.Security.Cryptography;
|
||||||
//using System.Windows.Forms;
|
using ModernKeePassLib.Utility;
|
||||||
//using System.Drawing;
|
using Windows.Security.Cryptography.Core;
|
||||||
|
#else
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
#endif
|
||||||
|
using System.IO;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
|
||||||
namespace ModernKeePassLib.Cryptography
|
namespace ModernKeePassLib.Cryptography
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cryptographically strong random number generator. The returned values
|
/// Cryptographically strong random number generator. The returned values
|
||||||
/// are unpredictable and cannot be reproduced.
|
/// are unpredictable and cannot be reproduced.
|
||||||
/// <c>CryptoRandom</c> is a singleton class.
|
/// <c>CryptoRandom</c> is a singleton class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class CryptoRandom
|
public sealed class CryptoRandom
|
||||||
{
|
{
|
||||||
//private byte[] m_pbEntropyPool = new byte[64];
|
private byte[] m_pbEntropyPool = new byte[64];
|
||||||
//private uint m_uCounter;
|
private uint m_uCounter;
|
||||||
//private RNGCryptoServiceProvider m_rng = new RNGCryptoServiceProvider();
|
#if ModernKeePassLib
|
||||||
//private ulong m_uGeneratedBytesCount = 0;
|
//private IRandomNumberGenerator m_rng = NetFxCrypto.RandomNumberGenerator;
|
||||||
|
#else
|
||||||
|
private RNGCryptoServiceProvider m_rng = new RNGCryptoServiceProvider();
|
||||||
|
#endif
|
||||||
|
private ulong m_uGeneratedBytesCount = 0;
|
||||||
|
|
||||||
// private object m_oSyncRoot = new object();
|
private object m_oSyncRoot = new object();
|
||||||
|
|
||||||
private static CryptoRandom m_pInstance = null;
|
private static CryptoRandom m_pInstance = null;
|
||||||
public static CryptoRandom Instance
|
public static CryptoRandom Instance
|
||||||
@@ -51,44 +61,7 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if KeePassWinRT
|
|
||||||
private CryptoRandom()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Update the internal seed of the random number generator based
|
|
||||||
/// on entropy data.
|
|
||||||
/// This method is thread-safe.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pbEntropy">Entropy bytes.</param>
|
|
||||||
public void AddEntropy(byte[] pbEntropy)
|
|
||||||
{
|
|
||||||
// Not used in WinRT version
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a number of cryptographically strong random bytes.
|
|
||||||
/// This method is thread-safe.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="uRequestedBytes">Number of requested random bytes.</param>
|
|
||||||
/// <returns>A byte array consisting of <paramref name="uRequestedBytes" />
|
|
||||||
/// random bytes.</returns>
|
|
||||||
public byte[] GetRandomBytes(uint uRequestedBytes)
|
|
||||||
{
|
|
||||||
if (uRequestedBytes == 0) return new byte[0]; // Allow zero-length array
|
|
||||||
|
|
||||||
byte[] pbRes;
|
|
||||||
|
|
||||||
Windows.Storage.Streams.IBuffer buffer = CryptographicBuffer.GenerateRandom(uRequestedBytes);
|
|
||||||
CryptographicBuffer.CopyToByteArray(buffer, out pbRes);
|
|
||||||
return pbRes;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
/// <summary>
|
|
||||||
/// Get the number of random bytes that this instance generated so far.
|
/// Get the number of random bytes that this instance generated so far.
|
||||||
/// Note that this number can be higher than the number of random bytes
|
/// Note that this number can be higher than the number of random bytes
|
||||||
/// actually requested using the <c>GetRandomBytes</c> method.
|
/// actually requested using the <c>GetRandomBytes</c> method.
|
||||||
@@ -126,20 +99,29 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
/// <param name="pbEntropy">Entropy bytes.</param>
|
/// <param name="pbEntropy">Entropy bytes.</param>
|
||||||
public void AddEntropy(byte[] pbEntropy)
|
public void AddEntropy(byte[] pbEntropy)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(pbEntropy == null) { Debug.Assert(false); return; }
|
if(pbEntropy == null) { Debug.Assert(false); return; }
|
||||||
if(pbEntropy.Length == 0) { Debug.Assert(false); return; }
|
if(pbEntropy.Length == 0) { Debug.Assert(false); return; }
|
||||||
|
|
||||||
byte[] pbNewData = pbEntropy;
|
byte[] pbNewData = pbEntropy;
|
||||||
if(pbEntropy.Length >= 64)
|
if(pbEntropy.Length >= 64)
|
||||||
{
|
{
|
||||||
#if !KeePassLibSD
|
#if ModernKeePassLib
|
||||||
|
/*var shaNew = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha512);
|
||||||
|
pbNewData = shaNew.HashData(pbEntropy);*/
|
||||||
|
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
|
||||||
|
var buffer = sha256.HashData(CryptographicBuffer.CreateFromByteArray(pbEntropy));
|
||||||
|
CryptographicBuffer.CopyToByteArray(buffer, out pbNewData);
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if !KeePassLibSD
|
||||||
SHA512Managed shaNew = new SHA512Managed();
|
SHA512Managed shaNew = new SHA512Managed();
|
||||||
#else
|
#else
|
||||||
SHA256Managed shaNew = new SHA256Managed();
|
SHA256Managed shaNew = new SHA256Managed();
|
||||||
#endif
|
#endif
|
||||||
pbNewData = shaNew.ComputeHash(pbEntropy);
|
pbNewData = shaNew.ComputeHash(pbEntropy);
|
||||||
}
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
MemoryStream ms = new MemoryStream();
|
MemoryStream ms = new MemoryStream();
|
||||||
lock(m_oSyncRoot)
|
lock(m_oSyncRoot)
|
||||||
@@ -148,6 +130,14 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
ms.Write(pbNewData, 0, pbNewData.Length);
|
ms.Write(pbNewData, 0, pbNewData.Length);
|
||||||
|
|
||||||
byte[] pbFinal = ms.ToArray();
|
byte[] pbFinal = ms.ToArray();
|
||||||
|
#if ModernKeePassLib
|
||||||
|
/*var shaPool = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha512);
|
||||||
|
m_pbEntropyPool = shaPool.HashData(pbFinal);*/
|
||||||
|
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
|
||||||
|
var buffer = sha256.HashData(CryptographicBuffer.CreateFromByteArray(pbFinal));
|
||||||
|
CryptographicBuffer.CopyToByteArray(buffer, out m_pbEntropyPool);
|
||||||
|
#else
|
||||||
|
|
||||||
#if !KeePassLibSD
|
#if !KeePassLibSD
|
||||||
Debug.Assert(pbFinal.Length == (64 + pbNewData.Length));
|
Debug.Assert(pbFinal.Length == (64 + pbNewData.Length));
|
||||||
SHA512Managed shaPool = new SHA512Managed();
|
SHA512Managed shaPool = new SHA512Managed();
|
||||||
@@ -155,16 +145,14 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
SHA256Managed shaPool = new SHA256Managed();
|
SHA256Managed shaPool = new SHA256Managed();
|
||||||
#endif
|
#endif
|
||||||
m_pbEntropyPool = shaPool.ComputeHash(pbFinal);
|
m_pbEntropyPool = shaPool.ComputeHash(pbFinal);
|
||||||
}
|
|
||||||
ms.Close();
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
ms.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static byte[] GetSystemData(Random rWeak)
|
private static byte[] GetSystemData(Random rWeak)
|
||||||
{
|
{
|
||||||
|
|
||||||
MemoryStream ms = new MemoryStream();
|
MemoryStream ms = new MemoryStream();
|
||||||
byte[] pb;
|
byte[] pb;
|
||||||
|
|
||||||
@@ -174,21 +162,36 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
pb = TimeUtil.PackTime(DateTime.Now);
|
pb = TimeUtil.PackTime(DateTime.Now);
|
||||||
ms.Write(pb, 0, pb.Length);
|
ms.Write(pb, 0, pb.Length);
|
||||||
|
|
||||||
#if !KeePassLibSD
|
#if (!ModernKeePassLib && !KeePassLibSD && !KeePassRT)
|
||||||
Point pt = Cursor.Position;
|
// In try-catch for systems without GUI;
|
||||||
pb = MemUtil.UInt32ToBytes((uint)pt.X);
|
// https://sourceforge.net/p/keepass/discussion/329221/thread/20335b73/
|
||||||
ms.Write(pb, 0, pb.Length);
|
try
|
||||||
pb = MemUtil.UInt32ToBytes((uint)pt.Y);
|
{
|
||||||
ms.Write(pb, 0, pb.Length);
|
Point pt = Cursor.Position;
|
||||||
|
pb = MemUtil.UInt32ToBytes((uint)pt.X);
|
||||||
|
ms.Write(pb, 0, pb.Length);
|
||||||
|
pb = MemUtil.UInt32ToBytes((uint)pt.Y);
|
||||||
|
ms.Write(pb, 0, pb.Length);
|
||||||
|
}
|
||||||
|
catch(Exception) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pb = MemUtil.UInt32ToBytes((uint)rWeak.Next());
|
pb = MemUtil.UInt32ToBytes((uint)rWeak.Next());
|
||||||
ms.Write(pb, 0, pb.Length);
|
ms.Write(pb, 0, pb.Length);
|
||||||
|
|
||||||
pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID());
|
#if ModernKeePassLib
|
||||||
|
pb = MemUtil.UInt32ToBytes((uint)Environment.ProcessorCount);
|
||||||
ms.Write(pb, 0, pb.Length);
|
ms.Write(pb, 0, pb.Length);
|
||||||
|
|
||||||
#if !KeePassLibSD
|
pb = MemUtil.UInt32ToBytes((uint)Environment.CurrentManagedThreadId);
|
||||||
|
ms.Write(pb, 0, pb.Length);
|
||||||
|
#else
|
||||||
|
pb = MemUtil.UInt32ToBytes((uint)NativeLib.GetPlatformID());
|
||||||
|
ms.Write(pb, 0, pb.Length);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (!ModernKeePassLib && !KeePassLibSD && !KeePassRT)
|
||||||
|
Process p = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pb = MemUtil.UInt32ToBytes((uint)Environment.ProcessorCount);
|
pb = MemUtil.UInt32ToBytes((uint)Environment.ProcessorCount);
|
||||||
@@ -197,13 +200,11 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
ms.Write(pb, 0, pb.Length);
|
ms.Write(pb, 0, pb.Length);
|
||||||
|
|
||||||
Version v = Environment.OSVersion.Version;
|
Version v = Environment.OSVersion.Version;
|
||||||
int nv = (v.Major << 28) + (v.MajorRevision << 24) +
|
pb = MemUtil.UInt32ToBytes((uint)v.GetHashCode());
|
||||||
(v.Minor << 20) + (v.MinorRevision << 16) +
|
|
||||||
(v.Revision << 12) + v.Build;
|
|
||||||
pb = MemUtil.UInt32ToBytes((uint)nv);
|
|
||||||
ms.Write(pb, 0, pb.Length);
|
ms.Write(pb, 0, pb.Length);
|
||||||
|
|
||||||
Process p = Process.GetCurrentProcess();
|
p = Process.GetCurrentProcess();
|
||||||
|
|
||||||
pb = MemUtil.UInt64ToBytes((ulong)p.Handle.ToInt64());
|
pb = MemUtil.UInt64ToBytes((ulong)p.Handle.ToInt64());
|
||||||
ms.Write(pb, 0, pb.Length);
|
ms.Write(pb, 0, pb.Length);
|
||||||
pb = MemUtil.UInt32ToBytes((uint)p.HandleCount);
|
pb = MemUtil.UInt32ToBytes((uint)p.HandleCount);
|
||||||
@@ -236,33 +237,31 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
// ms.Write(pb, 0, pb.Length);
|
// ms.Write(pb, 0, pb.Length);
|
||||||
}
|
}
|
||||||
catch(Exception) { }
|
catch(Exception) { }
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
try { if(p != null) p.Dispose(); }
|
||||||
|
catch(Exception) { Debug.Assert(false); }
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pb = Guid.NewGuid().ToByteArray();
|
pb = Guid.NewGuid().ToByteArray();
|
||||||
ms.Write(pb, 0, pb.Length);
|
ms.Write(pb, 0, pb.Length);
|
||||||
|
|
||||||
byte[] pbAll = ms.ToArray();
|
byte[] pbAll = ms.ToArray();
|
||||||
ms.Close();
|
ms.Dispose();
|
||||||
return pbAll;
|
return pbAll;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private byte[] GetCspData()
|
private byte[] GetCspData()
|
||||||
{
|
{
|
||||||
uint length = 32;
|
byte[] pbCspRandom = new byte[32];
|
||||||
byte[] pbCspRandom = new byte[length];
|
//m_rng.GetBytes(pbCspRandom);
|
||||||
|
CryptographicBuffer.CopyToByteArray(CryptographicBuffer.GenerateRandom(32), out pbCspRandom);
|
||||||
Windows.Storage.Streams.IBuffer buffer = CryptographicBuffer.GenerateRandom(length);
|
|
||||||
|
|
||||||
CryptographicBuffer.CopyToByteArray(buffer, pbCspRandom);
|
|
||||||
//m_rng.GetBytes(pbCspRandom);
|
|
||||||
return pbCspRandom;
|
return pbCspRandom;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] GenerateRandom256()
|
private byte[] GenerateRandom256()
|
||||||
{
|
{
|
||||||
|
|
||||||
if(this.GenerateRandom256Pre != null)
|
if(this.GenerateRandom256Pre != null)
|
||||||
this.GenerateRandom256Pre(this, EventArgs.Empty);
|
this.GenerateRandom256Pre(this, EventArgs.Empty);
|
||||||
|
|
||||||
@@ -281,15 +280,24 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
pbFinal = ms.ToArray();
|
pbFinal = ms.ToArray();
|
||||||
Debug.Assert(pbFinal.Length == (m_pbEntropyPool.Length +
|
Debug.Assert(pbFinal.Length == (m_pbEntropyPool.Length +
|
||||||
pbCounter.Length + pbCspRandom.Length));
|
pbCounter.Length + pbCspRandom.Length));
|
||||||
ms.Close();
|
ms.Dispose();
|
||||||
|
|
||||||
m_uGeneratedBytesCount += 32;
|
m_uGeneratedBytesCount += 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ModernKeePassLib
|
||||||
|
/*var sha256 = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256);
|
||||||
|
return sha256.HashData(pbFinal);*/
|
||||||
|
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
|
||||||
|
var buffer = sha256.HashData(CryptographicBuffer.CreateFromByteArray(pbFinal));
|
||||||
|
byte[] result;
|
||||||
|
CryptographicBuffer.CopyToByteArray(buffer, out result);
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
SHA256Managed sha256 = new SHA256Managed();
|
SHA256Managed sha256 = new SHA256Managed();
|
||||||
return sha256.ComputeHash(pbFinal);
|
return sha256.ComputeHash(pbFinal);
|
||||||
}
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a number of cryptographically strong random bytes.
|
/// Get a number of cryptographically strong random bytes.
|
||||||
@@ -312,7 +320,7 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
|
|
||||||
long lCopy = (long)((uRequestedBytes < 32) ? uRequestedBytes : 32);
|
long lCopy = (long)((uRequestedBytes < 32) ? uRequestedBytes : 32);
|
||||||
|
|
||||||
#if !KeePassLibSD
|
#if (!ModernKeePassLib && !KeePassLibSD && !KeePassRT)
|
||||||
Array.Copy(pbRandom256, 0, pbRes, lPos, lCopy);
|
Array.Copy(pbRandom256, 0, pbRes, lPos, lCopy);
|
||||||
#else
|
#else
|
||||||
Array.Copy(pbRandom256, 0, pbRes, (int)lPos, (int)lCopy);
|
Array.Copy(pbRandom256, 0, pbRes, (int)lPos, (int)lCopy);
|
||||||
@@ -325,8 +333,5 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
Debug.Assert((int)lPos == pbRes.Length);
|
Debug.Assert((int)lPos == pbRes.Length);
|
||||||
return pbRes;
|
return pbRes;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !KeePassWinRT
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
KeePass Password Safe - The Open-Source Password Manager
|
KeePass Password Safe - The Open-Source Password Manager
|
||||||
Copyright (C) 2003-2012 Dominik Reichl <dominik.reichl@t-online.de>
|
Copyright (C) 2003-2014 Dominik Reichl <dominik.reichl@t-online.de>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -18,15 +18,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using Windows.Security.Cryptography.Core;
|
||||||
|
#if ModernKeePassLib
|
||||||
|
using Windows.Security.Cryptography;
|
||||||
|
#else
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
#endif
|
||||||
|
|
||||||
using ModernKeePassLib.Cryptography.Cipher;
|
using ModernKeePassLib.Cryptography.Cipher;
|
||||||
|
|
||||||
namespace ModernKeePassLib.Cryptography
|
namespace ModernKeePassLib.Cryptography
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Algorithms supported by <c>CryptoRandomStream</c>.
|
/// Algorithms supported by <c>CryptoRandomStream</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum CrsAlgorithm
|
public enum CrsAlgorithm
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Not supported.
|
/// Not supported.
|
||||||
@@ -109,13 +116,21 @@ namespace ModernKeePassLib.Cryptography
|
|||||||
}
|
}
|
||||||
else if(genAlgorithm == CrsAlgorithm.Salsa20)
|
else if(genAlgorithm == CrsAlgorithm.Salsa20)
|
||||||
{
|
{
|
||||||
byte[] pbKey32 = SHA256Managed.Instance.ComputeHash(pbKey);
|
#if ModernKeePassLib
|
||||||
|
/*var sha256 = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(HashAlgorithm.Sha256);
|
||||||
byte[] pbIV = new byte[]{ 0xE8, 0x30, 0x09, 0x4B,
|
var pbKey32 = sha256.HashData(pbKey);*/
|
||||||
|
var sha256 = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
|
||||||
|
var buffer = sha256.HashData(CryptographicBuffer.CreateFromByteArray(pbKey));
|
||||||
|
byte[] pbKey32;
|
||||||
|
CryptographicBuffer.CopyToByteArray(buffer, out pbKey32);
|
||||||
|
#else
|
||||||
|
SHA256Managed sha256 = new SHA256Managed();
|
||||||
|
byte[] pbKey32 = sha256.ComputeHash(pbKey);
|
||||||
|
#endif
|
||||||
|
byte[] pbIV = new byte[8] { 0xE8, 0x30, 0x09, 0x4B,
|
||||||
0x97, 0x20, 0x5D, 0x2A }; // Unique constant
|
0x97, 0x20, 0x5D, 0x2A }; // Unique constant
|
||||||
|
|
||||||
m_salsa20 = new Salsa20Cipher(pbKey32, pbIV);
|
m_salsa20 = new Salsa20Cipher(pbKey32, pbIV);
|
||||||
|
|
||||||
}
|
}
|
||||||
else // Unknown algorithm
|
else // Unknown algorithm
|
||||||
{
|
{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user