From 37deac2ab972c64b0c5221aa271f8e624fb4779b Mon Sep 17 00:00:00 2001 From: BONNEVILLE Geoffroy Date: Mon, 10 Sep 2018 17:29:52 +0200 Subject: [PATCH] Basic CSV Import working --- .../ImportFormats/CsvImportFormat.cs | 28 ++++++++++++-- .../ImportFormats/NullImportFormat.cs | 7 +++- ModernKeePass/Interfaces/IFormat.cs | 6 ++- ModernKeePass/Interfaces/IImportService.cs | 6 ++- ModernKeePass/Services/ImportService.cs | 21 +++++----- ModernKeePass/Strings/en-US/CodeBehind.resw | 3 ++ ModernKeePass/Strings/en-US/Resources.resw | 6 +++ ModernKeePass/Strings/fr-FR/CodeBehind.resw | 3 ++ ModernKeePass/Strings/fr-FR/Resources.resw | 9 +++++ ModernKeePass/ViewModels/NewVm.cs | 37 ++++++++++++------ .../Views/MainPageFrames/NewDatabasePage.xaml | 26 +++++++++---- .../MainPageFrames/NewDatabasePage.xaml.cs | 38 ++++++++++--------- ModernKeePass/packages.config | 4 +- README.md | 3 +- 14 files changed, 138 insertions(+), 59 deletions(-) diff --git a/ModernKeePass/ImportFormats/CsvImportFormat.cs b/ModernKeePass/ImportFormats/CsvImportFormat.cs index 8d8ea3c..6a323e9 100644 --- a/ModernKeePass/ImportFormats/CsvImportFormat.cs +++ b/ModernKeePass/ImportFormats/CsvImportFormat.cs @@ -1,13 +1,35 @@ -using Windows.Storage; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Windows.Storage; using ModernKeePass.Interfaces; namespace ModernKeePass.ImportFormats { public class CsvImportFormat: IFormat { - public IPwEntity Import(IStorageFile source) + public bool HasHeaderRow { get; set; } = true; + public char Delimiter { get; set; } = ';'; + public char LineDelimiter { get; set; } = '\n'; + + public async Task>> Import(IStorageFile source) { - throw new System.NotImplementedException(); + var parsedResult = new List>(); + var content = await FileIO.ReadLinesAsync(source); + foreach (var line in content) + { + var fields = line.Split(Delimiter); + var recordItem = new Dictionary(); + var i = 0; + foreach (var field in fields) + { + recordItem.Add(i.ToString(), field); + i++; + } + parsedResult.Add(recordItem); + } + + return parsedResult; } } } \ No newline at end of file diff --git a/ModernKeePass/ImportFormats/NullImportFormat.cs b/ModernKeePass/ImportFormats/NullImportFormat.cs index 19b208c..1f8cb7e 100644 --- a/ModernKeePass/ImportFormats/NullImportFormat.cs +++ b/ModernKeePass/ImportFormats/NullImportFormat.cs @@ -1,13 +1,16 @@ using Windows.Storage; using ModernKeePass.Interfaces; +using System; +using System.Threading.Tasks; +using System.Collections.Generic; namespace ModernKeePass.ImportFormats { public class NullImportFormat: IFormat { - public IPwEntity Import(IStorageFile source) + public Task>> Import(IStorageFile source) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } } } \ No newline at end of file diff --git a/ModernKeePass/Interfaces/IFormat.cs b/ModernKeePass/Interfaces/IFormat.cs index b96cd17..a53567f 100644 --- a/ModernKeePass/Interfaces/IFormat.cs +++ b/ModernKeePass/Interfaces/IFormat.cs @@ -1,9 +1,11 @@ -using Windows.Storage; +using System.Collections.Generic; +using System.Threading.Tasks; +using Windows.Storage; namespace ModernKeePass.Interfaces { public interface IFormat { - IPwEntity Import(IStorageFile source); + Task>> Import(IStorageFile source); } } \ No newline at end of file diff --git a/ModernKeePass/Interfaces/IImportService.cs b/ModernKeePass/Interfaces/IImportService.cs index 226db19..57880c3 100644 --- a/ModernKeePass/Interfaces/IImportService.cs +++ b/ModernKeePass/Interfaces/IImportService.cs @@ -1,9 +1,11 @@ -using Windows.Storage; +using System.Threading.Tasks; +using Windows.Storage; +using ModernKeePass.ViewModels; namespace ModernKeePass.Interfaces { public interface IImportService where T: IFormat { - void Import(T format, IStorageFile source, IDatabaseService database); + Task Import(T format, IStorageFile source, GroupVm group); } } \ No newline at end of file diff --git a/ModernKeePass/Services/ImportService.cs b/ModernKeePass/Services/ImportService.cs index d29fee9..e339abc 100644 --- a/ModernKeePass/Services/ImportService.cs +++ b/ModernKeePass/Services/ImportService.cs @@ -1,23 +1,24 @@ -using ModernKeePass.Interfaces; +using System.Threading.Tasks; using Windows.Storage; +using ModernKeePass.Interfaces; using ModernKeePass.ViewModels; namespace ModernKeePass.Services { public class ImportService : IImportService { - public void Import(IFormat format, IStorageFile source, IDatabaseService databaseService) + public async Task Import(IFormat format, IStorageFile source, GroupVm group) { - var entities = (GroupVm)format.Import(source); + var data = await format.Import(source); - foreach (var entry in entities.Entries) + foreach (var entity in data) { - databaseService.RootGroup.Entries.Add(entry); - } - - foreach (var subGroup in entities.Groups) - { - databaseService.RootGroup.Groups.Add(subGroup); + var entry = group.AddNewEntry(); + entry.Name = entity["0"]; + entry.UserName = entity["1"]; + entry.Password = entity["2"]; + if (entity.Count > 3) entry.Url = entity["3"]; + if (entity.Count > 4) entry.Notes = entity["4"]; } } } diff --git a/ModernKeePass/Strings/en-US/CodeBehind.resw b/ModernKeePass/Strings/en-US/CodeBehind.resw index 224f4ac..858ffbc 100644 --- a/ModernKeePass/Strings/en-US/CodeBehind.resw +++ b/ModernKeePass/Strings/en-US/CodeBehind.resw @@ -255,4 +255,7 @@ Database successfully saved! + + The CSV file needs to be formatted as such: Name of the account;Login;Password;URL;Comments + \ No newline at end of file diff --git a/ModernKeePass/Strings/en-US/Resources.resw b/ModernKeePass/Strings/en-US/Resources.resw index 845621b..4c5c79e 100644 --- a/ModernKeePass/Strings/en-US/Resources.resw +++ b/ModernKeePass/Strings/en-US/Resources.resw @@ -486,4 +486,10 @@ Import existing data + + Select a file to import... + + + Format + \ No newline at end of file diff --git a/ModernKeePass/Strings/fr-FR/CodeBehind.resw b/ModernKeePass/Strings/fr-FR/CodeBehind.resw index 875639b..22a3848 100644 --- a/ModernKeePass/Strings/fr-FR/CodeBehind.resw +++ b/ModernKeePass/Strings/fr-FR/CodeBehind.resw @@ -255,4 +255,7 @@ Base de données sauvegardée avec succès ! + + Le fichier CSV doit être formatté de la façon suivante: Nom du compte;Login;Mot de passe;URL;Commentaires + \ No newline at end of file diff --git a/ModernKeePass/Strings/fr-FR/Resources.resw b/ModernKeePass/Strings/fr-FR/Resources.resw index b1870aa..e4635f6 100644 --- a/ModernKeePass/Strings/fr-FR/Resources.resw +++ b/ModernKeePass/Strings/fr-FR/Resources.resw @@ -486,4 +486,13 @@ Importer des données existantes + + Sélectionnez un fichier à importer... + + + Format + + + Le fichier CSV doit être formatté de la façon suivante: Nom du compte;Login;Mot de passe:URL;Commentaires + \ No newline at end of file diff --git a/ModernKeePass/ViewModels/NewVm.cs b/ModernKeePass/ViewModels/NewVm.cs index 594f085..01ff1d5 100644 --- a/ModernKeePass/ViewModels/NewVm.cs +++ b/ModernKeePass/ViewModels/NewVm.cs @@ -1,7 +1,7 @@ -using System; -using Windows.Storage; +using Windows.Storage; using Windows.UI.Xaml.Controls; using ModernKeePass.Converters; +using ModernKeePass.ImportFormats; using ModernKeePass.Interfaces; using ModernKeePassLib; @@ -9,41 +9,54 @@ namespace ModernKeePass.ViewModels { public class NewVm : OpenVm { + private string _importFormatHelp; public string Password { get; set; } public bool IsImportChecked { get; set; } public IStorageFile ImportFile { get; set; } + public string ImportFileExtensionFilter { get; set; } = "*"; + public IFormat ImportFormat { get; set; } - - public void PopulateInitialData(IDatabaseService database, ISettingsService settings, IImportService importService) + + public string ImportFormatHelp { - if (settings.GetSetting("Sample") && !IsImportChecked) CreateSampleData(database); - else if (IsImportChecked && ImportFile != null) importService.Import(ImportFormat, ImportFile, database); + get { return _importFormatHelp; } + set + { + _importFormatHelp = value; + OnPropertyChanged(nameof(ImportFormatHelp)); + } } - private void CreateSampleData(IDatabaseService database) + public void PopulateInitialData(IDatabaseService database, ISettingsService settings, IImportService importService) + { + if (settings.GetSetting("Sample") && !IsImportChecked) CreateSampleData(database.RootGroup); + else if (IsImportChecked && ImportFile != null && ! (ImportFormat is NullImportFormat)) importService.Import(ImportFormat, ImportFile, database.RootGroup); + } + + private void CreateSampleData(GroupVm group) { var converter = new IntToSymbolConverter(); - var bankingGroup = database.RootGroup.AddNewGroup("Banking"); + var bankingGroup = group.AddNewGroup("Banking"); bankingGroup.IconId = (int)converter.ConvertBack(Symbol.Calculator, null, null, string.Empty); - var emailGroup = database.RootGroup.AddNewGroup("Email"); + var emailGroup = group.AddNewGroup("Email"); emailGroup.IconId = (int)converter.ConvertBack(Symbol.Mail, null, null, string.Empty); - var internetGroup = database.RootGroup.AddNewGroup("Internet"); + var internetGroup = group.AddNewGroup("Internet"); internetGroup.IconId = (int)converter.ConvertBack(Symbol.World, null, null, string.Empty); - var sample1 = database.RootGroup.AddNewEntry(); + var sample1 = group.AddNewEntry(); sample1.Name = "Sample Entry"; sample1.UserName = "Username"; sample1.Url = PwDefs.HomepageUrl; sample1.Password = "Password"; sample1.Notes = "You may safely delete this sample"; - var sample2 = database.RootGroup.AddNewEntry(); + var sample2 = group.AddNewEntry(); sample2.Name = "Sample Entry #2"; sample2.UserName = "Michael321"; sample2.Url = PwDefs.HelpUrl + "kb/testform.html"; diff --git a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml index adc35ee..a4c2649 100644 --- a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml +++ b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml @@ -6,8 +6,6 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:converters="using:ModernKeePass.Converters" xmlns:viewModels="using:ModernKeePass.ViewModels" - xmlns:interactivity="using:Microsoft.Xaml.Interactivity" - xmlns:core="using:Microsoft.Xaml.Interactions.Core" xmlns:userControls="using:ModernKeePass.Views.UserControls" mc:Ignorable="d"> @@ -18,7 +16,7 @@ - + @@ -26,16 +24,28 @@ - + - - - - + + + CSV + + diff --git a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs index 017cdf8..5f37cad 100644 --- a/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs +++ b/ModernKeePass/Views/MainPageFrames/NewDatabasePage.xaml.cs @@ -33,7 +33,7 @@ namespace ModernKeePass.Views _mainFrame = e.Parameter as Frame; } - private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) + private async void CreateDatabaseButton_OnClick(object sender, RoutedEventArgs e) { var savePicker = new FileSavePicker { @@ -47,6 +47,23 @@ namespace ModernKeePass.Views Model.OpenFile(file); } + private void ImportFormatComboBox_OnSelectionChanged(object sender, SelectionChangedEventArgs e) + { + var resources = new ResourcesService(); + var comboBox = sender as ComboBox; + switch (comboBox?.SelectedIndex) + { + case 0: + Model.ImportFormat = new CsvImportFormat(); + Model.ImportFileExtensionFilter = ".csv"; + Model.ImportFormatHelp = resources.GetResourceValue("NewImportFormatHelpCSV"); + break; + default: + Model.ImportFormat = new NullImportFormat(); + break; + } + } + private async void ImportFileButton_OnClick(object sender, RoutedEventArgs e) { var picker = @@ -55,31 +72,18 @@ namespace ModernKeePass.Views ViewMode = PickerViewMode.List, SuggestedStartLocation = PickerLocationId.DocumentsLibrary }; - picker.FileTypeFilter.Add(".csv"); + if (!string.IsNullOrEmpty(Model.ImportFileExtensionFilter)) + picker.FileTypeFilter.Add(Model.ImportFileExtensionFilter); // Application now has read/write access to the picked file Model.ImportFile = await picker.PickSingleFileAsync(); + if (Model.ImportFile != null) ImportFileLink.Content = Model.ImportFile.Name; } private void CompositeKeyUserControl_OnValidationChecked(object sender, PasswordEventArgs e) { Model.PopulateInitialData(DatabaseService.Instance, new SettingsService(), new ImportService()); - _mainFrame.Navigate(typeof(GroupDetailPage), DatabaseService.Instance.RootGroup); } - - private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e) - { - var comboBox = sender as ComboBox; - switch (comboBox?.SelectedIndex) - { - case 0: - Model.ImportFormat = new CsvImportFormat(); - break; - default: - Model.ImportFormat = new NullImportFormat(); - break; - } - } } } diff --git a/ModernKeePass/packages.config b/ModernKeePass/packages.config index dee7229..90810db 100644 --- a/ModernKeePass/packages.config +++ b/ModernKeePass/packages.config @@ -4,9 +4,9 @@ - + - + diff --git a/README.md b/README.md index 007335f..503ae42 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ You can get it [here](https://www.microsoft.com/en-us/store/p/modernkeepass/9mwq # Features - Works on Windows 10, 8.1 and RT -- Read and write support of KDBX files version 2, 3 and 4 +- Full compatibility with classic KeePass databases: read and write support of KDBX files version 2, 3 and 4 - Open database with password and key file - Create new databases - Create new key files @@ -25,6 +25,7 @@ You can get it [here](https://www.microsoft.com/en-us/store/p/modernkeepass/9mwq - Change database compression - Change database key derivation - Displays and change entry colors and icons +- Import existing CSV data # Build and Test 1. Clone the repository