From 18cfbf729c36329e35e3c733f93e3fdc1d075998 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Sat, 9 Mar 2024 11:59:49 -0500 Subject: [PATCH] Add 1Password 1PUX and Bitwarden JSON Importers * Closes #7545 - Support 1Password 1PUX import format based on https://support.1password.com/1pux-format/ * Closes #8367 - Support Bitwarden JSON import format (both unencrypted and encrypted) based on https://bitwarden.com/help/encrypted-export/ * Fixes #9577 - OPVault import when fields have the same name or type * Introduce the import wizard to handle all import tasks (CSV, KDBX1, OPVault, 1PUX, JSON) * Clean up CSV parser code to make it much more efficient and easier to read * Combine all importer tests (except CSV) into one test file --- CMakeLists.txt | 3 + COPYING | 3 + docs/images/csv_import.png | Bin 68581 -> 102561 bytes docs/images/import_wizard.png | Bin 0 -> 118208 bytes docs/topics/ImportExport.adoc | 65 +- .../scalable/actions/bitwarden.svg | 1 + .../application/scalable/actions/csv.svg | 1 + .../scalable/actions/onepassword.svg | 1 + share/icons/icons.qrc | 3 + share/translations/keepassxc_en.ts | 373 +++-- src/CMakeLists.txt | 9 +- src/autotype/AutoType.cpp | 1 + src/format/BitwardenReader.cpp | 313 ++++ .../format/BitwardenReader.h | 40 +- src/format/CsvParser.cpp | 110 +- src/format/CsvParser.h | 8 +- src/format/KeePass1Reader.cpp | 5 + src/format/OPUXReader.cpp | 288 ++++ .../OPUXReader.h} | 31 +- src/format/OpVaultReader.cpp | 89 +- src/format/OpVaultReader.h | 10 +- src/format/OpVaultReaderAttachments.cpp | 4 + src/format/OpVaultReaderSections.cpp | 8 +- src/gui/CloneDialog.h | 2 + src/gui/DatabaseTabWidget.cpp | 129 +- src/gui/DatabaseTabWidget.h | 4 +- src/gui/DatabaseWidget.cpp | 88 +- src/gui/DatabaseWidget.h | 28 +- src/gui/EntryPreviewWidget.cpp | 2 +- src/gui/EntryPreviewWidget.h | 1 + src/gui/Icons.cpp | 2 + src/gui/KeePass1OpenWidget.cpp | 63 - src/gui/MainWindow.cpp | 31 +- src/gui/MainWindow.h | 4 +- src/gui/MainWindow.ui | 23 +- src/gui/OpVaultOpenWidget.cpp | 50 - src/gui/PasswordWidget.h | 1 + src/gui/TotpDialog.h | 2 + src/gui/TotpExportSettingsDialog.cpp | 1 + src/gui/TotpExportSettingsDialog.h | 2 + src/gui/TotpSetupDialog.h | 2 + src/gui/WelcomeWidget.cpp | 7 +- src/gui/WelcomeWidget.h | 4 +- src/gui/WelcomeWidget.ui | 52 +- src/gui/csvImport/CsvImportWidget.cpp | 288 ++-- src/gui/csvImport/CsvImportWidget.h | 47 +- src/gui/csvImport/CsvImportWidget.ui | 1382 ++++++++--------- src/gui/csvImport/CsvImportWizard.cpp | 45 - src/gui/csvImport/CsvImportWizard.h | 51 - src/gui/csvImport/CsvParserModel.cpp | 62 +- src/gui/csvImport/CsvParserModel.h | 12 +- src/gui/tag/TagsEdit.cpp | 1 + src/gui/wizard/ImportWizard.cpp | 84 + src/gui/wizard/ImportWizard.h | 60 + src/gui/wizard/ImportWizardPageReview.cpp | 202 +++ src/gui/wizard/ImportWizardPageReview.h | 60 + src/gui/wizard/ImportWizardPageReview.ui | 95 ++ src/gui/wizard/ImportWizardPageSelect.cpp | 236 +++ src/gui/wizard/ImportWizardPageSelect.h | 56 + src/gui/wizard/ImportWizardPageSelect.ui | 276 ++++ src/keeshare/CMakeLists.txt | 2 - tests/CMakeLists.txt | 2 +- tests/TestImports.cpp | 267 ++++ .../TestImports.h | 23 +- tests/TestOpVaultReader.cpp | 139 -- tests/data/1PasswordExport.1pux | Bin 0 -> 31621 bytes tests/data/bitwarden_encrypted_export.json | 11 + tests/data/bitwarden_export.json | 180 +++ tests/gui/TestGui.cpp | 22 - tests/gui/TestGui.h | 1 - 70 files changed, 3574 insertions(+), 1894 deletions(-) create mode 100644 docs/images/import_wizard.png create mode 100644 share/icons/application/scalable/actions/bitwarden.svg create mode 100644 share/icons/application/scalable/actions/csv.svg create mode 100644 share/icons/application/scalable/actions/onepassword.svg create mode 100644 src/format/BitwardenReader.cpp rename tests/TestOpVaultReader.h => src/format/BitwardenReader.h (51%) create mode 100644 src/format/OPUXReader.cpp rename src/{gui/OpVaultOpenWidget.h => format/OPUXReader.h} (58%) delete mode 100644 src/gui/KeePass1OpenWidget.cpp delete mode 100644 src/gui/OpVaultOpenWidget.cpp delete mode 100644 src/gui/csvImport/CsvImportWizard.cpp delete mode 100644 src/gui/csvImport/CsvImportWizard.h create mode 100644 src/gui/wizard/ImportWizard.cpp create mode 100644 src/gui/wizard/ImportWizard.h create mode 100644 src/gui/wizard/ImportWizardPageReview.cpp create mode 100644 src/gui/wizard/ImportWizardPageReview.h create mode 100644 src/gui/wizard/ImportWizardPageReview.ui create mode 100644 src/gui/wizard/ImportWizardPageSelect.cpp create mode 100644 src/gui/wizard/ImportWizardPageSelect.h create mode 100644 src/gui/wizard/ImportWizardPageSelect.ui create mode 100644 tests/TestImports.cpp rename src/gui/KeePass1OpenWidget.h => tests/TestImports.h (64%) delete mode 100644 tests/TestOpVaultReader.cpp create mode 100644 tests/data/1PasswordExport.1pux create mode 100644 tests/data/bitwarden_encrypted_export.json create mode 100644 tests/data/bitwarden_export.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 672ac4c0a..776d9bfa2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -567,6 +567,9 @@ if(ZLIB_VERSION_STRING VERSION_LESS "1.2.0") endif() include_directories(SYSTEM ${ZLIB_INCLUDE_DIR}) +# Find Minizip +find_package(Minizip REQUIRED) + if(WITH_XC_YUBIKEY) find_package(PCSC REQUIRED) include_directories(SYSTEM ${PCSC_INCLUDE_DIRS}) diff --git a/COPYING b/COPYING index 480b01f07..6baf4c27e 100644 --- a/COPYING +++ b/COPYING @@ -143,11 +143,13 @@ License: MIT Files: share/icons/application/scalable/actions/application-exit.svg share/icons/application/scalable/actions/attributes-copy.svg share/icons/application/scalable/actions/auto-type.svg + share/icons/application/scalable/actions/bitwarden.svg share/icons/application/scalable/actions/bugreport.svg share/icons/application/scalable/actions/chevron-double-down.svg share/icons/application/scalable/actions/chevron-double-right.svg share/icons/application/scalable/actions/clipboard-text.svg share/icons/application/scalable/actions/configure.svg + share/icons/application/scalable/actions/csv.svg share/icons/application/scalable/actions/database-change-key.svg share/icons/application/scalable/actions/database-lock.svg share/icons/application/scalable/actions/database-lock-all.svg @@ -192,6 +194,7 @@ Files: share/icons/application/scalable/actions/application-exit.svg share/icons/application/scalable/actions/move-up.svg share/icons/application/scalable/actions/object-locked.svg share/icons/application/scalable/actions/object-unlocked.svg + share/icons/application/scalable/actions/onepassword.svg share/icons/application/scalable/actions/paperclip.svg share/icons/application/scalable/actions/password-copy.svg share/icons/application/scalable/actions/passkey.svg diff --git a/docs/images/csv_import.png b/docs/images/csv_import.png index 8fce05e57f1157474f2e95c1df868217c9297284..cddd2c4e04389c7a0adc0531ef0f30d21739c56e 100644 GIT binary patch literal 102561 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 z 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

u*&jjVx2cpNEwA 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 Vd&+lqnj1JddAj+Igz<9RZ)5S5Q;?|qL>=7b2 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 literal 0 HcmV?d00001 diff --git a/docs/topics/ImportExport.adoc b/docs/topics/ImportExport.adoc index dad5d98bb..bcae4ce57 100644 --- a/docs/topics/ImportExport.adoc +++ b/docs/topics/ImportExport.adoc @@ -6,53 +6,66 @@ include::.sharedheader[] == Importing External Databases KeePassXC allows you to import external databases from the following options: -* Comma-Separated Values (CSV) file -* 1Password OPVault -* KeePass 1 Database +* Comma Separated Values (.csv) +* 1Password Export (.1pux) +* 1Password Vault (.opvault) +* Bitwarden (.json) +* KeePass 1 Database (.kdb) + +To import any of these files, start KeePassXC and either click the `Import File` button on the welcome screen or use the menu Database > Import... to launch the Import Wizard. + +.Import Wizard +image::import_wizard.png[] + +For each of the import options, you will be prompted to select the file to import and then provide credentials to unlock the file, if necessary. You can then choose to import the file into a new database or into an existing database that is already unlocked in KeePassXC. === Importing CSV File -If you have been saving your URLs, usernames, passwords, and so on in a CSV file, you can migrate all that information from the CSV file to KeePassXC and start using KeePassXC to maintain your data. +WARNING: A CSV file is unencrypted and you should securely delete this file after successfully importing it into KeePassXC. -To open the CSV file, perform the following steps: +1. Follow the steps above and click `Continue`. The CSV import wizard will appear. -1. Open KeePassXC. - -2. Click Import from CSV button on the welcome screen or use the menu Database > Import > CSV File. - -3. Navigate to the location of the your CSV file on your computer and open the file. The new database wizard will appear. Follow the steps of creating a new database in Chapter 1. - -4. After saving your new database file, the CSV import wizard will appear. On this dialog you can choose the various options for properly importing the data. You may need to select the _First line has field names_ checkbox before starting. Analyze the output in the preview at the bottom to determine the correct import settings. +2. On this dialog you can choose the various options for properly importing the data. Analyze the output in the preview at the bottom to determine the correct import settings. You may need to re-map the column associations to match the data in your CSV file. + .CSV Import Wizard image::csv_import.png[] -Your CSV file gets imported to KeePassXC and the data is converted to the KeePassXC format for further usage and maintenance. The new database file is saved on to your computer with the default `.kdbx` extension. +3. Click `Done` to complete the import. If you chose to create a new database, the New Database dialog will appear. Otherwise your entries will be nested under the group you chose for the existing database. + +=== Importing 1Password Export +WARNING: A 1Password Export file is unencrypted and you should securely delete this file after successfully importing it into KeePassXC. + +1. Open the Import Wizard as shown above. Select the 1Password Export option. + +2. Click `Continue` to unlock and preview the import. Click `Done` to complete the import. === Importing 1Password OPVault +NOTE: You must have 1Password version 7 or 8 to export your data to an OPVault. If you are using a newer version of 1Password, you should use the 1Password Export (1PUX) format instead. + Save your 1Password Vault locally to create an OPVault directory. Please see 1Password instructions on how to do this. Once an OPVault is created, perform the following steps: -1. Open KeePassXC. +1. Open the Import Wizard as shown above. Select the 1Password Vault option. -2. Use the menu Database > Import > 1Password Vault. Select the OPVault to import. +2. Enter the password for your vault and click `Continue` to unlock and preview the import. Click `Done` to complete the import. -3. Enter the password for your OPVault to unlock and import. +=== Importing Bitwarden +WARNING: A Bitwarden Export file may be unencrypted and you should securely delete this file after successfully importing it into KeePassXC. + +1. Open the Import Wizard as shown above. Select the Bitwarden option. + +2. Optionally provide a password to decrypt the Bitwarden export file. You should only need to do this if you have chosen the encrypted json export option within Bitwarden. + +3. Click `Continue` to unlock and preview the import. Click `Done` to complete the import. === Importing KeePass 1 Database -KeePass 1 database is an older format of the database created using legacy version of KeePass. KeePassXC lets your import this older format of the database and you can seamlessly start using this database in your new KeePassXC application. +KeePass 1 database is an older format of the database created using a legacy version of KeePass. KeePassXC lets your import this older format of the database and you can seamlessly start using this database in your new KeePassXC application. To import a KeePass 1 database file in KeePassXC, perform the following steps: -1. Open KeePassXC. +1. Open the Import Wizard as shown above. Select the KeePass1 Database option. -2. Click Import from KeePass 1 button on the welcome screen or use the menu Database > Import > KeePass 1 Database. +2. Enter the password for your database and optionally provide a key file if it was configured for your KeePass1 database. -3. Navigate to the location of the your legacy KeePass 1 database file (`.kdb`) on your computer and open the file. You are prompted for the password and the Key file for your `.kdb` file. - -4. Enter the password for your old `.kdb` file and click *OK*. You are prompted for provide a name for the new database format that KeePassXC recognizes. - -5. Provide a name for the new database format, select a folder on your computer to save the file, and click Save. - -6. The data from the `.kdb` file gets imported and converted to the new format, which is compatible with KeePassXC. You can now start using the new database file (`.kdbx`) in KeePassXC. +3. Click `Continue` to unlock and preview the import. Click `Done` to complete the import. == Exporting Databases KeePassXC supports multiple ways to export your database for transfer to another program or to print out and archive. diff --git a/share/icons/application/scalable/actions/bitwarden.svg b/share/icons/application/scalable/actions/bitwarden.svg new file mode 100644 index 000000000..9d22e9adc --- /dev/null +++ b/share/icons/application/scalable/actions/bitwarden.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/share/icons/application/scalable/actions/csv.svg b/share/icons/application/scalable/actions/csv.svg new file mode 100644 index 000000000..e76afb0a8 --- /dev/null +++ b/share/icons/application/scalable/actions/csv.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/share/icons/application/scalable/actions/onepassword.svg b/share/icons/application/scalable/actions/onepassword.svg new file mode 100644 index 000000000..b43237abc --- /dev/null +++ b/share/icons/application/scalable/actions/onepassword.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/share/icons/icons.qrc b/share/icons/icons.qrc index 78980d971..a846bf7bc 100644 --- a/share/icons/icons.qrc +++ b/share/icons/icons.qrc @@ -8,11 +8,13 @@ application/scalable/actions/application-exit.svg application/scalable/actions/attributes-copy.svg application/scalable/actions/auto-type.svg + application/scalable/actions/bitwarden.svg application/scalable/actions/bugreport.svg application/scalable/actions/chevron-double-down.svg application/scalable/actions/chevron-double-right.svg application/scalable/actions/clipboard-text.svg application/scalable/actions/configure.svg + application/scalable/actions/csv.svg application/scalable/actions/database-change-key.svg application/scalable/actions/database-lock.svg application/scalable/actions/database-lock-all.svg @@ -58,6 +60,7 @@ application/scalable/actions/move-up.svg application/scalable/actions/object-locked.svg application/scalable/actions/object-unlocked.svg + application/scalable/actions/onepassword.svg application/scalable/actions/paperclip.svg application/scalable/actions/passkey.svg application/scalable/actions/password-copy.svg diff --git a/share/translations/keepassxc_en.ts b/share/translations/keepassxc_en.ts index 494d42f3f..4f84ea6e8 100644 --- a/share/translations/keepassxc_en.ts +++ b/share/translations/keepassxc_en.ts @@ -1286,14 +1286,6 @@ Would you like to migrate your existing settings now? CsvImportWidget - - Import CSV fields - - - - filename - - size, rows, columns @@ -1402,18 +1394,6 @@ Would you like to migrate your existing settings now? Column %1 - - Imported from CSV file - - - - Original data: - - - - Error(s) detected in CSV file! - - [%n more message(s) skipped] @@ -1422,31 +1402,19 @@ Would you like to migrate your existing settings now? - Error + Failed to parse CSV file: %1 - CSV import: writer has errors: -%1 + Imported from CSV file: %1 CsvParserModel - - %1, %2, %3 - file info: bytes, rows, columns - - - - %n byte(s) - - - - - %n row(s) + CSV row count @@ -1454,6 +1422,7 @@ Would you like to migrate your existing settings now? %n column(s) + CSV column count @@ -2315,26 +2284,10 @@ This is definitely a bug, please report it to the developers. CSV file - - Select CSV file - - Merge database - - KeePass 1 database - - - - Open KeePass 1 database - - - - Open OPVault - - Export database to CSV file @@ -2355,15 +2308,6 @@ This is definitely a bug, please report it to the developers. You are about to export your database to an unencrypted file. This will leave your passwords and sensitive information vulnerable! Are you sure you want to continue? - - New Database - - - - %1 [New Database] - Database tab name modifier - - %1 [Locked] Database tab name modifier @@ -2541,6 +2485,19 @@ Disable safe saves and try again? Could not find database file: %1 + + New Database + + + + %1 [New Database] + Database tab name modifier + + + + Searches and Tags + + Entries expiring within %1 day(s) @@ -2549,17 +2506,13 @@ Disable safe saves and try again? - Searches and Tags + Save Enter a unique name or overwrite an existing search from the list: - - Save - - Save Search @@ -4311,6 +4264,147 @@ You can enable the DuckDuckGo website icon service in the security section of th + + ImportWizard + + Import Wizard + + + + + ImportWizardPageReview + + WizardPage + + + + Entry count: %1 + + + + Group + + + + Title + + + + Username + + + + Password + + + + Url + + + + + ImportWizardPageSelect + + Form + + + + Import File Selection + + + + Password: + + + + Key File: + + + + Browse… + + + + Import Into: + + + + New Database + + + + No unlocked databases available + + + + Existing Database: + + + + Import File: + + + + Comma Separated Values (.csv) + + + + 1Password Export (.1pux) + + + + 1Password Vault (.opvault) + + + + Bitwarden (.json) + + + + KeePass 1 Database (.kdb) + + + + Open OPVault + + + + Select import file + + + + All files + + + + Key files + + + + Select key file + + + + Comma Separated Values + + + + 1Password Export + + + + Bitwarden JSON Export + + + + 1Password Vault + + + + KeePass1 Database + + + KMessageWidget @@ -4738,17 +4832,6 @@ Line %2, column %3 - - KeePass1OpenWidget - - Import KeePass1 Database - - - - Unable to open the database. - - - KeePass1Reader @@ -5102,10 +5185,6 @@ Are you sure you want to continue with this file? &Recent Databases - - &Import - - &Export @@ -5558,7 +5637,19 @@ We recommend you use the AppImage available on our downloads page. - No Tags + 1Password 1PUX... + + + + Import a 1Password 1PUX file + + + + Import… + + + + Passkeys… @@ -5588,10 +5679,6 @@ We recommend you use the AppImage available on our downloads page. Allow Screen Capture - - Passkeys… - - Passkeys @@ -5600,6 +5687,10 @@ We recommend you use the AppImage available on our downloads page. Import Passkey + + No Tags + + ManageDatabase @@ -5824,14 +5915,6 @@ We recommend you use the AppImage available on our downloads page. - - OpVaultOpenWidget - - Read Database did not produce an instance -%1 - - - OpVaultReader @@ -8275,7 +8358,73 @@ This options is deprecated, use --set-key-file instead. - Credential is excluded + Favorite + Tag for favorite entries + + + + File does not exist. + + + + Cannot open file: %1 + + + + Cannot parse file: %1 at position %2 + + + + Failed to decrypt json file: %1 + + + + Invalid encKeyValidation field + + + + Invalid cipher list within encKeyValidation field + + + + Wrong password + + + + Invalid encrypted data field + + + + Invalid cipher list within encrypted data field + + + + Cannot initialize cipher + + + + Cannot decrypt data + + + + Bitwarden Import + + + + Archived + Tag for archived entries + + + + Invalid 1PUX file format: Not a valid ZIP file. + + + + Invalid 1PUX file format: Missing export.data + + + + 1Password Import @@ -8302,6 +8451,10 @@ This options is deprecated, use --set-key-file instead. Cannot remove file key: The database does not have a file key. + + Credential is excluded + + QtIOCompressor @@ -9339,26 +9492,6 @@ Example: JBSWY3DPEHPK3PXP Start storing your passwords securely in a KeePassXC database - - Create new database - - - - Open existing database - - - - Import from KeePass 1 - - - - Import from 1Password - - - - Import from CSV - - Recent databases @@ -9371,6 +9504,18 @@ Example: JBSWY3DPEHPK3PXP Welcome to KeePassXC %1 + + Create Database + + + + Open Database + + + + Import File + + WinUtils diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f3886d960..40dae9371 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -71,6 +71,7 @@ set(keepassx_SOURCES crypto/kdf/Kdf.cpp crypto/kdf/AesKdf.cpp crypto/kdf/Argon2Kdf.cpp + format/BitwardenReader.cpp format/CsvExporter.cpp format/CsvParser.cpp format/KeePass1Reader.cpp @@ -87,6 +88,7 @@ set(keepassx_SOURCES format/Kdbx4Writer.cpp format/KdbxXmlWriter.cpp format/OpData01.cpp + format/OPUXReader.cpp format/OpVaultReader.cpp format/OpVaultReaderAttachments.cpp format/OpVaultReaderBandEntry.cpp @@ -117,12 +119,10 @@ set(keepassx_SOURCES gui/GuiTools.cpp gui/HtmlExporter.cpp gui/IconModels.cpp - gui/KeePass1OpenWidget.cpp gui/KMessageWidget.cpp gui/MainWindow.cpp gui/MessageBox.cpp gui/MessageWidget.cpp - gui/OpVaultOpenWidget.cpp gui/PasswordWidget.cpp gui/PasswordGeneratorWidget.cpp gui/ApplicationSettingsWidget.cpp @@ -137,7 +137,6 @@ set(keepassx_SOURCES gui/URLEdit.cpp gui/WelcomeWidget.cpp gui/csvImport/CsvImportWidget.cpp - gui/csvImport/CsvImportWizard.cpp gui/csvImport/CsvParserModel.cpp gui/entry/AutoTypeAssociationsModel.cpp gui/entry/EditEntryWidget.cpp @@ -180,6 +179,9 @@ set(keepassx_SOURCES gui/widgets/ElidedLabel.cpp gui/widgets/KPToolBar.cpp gui/widgets/PopupHelpWidget.cpp + gui/wizard/ImportWizard.cpp + gui/wizard/ImportWizardPageReview.cpp + gui/wizard/ImportWizardPageSelect.cpp gui/wizard/NewDatabaseWizard.cpp gui/wizard/NewDatabaseWizardPage.cpp gui/wizard/NewDatabaseWizardPageMetaData.cpp @@ -366,6 +368,7 @@ target_link_libraries(keepassx_core ${PCSC_LIBRARIES} ${ZXCVBN_LIBRARIES} ${ZLIB_LIBRARIES} + ${MINIZIP_LIBRARIES} ${ARGON2_LIBRARIES} ${thirdparty_LIBRARIES} ) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 750053955..d530f09ed 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "config-keepassx.h" diff --git a/src/format/BitwardenReader.cpp b/src/format/BitwardenReader.cpp new file mode 100644 index 000000000..8f7a926fa --- /dev/null +++ b/src/format/BitwardenReader.cpp @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2023 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "BitwardenReader.h" + +#include "core/Database.h" +#include "core/Entry.h" +#include "core/Group.h" +#include "core/Metadata.h" +#include "core/Tools.h" +#include "core/Totp.h" +#include "crypto/CryptoHash.h" +#include "crypto/SymmetricCipher.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + Entry* readItem(const QJsonObject& item, QString& folderId) + { + // Create the item map and extract the folder id + const auto itemMap = item.toVariantMap(); + folderId = itemMap.value("folderId").toString(); + + // Create entry and assign basic values + QScopedPointer entry(new Entry()); + entry->setUuid(QUuid::createUuid()); + entry->setTitle(itemMap.value("name").toString()); + entry->setNotes(itemMap.value("notes").toString()); + + if (itemMap.value("favorite").toBool()) { + entry->addTag(QObject::tr("Favorite", "Tag for favorite entries")); + } + + // Parse login details if present + if (itemMap.contains("login")) { + const auto loginMap = itemMap.value("login").toMap(); + entry->setUsername(loginMap.value("username").toString()); + entry->setPassword(loginMap.value("password").toString()); + if (loginMap.contains("totp")) { + // Bitwarden stores TOTP as otpauth string + entry->setTotp(Totp::parseSettings(loginMap.value("totp").toString())); + } + + // Set the entry url(s) + int i = 1; + for (const auto& urlObj : loginMap.value("uris").toList()) { + const auto url = urlObj.toMap().value("uri").toString(); + if (entry->url().isEmpty()) { + // First url encountered is set as the primary url + entry->setUrl(url); + } else { + // Subsequent urls + entry->attributes()->set( + QString("%1_%2").arg(EntryAttributes::AdditionalUrlAttribute, QString::number(i)), url); + ++i; + } + } + } + + // Parse identity details if present + if (itemMap.contains("identity")) { + const auto idMap = itemMap.value("identity").toMap(); + + // Combine name attributes + auto attrs = QStringList({idMap.value("title").toString(), + idMap.value("firstName").toString(), + idMap.value("middleName").toString(), + idMap.value("lastName").toString()}); + attrs.removeAll(""); + entry->attributes()->set("identity_name", attrs.join(" ")); + + // Combine all the address attributes + attrs = QStringList({idMap.value("address1").toString(), + idMap.value("address2").toString(), + idMap.value("address3").toString()}); + attrs.removeAll(""); + auto address = attrs.join("\n") + "\n" + idMap.value("city").toString() + ", " + + idMap.value("state").toString() + " " + idMap.value("postalCode").toString() + "\n" + + idMap.value("country").toString(); + entry->attributes()->set("identity_address", address); + + // Add the remaining attributes + attrs = QStringList({"company", "email", "phone", "ssn", "passportNumber", "licenseNumber"}); + const QStringList sensitive({"ssn", "passportNumber", "licenseNumber"}); + for (const auto& attr : attrs) { + const auto value = idMap.value(attr).toString(); + if (!value.isEmpty()) { + entry->attributes()->set("identity_" + attr, value, sensitive.contains(attr)); + } + } + + // Set the username or push it into attributes if already set + const auto username = idMap.value("username").toString(); + if (!username.isEmpty()) { + if (entry->username().isEmpty()) { + entry->setUsername(username); + } else { + entry->attributes()->set("identity_username", username); + } + } + } + + // Parse card details if present + if (itemMap.contains("card")) { + const auto cardMap = itemMap.value("card").toMap(); + const QStringList attrs({"cardholderName", "brand", "number", "expMonth", "expYear", "code"}); + const QStringList sensitive({"code"}); + for (const auto& attr : attrs) { + auto value = cardMap.value(attr).toString(); + if (!value.isEmpty()) { + entry->attributes()->set("card_" + attr, value, sensitive.contains(attr)); + } + } + } + + // Parse remaining fields + for (const auto& field : itemMap.value("fields").toList()) { + // Derive a prefix for attribute names using the title or uuid if missing + const auto fieldMap = field.toMap(); + auto name = fieldMap.value("name").toString(); + if (entry->attributes()->hasKey(name)) { + name = QString("%1_%2").arg(name, QUuid::createUuid().toString().mid(1, 5)); + } + + const auto value = fieldMap.value("value").toString(); + const auto type = fieldMap.value("type").toInt(); + + entry->attributes()->set(name, value, type == 1); + } + + // Collapse any accumulated history + entry->removeHistoryItems(entry->historyItems()); + + return entry.take(); + } + + void writeVaultToDatabase(const QJsonObject& vault, QSharedPointer db) + { + if (!vault.contains("folders") || !vault.contains("items")) { + // Early out if the vault is missing critical items + return; + } + + // Create groups from folders and store a temporary map of id -> uuid + QMap folderMap; + for (const auto& folder : vault.value("folders").toArray()) { + auto group = new Group(); + group->setUuid(QUuid::createUuid()); + group->setName(folder.toObject().value("name").toString()); + group->setParent(db->rootGroup()); + + folderMap.insert(folder.toObject().value("id").toString(), group); + } + + QString folderId; + const auto items = vault.value("items").toArray(); + for (const auto& item : items) { + auto entry = readItem(item.toObject(), folderId); + if (entry) { + entry->setGroup(folderMap.value(folderId, db->rootGroup()), false); + } + } + } +} // namespace + +bool BitwardenReader::hasError() +{ + return !m_error.isEmpty(); +} + +QString BitwardenReader::errorString() +{ + return m_error; +} + +QSharedPointer BitwardenReader::convert(const QString& path, const QString& password) +{ + m_error.clear(); + + QFileInfo fileinfo(path); + if (!fileinfo.exists()) { + m_error = QObject::tr("File does not exist.").arg(path); + return {}; + } + + // Bitwarden uses a json file format + QFile file(fileinfo.absoluteFilePath()); + if (!file.open(QFile::ReadOnly)) { + m_error = QObject::tr("Cannot open file: %1").arg(file.errorString()); + return {}; + } + + QJsonParseError error; + auto json = QJsonDocument::fromJson(file.readAll(), &error).object(); + if (error.error != QJsonParseError::NoError) { + m_error = + QObject::tr("Cannot parse file: %1 at position %2").arg(error.errorString(), QString::number(error.offset)); + return {}; + } + + file.close(); + + // Check if this is an encrypted json + if (json.contains("encrypted") && json.value("encrypted").toBool()) { + auto buildError = [](const QString& errorString) { + return QObject::tr("Failed to decrypt json file: %1").arg(errorString); + }; + + QByteArray key(32, '\0'); + auto salt = json.value("salt").toString().toUtf8(); + + auto pwd_fam = Botan::PasswordHashFamily::create_or_throw("PBKDF2(SHA-256)"); + auto kdf = Botan::KDF::create_or_throw("HKDF-Expand(SHA-256)"); + + // Derive the Master Key + auto pwd_hash = pwd_fam->from_params(json.value("kdfIterations").toInt()); + pwd_hash->derive_key(reinterpret_cast(key.data()), + key.size(), + password.toUtf8().data(), + password.toUtf8().size(), + reinterpret_cast(salt.data()), + salt.size()); + // Derive the MAC Key + auto stretched_mac = kdf->derive_key(32, reinterpret_cast(key.data()), key.size(), "", "mac"); + auto mac = QByteArray(reinterpret_cast(stretched_mac.data()), stretched_mac.size()); + + // Stretch the Master Key + auto stretched_key = kdf->derive_key(32, reinterpret_cast(key.data()), key.size(), "", "enc"); + key = QByteArray(reinterpret_cast(stretched_key.data()), stretched_key.size()); + + // Validate the encryption key + auto keyList = json.value("encKeyValidation_DO_NOT_EDIT").toString().split("."); + if (keyList.size() < 2) { + m_error = buildError(QObject::tr("Invalid encKeyValidation field")); + return {}; + } + auto cipherList = keyList[1].split("|"); + if (cipherList.size() < 3) { + m_error = buildError(QObject::tr("Invalid cipher list within encKeyValidation field")); + return {}; + } + CryptoHash hash(CryptoHash::Sha256, true); + hash.setKey(mac); + hash.addData(QByteArray::fromBase64(cipherList[0].toUtf8())); // iv + hash.addData(QByteArray::fromBase64(cipherList[1].toUtf8())); // ciphertext + if (hash.result().toBase64() != cipherList[2].toUtf8()) { + // Calculated MAC doesn't equal the Validation + m_error = buildError(QObject::tr("Wrong password")); + return {}; + } + + // Decrypt data field using AES-256-CBC + keyList = json.value("data").toString().split("."); + if (keyList.size() < 2) { + m_error = buildError(QObject::tr("Invalid encrypted data field")); + return {}; + } + cipherList = keyList[1].split("|"); + if (cipherList.size() < 2) { + m_error = buildError(QObject::tr("Invalid cipher list within encrypted data field")); + return {}; + } + auto iv = QByteArray::fromBase64(cipherList[0].toUtf8()); + auto data = QByteArray::fromBase64(cipherList[1].toUtf8()); + + SymmetricCipher cipher; + if (!cipher.init(SymmetricCipher::Aes256_CBC, SymmetricCipher::Decrypt, key, iv)) { + m_error = buildError(QObject::tr("Cannot initialize cipher")); + return {}; + } + if (!cipher.finish(data)) { + m_error = buildError(QObject::tr("Cannot decrypt data")); + return {}; + } + + json = QJsonDocument::fromJson(data, &error).object(); + if (error.error != QJsonParseError::NoError) { + m_error = buildError(error.errorString()); + return {}; + } + } + + auto db = QSharedPointer::create(); + db->rootGroup()->setName(QObject::tr("Bitwarden Import")); + + writeVaultToDatabase(json, db); + + return db; +} diff --git a/tests/TestOpVaultReader.h b/src/format/BitwardenReader.h similarity index 51% rename from tests/TestOpVaultReader.h rename to src/format/BitwardenReader.h index feb904c6d..52e1e6f70 100644 --- a/tests/TestOpVaultReader.h +++ b/src/format/BitwardenReader.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 KeePassXC Team + * Copyright (C) 2023 KeePassXC Team * * 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 @@ -15,31 +15,29 @@ * along with this program. If not, see . */ -#ifndef TEST_OPVAULT_READER_H_ -#define TEST_OPVAULT_READER_H_ +#ifndef BITWARDEN_READER_H +#define BITWARDEN_READER_H -#include -#include +#include -class TestOpVaultReader : public QObject +class Database; + +/*! + * Imports a Bitwarden vault in JSON format: https://bitwarden.com/help/encrypted-export/ + */ +class BitwardenReader { - Q_OBJECT +public: + explicit BitwardenReader() = default; + ~BitwardenReader() = default; -private slots: - void initTestCase(); - void testReadIntoDatabase(); + QSharedPointer convert(const QString& path, const QString& password = {}); + + bool hasError(); + QString errorString(); private: - // absolute path to the .opvault directory - QString m_opVaultPath; - - /* - * Points to the file made by using the 1Password GUI to "Export all" - * to its text file format, which are almost key=value pairs - * except for multi-line strings. - */ - QString m_opVaultTextExportPath; - QStringList m_categories; + QString m_error; }; -#endif /* TEST_OPVAULT_READER_H_ */ +#endif // BITWARDEN_READER_H diff --git a/src/format/CsvParser.cpp b/src/format/CsvParser.cpp index a376e3662..0e174fe35 100644 --- a/src/format/CsvParser.cpp +++ b/src/format/CsvParser.cpp @@ -24,20 +24,13 @@ #include "core/Tools.h" CsvParser::CsvParser() - : m_ch(0) - , m_comment('#') - , m_currCol(1) - , m_currRow(1) + : m_comment('#') , m_isBackslashSyntax(false) - , m_isEof(false) , m_isFileLoaded(false) - , m_isGood(true) - , m_lastPos(-1) - , m_maxCols(0) , m_qualifier('"') , m_separator(',') - , m_statusMsg("") { + reset(); m_csv.setBuffer(&m_array); m_ts.setDevice(&m_csv); m_csv.open(QIODevice::ReadOnly); @@ -105,10 +98,10 @@ void CsvParser::reset() m_isGood = true; m_lastPos = -1; m_maxCols = 0; - m_statusMsg = ""; + m_statusMsg.clear(); m_ts.seek(0); m_table.clear(); - // the following are users' concern :) + // the following can be overridden by the user // m_comment = '#'; // m_backslashSyntax = false; // m_comment = '#'; @@ -148,7 +141,7 @@ void CsvParser::parseRecord() do { parseField(row); getChar(m_ch); - } while (isSeparator(m_ch) && !m_isEof); + } while (m_ch == m_separator && !m_isEof); if (!m_isEof) { ungetChar(); @@ -168,7 +161,7 @@ void CsvParser::parseField(CsvRow& row) { QString field; peek(m_ch); - if (!isTerminator(m_ch)) { + if (m_ch != m_separator && m_ch != '\n' && m_ch != '\r') { if (isQualifier(m_ch)) { parseQuoted(field); } else { @@ -182,7 +175,7 @@ void CsvParser::parseSimple(QString& s) { QChar c; getChar(c); - while ((isText(c)) && (!m_isEof)) { + while (c != '\n' && c != m_separator && !m_isEof) { s.append(c); getChar(c); } @@ -215,7 +208,7 @@ void CsvParser::parseEscaped(QString& s) void CsvParser::parseEscapedText(QString& s) { getChar(m_ch); - while ((!isQualifier(m_ch)) && !m_isEof) { + while (!isQualifier(m_ch) && !m_isEof) { s.append(m_ch); getChar(m_ch); } @@ -223,10 +216,9 @@ void CsvParser::parseEscapedText(QString& s) bool CsvParser::processEscapeMark(QString& s, QChar c) { - QChar buf; - peek(buf); QChar c2; - if (true == m_isBackslashSyntax) { + peek(c2); + if (m_isBackslashSyntax) { // escape-character syntax, e.g. \" if (c != '\\') { return false; @@ -237,25 +229,24 @@ bool CsvParser::processEscapeMark(QString& s, QChar c) c2 = '\\'; s.append('\\'); return false; - } else { - s.append(c2); - return true; - } - } else { - // double quote syntax, e.g. "" - if (!isQualifier(c)) { - return false; - } - peek(c2); - if (!m_isEof) { // not EOF, can read one char - if (isQualifier(c2)) { - s.append(c2); - getChar(c2); - return true; - } } + s.append(c2); + return true; + } + + // double quote syntax, e.g. "" + if (!isQualifier(c)) { return false; } + peek(c2); + if (!m_isEof) { // not EOF, can read one char + if (isQualifier(c2)) { + s.append(c2); + getChar(c2); + return true; + } + } + return false; } void CsvParser::fillColumns() @@ -282,7 +273,7 @@ void CsvParser::skipLine() bool CsvParser::skipEndline() { getChar(m_ch); - return (m_ch == '\n'); + return m_ch == '\n'; } void CsvParser::getChar(QChar& c) @@ -312,11 +303,10 @@ void CsvParser::peek(QChar& c) bool CsvParser::isQualifier(const QChar& c) const { - if (true == m_isBackslashSyntax && (c != m_qualifier)) { - return (c == '\\'); - } else { - return (c == m_qualifier); + if (m_isBackslashSyntax && c != m_qualifier) { + return c == '\\'; } + return c == m_qualifier; } bool CsvParser::isComment() @@ -327,7 +317,7 @@ bool CsvParser::isComment() do { getChar(c2); - } while ((isSpace(c2) || isTab(c2)) && (!m_isEof)); + } while ((c2 == ' ' || c2 == '\t') && !m_isEof); if (c2 == m_comment) { result = true; @@ -336,47 +326,16 @@ bool CsvParser::isComment() return result; } -bool CsvParser::isText(QChar c) const -{ - return !((isCRLF(c)) || (isSeparator(c))); -} - bool CsvParser::isEmptyRow(const CsvRow& row) const { - CsvRow::const_iterator it = row.constBegin(); - for (; it != row.constEnd(); ++it) { - if (((*it) != "\n") && ((*it) != "")) { + for (auto it = row.constBegin(); it != row.constEnd(); ++it) { + if (*it != "\n" && *it != "") { return false; } } return true; } -bool CsvParser::isCRLF(const QChar& c) const -{ - return (c == '\n'); -} - -bool CsvParser::isSpace(const QChar& c) const -{ - return (c == ' '); -} - -bool CsvParser::isTab(const QChar& c) const -{ - return (c == '\t'); -} - -bool CsvParser::isSeparator(const QChar& c) const -{ - return (c == m_separator); -} - -bool CsvParser::isTerminator(const QChar& c) const -{ - return (isSeparator(c) || (c == '\n') || (c == '\r')); -} - void CsvParser::setBackslashSyntax(bool set) { m_isBackslashSyntax = set; @@ -407,7 +366,7 @@ int CsvParser::getFileSize() const return m_csv.size(); } -const CsvTable CsvParser::getCsvTable() const +CsvTable CsvParser::getCsvTable() const { return m_table; } @@ -421,9 +380,8 @@ int CsvParser::getCsvCols() const { if (!m_table.isEmpty() && !m_table.at(0).isEmpty()) { return m_table.at(0).size(); - } else { - return 0; } + return 0; } int CsvParser::getCsvRows() const diff --git a/src/format/CsvParser.h b/src/format/CsvParser.h index 73fb13d24..afba9688d 100644 --- a/src/format/CsvParser.h +++ b/src/format/CsvParser.h @@ -47,7 +47,7 @@ public: int getCsvRows() const; int getCsvCols() const; QString getStatus() const; - const CsvTable getCsvTable() const; + CsvTable getCsvTable() const; protected: CsvTable m_table; @@ -74,15 +74,9 @@ private: void ungetChar(); void peek(QChar& c); void fillColumns(); - bool isTerminator(const QChar& c) const; - bool isSeparator(const QChar& c) const; bool isQualifier(const QChar& c) const; bool processEscapeMark(QString& s, QChar c); - bool isText(QChar c) const; bool isComment(); - bool isCRLF(const QChar& c) const; - bool isSpace(const QChar& c) const; - bool isTab(const QChar& c) const; bool isEmptyRow(const CsvRow& row) const; bool parseFile(); void parseRecord(); diff --git a/src/format/KeePass1Reader.cpp b/src/format/KeePass1Reader.cpp index 0b7f168a4..1461b22c5 100644 --- a/src/format/KeePass1Reader.cpp +++ b/src/format/KeePass1Reader.cpp @@ -18,6 +18,7 @@ #include "KeePass1Reader.h" #include +#include #include #include "core/Endian.h" @@ -275,6 +276,10 @@ KeePass1Reader::readDatabase(const QString& filename, const QString& password, c return {}; } + if (db) { + db->metadata()->setName(QFileInfo(filename).completeBaseName()); + } + return db; } diff --git a/src/format/OPUXReader.cpp b/src/format/OPUXReader.cpp new file mode 100644 index 000000000..d52aa4640 --- /dev/null +++ b/src/format/OPUXReader.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2023 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "OPUXReader.h" + +#include "core/Database.h" +#include "core/Entry.h" +#include "core/Group.h" +#include "core/Metadata.h" +#include "core/Totp.h" + +#include +#include +#include +#include +#include +#include + +#include + +namespace +{ + QByteArray extractFile(unzFile uf, QString filename) + { + if (unzLocateFile(uf, filename.toLatin1(), 2) != UNZ_OK) { + qWarning("Failed to extract 1PUX document: %s", qPrintable(filename)); + return {}; + } + + // Read export.data into memory + int bytes, bytesRead = 0; + QByteArray data; + unzOpenCurrentFile(uf); + do { + data.resize(data.size() + 8192); + bytes = unzReadCurrentFile(uf, data.data() + bytesRead, 8192); + if (bytes > 0) { + bytesRead += bytes; + } + } while (bytes > 0); + unzCloseCurrentFile(uf); + data.truncate(bytesRead); + + return data; + } + + Entry* readItem(const QJsonObject& item, unzFile uf = nullptr) + { + const auto itemMap = item.toVariantMap(); + const auto overviewMap = itemMap.value("overview").toMap(); + const auto detailsMap = itemMap.value("details").toMap(); + + // Create entry and assign basic values + QScopedPointer entry(new Entry()); + entry->setUuid(QUuid::createUuid()); + entry->setTitle(overviewMap.value("title").toString()); + entry->setUrl(overviewMap.value("url").toString()); + if (overviewMap.contains("urls")) { + int i = 1; + for (const auto& urlRaw : overviewMap.value("urls").toList()) { + const auto urlMap = urlRaw.toMap(); + const auto url = urlMap.value("url").toString(); + if (entry->url() != url) { + entry->attributes()->set( + QString("%1_%2").arg(EntryAttributes::AdditionalUrlAttribute, QString::number(i)), url); + ++i; + } + } + } + if (overviewMap.contains("tags")) { + entry->setTags(overviewMap.value("tags").toStringList().join(",")); + } + if (itemMap.value("favIndex").toString() == "1") { + entry->addTag(QObject::tr("Favorite", "Tag for favorite entries")); + } + if (itemMap.value("state").toString() == "archived") { + entry->addTag(QObject::tr("Archived", "Tag for archived entries")); + } + + // Parse the details map by setting the username, password, and notes first + const auto loginFields = detailsMap.value("loginFields").toList(); + for (const auto& field : loginFields) { + const auto fieldMap = field.toMap(); + const auto designation = fieldMap.value("designation").toString(); + if (designation.compare("username", Qt::CaseInsensitive) == 0) { + entry->setUsername(fieldMap.value("value").toString()); + } else if (designation.compare("password", Qt::CaseInsensitive) == 0) { + entry->setPassword(fieldMap.value("value").toString()); + } + } + entry->setNotes(detailsMap.value("notesPlain").toString()); + + // Dive into the item sections to pull out advanced attributes + const auto sections = detailsMap.value("sections").toList(); + for (const auto& section : sections) { + // Derive a prefix for attribute names using the title or uuid if missing + const auto sectionMap = section.toMap(); + auto prefix = sectionMap.value("title").toString(); + if (prefix.isEmpty()) { + prefix = QUuid::createUuid().toString().mid(1, 5); + } + + for (const auto& field : sectionMap.value("fields").toList()) { + // Form the name of the attribute using the prefix and title or id + const auto fieldMap = field.toMap(); + auto name = fieldMap.value("title").toString(); + if (name.isEmpty()) { + name = fieldMap.value("id").toString(); + } + name = QString("%1_%2").arg(prefix, name); + + const auto valueMap = fieldMap.value("value").toMap(); + const auto key = valueMap.firstKey(); + if (key == "totp") { + // Build otpauth url + QUrl otpurl(QString("otpauth://totp/%1:%2?secret=%3") + .arg(entry->title(), entry->username(), valueMap.value(key).toString())); + + if (entry->hasTotp()) { + // Store multiple TOTP definitions as additional otp attributes + int i = 0; + name = "otp"; + const auto attributes = entry->attributes()->keys(); + while (attributes.contains(name)) { + name = QString("otp_%1").arg(++i); + } + entry->attributes()->set(name, otpurl.toEncoded(), true); + } else { + // First otp value encountered gets formal storage + entry->setTotp(Totp::parseSettings(otpurl.toEncoded())); + } + } else if (key == "file") { + // Add a file to the entry attachments + const auto fileMap = valueMap.value(key).toMap(); + const auto fileName = fileMap.value("fileName").toString(); + const auto docId = fileMap.value("documentId").toString(); + const auto data = extractFile(uf, QString("files/%1__%2").arg(docId, fileName)); + if (!data.isNull()) { + entry->attachments()->set(fileName, data); + } + } else { + auto value = valueMap.value(key).toString(); + if (key == "date") { + // Convert date fields from Unix time + value = QDateTime::fromSecsSinceEpoch(valueMap.value(key).toULongLong(), Qt::UTC).toString(); + } else if (key == "email") { + // Email address is buried in a sub-value + value = valueMap.value(key).toMap().value("email_address").toString(); + } else if (key == "address") { + // Combine all the address attributes into a fully formed structure + const auto address = valueMap.value(key).toMap(); + value = address.value("street").toString() + "\n" + address.value("city").toString() + ", " + + address.value("state").toString() + " " + address.value("zip").toString() + "\n" + + address.value("country").toString(); + } + + if (!value.isEmpty()) { + entry->attributes()->set(name, value, key == "concealed"); + } + } + } + } + + // Add a document attachment if defined + if (detailsMap.contains("documentAttributes")) { + const auto document = detailsMap.value("documentAttributes").toMap(); + const auto fileName = document.value("fileName").toString(); + const auto docId = document.value("documentId").toString(); + const auto data = extractFile(uf, QString("files/%1__%2").arg(docId, fileName)); + if (!data.isNull()) { + entry->attachments()->set(fileName, data); + } + } + + // Collapse any accumulated history + entry->removeHistoryItems(entry->historyItems()); + + // Adjust the created and modified times + auto timeInfo = entry->timeInfo(); + const auto createdTime = QDateTime::fromSecsSinceEpoch(itemMap.value("createdAt").toULongLong(), Qt::UTC); + const auto modifiedTime = QDateTime::fromSecsSinceEpoch(itemMap.value("updatedAt").toULongLong(), Qt::UTC); + timeInfo.setCreationTime(createdTime); + timeInfo.setLastModificationTime(modifiedTime); + timeInfo.setLastAccessTime(modifiedTime); + entry->setTimeInfo(timeInfo); + + return entry.take(); + } + + void writeVaultToDatabase(const QJsonObject& vault, QSharedPointer db, unzFile uf = nullptr) + { + if (!vault.contains("attrs") || !vault.contains("items")) { + // Early out if the vault is missing critical items + return; + } + + const auto attr = vault.value("attrs").toObject().toVariantMap(); + + // Create group and assign basic values + auto group = new Group(); + group->setUuid(QUuid::createUuid()); + group->setName(attr.value("name").toString()); + group->setParent(db->rootGroup()); + + const auto items = vault.value("items").toArray(); + for (const auto& item : items) { + auto entry = readItem(item.toObject(), uf); + if (entry) { + entry->setGroup(group, false); + } + } + + // Add the group icon if present + const auto icon = attr.value("avatar").toString(); + if (!icon.isEmpty()) { + auto data = extractFile(uf, QString("files/%1").arg(icon)); + if (!data.isNull()) { + const auto uuid = QUuid::createUuid(); + db->metadata()->addCustomIcon(uuid, data); + group->setIcon(uuid); + } + } + } +} // namespace + +bool OPUXReader::hasError() +{ + return !m_error.isEmpty(); +} + +QString OPUXReader::errorString() +{ + return m_error; +} + +QSharedPointer OPUXReader::convert(const QString& path) +{ + m_error.clear(); + + QFileInfo fileinfo(path); + if (!fileinfo.exists()) { + m_error = QObject::tr("File does not exist.").arg(path); + return {}; + } + + // 1PUX is a zip file format, open it and process the contents in memory + auto uf = unzOpen64(fileinfo.absoluteFilePath().toLatin1().constData()); + if (!uf) { + m_error = QObject::tr("Invalid 1PUX file format: Not a valid ZIP file."); + return {}; + } + + // Find the export.data file, if not found this isn't a 1PUX file + auto data = extractFile(uf, "export.data"); + if (data.isNull()) { + m_error = QObject::tr("Invalid 1PUX file format: Missing export.data"); + unzClose(uf); + return {}; + } + + auto db = QSharedPointer::create(); + db->rootGroup()->setName(QObject::tr("1Password Import")); + const auto json = QJsonDocument::fromJson(data); + + const auto account = json.object().value("accounts").toArray().first().toObject(); + const auto vaults = account.value("vaults").toArray(); + + for (const auto& vault : vaults) { + writeVaultToDatabase(vault.toObject(), db, uf); + } + + unzClose(uf); + return db; +} diff --git a/src/gui/OpVaultOpenWidget.h b/src/format/OPUXReader.h similarity index 58% rename from src/gui/OpVaultOpenWidget.h rename to src/format/OPUXReader.h index aed96caba..e2779c814 100644 --- a/src/gui/OpVaultOpenWidget.h +++ b/src/format/OPUXReader.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 KeePassXC Team + * Copyright (C) 2023 KeePassXC Team * * 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 @@ -15,20 +15,29 @@ * along with this program. If not, see . */ -#ifndef KEEPASSXC_OPVAULTOPENWIDGET_H -#define KEEPASSXC_OPVAULTOPENWIDGET_H +#ifndef OPUX_READER_H +#define OPUX_READER_H -#include "gui/DatabaseOpenWidget.h" +#include -class OpVaultOpenWidget : public DatabaseOpenWidget +class Database; + +/*! + * Imports a 1Password vault in 1PUX format: https://support.1password.com/1pux-format/ + */ +class OPUXReader { - Q_OBJECT - public: - explicit OpVaultOpenWidget(QWidget* parent = nullptr); + explicit OPUXReader() = default; + ~OPUXReader() = default; -protected: - void openDatabase() override; + QSharedPointer convert(const QString& path); + + bool hasError(); + QString errorString(); + +private: + QString m_error; }; -#endif // KEEPASSXC_OPVAULTOPENWIDGET_H +#endif // OPUX_READER_H diff --git a/src/format/OpVaultReader.cpp b/src/format/OpVaultReader.cpp index 201354bce..fa4034a00 100644 --- a/src/format/OpVaultReader.cpp +++ b/src/format/OpVaultReader.cpp @@ -31,7 +31,6 @@ OpVaultReader::OpVaultReader(QObject* parent) : QObject(parent) - , m_error(false) { } @@ -39,62 +38,44 @@ OpVaultReader::~OpVaultReader() { } -Database* OpVaultReader::readDatabase(QDir& opdataDir, const QString& password) +QSharedPointer OpVaultReader::convert(QDir& opdataDir, const QString& password) { if (!opdataDir.exists()) { - m_error = true; - m_errorStr = tr("Directory .opvault must exist"); - return nullptr; + m_error = tr("Directory .opvault must exist"); + return {}; } if (!opdataDir.isReadable()) { - m_error = true; - m_errorStr = tr("Directory .opvault must be readable"); - return nullptr; + m_error = tr("Directory .opvault must be readable"); + return {}; } // https://support.1password.com/opvault-design/#directory-layout QDir defaultDir = QDir(opdataDir); if (!defaultDir.cd("default")) { - m_error = true; - m_errorStr = tr("Directory .opvault/default must exist"); - return nullptr; + m_error = tr("Directory .opvault/default must exist"); + return {}; } if (!defaultDir.isReadable()) { - m_error = true; - m_errorStr = tr("Directory .opvault/default must be readable"); - return nullptr; + m_error = tr("Directory .opvault/default must be readable"); + return {}; } auto vaultName = opdataDir.dirName(); - auto key = QSharedPointer::create(); - key->addKey(QSharedPointer::create(password)); - - QScopedPointer db(new Database()); - db->setKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2D)); - db->setCipher(KeePass2::CIPHER_AES256); - db->setKey(key, true, false); - db->metadata()->setName(vaultName); - + auto db = QSharedPointer::create(); auto rootGroup = db->rootGroup(); - rootGroup->setTimeInfo({}); - rootGroup->setUpdateTimeinfo(false); rootGroup->setName(vaultName.remove(".opvault")); - rootGroup->setUuid(QUuid::createUuid()); populateCategoryGroups(rootGroup); QFile profileJsFile(defaultDir.absoluteFilePath("profile.js")); QJsonObject profileJson = readAndAssertJsonFile(profileJsFile, "var profile=", ";"); if (profileJson.isEmpty()) { - return nullptr; + return {}; } if (!processProfileJson(profileJson, password, rootGroup)) { zeroKeys(); - return nullptr; - } - if (profileJson.contains("uuid") and profileJson["uuid"].isString()) { - rootGroup->setUuid(Tools::hexToUuid(profileJson["uuid"].toString())); + return {}; } QFile foldersJsFile(defaultDir.filePath("folders.js")); @@ -102,7 +83,7 @@ Database* OpVaultReader::readDatabase(QDir& opdataDir, const QString& password) QJsonObject foldersJs = readAndAssertJsonFile(foldersJsFile, "loadFolders(", ");"); if (!processFolderJson(foldersJs, rootGroup)) { zeroKeys(); - return nullptr; + return {}; } } @@ -152,17 +133,17 @@ Database* OpVaultReader::readDatabase(QDir& opdataDir, const QString& password) } zeroKeys(); - return db.take(); + return db; } bool OpVaultReader::hasError() { - return m_error; + return !m_error.isEmpty(); } QString OpVaultReader::errorString() { - return m_errorStr; + return m_error; } bool OpVaultReader::processProfileJson(QJsonObject& profileJson, const QString& password, Group* rootGroup) @@ -184,38 +165,29 @@ bool OpVaultReader::processProfileJson(QJsonObject& profileJson, const QString& rootGroupTime.setLastModificationTime(QDateTime::fromTime_t(updatedAt, Qt::UTC)); rootGroup->setUuid(Tools::hexToUuid(profileJson["uuid"].toString())); - const auto derivedKeys = deriveKeysFromPassPhrase(salt, password, iterations); - if (derivedKeys->error) { - m_error = true; - m_errorStr = derivedKeys->errorStr; - delete derivedKeys; + QScopedPointer derivedKeys(deriveKeysFromPassPhrase(salt, password, iterations)); + if (!derivedKeys->error.isEmpty()) { + m_error = derivedKeys->error; return false; } QByteArray encKey = derivedKeys->encrypt; QByteArray hmacKey = derivedKeys->hmac; - delete derivedKeys; - auto masterKeys = decodeB64CompositeKeys(masterKeyB64, encKey, hmacKey); - if (masterKeys->error) { - m_error = true; - m_errorStr = masterKeys->errorStr; - delete masterKeys; + QScopedPointer masterKeys(decodeB64CompositeKeys(masterKeyB64, encKey, hmacKey)); + if (!masterKeys->error.isEmpty()) { + m_error = masterKeys->error; return false; } m_masterKey = masterKeys->encrypt; m_masterHmacKey = masterKeys->hmac; - delete masterKeys; - auto overviewKeys = decodeB64CompositeKeys(overviewKeyB64, encKey, hmacKey); - if (overviewKeys->error) { - m_error = true; - m_errorStr = overviewKeys->errorStr; - delete overviewKeys; + QScopedPointer overviewKeys(decodeB64CompositeKeys(overviewKeyB64, encKey, hmacKey)); + if (!overviewKeys->error.isEmpty()) { + m_error = overviewKeys->error; return false; } m_overviewKey = overviewKeys->encrypt; m_overviewHmacKey = overviewKeys->hmac; - delete overviewKeys; return true; } @@ -340,15 +312,13 @@ QJsonObject OpVaultReader::readAndAssertJsonFile(QFile& file, const QString& str OpVaultReader::DerivedKeyHMAC* OpVaultReader::decodeB64CompositeKeys(const QString& b64, const QByteArray& encKey, const QByteArray& hmacKey) { - auto result = new DerivedKeyHMAC(); OpData01 keyKey01; if (!keyKey01.decodeBase64(b64, encKey, hmacKey)) { - result->error = true; - result->errorStr = tr("Unable to decode masterKey: %1").arg(keyKey01.errorString()); + auto result = new DerivedKeyHMAC(); + result->error = tr("Unable to decode masterKey: %1").arg(keyKey01.errorString()); return result; } - delete result; const QByteArray keyKey = keyKey01.getClearText(); @@ -366,7 +336,6 @@ OpVaultReader::decodeB64CompositeKeys(const QString& b64, const QByteArray& encK OpVaultReader::DerivedKeyHMAC* OpVaultReader::decodeCompositeKeys(const QByteArray& keyKey) { auto result = new DerivedKeyHMAC; - result->error = false; auto digest = CryptoHash::hash(keyKey, CryptoHash::Sha512); result->encrypt = digest.left(32); @@ -385,7 +354,6 @@ OpVaultReader::DerivedKeyHMAC* OpVaultReader::deriveKeysFromPassPhrase(QByteArray& salt, const QString& password, unsigned long iterations) { auto result = new DerivedKeyHMAC; - result->error = false; QByteArray out(64, '\0'); try { @@ -397,8 +365,7 @@ OpVaultReader::deriveKeysFromPassPhrase(QByteArray& salt, const QString& passwor reinterpret_cast(salt.constData()), salt.size()); } catch (std::exception& e) { - result->error = true; - result->errorStr = tr("Unable to derive master key: %1").arg(e.what()); + result->error = tr("Unable to derive master key: %1").arg(e.what()); return result; } diff --git a/src/format/OpVaultReader.h b/src/format/OpVaultReader.h index 0dff45c2d..50ccf0b96 100644 --- a/src/format/OpVaultReader.h +++ b/src/format/OpVaultReader.h @@ -39,7 +39,7 @@ public: explicit OpVaultReader(QObject* parent = nullptr); ~OpVaultReader() override; - Database* readDatabase(QDir& opdataDir, const QString& password); + QSharedPointer convert(QDir& opdataDir, const QString& password); bool hasError(); QString errorString(); @@ -49,8 +49,7 @@ private: { QByteArray encrypt; QByteArray hmac; - bool error; - QString errorStr; + QString error; }; QJsonObject readAndAssertJsonFile(QFile& file, const QString& stripLeading, const QString& stripTrailing); @@ -106,15 +105,14 @@ private: /*! Used to blank the memory after the keys have been used. */ void zeroKeys(); - bool m_error; - QString m_errorStr; + QString m_error; QByteArray m_masterKey; QByteArray m_masterHmacKey; /*! Used to decrypt overview text, such as folder names. */ QByteArray m_overviewKey; QByteArray m_overviewHmacKey; - friend class TestOpVaultReader; + friend class TestImports; }; #endif /* OPVAULT_READER_H_ */ diff --git a/src/format/OpVaultReaderAttachments.cpp b/src/format/OpVaultReaderAttachments.cpp index 7c65b7f5a..c9dc6c76e 100644 --- a/src/format/OpVaultReaderAttachments.cpp +++ b/src/format/OpVaultReaderAttachments.cpp @@ -229,6 +229,10 @@ void OpVaultReader::fillAttachment(Entry* entry, qWarning() << QString("Unexpected type of attachment \"filename\": %1").arg(attFilename.type()); } } + if (entry->attachments()->hasKey(attachKey)) { + // Prepend a random string to the attachment name to avoid collisions + attachKey.prepend(QString("%1_").arg(QUuid::createUuid().toString().mid(1, 5))); + } entry->attachments()->set(attachKey, attachPayload); } diff --git a/src/format/OpVaultReaderSections.cpp b/src/format/OpVaultReaderSections.cpp index d05f8fca1..42da14bb6 100644 --- a/src/format/OpVaultReaderSections.cpp +++ b/src/format/OpVaultReaderSections.cpp @@ -92,7 +92,7 @@ void OpVaultReader::fillFromSectionField(Entry* entry, const QString& sectionNam while (attributes.contains(name)) { name = QString("otp_%1").arg(++i); } - entry->attributes()->set(name, attrValue); + entry->attributes()->set(name, attrValue, true); } else if (attrValue.startsWith("otpauth://")) { QUrlQuery query(attrValue); // at least as of 1Password 7, they don't append the digits= and period= which totp.cpp requires @@ -128,10 +128,14 @@ void OpVaultReader::fillFromSectionField(Entry* entry, const QString& sectionNam } else if (kind == "address") { // Expand address into multiple attributes auto addrFields = field.value("v").toObject().toVariantMap(); - for (auto part : addrFields.keys()) { + for (auto& part : addrFields.keys()) { entry->attributes()->set(attrName + QString("_%1").arg(part), addrFields.value(part).toString()); } } else { + if (entry->attributes()->hasKey(attrName)) { + // Append a random string to the attribute name to avoid collisions + attrName += QString("_%1").arg(QUuid::createUuid().toString().mid(1, 5)); + } entry->attributes()->set(attrName, attrValue, (kind == "password" || kind == "concealed")); } } diff --git a/src/gui/CloneDialog.h b/src/gui/CloneDialog.h index 4f72e9011..649ab1d5f 100644 --- a/src/gui/CloneDialog.h +++ b/src/gui/CloneDialog.h @@ -18,6 +18,8 @@ #ifndef KEEPASSX_CLONEDIALOG_H #define KEEPASSX_CLONEDIALOG_H +#include + #include "core/Database.h" #include "gui/DatabaseWidget.h" diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 1b9802699..949c30513 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -21,6 +21,7 @@ #include #include "autotype/AutoType.h" +#include "core/Merger.h" #include "core/Tools.h" #include "format/CsvExporter.h" #include "gui/Clipboard.h" @@ -28,13 +29,13 @@ #include "gui/DatabaseWidget.h" #include "gui/DatabaseWidgetStateSync.h" #include "gui/FileDialog.h" -#include "gui/HtmlExporter.h" #include "gui/MessageBox.h" #include "gui/export/ExportDialog.h" #ifdef Q_OS_MACOS #include "gui/osutils/macutils/MacUtils.h" #endif #include "gui/wizard/NewDatabaseWizard.h" +#include "wizard/ImportWizard.h" DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) : QTabWidget(parent) @@ -252,24 +253,52 @@ void DatabaseTabWidget::addDatabaseTab(DatabaseWidget* dbWidget, bool inBackgrou connect(dbWidget, SIGNAL(databaseLocked()), SLOT(emitDatabaseLockChanged())); } -void DatabaseTabWidget::importCsv() +DatabaseWidget* DatabaseTabWidget::importFile() { - auto filter = QString("%1 (*.csv);;%2 (*)").arg(tr("CSV file"), tr("All files")); - auto fileName = fileDialog()->getOpenFileName(this, tr("Select CSV file"), FileDialog::getLastDir("csv"), filter); - if (fileName.isEmpty()) { - return; + // Show the import wizard + QScopedPointer wizard(new ImportWizard(this)); + if (!wizard->exec()) { + return nullptr; } - FileDialog::saveLastDir("csv", fileName, true); - - auto db = execNewDatabaseWizard(); + auto db = wizard->database(); if (!db) { - return; + // Import wizard was cancelled + return nullptr; } - auto* dbWidget = new DatabaseWidget(db, this); - addDatabaseTab(dbWidget); - dbWidget->switchToCsvImport(fileName); + auto importInto = wizard->importInto(); + if (importInto.first.isNull()) { + // Start the new database wizard with the imported database + auto newDb = execNewDatabaseWizard(); + if (newDb) { + // Merge the imported db into the new one + Merger merger(db.data(), newDb.data()); + merger.merge(); + // Show the new database + auto dbWidget = new DatabaseWidget(newDb, this); + addDatabaseTab(dbWidget); + newDb->markAsModified(); + return dbWidget; + } + } else { + for (int i = 0, c = count(); i < c; ++i) { + // Find the database and group to import into based on import wizard choice + auto dbWidget = databaseWidgetFromIndex(i); + if (!dbWidget->isLocked() && dbWidget->database()->uuid() == importInto.first) { + auto group = dbWidget->database()->rootGroup()->findGroupByUuid(importInto.second); + if (group) { + // Extract the root group from the import database + auto importGroup = db->setRootGroup(new Group()); + importGroup->setParent(group); + setCurrentIndex(i); + return dbWidget; + } + } + } + } + + return nullptr; } void DatabaseTabWidget::mergeDatabase() @@ -291,44 +320,6 @@ void DatabaseTabWidget::mergeDatabase(const QString& filePath) unlockDatabaseInDialog(currentDatabaseWidget(), DatabaseOpenDialog::Intent::Merge, filePath); } -void DatabaseTabWidget::importKeePass1Database() -{ - auto filter = QString("%1 (*.kdb);;%2 (*)").arg(tr("KeePass 1 database"), tr("All files")); - auto fileName = - fileDialog()->getOpenFileName(this, tr("Open KeePass 1 database"), FileDialog::getLastDir("kp1"), filter); - if (fileName.isEmpty()) { - return; - } - - FileDialog::saveLastDir("kp1", fileName, true); - - auto db = QSharedPointer::create(); - auto* dbWidget = new DatabaseWidget(db, this); - addDatabaseTab(dbWidget); - dbWidget->switchToImportKeepass1(fileName); -} - -void DatabaseTabWidget::importOpVaultDatabase() -{ - auto defaultDir = FileDialog::getLastDir("opvault"); -#ifdef Q_OS_MACOS - QString fileName = fileDialog()->getOpenFileName(this, tr("Open OPVault"), defaultDir, "OPVault (*.opvault)"); -#else - QString fileName = fileDialog()->getExistingDirectory(this, tr("Open OPVault"), defaultDir); -#endif - - if (fileName.isEmpty()) { - return; - } - - FileDialog::saveLastDir("opvault", fileName); - - auto db = QSharedPointer::create(); - auto* dbWidget = new DatabaseWidget(db, this); - addDatabaseTab(dbWidget); - dbWidget->switchToImportOpVault(fileName); -} - /** * Attempt to close the current database and remove its tab afterwards. * @@ -613,43 +604,18 @@ bool DatabaseTabWidget::hasLockableDatabases() const */ QString DatabaseTabWidget::tabName(int index) { - if (index == -1 || index > count()) { - return ""; + auto dbWidget = databaseWidgetFromIndex(index); + if (!dbWidget) { + return {}; } - auto* dbWidget = databaseWidgetFromIndex(index); - - auto db = dbWidget->database(); - Q_ASSERT(db); - if (!db) { - return ""; - } - - QString tabName; - - if (!db->filePath().isEmpty()) { - QFileInfo fileInfo(db->filePath()); - - if (db->metadata()->name().isEmpty()) { - tabName = fileInfo.fileName(); - } else { - tabName = db->metadata()->name(); - } - - setTabToolTip(index, fileInfo.absoluteFilePath()); - } else { - if (db->metadata()->name().isEmpty()) { - tabName = tr("New Database"); - } else { - tabName = tr("%1 [New Database]", "Database tab name modifier").arg(db->metadata()->name()); - } - } + auto tabName = dbWidget->displayName(); if (dbWidget->isLocked()) { tabName = tr("%1 [Locked]", "Database tab name modifier").arg(tabName); } - if (db->isModified()) { + if (dbWidget->database()->isModified()) { tabName.append("*"); } @@ -672,6 +638,7 @@ void DatabaseTabWidget::updateTabName(int index) } index = indexOf(dbWidget); setTabText(index, tabName(index)); + setTabToolTip(index, dbWidget->displayFilePath()); emit tabNameChanged(); } diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index 8f2703878..5c995b536 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -64,9 +64,7 @@ public slots: DatabaseWidget* newDatabase(); void openDatabase(); void mergeDatabase(); - void importCsv(); - void importKeePass1Database(); - void importOpVaultDatabase(); + DatabaseWidget* importFile(); bool saveDatabase(int index = -1); bool saveDatabaseAs(int index = -1); bool saveDatabaseBackup(int index = -1); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index deeec3662..d51e9483d 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -30,20 +30,20 @@ #include #include #include -#include #include "autotype/AutoType.h" #include "core/EntrySearcher.h" #include "core/Merger.h" +#include "core/Tools.h" #include "gui/Clipboard.h" #include "gui/CloneDialog.h" +#include "gui/DatabaseOpenDialog.h" +#include "gui/DatabaseOpenWidget.h" #include "gui/EntryPreviewWidget.h" #include "gui/FileDialog.h" #include "gui/GuiTools.h" -#include "gui/KeePass1OpenWidget.h" #include "gui/MainWindow.h" #include "gui/MessageBox.h" -#include "gui/OpVaultOpenWidget.h" #include "gui/TotpDialog.h" #include "gui/TotpExportSettingsDialog.h" #include "gui/TotpSetupDialog.h" @@ -79,15 +79,12 @@ DatabaseWidget::DatabaseWidget(QSharedPointer db, QWidget* parent) , m_previewSplitter(new QSplitter(m_mainWidget)) , m_searchingLabel(new QLabel(this)) , m_shareLabel(new ElidedLabel(this)) - , m_csvImportWizard(new CsvImportWizard(this)) , m_editEntryWidget(new EditEntryWidget(this)) , m_editGroupWidget(new EditGroupWidget(this)) , m_historyEditEntryWidget(new EditEntryWidget(this)) , m_reportsDialog(new ReportsDialog(this)) , m_databaseSettingDialog(new DatabaseSettingsDialog(this)) , m_databaseOpenWidget(new DatabaseOpenWidget(this)) - , m_keepass1OpenWidget(new KeePass1OpenWidget(this)) - , m_opVaultOpenWidget(new OpVaultOpenWidget(this)) , m_groupView(new GroupView(m_db.data(), this)) , m_tagView(new TagView(this)) , m_saveAttempts(0) @@ -179,12 +176,9 @@ DatabaseWidget::DatabaseWidget(QSharedPointer db, QWidget* parent) m_editEntryWidget->setObjectName("editEntryWidget"); m_editGroupWidget->setObjectName("editGroupWidget"); - m_csvImportWizard->setObjectName("csvImportWizard"); m_reportsDialog->setObjectName("reportsDialog"); m_databaseSettingDialog->setObjectName("databaseSettingsDialog"); m_databaseOpenWidget->setObjectName("databaseOpenWidget"); - m_keepass1OpenWidget->setObjectName("keepass1OpenWidget"); - m_opVaultOpenWidget->setObjectName("opVaultOpenWidget"); addChildWidget(m_mainWidget); addChildWidget(m_editEntryWidget); @@ -193,9 +187,6 @@ DatabaseWidget::DatabaseWidget(QSharedPointer db, QWidget* parent) addChildWidget(m_databaseSettingDialog); addChildWidget(m_historyEditEntryWidget); addChildWidget(m_databaseOpenWidget); - addChildWidget(m_csvImportWizard); - addChildWidget(m_keepass1OpenWidget); - addChildWidget(m_opVaultOpenWidget); // clang-format off connect(m_mainSplitter, SIGNAL(splitterMoved(int,int)), SIGNAL(splitterSizesChanged())); @@ -216,9 +207,6 @@ DatabaseWidget::DatabaseWidget(QSharedPointer db, QWidget* parent) connect(m_reportsDialog, SIGNAL(editFinished(bool)), SLOT(switchToMainView(bool))); connect(m_databaseSettingDialog, SIGNAL(editFinished(bool)), SLOT(switchToMainView(bool))); connect(m_databaseOpenWidget, SIGNAL(dialogFinished(bool)), SLOT(loadDatabase(bool))); - connect(m_keepass1OpenWidget, SIGNAL(dialogFinished(bool)), SLOT(loadDatabase(bool))); - connect(m_opVaultOpenWidget, SIGNAL(dialogFinished(bool)), SLOT(loadDatabase(bool))); - connect(m_csvImportWizard, SIGNAL(importFinished(bool)), SLOT(csvImportFinished(bool))); connect(this, SIGNAL(currentChanged(int)), SLOT(emitCurrentModeChanged())); connect(this, SIGNAL(requestGlobalAutoType(const QString&)), parent, SLOT(performGlobalAutoType(const QString&))); // clang-format on @@ -269,10 +257,8 @@ DatabaseWidget::Mode DatabaseWidget::currentMode() const return Mode::None; } else if (currentWidget() == m_mainWidget) { return Mode::ViewMode; - } else if (currentWidget() == m_databaseOpenWidget || currentWidget() == m_keepass1OpenWidget) { + } else if (currentWidget() == m_databaseOpenWidget) { return Mode::LockedMode; - } else if (currentWidget() == m_csvImportWizard) { - return Mode::ImportMode; } else { return Mode::EditMode; } @@ -323,6 +309,45 @@ bool DatabaseWidget::isEditWidgetModified() const return false; } +QString DatabaseWidget::displayName() const +{ + if (!m_db) { + return {}; + } + + auto displayName = m_db->metadata()->name(); + if (!m_db->filePath().isEmpty()) { + if (displayName.isEmpty()) { + displayName = displayFileName(); + } + } else { + if (displayName.isEmpty()) { + displayName = tr("New Database"); + } else { + displayName = tr("%1 [New Database]", "Database tab name modifier").arg(displayName); + } + } + + return displayName; +} + +QString DatabaseWidget::displayFileName() const +{ + if (m_db) { + QFileInfo fileinfo(m_db->filePath()); + return fileinfo.fileName(); + } + return {}; +} + +QString DatabaseWidget::displayFilePath() const +{ + if (m_db) { + return m_db->canonicalFilePath(); + } + return {}; +} + QHash> DatabaseWidget::splitterSizes() const { return {{Config::GUI_SplitterState, m_mainSplitter->sizes()}, @@ -1337,33 +1362,6 @@ void DatabaseWidget::switchToOpenDatabase(const QString& filePath, const QString m_databaseOpenWidget->enterKey(password, keyFile); } -void DatabaseWidget::switchToCsvImport(const QString& filePath) -{ - setCurrentWidget(m_csvImportWizard); - m_csvImportWizard->load(filePath, m_db.data()); -} - -void DatabaseWidget::csvImportFinished(bool accepted) -{ - if (!accepted) { - emit closeRequest(); - } else { - switchToMainView(); - } -} - -void DatabaseWidget::switchToImportKeepass1(const QString& filePath) -{ - m_keepass1OpenWidget->load(filePath); - setCurrentWidget(m_keepass1OpenWidget); -} - -void DatabaseWidget::switchToImportOpVault(const QString& fileName) -{ - m_opVaultOpenWidget->load(fileName); - setCurrentWidget(m_opVaultOpenWidget); -} - void DatabaseWidget::switchToEntryEdit() { auto entry = m_entryView->currentEntry(); diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 77fa3d7f4..571db44a4 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -19,35 +19,29 @@ #ifndef KEEPASSX_DATABASEWIDGET_H #define KEEPASSX_DATABASEWIDGET_H -#include -#include +#include #include -#include "DatabaseOpenDialog.h" -#include "config-keepassx.h" +#include "core/Database.h" +#include "core/Group.h" +#include "core/Metadata.h" #include "gui/MessageWidget.h" -#include "gui/csvImport/CsvImportWizard.h" #include "gui/entry/EntryModel.h" +class DatabaseOpenDialog; class DatabaseOpenWidget; -class KeePass1OpenWidget; -class OpVaultOpenWidget; class DatabaseSettingsDialog; class ReportsDialog; -class Database; class FileWatcher; class EditEntryWidget; class EditGroupWidget; -class Entry; class EntryView; class EntrySearcher; -class Group; class GroupView; class QFile; class QMenu; class QSplitter; class QLabel; -class MessageWidget; class EntryPreviewWidget; class TagView; class ElidedLabel; @@ -67,7 +61,6 @@ public: enum class Mode { None, - ImportMode, ViewMode, EditMode, LockedMode @@ -104,6 +97,10 @@ public: int numberOfSelectedEntries() const; int currentEntryIndex() const; + QString displayName() const; + QString displayFileName() const; + QString displayFilePath() const; + QStringList customEntryAttributes() const; bool isEditWidgetModified() const; void clearAllWidgets(); @@ -219,11 +216,7 @@ public slots: void switchToOpenDatabase(); void switchToOpenDatabase(const QString& filePath); void switchToOpenDatabase(const QString& filePath, const QString& password, const QString& keyFile); - void switchToCsvImport(const QString& filePath); void performUnlockDatabase(const QString& password, const QString& keyfile = {}); - void csvImportFinished(bool accepted); - void switchToImportKeepass1(const QString& filePath); - void switchToImportOpVault(const QString& fileName); void emptyRecycleBin(); // Search related slots @@ -286,15 +279,12 @@ private: QPointer m_previewSplitter; QPointer m_searchingLabel; QPointer m_shareLabel; - QPointer m_csvImportWizard; QPointer m_editEntryWidget; QPointer m_editGroupWidget; QPointer m_historyEditEntryWidget; QPointer m_reportsDialog; QPointer m_databaseSettingDialog; QPointer m_databaseOpenWidget; - QPointer m_keepass1OpenWidget; - QPointer m_opVaultOpenWidget; QPointer m_groupView; QPointer m_tagView; QPointer m_entryView; diff --git a/src/gui/EntryPreviewWidget.cpp b/src/gui/EntryPreviewWidget.cpp index b7c8ca1bc..3ae0dc08b 100644 --- a/src/gui/EntryPreviewWidget.cpp +++ b/src/gui/EntryPreviewWidget.cpp @@ -31,7 +31,7 @@ #endif #include - +#include namespace { constexpr int GeneralTabIndex = 0; diff --git a/src/gui/EntryPreviewWidget.h b/src/gui/EntryPreviewWidget.h index f4ea8be66..83af07ee9 100644 --- a/src/gui/EntryPreviewWidget.h +++ b/src/gui/EntryPreviewWidget.h @@ -26,6 +26,7 @@ namespace Ui class EntryPreviewWidget; } +class QTabWidget; class QTextEdit; class EntryPreviewWidget : public QWidget diff --git a/src/gui/Icons.cpp b/src/gui/Icons.cpp index 50b9c1e7d..194c6625d 100644 --- a/src/gui/Icons.cpp +++ b/src/gui/Icons.cpp @@ -18,6 +18,7 @@ #include "Icons.h" +#include #include #include #include @@ -25,6 +26,7 @@ #include "config-keepassx.h" #include "core/Config.h" +#include "core/Database.h" #include "gui/DatabaseIcons.h" #include "gui/MainWindow.h" #include "gui/osutils/OSUtils.h" diff --git a/src/gui/KeePass1OpenWidget.cpp b/src/gui/KeePass1OpenWidget.cpp deleted file mode 100644 index 9a485a7f1..000000000 --- a/src/gui/KeePass1OpenWidget.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "KeePass1OpenWidget.h" -#include "ui_DatabaseOpenWidget.h" - -#include - -#include "core/Database.h" -#include "core/Metadata.h" -#include "format/KeePass1Reader.h" - -KeePass1OpenWidget::KeePass1OpenWidget(QWidget* parent) - : DatabaseOpenWidget(parent) -{ - m_ui->labelHeadline->setText(tr("Import KeePass1 Database")); -} - -void KeePass1OpenWidget::openDatabase() -{ - KeePass1Reader reader; - - QString password; - QString keyFileName = m_ui->keyFileLineEdit->text(); - - if (!m_ui->editPassword->text().isEmpty() || m_retryUnlockWithEmptyPassword) { - password = m_ui->editPassword->text(); - } - - QFile file(m_filename); - if (!file.open(QIODevice::ReadOnly)) { - m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n").append(file.errorString()), - MessageWidget::Error); - return; - } - - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - m_db = reader.readDatabase(&file, password, keyFileName); - QApplication::restoreOverrideCursor(); - - if (m_db) { - m_db->metadata()->setName(QFileInfo(m_filename).completeBaseName()); - emit dialogFinished(true); - clearForms(); - } else { - m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n").append(reader.errorString()), - MessageWidget::Error); - } -} diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index d08c709d6..845072ccb 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -388,7 +388,7 @@ MainWindow::MainWindow() m_ui->actionLockAllDatabases->setIcon(icons()->icon("database-lock-all")); m_ui->actionQuit->setIcon(icons()->icon("application-exit")); m_ui->actionDatabaseMerge->setIcon(icons()->icon("database-merge")); - m_ui->menuImport->setIcon(icons()->icon("document-import")); + m_ui->actionImport->setIcon(icons()->icon("document-import")); m_ui->menuExport->setIcon(icons()->icon("document-export")); m_ui->actionEntryNew->setIcon(icons()->icon("entry-new")); @@ -498,9 +498,7 @@ MainWindow::MainWindow() connect(m_ui->actionImportPasskey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importPasskey())); connect(m_ui->actionEntryImportPasskey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importPasskeyToEntry())); #endif - connect(m_ui->actionImportCsv, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importCsv())); - connect(m_ui->actionImportKeePass1, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importKeePass1Database())); - connect(m_ui->actionImportOpVault, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importOpVaultDatabase())); + connect(m_ui->actionImport, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importFile())); connect(m_ui->actionExportCsv, SIGNAL(triggered()), m_ui->tabWidget, SLOT(exportToCsv())); connect(m_ui->actionExportHtml, SIGNAL(triggered()), m_ui->tabWidget, SLOT(exportToHtml())); connect(m_ui->actionExportXML, SIGNAL(triggered()), m_ui->tabWidget, SLOT(exportToXML())); @@ -566,9 +564,7 @@ MainWindow::MainWindow() connect(m_ui->welcomeWidget, SIGNAL(newDatabase()), SLOT(switchToNewDatabase())); connect(m_ui->welcomeWidget, SIGNAL(openDatabase()), SLOT(switchToOpenDatabase())); connect(m_ui->welcomeWidget, SIGNAL(openDatabaseFile(QString)), SLOT(switchToDatabaseFile(QString))); - connect(m_ui->welcomeWidget, SIGNAL(importKeePass1Database()), SLOT(switchToKeePass1Database())); - connect(m_ui->welcomeWidget, SIGNAL(importOpVaultDatabase()), SLOT(switchToOpVaultDatabase())); - connect(m_ui->welcomeWidget, SIGNAL(importCsv()), SLOT(switchToCsvImport())); + connect(m_ui->welcomeWidget, SIGNAL(importFile()), m_ui->tabWidget, SLOT(importFile())); connect(m_ui->actionAbout, SIGNAL(triggered()), SLOT(showAboutDialog())); connect(m_ui->actionDonate, SIGNAL(triggered()), SLOT(openDonateUrl())); @@ -897,7 +893,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionDatabaseNew->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->actionDatabaseOpen->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->menuRecentDatabases->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); - m_ui->menuImport->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); + m_ui->actionImport->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->actionLockDatabase->setEnabled(m_ui->tabWidget->hasLockableDatabases()); m_ui->actionLockDatabaseToolbar->setEnabled(m_ui->tabWidget->hasLockableDatabases()); m_ui->actionLockAllDatabases->setEnabled(m_ui->tabWidget->hasLockableDatabases()); @@ -1011,7 +1007,6 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) break; } case DatabaseWidget::Mode::EditMode: - case DatabaseWidget::Mode::ImportMode: case DatabaseWidget::Mode::LockedMode: { // Enable select actions when editing an entry bool editEntryActive = dbWidget->isEntryEditActive(); @@ -1325,24 +1320,6 @@ void MainWindow::switchToDatabaseFile(const QString& file) switchToDatabases(); } -void MainWindow::switchToKeePass1Database() -{ - m_ui->tabWidget->importKeePass1Database(); - switchToDatabases(); -} - -void MainWindow::switchToOpVaultDatabase() -{ - m_ui->tabWidget->importOpVaultDatabase(); - switchToDatabases(); -} - -void MainWindow::switchToCsvImport() -{ - m_ui->tabWidget->importCsv(); - switchToDatabases(); -} - void MainWindow::databaseStatusChanged(DatabaseWidget* dbWidget) { Q_UNUSED(dbWidget); diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 2e548abc2..1f96a6ec0 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -24,6 +24,7 @@ #include #include #include +#include #include "core/SignalMultiplexer.h" #include "gui/DatabaseWidget.h" @@ -124,9 +125,6 @@ private slots: void switchToNewDatabase(); void switchToOpenDatabase(); void switchToDatabaseFile(const QString& file); - void switchToKeePass1Database(); - void switchToOpVaultDatabase(); - void switchToCsvImport(); void databaseStatusChanged(DatabaseWidget* dbWidget); void databaseTabChanged(int tabIndex); void openRecentDatabase(QAction* action); diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index a0b8d6e68..48574049e 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -231,14 +231,6 @@ &Recent Databases - - - &Import - - - - - &Export @@ -266,7 +258,7 @@ - + @@ -1163,6 +1155,19 @@ Allow Screen Capture + + + 1Password 1PUX... + + + Import a 1Password 1PUX file + + + + + Import… + + diff --git a/src/gui/OpVaultOpenWidget.cpp b/src/gui/OpVaultOpenWidget.cpp deleted file mode 100644 index cae569cf2..000000000 --- a/src/gui/OpVaultOpenWidget.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2019 KeePassXC Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "OpVaultOpenWidget.h" - -#include "core/Database.h" -#include "format/OpVaultReader.h" -#include "ui_DatabaseOpenWidget.h" - -OpVaultOpenWidget::OpVaultOpenWidget(QWidget* parent) - : DatabaseOpenWidget(parent) -{ - m_ui->labelHeadline->setText("Import 1Password Database"); -} - -void OpVaultOpenWidget::openDatabase() -{ - OpVaultReader reader; - - QString password; - password = m_ui->editPassword->text(); - - QDir opVaultDir(m_filename); - - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - m_db.reset(reader.readDatabase(opVaultDir, password)); - QApplication::restoreOverrideCursor(); - - if (m_db) { - emit dialogFinished(true); - } else { - m_ui->messageWidget->showMessage(tr("Read Database did not produce an instance\n%1").arg(reader.errorString()), - MessageWidget::Error); - m_ui->editPassword->clear(); - } -} diff --git a/src/gui/PasswordWidget.h b/src/gui/PasswordWidget.h index 0014b696f..d803b1f81 100644 --- a/src/gui/PasswordWidget.h +++ b/src/gui/PasswordWidget.h @@ -33,6 +33,7 @@ class PasswordWidget : public QWidget { Q_OBJECT + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged USER true) public: explicit PasswordWidget(QWidget* parent = nullptr); ~PasswordWidget() override; diff --git a/src/gui/TotpDialog.h b/src/gui/TotpDialog.h index 1782c2de8..d64549759 100644 --- a/src/gui/TotpDialog.h +++ b/src/gui/TotpDialog.h @@ -19,6 +19,8 @@ #ifndef KEEPASSX_TOTPDIALOG_H #define KEEPASSX_TOTPDIALOG_H +#include + #include "core/Database.h" #include "gui/DatabaseWidget.h" diff --git a/src/gui/TotpExportSettingsDialog.cpp b/src/gui/TotpExportSettingsDialog.cpp index 8e56d5d2e..0568996b1 100644 --- a/src/gui/TotpExportSettingsDialog.cpp +++ b/src/gui/TotpExportSettingsDialog.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include diff --git a/src/gui/TotpExportSettingsDialog.h b/src/gui/TotpExportSettingsDialog.h index 8c80c9be5..ff8308d82 100644 --- a/src/gui/TotpExportSettingsDialog.h +++ b/src/gui/TotpExportSettingsDialog.h @@ -18,6 +18,8 @@ #ifndef KEEPASSX_TotpExportSettingsDialog_H #define KEEPASSX_TotpExportSettingsDialog_H +#include + #include "core/Database.h" #include "gui/DatabaseWidget.h" diff --git a/src/gui/TotpSetupDialog.h b/src/gui/TotpSetupDialog.h index 9781b3954..3822f119f 100644 --- a/src/gui/TotpSetupDialog.h +++ b/src/gui/TotpSetupDialog.h @@ -19,6 +19,8 @@ #ifndef KEEPASSX_SETUPTOTPDIALOG_H #define KEEPASSX_SETUPTOTPDIALOG_H +#include + #include "core/Database.h" #include "gui/DatabaseWidget.h" diff --git a/src/gui/WelcomeWidget.cpp b/src/gui/WelcomeWidget.cpp index 49563ff73..03f3925a6 100644 --- a/src/gui/WelcomeWidget.cpp +++ b/src/gui/WelcomeWidget.cpp @@ -37,14 +37,15 @@ WelcomeWidget::WelcomeWidget(QWidget* parent) m_ui->welcomeLabel->setFont(welcomeLabelFont); m_ui->iconLabel->setPixmap(icons()->applicationIcon().pixmap(64)); + m_ui->buttonNewDatabase->setIcon(icons()->icon("document-new")); + m_ui->buttonOpenDatabase->setIcon(icons()->icon("document-open")); + m_ui->buttonImport->setIcon(icons()->icon("document-import")); refreshLastDatabases(); connect(m_ui->buttonNewDatabase, SIGNAL(clicked()), SIGNAL(newDatabase())); connect(m_ui->buttonOpenDatabase, SIGNAL(clicked()), SIGNAL(openDatabase())); - connect(m_ui->buttonImportKeePass1, SIGNAL(clicked()), SIGNAL(importKeePass1Database())); - connect(m_ui->buttonImportOpVault, SIGNAL(clicked()), SIGNAL(importOpVaultDatabase())); - connect(m_ui->buttonImportCSV, SIGNAL(clicked()), SIGNAL(importCsv())); + connect(m_ui->buttonImport, SIGNAL(clicked()), SIGNAL(importFile())); connect(m_ui->recentListWidget, SIGNAL(itemActivated(QListWidgetItem*)), this, diff --git a/src/gui/WelcomeWidget.h b/src/gui/WelcomeWidget.h index 15f93466c..15c3da7ff 100644 --- a/src/gui/WelcomeWidget.h +++ b/src/gui/WelcomeWidget.h @@ -39,9 +39,7 @@ signals: void newDatabase(); void openDatabase(); void openDatabaseFile(QString); - void importKeePass1Database(); - void importOpVaultDatabase(); - void importCsv(); + void importFile(); protected: void keyPressEvent(QKeyEvent* event) override; diff --git a/src/gui/WelcomeWidget.ui b/src/gui/WelcomeWidget.ui index 8b72df840..7a753e010 100644 --- a/src/gui/WelcomeWidget.ui +++ b/src/gui/WelcomeWidget.ui @@ -70,6 +70,22 @@ + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + @@ -103,40 +119,26 @@ - - - - Create new database - - - - - - - Open existing database - - - - + - Import from KeePass 1 + Create Database - + - Import from 1Password + Open Database - + - Import from CSV + Import File @@ -148,12 +150,12 @@ Qt::Vertical - QSizePolicy::Minimum + QSizePolicy::Fixed 0 - 5 + 20 @@ -193,11 +195,7 @@ - buttonNewDatabase - buttonOpenDatabase - buttonImportKeePass1 - buttonImportOpVault - buttonImportCSV + buttonImport recentListWidget diff --git a/src/gui/csvImport/CsvImportWidget.cpp b/src/gui/csvImport/CsvImportWidget.cpp index 08f6d6589..cbf2ae0a2 100644 --- a/src/gui/csvImport/CsvImportWidget.cpp +++ b/src/gui/csvImport/CsvImportWidget.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2016 Enrico Mariotti * Copyright (C) 2017 KeePassXC Team * @@ -19,38 +19,69 @@ #include "CsvImportWidget.h" #include "ui_CsvImportWidget.h" +#include "core/Clock.h" +#include "core/Database.h" +#include "core/Group.h" +#include "core/Totp.h" +#include "format/CsvParser.h" +#include "format/KeePass2Writer.h" +#include "gui/csvImport/CsvParserModel.h" + #include -#include "core/Clock.h" -#include "core/Totp.h" -#include "format/KeePass2Writer.h" -#include "gui/MessageBox.h" +namespace +{ + // Extract group names from nested path and return the last group created + Group* createGroupStructure(Database* db, const QString& groupPath) + { + auto group = db->rootGroup(); + if (!group || groupPath.isEmpty()) { + return group; + } -// I wanted to make the CSV import GUI future-proof, so if one day you need a new field, -// all you have to do is add a field to m_columnHeader, and the GUI will follow: -// dynamic generation of comboBoxes, labels, placement and so on. Try it for immense fun! + auto nameList = groupPath.split("/", QString::SkipEmptyParts); + // Skip over first group name if root + if (nameList.first().compare("root", Qt::CaseInsensitive)) { + nameList.removeFirst(); + } + + for (const auto& name : qAsConst(nameList)) { + auto child = group->findChildByName(name); + if (!child) { + auto newGroup = new Group(); + newGroup->setUuid(QUuid::createUuid()); + newGroup->setName(name); + newGroup->setParent(group); + group = newGroup; + } else { + group = child; + } + } + return group; + } +} // namespace CsvImportWidget::CsvImportWidget(QWidget* parent) : QWidget(parent) , m_ui(new Ui::CsvImportWidget()) , m_parserModel(new CsvParserModel(this)) , m_comboModel(new QStringListModel(this)) - , m_columnHeader(QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") - << QObject::tr("Password") << QObject::tr("URL") << QObject::tr("Notes") - << QObject::tr("TOTP") << QObject::tr("Icon") << QObject::tr("Last Modified") - << QObject::tr("Created")) - , m_fieldSeparatorList(QStringList() << "," - << ";" - << "-" - << ":" - << "." - << "\t") { m_ui->setupUi(this); m_ui->tableViewFields->setSelectionMode(QAbstractItemView::NoSelection); m_ui->tableViewFields->setFocusPolicy(Qt::NoFocus); - m_ui->messageWidget->setHidden(true); + + m_columnHeader << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") << QObject::tr("Password") + << QObject::tr("URL") << QObject::tr("Notes") << QObject::tr("TOTP") << QObject::tr("Icon") + << QObject::tr("Last Modified") << QObject::tr("Created"); + + m_fieldSeparatorList << "," + << ";" + << "-" + << ":" + << "." + << "\t"; m_combos << m_ui->groupCombo << m_ui->titleCombo << m_ui->usernameCombo << m_ui->passwordCombo << m_ui->urlCombo << m_ui->notesCombo << m_ui->totpCombo << m_ui->iconCombo << m_ui->lastModifiedCombo << m_ui->createdCombo; @@ -70,15 +101,12 @@ CsvImportWidget::CsvImportWidget(QWidget* parent) connect(m_ui->comboBoxFieldSeparator, SIGNAL(currentIndexChanged(int)), SLOT(parse())); connect(m_ui->checkBoxBackslash, SIGNAL(toggled(bool)), SLOT(parse())); connect(m_ui->checkBoxFieldNames, SIGNAL(toggled(bool)), SLOT(updatePreview())); - - connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(writeDatabase())); - connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); } void CsvImportWidget::comboChanged(int index) { // this line is the one that actually updates GUI table - m_parserModel->mapColumns(index, m_combos.indexOf(qobject_cast(sender()))); + m_parserModel->mapColumns(index - 1, m_combos.indexOf(qobject_cast(sender()))); updateTableview(); } @@ -94,68 +122,81 @@ CsvImportWidget::~CsvImportWidget() void CsvImportWidget::configParser() { - m_parserModel->setBackslashSyntax(m_ui->checkBoxBackslash->isChecked()); - m_parserModel->setComment(m_ui->comboBoxComment->currentText().at(0)); - m_parserModel->setTextQualifier(m_ui->comboBoxTextQualifier->currentText().at(0)); - m_parserModel->setCodec(m_ui->comboBoxCodec->currentText()); - m_parserModel->setFieldSeparator(m_fieldSeparatorList.at(m_ui->comboBoxFieldSeparator->currentIndex()).at(0)); + auto parser = m_parserModel->parser(); + parser->setBackslashSyntax(m_ui->checkBoxBackslash->isChecked()); + parser->setComment(m_ui->comboBoxComment->currentText().at(0)); + parser->setTextQualifier(m_ui->comboBoxTextQualifier->currentText().at(0)); + parser->setCodec(m_ui->comboBoxCodec->currentText()); + parser->setFieldSeparator(m_fieldSeparatorList.at(m_ui->comboBoxFieldSeparator->currentIndex()).at(0)); } void CsvImportWidget::updateTableview() { - m_ui->tableViewFields->resizeRowsToContents(); - m_ui->tableViewFields->resizeColumnsToContents(); + if (!m_buildingPreview) { + m_ui->tableViewFields->resizeRowsToContents(); + m_ui->tableViewFields->resizeColumnsToContents(); - for (int c = 0; c < m_ui->tableViewFields->horizontalHeader()->count(); ++c) { - m_ui->tableViewFields->horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch); + for (int c = 0; c < m_ui->tableViewFields->horizontalHeader()->count(); ++c) { + m_ui->tableViewFields->horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch); + } } } void CsvImportWidget::updatePreview() { - int minSkip = 0; - if (m_ui->checkBoxFieldNames->isChecked()) { - minSkip = 1; - } + m_buildingPreview = true; + + int minSkip = m_ui->checkBoxFieldNames->isChecked() ? 1 : 0; m_ui->labelSizeRowsCols->setText(m_parserModel->getFileInfo()); m_ui->spinBoxSkip->setRange(minSkip, qMax(minSkip, m_parserModel->rowCount() - 1)); m_ui->spinBoxSkip->setValue(minSkip); - QStringList list(tr("Not Present")); - for (int i = 1; i < m_parserModel->getCsvCols(); ++i) { + QStringList csvColumns(tr("Not Present")); + auto parser = m_parserModel->parser(); + for (int i = 0; i < parser->getCsvCols(); ++i) { if (m_ui->checkBoxFieldNames->isChecked()) { - auto columnName = m_parserModel->getCsvTable().at(0).at(i); + auto columnName = parser->getCsvTable().at(0).at(i); if (columnName.isEmpty()) { - list << QString(tr("Column %1").arg(i)); + csvColumns << QString(tr("Column %1").arg(i)); } else { - list << columnName; + csvColumns << columnName; } } else { - list << QString(tr("Column %1").arg(i)); + csvColumns << QString(tr("Column %1").arg(i)); } } - m_comboModel->setStringList(list); + m_comboModel->setStringList(csvColumns); - int j = 1; - for (QComboBox* b : m_combos) { - if (j < m_parserModel->getCsvCols()) { - b->setCurrentIndex(j); - } else { - b->setCurrentIndex(0); + // Try to match named columns to the combo boxes + for (int i = 0; i < m_columnHeader.size(); ++i) { + if (i >= m_combos.size()) { + // This should not happen, it is a programming error otherwise + Q_ASSERT(false); + break; + } + + bool found = false; + for (int j = 0; j < csvColumns.size(); ++j) { + if (m_columnHeader.at(i).compare(csvColumns.at(j), Qt::CaseInsensitive) == 0) { + m_combos.at(i)->setCurrentIndex(j); + found = true; + break; + } + } + // Named column not found, default to "Not Present" + if (!found) { + m_combos.at(i)->setCurrentIndex(0); } - ++j; } + + m_buildingPreview = false; + updateTableview(); } -void CsvImportWidget::load(const QString& filename, Database* const db) +void CsvImportWidget::load(const QString& filename) { - // QApplication::processEvents(); - m_db = db; + m_filename = filename; m_parserModel->setFilename(filename); - m_ui->labelFilename->setText(filename); - Group* group = m_db->rootGroup(); - group->setUuid(QUuid::createUuid()); - group->setNotes(tr("Imported from CSV file").append("\n").append(tr("Original data: ")) + filename); parse(); } @@ -163,42 +204,33 @@ void CsvImportWidget::parse() { configParser(); QApplication::setOverrideCursor(Qt::WaitCursor); - // QApplication::processEvents(); + QApplication::processEvents(); bool good = m_parserModel->parse(); updatePreview(); QApplication::restoreOverrideCursor(); if (!good) { - m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file!").append("\n").append(formatStatusText()), - MessageWidget::Warning); - } else { - m_ui->messageWidget->setHidden(true); + emit message(tr("Failed to parse CSV file: %1").arg(formatStatusText())); } } -QString CsvImportWidget::formatStatusText() const +QSharedPointer CsvImportWidget::buildDatabase() { - QString text = m_parserModel->getStatus(); - int items = text.count('\n'); - if (items > 2) { - return text.section('\n', 0, 1).append("\n").append(tr("[%n more message(s) skipped]", "", items - 2)); - } - if (items == 1) { - text.append(QString("\n")); - } - return text; -} + auto db = QSharedPointer::create(); + db->rootGroup()->setNotes(tr("Imported from CSV file: %1").arg(m_filename)); -void CsvImportWidget::writeDatabase() -{ - setRootGroup(); for (int r = 0; r < m_parserModel->rowCount(); ++r) { // use validity of second column as a GO/NOGO for all others fields - if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) { + if (!m_parserModel->data(m_parserModel->index(r, 1)).isValid()) { continue; } - Entry* entry = new Entry(); + auto group = createGroupStructure(db.data(), m_parserModel->data(m_parserModel->index(r, 0)).toString()); + if (!group) { + continue; + } + + auto entry = new Entry(); entry->setUuid(QUuid::createUuid()); - entry->setGroup(splitGroups(m_parserModel->data(m_parserModel->index(r, 0)).toString())); + entry->setGroup(group); entry->setTitle(m_parserModel->data(m_parserModel->index(r, 1)).toString()); entry->setUsername(m_parserModel->data(m_parserModel->index(r, 2)).toString()); entry->setPassword(m_parserModel->data(m_parserModel->index(r, 3)).toString()); @@ -257,99 +289,19 @@ void CsvImportWidget::writeDatabase() } entry->setTimeInfo(timeInfo); } - QBuffer buffer; - buffer.open(QBuffer::ReadWrite); - KeePass2Writer writer; - writer.writeDatabase(&buffer, m_db); - if (writer.hasError()) { - MessageBox::warning(this, - tr("Error"), - tr("CSV import: writer has errors:\n%1").arg(writer.errorString()), - MessageBox::Ok, - MessageBox::Ok); - } - emit editFinished(true); + return db; } -void CsvImportWidget::setRootGroup() +QString CsvImportWidget::formatStatusText() const { - QString groupLabel; - QStringList groupList; - bool is_root = false; - bool is_empty = false; - bool is_label = false; - - for (int r = 0; r < m_parserModel->rowCount(); ++r) { - // use validity of second column as a GO/NOGO for all others fields - if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) { - continue; - } - groupLabel = m_parserModel->data(m_parserModel->index(r, 0)).toString(); - // check if group name is either "root", "" (empty) or some other label - groupList = groupLabel.split("/", QString::SkipEmptyParts); - if (groupList.isEmpty()) { - is_empty = true; - } else if (not groupList.first().compare("Root", Qt::CaseSensitive)) { - is_root = true; - } else if (not groupLabel.compare("")) { - is_empty = true; - } else { - is_label = true; - } - - groupList.clear(); + QString text = m_parserModel->parser()->getStatus(); + int items = text.count('\n'); + if (items > 2) { + return text.section('\n', 0, 1).append("\n").append(tr("[%n more message(s) skipped]", "", items - 2)); } - - if ((is_empty and is_root) or (is_label and not is_empty and is_root)) { - m_db->rootGroup()->setName("CSV IMPORTED"); - } else { - m_db->rootGroup()->setName("Root"); + if (items == 1) { + text.append(QString("\n")); } -} - -Group* CsvImportWidget::splitGroups(const QString& label) -{ - // extract group names from nested path provided in "label" - Group* current = m_db->rootGroup(); - if (label.isEmpty()) { - return current; - } - - QStringList groupList = label.split("/", QString::SkipEmptyParts); - // avoid the creation of a subgroup with the same name as Root - if (m_db->rootGroup()->name() == "Root" && groupList.first() == "Root") { - groupList.removeFirst(); - } - - for (const QString& groupName : groupList) { - Group* children = hasChildren(current, groupName); - if (children == nullptr) { - Group* brandNew = new Group(); - brandNew->setParent(current); - brandNew->setName(groupName); - brandNew->setUuid(QUuid::createUuid()); - current = brandNew; - } else { - Q_ASSERT(children != nullptr); - current = children; - } - } - return current; -} - -Group* CsvImportWidget::hasChildren(Group* current, const QString& groupName) -{ - // returns the group whose name is "groupName" and is child of "current" group - for (Group* group : current->children()) { - if (group->name() == groupName) { - return group; - } - } - return nullptr; -} - -void CsvImportWidget::reject() -{ - emit editFinished(false); + return text; } diff --git a/src/gui/csvImport/CsvImportWidget.h b/src/gui/csvImport/CsvImportWidget.h index 1711e32a6..d5f29c43a 100644 --- a/src/gui/csvImport/CsvImportWidget.h +++ b/src/gui/csvImport/CsvImportWidget.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2016 Enrico Mariotti * Copyright (C) 2017 KeePassXC Team * @@ -19,12 +19,13 @@ #ifndef KEEPASSX_CSVIMPORTWIDGET_H #define KEEPASSX_CSVIMPORTWIDGET_H -#include +#include +#include -#include "core/Metadata.h" -#include "gui/csvImport/CsvParserModel.h" - -class QStringListModel; +class CsvParserModel; +class Database; +class Group; +class QComboBox; namespace Ui { @@ -37,36 +38,36 @@ class CsvImportWidget : public QWidget public: explicit CsvImportWidget(QWidget* parent = nullptr); - ~CsvImportWidget(); - void load(const QString& filename, Database* const db); + ~CsvImportWidget() override; + + void load(const QString& filename); + QSharedPointer buildDatabase(); signals: - void editFinished(bool accepted); + void message(QString msg); private slots: void parse(); void comboChanged(int index); void skippedChanged(int rows); - void writeDatabase(); void updatePreview(); - void setRootGroup(); - void reject(); private: - Q_DISABLE_COPY(CsvImportWidget) - const QScopedPointer m_ui; - CsvParserModel* const m_parserModel; - QStringListModel* const m_comboModel; - QList m_combos; - Database* m_db; - - const QStringList m_columnHeader; - QStringList m_fieldSeparatorList; void configParser(); void updateTableview(); - Group* splitGroups(const QString& label); - Group* hasChildren(Group* current, const QString& groupName); QString formatStatusText() const; + + QScopedPointer m_ui; + + CsvParserModel* m_parserModel; + QStringListModel* m_comboModel; + QList m_combos; + QStringList m_columnHeader; + QStringList m_fieldSeparatorList; + QString m_filename; + bool m_buildingPreview = false; + + Q_DISABLE_COPY(CsvImportWidget) }; #endif // KEEPASSX_CSVIMPORTWIDGET_H diff --git a/src/gui/csvImport/CsvImportWidget.ui b/src/gui/csvImport/CsvImportWidget.ui index 7a5627d98..cd7af9816 100644 --- a/src/gui/csvImport/CsvImportWidget.ui +++ b/src/gui/csvImport/CsvImportWidget.ui @@ -6,763 +6,677 @@ 0 0 - 788 - 530 + 820 + 523 + + 0 + + + 0 + + + 0 + + + 0 + - - - - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 753 - 615 - - - - - - - - 11 - 75 - true - - - - Import CSV fields - - - - - - - - - filename - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - size, rows, columns - - - - - - - - - - - - 75 - true - - - - Column Association - - - - - - - - - - - - 50 - false - - - - Password - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 2 - - - - - - - - 50 - false - - - - Username - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 2 - - - - - - - - - - - - - - 50 - false - - - - Title - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 2 - - - - - - - - - - - 50 - false - - - - Group - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 2 - - - - - - - - 50 - false - - - - URL - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 2 - - - - - - - - - - - 50 - false - - - - Notes - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 2 - - - - - - - - - - - 50 - false - - - - TOTP - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 2 - - - - - - - - - - - - - - 50 - false - - - - Created - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 2 - - - - - - - - 50 - false - - - - Last Modified - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 2 - - - - - - - - - - - 50 - false - - - - Icon - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - 2 - - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - 75 - true - - - - Encoding - - - - - - - 50 - false - - - - Codec - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - false - - - - Codec - - - false - - - UTF-8 - - - - UTF-8 - - - - - Windows-1252 - - - - - UTF-16 - - - - - UTF-16LE - - - - - - - - - 50 - false - - - - Text is qualified by - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - false - - - - Text qualification - - - false - - - " - - - - " - - - - - ' - - - - - : - - - - - . - - - - - | - - - - - - - - - 50 - false - - - - Fields are separated by - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - false - - - - Field separation - - - false - - - , - - - - , - - - - - ; - - - - - - - - - - - : - - - - - . - - - - - TAB (\t) - - - - - - - - - 50 - false - - - - Comments start with - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - false - - - - Comments start with - - - false - - - # - - - - # - - - - - ; - - - - - : - - - - - @ - - - - - - - - - 50 - false - - - - Header lines skipped - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - 50 - false - - - - Number of header lines to discard - - - - - - - Qt::Horizontal - - - - 122 - 20 - - - - - - - - - - - 50 - false - - - - First line has field names - - - - - - - - 50 - false - - - - Consider '\' an escape character - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - 75 - true - - - - Preview - - - false - - + + + + + + 75 + true + + + + Column Association + + + + + + + 50 + false + + + + Icon + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 2 + + + + + + + + 50 + false + + + + TOTP + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 2 + + + + + + + + + + + 50 + false + + + + Notes + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 2 + + + + + + + + 50 + false + + + + Title + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 2 + + + + + + + + + + + + + + + + + + + + 50 + false + + + + First line has field names + + + true + + + + + + + + + + + + + + 50 + false + + + + Password + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 2 + + + + + + + + 50 + false + + + + Group + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 2 + + + + + + + + + + + 50 + false + + + + Username + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 2 + + + + + + + + 50 + false + + + + URL + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 2 + + + + + + + + + + + 50 + false + + + + Created + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 2 + + + + + + + + + + + 50 + false + + + + Last Modified + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 2 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 6 + 20 + + + + + + + + + + + + 75 + true + + + + Encoding + + + + + + + 50 + false + + + + Codec + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + Codec + + + false + + + UTF-8 + - - - - 0 - 0 - - - - - 0 - 300 - - - - - 50 - false - - - - CSV import preview - - - false - - - true - - + + UTF-8 + - - - - - - + + + Windows-1252 + + + + + UTF-16 + + + + + UTF-16LE + + + + + + + + + 50 + false + + + + Text is qualified by + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + Text qualification + + + false + + + " + + + + " + + + + + ' + + + + + : + + + + + . + + + + + | + + + + + + + + + 50 + false + + + + Fields are separated by + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + Field separation + + + false + + + , + + + + , + + + + + ; + + + + + - + + + + + : + + + + + . + + + + + TAB (\t) + + + + + + + + + 50 + false + + + + Comments start with + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + Comments start with + + + false + + + # + + + + # + + + + + ; + + + + + : + + + + + @ + + + + + + + + + 50 + false + + + + Header lines skipped + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + Number of header lines to discard + + + + + + + + 50 + false + + + + Consider '\' an escape character + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + 75 + true + - + + Preview + + false + + + 3 + + + 0 + + + + + + 50 + false + + + + size, rows, columns + + + + + + + + 0 + 0 + + + + + 800 + 300 + + + + + 50 + false + + + + CSV import preview + + + false + + + true + + + + - - - MessageWidget - QWidget -

gui/MessageWidget.h
- 1 - - - scrollArea - groupCombo - titleCombo - usernameCombo - passwordCombo - urlCombo - notesCombo - totpCombo - iconCombo - lastModifiedCombo - createdCombo comboBoxCodec comboBoxTextQualifier comboBoxFieldSeparator comboBoxComment - spinBoxSkip - checkBoxFieldNames - checkBoxBackslash tableViewFields diff --git a/src/gui/csvImport/CsvImportWizard.cpp b/src/gui/csvImport/CsvImportWizard.cpp deleted file mode 100644 index 4595c06d9..000000000 --- a/src/gui/csvImport/CsvImportWizard.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2016 Enrico Mariotti - * Copyright (C) 2017 KeePassXC Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "CsvImportWizard.h" - -#include - -CsvImportWizard::CsvImportWizard(QWidget* parent) - : DialogyWidget(parent) -{ - m_layout = new QGridLayout(this); - m_layout->addWidget(m_parse = new CsvImportWidget(this), 0, 0); - - connect(m_parse, SIGNAL(editFinished(bool)), this, SLOT(parseFinished(bool))); -} - -CsvImportWizard::~CsvImportWizard() -{ -} - -void CsvImportWizard::load(const QString& filename, Database* database) -{ - m_db = database; - m_parse->load(filename, database); -} - -void CsvImportWizard::parseFinished(bool accepted) -{ - emit importFinished(accepted); -} diff --git a/src/gui/csvImport/CsvImportWizard.h b/src/gui/csvImport/CsvImportWizard.h deleted file mode 100644 index 084d8794d..000000000 --- a/src/gui/csvImport/CsvImportWizard.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2016 Enrico Mariotti - * Copyright (C) 2017 KeePassXC Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef KEEPASSX_CSVIMPORTWIZARD_H -#define KEEPASSX_CSVIMPORTWIZARD_H - -#include "CsvImportWidget.h" - -#include "gui/DialogyWidget.h" - -class QGridLayout; - -class CsvImportWidget; - -class CsvImportWizard : public DialogyWidget -{ - Q_OBJECT - -public: - explicit CsvImportWizard(QWidget* parent = nullptr); - ~CsvImportWizard() override; - void load(const QString& filename, Database* database); - -signals: - void importFinished(bool accepted); - -private slots: - void parseFinished(bool accepted); - -private: - QPointer m_db; - CsvImportWidget* m_parse; - QGridLayout* m_layout; -}; - -#endif // KEEPASSX_CSVIMPORTWIZARD_H diff --git a/src/gui/csvImport/CsvParserModel.cpp b/src/gui/csvImport/CsvParserModel.cpp index 77abb5931..0ae350817 100644 --- a/src/gui/csvImport/CsvParserModel.cpp +++ b/src/gui/csvImport/CsvParserModel.cpp @@ -18,10 +18,14 @@ #include "CsvParserModel.h" +#include "core/Tools.h" +#include "format/CsvParser.h" + #include CsvParserModel::CsvParserModel(QObject* parent) : QAbstractTableModel(parent) + , m_parser(new CsvParser()) , m_skipped(0) { } @@ -30,6 +34,11 @@ CsvParserModel::~CsvParserModel() { } +CsvParser* CsvParserModel::parser() +{ + return m_parser; +} + void CsvParserModel::setFilename(const QString& filename) { m_filename = filename; @@ -37,11 +46,10 @@ void CsvParserModel::setFilename(const QString& filename) QString CsvParserModel::getFileInfo() { - QString a(tr("%1, %2, %3", "file info: bytes, rows, columns") - .arg(tr("%n byte(s)", nullptr, getFileSize()), - tr("%n row(s)", nullptr, getCsvRows()), - tr("%n column(s)", nullptr, qMax(0, getCsvCols() - 1)))); - return a; + return QString("%1, %2, %3") + .arg(Tools::humanReadableFileSize(m_parser->getFileSize()), + tr("%n row(s)", "CSV row count", m_parser->getCsvRows()), + tr("%n column(s)", "CSV column count", qMax(0, m_parser->getCsvCols() - 1))); } bool CsvParserModel::parse() @@ -49,37 +57,28 @@ bool CsvParserModel::parse() bool r; beginResetModel(); m_columnMap.clear(); - if (CsvParser::isFileLoaded()) { - r = CsvParser::reparse(); + if (m_parser->isFileLoaded()) { + r = m_parser->reparse(); } else { QFile csv(m_filename); - r = CsvParser::parse(&csv); + r = m_parser->parse(&csv); } for (int i = 0; i < columnCount(); ++i) { m_columnMap.insert(i, 0); } - addEmptyColumn(); endResetModel(); return r; } -void CsvParserModel::addEmptyColumn() -{ - for (int i = 0; i < m_table.size(); ++i) { - CsvRow r = m_table.at(i); - r.prepend(QString("")); - m_table.replace(i, r); - } -} - void CsvParserModel::mapColumns(int csvColumn, int dbColumn) { - if ((csvColumn < 0) || (dbColumn < 0)) { + if (dbColumn < 0 || dbColumn >= m_columnMap.size()) { return; } beginResetModel(); - if (csvColumn >= getCsvCols()) { - m_columnMap[dbColumn] = 0; // map to the empty column + if (csvColumn < 0 || csvColumn >= m_parser->getCsvCols()) { + // This indicates a blank cell + m_columnMap[dbColumn] = -1; } else { m_columnMap[dbColumn] = csvColumn; } @@ -105,7 +104,7 @@ int CsvParserModel::rowCount(const QModelIndex& parent) const if (parent.isValid()) { return 0; } - return getCsvRows(); + return m_parser->getCsvRows(); } int CsvParserModel::columnCount(const QModelIndex& parent) const @@ -118,11 +117,14 @@ int CsvParserModel::columnCount(const QModelIndex& parent) const QVariant CsvParserModel::data(const QModelIndex& index, int role) const { - if ((index.column() >= m_columnHeader.size()) || (index.row() + m_skipped >= rowCount()) || !index.isValid()) { - return QVariant(); + if (index.column() >= m_columnHeader.size() || index.row() + m_skipped >= rowCount() || !index.isValid()) { + return {}; } if (role == Qt::DisplayRole) { - return m_table.at(index.row() + m_skipped).at(m_columnMap[index.column()]); + auto column = m_columnMap[index.column()]; + if (column >= 0) { + return m_parser->getCsvTable().at(index.row() + m_skipped).at(column); + } } return QVariant(); } @@ -131,15 +133,13 @@ QVariant CsvParserModel::headerData(int section, Qt::Orientation orientation, in { if (role == Qt::DisplayRole) { if (orientation == Qt::Horizontal) { - if ((section < 0) || (section >= m_columnHeader.size())) { - return QVariant(); + if (section >= 0 && section < m_columnHeader.size()) { + return m_columnHeader.at(section); } - return m_columnHeader.at(section); } else if (orientation == Qt::Vertical) { - if (section + m_skipped >= rowCount()) { - return QVariant(); + if (section + m_skipped < rowCount()) { + return QString::number(section + 1); } - return QString::number(section + 1); } } return QVariant(); diff --git a/src/gui/csvImport/CsvParserModel.h b/src/gui/csvImport/CsvParserModel.h index 5e979421c..2717b826d 100644 --- a/src/gui/csvImport/CsvParserModel.h +++ b/src/gui/csvImport/CsvParserModel.h @@ -21,20 +21,22 @@ #include -#include "core/Group.h" -#include "format/CsvParser.h" +class CsvParser; -class CsvParserModel : public QAbstractTableModel, public CsvParser +class CsvParserModel : public QAbstractTableModel { Q_OBJECT public: explicit CsvParserModel(QObject* parent = nullptr); - ~CsvParserModel(); + ~CsvParserModel() override; + void setFilename(const QString& filename); QString getFileInfo(); bool parse(); + CsvParser* parser(); + void setHeaderLabels(const QStringList& labels); void mapColumns(int csvColumn, int dbColumn); @@ -47,12 +49,12 @@ public slots: void setSkippedRows(int skipped); private: + CsvParser* m_parser; int m_skipped; QString m_filename; QStringList m_columnHeader; // first column of model must be empty (aka combobox row "Not present in CSV file") void addEmptyColumn(); - // mapping CSV columns to keepassx columns QMap m_columnMap; }; diff --git a/src/gui/tag/TagsEdit.cpp b/src/gui/tag/TagsEdit.cpp index 7d5b657ce..4388f4790 100644 --- a/src/gui/tag/TagsEdit.cpp +++ b/src/gui/tag/TagsEdit.cpp @@ -24,6 +24,7 @@ #include "TagsEdit.h" #include "gui/MainWindow.h" +#include #include #include #include diff --git a/src/gui/wizard/ImportWizard.cpp b/src/gui/wizard/ImportWizard.cpp new file mode 100644 index 000000000..05fdbfe38 --- /dev/null +++ b/src/gui/wizard/ImportWizard.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2018 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ImportWizard.h" +#include "ImportWizardPageReview.h" +#include "ImportWizardPageSelect.h" + +#include "core/Global.h" +#include "core/Group.h" + +#include +#include + +ImportWizard::ImportWizard(QWidget* parent) + : QWizard(parent) + , m_pageSelect(new ImportWizardPageSelect) + , m_pageReview(new ImportWizardPageReview) +{ + setWizardStyle(MacStyle); + setOption(HaveHelpButton, false); + setOption(NoDefaultButton, false); // Needed for macOS + + addPage(m_pageSelect.data()); + addPage(m_pageReview.data()); + + setWindowTitle(tr("Import Wizard")); + + Q_INIT_RESOURCE(wizard); + setPixmap(BackgroundPixmap, QPixmap(":/wizard/background-pixmap.png")); + + // Fix MacStyle QWizard page frame too bright in dark mode (QTBUG-70346, QTBUG-71696) + QPalette defaultPalette; + auto windowColor = defaultPalette.color(QPalette::Window); + windowColor.setAlpha(153); + auto baseColor = defaultPalette.color(QPalette::Base); + baseColor.setAlpha(153); + + auto* pageFrame = findChildren()[0]; + auto framePalette = pageFrame->palette(); + framePalette.setBrush(QPalette::Window, windowColor.lighter(120)); + framePalette.setBrush(QPalette::Base, baseColor.lighter(120)); + pageFrame->setPalette(framePalette); +} + +ImportWizard::~ImportWizard() +{ +} + +bool ImportWizard::validateCurrentPage() +{ + bool ret = QWizard::validateCurrentPage(); + if (ret && currentPage() == m_pageReview) { + m_db = m_pageReview->database(); + } + return ret; +} + +QPair ImportWizard::importInto() +{ + auto list = field("ImportInto").toList(); + if (list.size() >= 2) { + return qMakePair(QUuid(list[0].toString()), QUuid(list[1].toString())); + } + return {}; +} + +QSharedPointer ImportWizard::database() +{ + return m_db; +} diff --git a/src/gui/wizard/ImportWizard.h b/src/gui/wizard/ImportWizard.h new file mode 100644 index 000000000..b7e9de68d --- /dev/null +++ b/src/gui/wizard/ImportWizard.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_IMPORTWIZARD_H +#define KEEPASSXC_IMPORTWIZARD_H + +#include +#include + +class Database; +class ImportWizardPageSelect; +class ImportWizardPageReview; + +/** + * Setup wizard for importing a file into a database. + */ +class ImportWizard : public QWizard +{ + Q_OBJECT + +public: + explicit ImportWizard(QWidget* parent = nullptr); + ~ImportWizard() override; + + bool validateCurrentPage() override; + + QSharedPointer database(); + QPair importInto(); + + enum ImportType + { + IMPORT_NONE = 0, + IMPORT_CSV, + IMPORT_OPVAULT, + IMPORT_OPUX, + IMPORT_BITWARDEN, + IMPORT_KEEPASS1 + }; + +private: + QSharedPointer m_db; + QPointer m_pageSelect; + QPointer m_pageReview; +}; + +#endif // KEEPASSXC_IMPORTWIZARD_H diff --git a/src/gui/wizard/ImportWizardPageReview.cpp b/src/gui/wizard/ImportWizardPageReview.cpp new file mode 100644 index 000000000..2cb56791b --- /dev/null +++ b/src/gui/wizard/ImportWizardPageReview.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2023 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ImportWizardPageReview.h" +#include "ui_ImportWizardPageReview.h" + +#include "core/Database.h" +#include "core/Group.h" +#include "format/BitwardenReader.h" +#include "format/KeePass1Reader.h" +#include "format/OPUXReader.h" +#include "format/OpVaultReader.h" +#include "gui/csvImport/CsvImportWidget.h" +#include "gui/wizard/ImportWizard.h" + +#include +#include +#include +#include + +ImportWizardPageReview::ImportWizardPageReview(QWidget* parent) + : QWizardPage(parent) + , m_ui(new Ui::ImportWizardPageReview) +{ +} + +ImportWizardPageReview::~ImportWizardPageReview() +{ +} + +void ImportWizardPageReview::initializePage() +{ + m_db.reset(); + + // Reset the widget in case we changed the import type + for (auto child : children()) { + delete child; + } + m_ui->setupUi(this); + + auto filename = field("ImportFile").toString(); + m_ui->filenameLabel->setText(filename); + + m_ui->messageWidget->hideMessage(); + m_ui->messageWidget->setAnimate(false); + m_ui->messageWidget->setCloseButtonVisible(false); + + auto importType = field("ImportType").toInt(); + switch (importType) { + case ImportWizard::IMPORT_CSV: + setupCsvImport(filename); + break; + case ImportWizard::IMPORT_OPVAULT: + m_db = importOPVault(filename, field("ImportPassword").toString()); + setupDatabasePreview(); + break; + case ImportWizard::IMPORT_OPUX: + m_db = importOPUX(filename); + setupDatabasePreview(); + break; + case ImportWizard::IMPORT_KEEPASS1: + m_db = importKeePass1(filename, field("ImportPassword").toString(), field("ImportKeyFile").toString()); + setupDatabasePreview(); + break; + case ImportWizard::IMPORT_BITWARDEN: + m_db = importBitwarden(filename, field("ImportPassword").toString()); + setupDatabasePreview(); + break; + default: + break; + } +} + +bool ImportWizardPageReview::validatePage() +{ + if (m_csvWidget && field("ImportType").toInt() == ImportWizard::IMPORT_CSV) { + m_db = m_csvWidget->buildDatabase(); + } + return !m_db.isNull(); +} + +QSharedPointer ImportWizardPageReview::database() +{ + return m_db; +} + +void ImportWizardPageReview::setupCsvImport(const QString& filename) +{ + // No need for this label with CSV + m_ui->previewLabel->hide(); + + m_csvWidget = new CsvImportWidget(); + connect(m_csvWidget, &CsvImportWidget::message, m_ui->messageWidget, [this](QString message) { + m_ui->messageWidget->showMessage(message, KMessageWidget::Error, -1); + }); + + m_csvWidget->load(filename); + + // Qt does not automatically resize a QScrollWidget in a QWizard... + m_ui->scrollAreaContents->layout()->addWidget(m_csvWidget); + m_ui->scrollArea->setMinimumSize(m_csvWidget->width() + 50, m_csvWidget->height() + 100); +} + +void ImportWizardPageReview::setupDatabasePreview() +{ + if (!m_db) { + m_ui->scrollArea->setVisible(false); + return; + } + + auto entryList = m_db->rootGroup()->entriesRecursive(); + m_ui->previewLabel->setText(tr("Entry count: %1").arg(entryList.count())); + + QStringList headerLabels({tr("Group"), tr("Title"), tr("Username"), tr("Password"), tr("Url")}); + + auto tableWidget = new QTableWidget(entryList.count(), headerLabels.count()); + tableWidget->setHorizontalHeaderLabels(headerLabels); + + int row = 0; + for (auto entry : entryList) { + QList items({new QTableWidgetItem(entry->group()->name()), + new QTableWidgetItem(entry->title()), + new QTableWidgetItem(entry->username()), + new QTableWidgetItem(entry->password()), + new QTableWidgetItem(entry->url())}); + int column = 0; + for (auto item : items) { + tableWidget->setItem(row, column++, item); + } + ++row; + } + + tableWidget->setSortingEnabled(true); + tableWidget->setSelectionMode(QTableWidget::NoSelection); + tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + tableWidget->setWordWrap(true); + tableWidget->horizontalHeader()->setMaximumSectionSize(200); + tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + tableWidget->horizontalHeader()->setStretchLastSection(true); + + m_ui->scrollAreaContents->layout()->addWidget(tableWidget); +} + +QSharedPointer ImportWizardPageReview::importOPUX(const QString& filename) +{ + OPUXReader reader; + auto db = reader.convert(filename); + if (reader.hasError()) { + m_ui->messageWidget->showMessage(reader.errorString(), KMessageWidget::Error, -1); + } + return db; +} + +QSharedPointer ImportWizardPageReview::importBitwarden(const QString& filename, const QString& password) +{ + BitwardenReader reader; + auto db = reader.convert(filename, password); + if (reader.hasError()) { + m_ui->messageWidget->showMessage(reader.errorString(), KMessageWidget::Error, -1); + } + return db; +} + +QSharedPointer ImportWizardPageReview::importOPVault(const QString& filename, const QString& password) +{ + OpVaultReader reader; + QDir opVault(filename); + auto db = reader.convert(opVault, password); + if (reader.hasError()) { + m_ui->messageWidget->showMessage(reader.errorString(), KMessageWidget::Error, -1); + } + return db; +} + +QSharedPointer +ImportWizardPageReview::importKeePass1(const QString& filename, const QString& password, const QString& keyfile) +{ + KeePass1Reader reader; + + // TODO: Handle case of empty password? + + auto db = reader.readDatabase(filename, password, keyfile); + if (reader.hasError()) { + m_ui->messageWidget->showMessage(reader.errorString(), KMessageWidget::Error, -1); + } + + return db; +} diff --git a/src/gui/wizard/ImportWizardPageReview.h b/src/gui/wizard/ImportWizardPageReview.h new file mode 100644 index 000000000..87f501c85 --- /dev/null +++ b/src/gui/wizard/ImportWizardPageReview.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2023 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_IMPORTWIZARDPAGEREVIEW_H +#define KEEPASSXC_IMPORTWIZARDPAGEREVIEW_H + +#include +#include + +class CsvImportWidget; +class Database; +namespace Ui +{ + class ImportWizardPageReview; +}; + +class ImportWizardPageReview : public QWizardPage +{ + Q_OBJECT + +public: + explicit ImportWizardPageReview(QWidget* parent = nullptr); + Q_DISABLE_COPY(ImportWizardPageReview) + ~ImportWizardPageReview() override; + + void initializePage() override; + bool validatePage() override; + + QSharedPointer database(); + +private: + void setupCsvImport(const QString& filename); + QSharedPointer importOPUX(const QString& filename); + QSharedPointer importBitwarden(const QString& filename, const QString& password); + QSharedPointer importOPVault(const QString& filename, const QString& password); + QSharedPointer importKeePass1(const QString& filename, const QString& password, const QString& keyfile); + + void setupDatabasePreview(); + + QScopedPointer m_ui; + + QSharedPointer m_db; + QPointer m_csvWidget; +}; + +#endif diff --git a/src/gui/wizard/ImportWizardPageReview.ui b/src/gui/wizard/ImportWizardPageReview.ui new file mode 100644 index 000000000..6872ec4ea --- /dev/null +++ b/src/gui/wizard/ImportWizardPageReview.ui @@ -0,0 +1,95 @@ + + + ImportWizardPageReview + + + + 0 + 0 + 518 + 334 + + + + WizardPage + + + + + + + + + + 500 + 300 + + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustToContentsOnFirstShow + + + true + + + + + 0 + 0 + 498 + 298 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 75 + true + + + + filename + + + + + + + Entry count: %1 + + + + + + + + + + + + MessageWidget + QWidget +
gui/MessageWidget.h
+ 1 +
+
+ + +
diff --git a/src/gui/wizard/ImportWizardPageSelect.cpp b/src/gui/wizard/ImportWizardPageSelect.cpp new file mode 100644 index 000000000..7bca1a39a --- /dev/null +++ b/src/gui/wizard/ImportWizardPageSelect.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2023 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ImportWizardPageSelect.h" +#include "ui_ImportWizardPageSelect.h" + +#include "ImportWizard.h" + +#include "gui/DatabaseWidget.h" +#include "gui/FileDialog.h" +#include "gui/Icons.h" +#include "gui/MainWindow.h" + +ImportWizardPageSelect::ImportWizardPageSelect(QWidget* parent) + : QWizardPage(parent) + , m_ui(new Ui::ImportWizardPageSelect()) +{ + m_ui->setupUi(this); + + new QListWidgetItem(icons()->icon("csv"), tr("Comma Separated Values (.csv)"), m_ui->importTypeList); + new QListWidgetItem(icons()->icon("onepassword"), tr("1Password Export (.1pux)"), m_ui->importTypeList); + new QListWidgetItem(icons()->icon("onepassword"), tr("1Password Vault (.opvault)"), m_ui->importTypeList); + new QListWidgetItem(icons()->icon("bitwarden"), tr("Bitwarden (.json)"), m_ui->importTypeList); + new QListWidgetItem(icons()->icon("object-locked"), tr("KeePass 1 Database (.kdb)"), m_ui->importTypeList); + + m_ui->importTypeList->item(0)->setData(Qt::UserRole, ImportWizard::IMPORT_CSV); + m_ui->importTypeList->item(1)->setData(Qt::UserRole, ImportWizard::IMPORT_OPUX); + m_ui->importTypeList->item(2)->setData(Qt::UserRole, ImportWizard::IMPORT_OPVAULT); + m_ui->importTypeList->item(3)->setData(Qt::UserRole, ImportWizard::IMPORT_BITWARDEN); + m_ui->importTypeList->item(4)->setData(Qt::UserRole, ImportWizard::IMPORT_KEEPASS1); + + connect(m_ui->importTypeList, &QListWidget::currentItemChanged, this, &ImportWizardPageSelect::itemSelected); + m_ui->importTypeList->setCurrentRow(0); + + connect(m_ui->importFileButton, &QAbstractButton::clicked, this, &ImportWizardPageSelect::chooseImportFile); + connect(m_ui->keyFileButton, &QAbstractButton::clicked, this, &ImportWizardPageSelect::chooseKeyFile); + connect(m_ui->existingDatabaseRadio, &QRadioButton::toggled, this, [this](bool state) { + m_ui->existingDatabaseChoice->setEnabled(state); + }); + + updateDatabaseChoices(); + + registerField("ImportType", this); + registerField("ImportFile*", m_ui->importFileEdit); + registerField("ImportInto", m_ui->importIntoLabel); + registerField("ImportPassword", m_ui->passwordEdit, "text", "textChanged"); + registerField("ImportKeyFile", m_ui->keyFileEdit); +} + +ImportWizardPageSelect::~ImportWizardPageSelect() +{ +} + +void ImportWizardPageSelect::initializePage() +{ + setField("ImportType", m_ui->importTypeList->currentItem()->data(Qt::UserRole).toInt()); + adjustSize(); +} + +bool ImportWizardPageSelect::validatePage() +{ + if (m_ui->existingDatabaseRadio->isChecked()) { + if (m_ui->existingDatabaseChoice->currentIndex() == -1) { + return false; + } + setField("ImportInto", m_ui->existingDatabaseChoice->currentData()); + } else { + setField("ImportInto", {}); + } + + return true; +} + +void ImportWizardPageSelect::itemSelected(QListWidgetItem* current, QListWidgetItem* previous) +{ + Q_UNUSED(previous) + + if (!current) { + setCredentialState(false); + return; + } + + m_ui->importFileEdit->clear(); + m_ui->passwordEdit->clear(); + m_ui->keyFileEdit->clear(); + + auto type = current->data(Qt::UserRole).toInt(); + setField("ImportType", type); + switch (type) { + // Unencrypted types + case ImportWizard::IMPORT_CSV: + case ImportWizard::IMPORT_OPUX: + setCredentialState(false); + break; + // Password may be required + case ImportWizard::IMPORT_BITWARDEN: + case ImportWizard::IMPORT_OPVAULT: + setCredentialState(true); + break; + // Password and/or Key File may be required + case ImportWizard::IMPORT_KEEPASS1: + setCredentialState(true, true); + break; + default: + Q_ASSERT(false); + } +} + +void ImportWizardPageSelect::updateDatabaseChoices() const +{ + m_ui->existingDatabaseChoice->clear(); + auto mainWindow = getMainWindow(); + if (mainWindow) { + for (auto dbWidget : mainWindow->getOpenDatabases()) { + // Skip over locked databases + if (dbWidget->isLocked()) { + continue; + } + + // Enable the selection of an existing database + m_ui->existingDatabaseRadio->setEnabled(true); + m_ui->existingDatabaseRadio->setToolTip(""); + + // Add a separator between databases + if (m_ui->existingDatabaseChoice->count() > 0) { + m_ui->existingDatabaseChoice->insertSeparator(m_ui->existingDatabaseChoice->count()); + } + + // Add the root group as a special line item + auto db = dbWidget->database(); + m_ui->existingDatabaseChoice->addItem( + QString("%1 (%2)").arg(dbWidget->displayName(), db->rootGroup()->name()), + QList() << db->uuid() << db->rootGroup()->uuid()); + + if (dbWidget->isVisible()) { + m_ui->existingDatabaseChoice->setCurrentIndex(m_ui->existingDatabaseChoice->count() - 1); + } + + // Add remaining groups + for (const auto& group : db->rootGroup()->groupsRecursive(false)) { + if (!group->isRecycled()) { + auto path = group->hierarchy(); + path.removeFirst(); + m_ui->existingDatabaseChoice->addItem(QString(" / %1").arg(path.join(" / ")), + QList() << db->uuid() << group->uuid()); + } + } + } + } +} + +void ImportWizardPageSelect::chooseImportFile() +{ + QString file; +#ifndef Q_OS_MACOS + // OPVault is a folder except on macOS + if (field("ImportType").toInt() == ImportWizard::IMPORT_OPVAULT) { + file = fileDialog()->getExistingDirectory(this, tr("Open OPVault"), QDir::homePath()); + } else { +#endif + file = fileDialog()->getOpenFileName(this, tr("Select import file"), QDir::homePath(), importFileFilter()); +#ifndef Q_OS_MACOS + } +#endif + + if (!file.isEmpty()) { + m_ui->importFileEdit->setText(file); + } +} + +void ImportWizardPageSelect::chooseKeyFile() +{ + auto filter = QString("%1 (*);;%2 (*.keyx; *.key)").arg(tr("All files"), tr("Key files")); + auto file = fileDialog()->getOpenFileName(this, tr("Select key file"), QDir::homePath(), filter); + if (!file.isEmpty()) { + m_ui->keyFileEdit->setText(file); + } +} + +void ImportWizardPageSelect::setCredentialState(bool passwordEnabled, bool keyFileEnable) +{ + bool passwordStateChanged = m_ui->passwordLabel->isVisible() != passwordEnabled; + m_ui->passwordLabel->setVisible(passwordEnabled); + m_ui->passwordEdit->setVisible(passwordEnabled); + + bool keyFileStateChanged = m_ui->keyFileLabel->isVisible() != keyFileEnable; + m_ui->keyFileLabel->setVisible(keyFileEnable); + m_ui->keyFileEdit->setVisible(keyFileEnable); + m_ui->keyFileButton->setVisible(keyFileEnable); + + // Workaround Qt bug where the wizard window is not updated when the internal layout changes + if (window()) { + int height = window()->height(); + if (passwordStateChanged) { + auto diff = m_ui->passwordEdit->height() + m_ui->inputFields->layout()->spacing(); + height += passwordEnabled ? diff : -diff; + } + if (keyFileStateChanged) { + auto diff = m_ui->keyFileEdit->height() + m_ui->inputFields->layout()->spacing(); + height += keyFileEnable ? diff : -diff; + } + window()->resize(window()->width(), height); + } +} + +QString ImportWizardPageSelect::importFileFilter() +{ + switch (field("ImportType").toInt()) { + case ImportWizard::IMPORT_CSV: + return QString("%1 (*.csv);;%2 (*)").arg(tr("Comma Separated Values"), tr("All files")); + case ImportWizard::IMPORT_OPUX: + return QString("%1 (*.1pux)").arg(tr("1Password Export")); + case ImportWizard::IMPORT_BITWARDEN: + return QString("%1 (*.json)").arg(tr("Bitwarden JSON Export")); + case ImportWizard::IMPORT_OPVAULT: + return QString("%1 (*.opvault)").arg(tr("1Password Vault")); + case ImportWizard::IMPORT_KEEPASS1: + return QString("%1 (*.kdb)").arg(tr("KeePass1 Database")); + default: + return {}; + } +} diff --git a/src/gui/wizard/ImportWizardPageSelect.h b/src/gui/wizard/ImportWizardPageSelect.h new file mode 100644 index 000000000..029865a56 --- /dev/null +++ b/src/gui/wizard/ImportWizardPageSelect.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2023 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_IMPORTWIZARDPAGESELECT_H +#define KEEPASSXC_IMPORTWIZARDPAGESELECT_H + +#include +#include + +class QListWidgetItem; + +namespace Ui +{ + class ImportWizardPageSelect; +} + +class ImportWizardPageSelect : public QWizardPage +{ + Q_OBJECT + +public: + explicit ImportWizardPageSelect(QWidget* parent = nullptr); + Q_DISABLE_COPY(ImportWizardPageSelect) + ~ImportWizardPageSelect() override; + + void initializePage() override; + bool validatePage() override; + +private slots: + void itemSelected(QListWidgetItem* current, QListWidgetItem* previous); + void chooseImportFile(); + void chooseKeyFile(); + void updateDatabaseChoices() const; + +private: + QString importFileFilter(); + void setCredentialState(bool passwordEnabled, bool keyFileEnable = false); + + QScopedPointer m_ui; +}; + +#endif diff --git a/src/gui/wizard/ImportWizardPageSelect.ui b/src/gui/wizard/ImportWizardPageSelect.ui new file mode 100644 index 000000000..6a7c8adad --- /dev/null +++ b/src/gui/wizard/ImportWizardPageSelect.ui @@ -0,0 +1,276 @@ + + + ImportWizardPageSelect + + + + 0 + 0 + 500 + 388 + + + + Form + + + Import File Selection + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 500 + 125 + + + + QAbstractScrollArea::AdjustToContents + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::SelectRows + + + Qt::ElideNone + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + + 0 + 0 + + + + + 400 + 0 + + + + + QLayout::SetMinimumSize + + + + + Import File: + + + + + + + + + + + + Browse… + + + + + + + + + Password: + + + + + + + + + + Key File: + + + + + + + + + + + + Browse… + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 15 + + + + + + + + Import Into: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + 0 + 0 + + + + + 0 + 60 + + + + + + + + QLayout::SetMinimumSize + + + 6 + + + 6 + + + 6 + + + 6 + + + + + New Database + + + true + + + + + + + + + false + + + No unlocked databases available + + + Existing Database: + + + + + + + false + + + + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 20 + 40 + + + + + + + + + PasswordWidget + QWidget +
gui/PasswordWidget.h
+ 1 +
+
+ + +
diff --git a/src/keeshare/CMakeLists.txt b/src/keeshare/CMakeLists.txt index 3adf272ad..5f7a39658 100644 --- a/src/keeshare/CMakeLists.txt +++ b/src/keeshare/CMakeLists.txt @@ -13,8 +13,6 @@ if(WITH_XC_KEESHARE) ShareObserver.cpp ) - find_package(Minizip REQUIRED) - add_library(keeshare STATIC ${keeshare_SOURCES}) target_link_libraries(keeshare PUBLIC Qt5::Core Qt5::Widgets ${BOTAN_LIBRARIES} ${ZLIB_LIBRARIES} PRIVATE ${MINIZIP_LIBRARIES}) include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1181921c2..2285995b5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -140,7 +140,7 @@ add_unit_test(NAME testdeletedobjects SOURCES TestDeletedObjects.cpp add_unit_test(NAME testkeepass1reader SOURCES TestKeePass1Reader.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testopvaultreader SOURCES TestOpVaultReader.cpp +add_unit_test(NAME testimports SOURCES TestImports.cpp LIBS ${TEST_LIBRARIES}) if(WITH_XC_NETWORKING) diff --git a/tests/TestImports.cpp b/tests/TestImports.cpp new file mode 100644 index 000000000..a809cc3ed --- /dev/null +++ b/tests/TestImports.cpp @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2022 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TestImports.h" + +#include "config-keepassx-tests.h" +#include "core/Group.h" +#include "core/Metadata.h" +#include "core/Totp.h" +#include "crypto/Crypto.h" +#include "format/BitwardenReader.h" +#include "format/OPUXReader.h" +#include "format/OpVaultReader.h" + +#include +#include +#include + +QTEST_GUILESS_MAIN(TestImports) + +void TestImports::initTestCase() +{ + QVERIFY(Crypto::init()); +} + +void TestImports::testOPUX() +{ + auto opuxPath = QStringLiteral("%1/%2").arg(KEEPASSX_TEST_DATA_DIR, QStringLiteral("/1PasswordExport.1pux")); + + OPUXReader reader; + auto db = reader.convert(opuxPath); + QVERIFY2(!reader.hasError(), qPrintable(reader.errorString())); + QVERIFY(db); + + // Confirm specific entry details are valid + auto entry = db->rootGroup()->findEntryByPath("/Personal/Login"); + QVERIFY(entry); + QCOMPARE(entry->title(), QStringLiteral("Login")); + QCOMPARE(entry->username(), QStringLiteral("team@keepassxc.org")); + QCOMPARE(entry->password(), QStringLiteral("password")); + QCOMPARE(entry->url(), QStringLiteral("https://keepassxc.org")); + QCOMPARE(entry->notes(), QStringLiteral("Note to self")); + // Check extra URL's + QCOMPARE(entry->attribute("KP2A_URL_1"), QStringLiteral("https://twitter.com")); + // Check TOTP + QVERIFY(entry->hasTotp()); + QVERIFY(!entry->attribute("otp_1").isEmpty()); + // Check tags + QVERIFY(entry->tagList().contains("Favorite")); + QVERIFY(entry->tagList().contains("website")); + + // Check attachments + entry = db->rootGroup()->findEntryByPath("/Personal/KeePassXC Logo"); + auto attachments = entry->attachments(); + QCOMPARE(attachments->keys().count(), 1); + QCOMPARE(attachments->keys()[0], QString("keepassxc.png")); + + // Confirm advanced attributes + // NOTE: 1PUX does not support an explicit expiration field + entry = db->rootGroup()->findEntryByPath("/Personal/Credit Card"); + QVERIFY(entry); + auto tmpl = QString("Credit Card Fields_%1"); + auto attr = entry->attributes(); + QCOMPARE(attr->value(tmpl.arg("cardholder name")), QStringLiteral("KeePassXC")); + QCOMPARE(attr->value(tmpl.arg("expiry date")), QStringLiteral("202206")); + QCOMPARE(attr->value(tmpl.arg("verification number")), QStringLiteral("123")); + QVERIFY(attr->isProtected(tmpl.arg("verification number"))); + + // Confirm address fields + entry = db->rootGroup()->findEntryByPath("/Personal/Identity"); + QVERIFY(entry); + attr = entry->attributes(); + QCOMPARE(attr->value("Address_address"), QStringLiteral("123 Avenue Rd\nBoston, MA 12345\nus")); + + // Check archived entries + entry = db->rootGroup()->findEntryByPath("/Personal/Login Archived"); + QVERIFY(entry); + QVERIFY(entry->tagList().contains("Archived")); + + // Check vault to group structure + entry = db->rootGroup()->findEntryByPath("/Shared/Bank Account"); + QVERIFY(entry); + // Check custom group icon + QVERIFY(!entry->group()->iconUuid().isNull()); +} + +void TestImports::testOPVault() +{ + auto opVaultPath = QStringLiteral("%1/%2").arg(KEEPASSX_TEST_DATA_DIR, QStringLiteral("/keepassxc.opvault")); + + auto categories = QStringList({QStringLiteral("Login"), + QStringLiteral("Credit Card"), + QStringLiteral("Secure Note"), + QStringLiteral("Identity"), + QStringLiteral("Password"), + QStringLiteral("Tombstone"), + QStringLiteral("Software License"), + QStringLiteral("Bank Account"), + QStringLiteral("Database"), + QStringLiteral("Driver License"), + QStringLiteral("Outdoor License"), + QStringLiteral("Membership"), + QStringLiteral("Passport"), + QStringLiteral("Rewards"), + QStringLiteral("SSN"), + QStringLiteral("Router"), + QStringLiteral("Server"), + QStringLiteral("Email")}); + + QDir opVaultDir(opVaultPath); + + OpVaultReader reader; + auto db = reader.convert(opVaultDir, "a"); + QVERIFY2(!reader.hasError(), qPrintable(reader.errorString())); + QVERIFY(db); + + // Confirm specific entry details are valid + auto entry = db->rootGroup()->findEntryByPath("/Login/KeePassXC"); + QVERIFY(entry); + QCOMPARE(entry->title(), QStringLiteral("KeePassXC")); + QCOMPARE(entry->username(), QStringLiteral("keepassxc")); + QCOMPARE(entry->password(), QStringLiteral("opvault")); + QCOMPARE(entry->url(), QStringLiteral("https://www.keepassxc.org")); + QCOMPARE(entry->notes(), QStringLiteral("KeePassXC Account")); + // Check extra URL's + QCOMPARE(entry->attribute("KP2A_URL_1"), QStringLiteral("https://snapshot.keepassxc.org")); + // Check TOTP + QVERIFY(entry->hasTotp()); + // Check attachments + auto attachments = entry->attachments(); + QCOMPARE(attachments->keys().count(), 1); + QCOMPARE(*attachments->values().begin(), QByteArray("attachment")); + + // Confirm expired entries + entry = db->rootGroup()->findEntryByPath("/Login/Expired Login"); + QVERIFY(entry->isExpired()); + + // Confirm advanced attributes + entry = db->rootGroup()->findEntryByPath("/Credit Card/My Credit Card"); + QVERIFY(entry); + auto attr = entry->attributes(); + QCOMPARE(attr->value("cardholder name"), QStringLiteral("Team KeePassXC")); + QVERIFY(!attr->value("valid from").isEmpty()); + QCOMPARE(attr->value("Additional Details_PIN"), QStringLiteral("1234")); + QVERIFY(attr->isProtected("Additional Details_PIN")); + + // Confirm address fields + entry = db->rootGroup()->findEntryByPath("/Identity/Team KeePassXC"); + QVERIFY(entry); + attr = entry->attributes(); + QCOMPARE(attr->value("address_street"), QStringLiteral("123 Password Lane")); + + // Confirm complex passwords + entry = db->rootGroup()->findEntryByPath("/Password/Complex Password"); + QVERIFY(entry); + QCOMPARE(entry->password(), QStringLiteral("HfgcHjEL}iO}^3N!?*cv~O:9GJZQ0>oC")); + QVERIFY(entry->hasTotp()); + auto totpSettings = entry->totpSettings(); + QCOMPARE(totpSettings->digits, static_cast(8)); + QCOMPARE(totpSettings->step, static_cast(45)); + + // Add another OTP to this entry to confirm it doesn't overwrite the existing one + auto field = QJsonObject::fromVariantMap({{"n", "TOTP_SETTINGS"}, {"v", "otpauth://test.url?digits=6"}}); + reader.fillFromSectionField(entry, "", field); + QVERIFY(entry->hasTotp()); + totpSettings = entry->totpSettings(); + QCOMPARE(totpSettings->digits, static_cast(8)); + QCOMPARE(totpSettings->step, static_cast(45)); + QVERIFY(entry->attributes()->contains("otp_1")); + + // Confirm trashed entries are sent to the recycle bin + auto recycleBin = db->metadata()->recycleBin(); + QVERIFY(recycleBin); + QVERIFY(!recycleBin->isEmpty()); + QVERIFY(recycleBin->findEntryByPath("Trashed Password")); + + // Confirm created groups align with category names + for (const auto group : db->rootGroup()->children()) { + if (group == recycleBin) { + continue; + } + QVERIFY2(categories.contains(group->name()), + qPrintable(QStringLiteral("Invalid group name: %1").arg(group->name()))); + // Confirm each group is not empty + QVERIFY2(!group->isEmpty(), qPrintable(QStringLiteral("Group %1 is empty").arg(group->name()))); + } +} + +void TestImports::testBitwarden() +{ + auto bitwardenPath = QStringLiteral("%1/%2").arg(KEEPASSX_TEST_DATA_DIR, QStringLiteral("/bitwarden_export.json")); + + BitwardenReader reader; + auto db = reader.convert(bitwardenPath); + QVERIFY2(!reader.hasError(), qPrintable(reader.errorString())); + QVERIFY(db); + + // Confirm Login fields + auto entry = db->rootGroup()->findEntryByPath("/My Folder/Login Name"); + QVERIFY(entry); + QCOMPARE(entry->title(), QStringLiteral("Login Name")); + QCOMPARE(entry->username(), QStringLiteral("myusername@gmail.com")); + QCOMPARE(entry->password(), QStringLiteral("mypassword")); + QCOMPARE(entry->url(), QStringLiteral("https://mail.google.com")); + QCOMPARE(entry->notes(), QStringLiteral("1st line of note text\n2nd Line of note text")); + // Check extra URL's + QCOMPARE(entry->attribute("KP2A_URL_1"), QStringLiteral("https://google.com")); + QCOMPARE(entry->attribute("KP2A_URL_2"), QStringLiteral("https://gmail.com")); + // Check TOTP + QVERIFY(entry->hasTotp()); + // NOTE: Bitwarden does not export attachments + // NOTE: Bitwarden does not export expiration dates + + // Confirm Identity fields + entry = db->rootGroup()->findEntryByPath("/My Folder/My Identity"); + QVERIFY(entry); + auto attr = entry->attributes(); + // NOTE: The extra spaces are deliberate to test unmodified ingest of data + QCOMPARE(attr->value("identity_address"), + QStringLiteral(" 1 North Calle Cesar Chavez \nSanta Barbara, CA 93103\nUnited States ")); + QCOMPARE(attr->value("identity_name"), QStringLiteral("Mrs Jane A Doe")); + QCOMPARE(attr->value("identity_ssn"), QStringLiteral("123-12-1234")); + QVERIFY(attr->isProtected("identity_ssn")); + + // Confirm Secure Note + entry = db->rootGroup()->findEntryByPath("/My Folder/My Secure Note"); + QVERIFY(entry); + QCOMPARE(entry->notes(), + QStringLiteral("1st line of secure note\n2nd line of secure note\n3rd line of secure note")); + + // Confirm Credit Card + entry = db->rootGroup()->findEntryByPath("/Second Folder/Card Name"); + QVERIFY(entry); + attr = entry->attributes(); + QCOMPARE(attr->value("card_cardholderName"), QStringLiteral("Jane Doe")); + QCOMPARE(attr->value("card_number"), QStringLiteral("1234567891011121")); + QCOMPARE(attr->value("card_code"), QStringLiteral("123")); + QVERIFY(attr->isProtected("card_code")); +} + +void TestImports::testBitwardenEncrypted() +{ + // We already tested the parser so just test that decryption works properly + auto bitwardenPath = + QStringLiteral("%1/%2").arg(KEEPASSX_TEST_DATA_DIR, QStringLiteral("/bitwarden_encrypted_export.json")); + + BitwardenReader reader; + auto db = reader.convert(bitwardenPath, "a"); + if (reader.hasError()) { + QFAIL(qPrintable(reader.errorString())); + } + QVERIFY(db); +} diff --git a/src/gui/KeePass1OpenWidget.h b/tests/TestImports.h similarity index 64% rename from src/gui/KeePass1OpenWidget.h rename to tests/TestImports.h index 203b78632..2e00de9a6 100644 --- a/src/gui/KeePass1OpenWidget.h +++ b/tests/TestImports.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2022 KeePassXC Team * * 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 @@ -15,20 +15,21 @@ * along with this program. If not, see . */ -#ifndef KEEPASSX_KEEPASS1OPENWIDGET_H -#define KEEPASSX_KEEPASS1OPENWIDGET_H +#ifndef TEST_IMPORTS_H +#define TEST_IMPORTS_H -#include "gui/DatabaseOpenWidget.h" +#include -class KeePass1OpenWidget : public DatabaseOpenWidget +class TestImports : public QObject { Q_OBJECT -public: - explicit KeePass1OpenWidget(QWidget* parent = nullptr); - -protected: - void openDatabase() override; +private slots: + void initTestCase(); + void testOPUX(); + void testOPVault(); + void testBitwarden(); + void testBitwardenEncrypted(); }; -#endif // KEEPASSX_KEEPASS1OPENWIDGET_H +#endif /* TEST_IMPORTS_H */ diff --git a/tests/TestOpVaultReader.cpp b/tests/TestOpVaultReader.cpp deleted file mode 100644 index 4899d335f..000000000 --- a/tests/TestOpVaultReader.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2019 KeePassXC Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "TestOpVaultReader.h" - -#include "config-keepassx-tests.h" -#include "core/Group.h" -#include "core/Metadata.h" -#include "core/Totp.h" -#include "crypto/Crypto.h" -#include "format/OpVaultReader.h" - -#include -#include -#include -#include - -QTEST_GUILESS_MAIN(TestOpVaultReader) - -void TestOpVaultReader::initTestCase() -{ - QVERIFY(Crypto::init()); - - m_opVaultPath = QStringLiteral("%1/%2").arg(KEEPASSX_TEST_DATA_DIR, QStringLiteral("/keepassxc.opvault")); - - m_categories = QStringList({QStringLiteral("Login"), - QStringLiteral("Credit Card"), - QStringLiteral("Secure Note"), - QStringLiteral("Identity"), - QStringLiteral("Password"), - QStringLiteral("Tombstone"), - QStringLiteral("Software License"), - QStringLiteral("Bank Account"), - QStringLiteral("Database"), - QStringLiteral("Driver License"), - QStringLiteral("Outdoor License"), - QStringLiteral("Membership"), - QStringLiteral("Passport"), - QStringLiteral("Rewards"), - QStringLiteral("SSN"), - QStringLiteral("Router"), - QStringLiteral("Server"), - QStringLiteral("Email")}); -} - -void TestOpVaultReader::testReadIntoDatabase() -{ - QDir opVaultDir(m_opVaultPath); - - OpVaultReader reader; - QScopedPointer db(reader.readDatabase(opVaultDir, "a")); - QVERIFY(db); - QVERIFY2(!reader.hasError(), qPrintable(reader.errorString())); - - // Confirm specific entry details are valid - auto entry = db->rootGroup()->findEntryByPath("/Login/KeePassXC"); - QVERIFY(entry); - QCOMPARE(entry->title(), QStringLiteral("KeePassXC")); - QCOMPARE(entry->username(), QStringLiteral("keepassxc")); - QCOMPARE(entry->password(), QStringLiteral("opvault")); - QCOMPARE(entry->url(), QStringLiteral("https://www.keepassxc.org")); - QCOMPARE(entry->notes(), QStringLiteral("KeePassXC Account")); - // Check extra URL's - QCOMPARE(entry->attribute("KP2A_URL_1"), QStringLiteral("https://snapshot.keepassxc.org")); - // Check TOTP - QVERIFY(entry->hasTotp()); - // Check attachments - auto attachments = entry->attachments(); - QCOMPARE(attachments->keys().count(), 1); - QCOMPARE(*attachments->values().begin(), QByteArray("attachment")); - - // Confirm expired entries - entry = db->rootGroup()->findEntryByPath("/Login/Expired Login"); - QVERIFY(entry->isExpired()); - - // Confirm advanced attributes - entry = db->rootGroup()->findEntryByPath("/Credit Card/My Credit Card"); - QVERIFY(entry); - auto attr = entry->attributes(); - QCOMPARE(attr->value("cardholder name"), QStringLiteral("Team KeePassXC")); - QVERIFY(!attr->value("valid from").isEmpty()); - QCOMPARE(attr->value("Additional Details_PIN"), QStringLiteral("1234")); - QVERIFY(attr->isProtected("Additional Details_PIN")); - - // Confirm address fields - entry = db->rootGroup()->findEntryByPath("/Identity/Team KeePassXC"); - QVERIFY(entry); - attr = entry->attributes(); - QCOMPARE(attr->value("address_street"), QStringLiteral("123 Password Lane")); - - // Confirm complex passwords - entry = db->rootGroup()->findEntryByPath("/Password/Complex Password"); - QVERIFY(entry); - QCOMPARE(entry->password(), QStringLiteral("HfgcHjEL}iO}^3N!?*cv~O:9GJZQ0>oC")); - QVERIFY(entry->hasTotp()); - auto totpSettings = entry->totpSettings(); - QCOMPARE(totpSettings->digits, static_cast(8)); - QCOMPARE(totpSettings->step, static_cast(45)); - - // Add another OTP to this entry to confirm it doesn't overwrite the existing one - auto field = QJsonObject::fromVariantMap({{"n", "TOTP_SETTINGS"}, {"v", "otpauth://test.url?digits=6"}}); - reader.fillFromSectionField(entry, "", field); - QVERIFY(entry->hasTotp()); - totpSettings = entry->totpSettings(); - QCOMPARE(totpSettings->digits, static_cast(8)); - QCOMPARE(totpSettings->step, static_cast(45)); - QVERIFY(entry->attributes()->contains("otp_1")); - - // Confirm trashed entries are sent to the recycle bin - auto recycleBin = db->metadata()->recycleBin(); - QVERIFY(recycleBin); - QVERIFY(!recycleBin->isEmpty()); - QVERIFY(recycleBin->findEntryByPath("Trashed Password")); - - // Confirm created groups align with category names - for (const auto group : db->rootGroup()->children()) { - if (group == recycleBin) { - continue; - } - QVERIFY2(m_categories.contains(group->name()), - qPrintable(QStringLiteral("Invalid group name: %1").arg(group->name()))); - // Confirm each group is not empty - QVERIFY2(!group->isEmpty(), qPrintable(QStringLiteral("Group %1 is empty").arg(group->name()))); - } -} diff --git a/tests/data/1PasswordExport.1pux b/tests/data/1PasswordExport.1pux new file mode 100644 index 0000000000000000000000000000000000000000..509d7d07b79726eb648ec263d1fbc9c46f58b529 GIT binary patch literal 31621 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 PU}cDAWMB}f0;vK3ePY>V literal 0 HcmV?d00001 diff --git a/tests/data/bitwarden_encrypted_export.json b/tests/data/bitwarden_encrypted_export.json new file mode 100644 index 000000000..0f759686c --- /dev/null +++ b/tests/data/bitwarden_encrypted_export.json @@ -0,0 +1,11 @@ +{ + "encrypted": true, + "passwordProtected": true, + "salt": "jxJdzv853aLmu0y/mCgSxg==", + "kdfType": 0, + "kdfIterations": 100000, + "kdfMemory": null, + "kdfParallelism": null, + "encKeyValidation_DO_NOT_EDIT": "2.6O5+RkqPRTCxGIjEIyqukQ==|J7Ks4QhjfOyt7qMU82XEuJoGw0GpQabv0vGerKC+YjSQWmaqbbyMDgba78vyRvSU|f0nwbY+JRc2KfkU6mY0dmiKNiDb00A0CngpF4TEEM0c=", + "data": "2.OA/bDI14kq+642rwmWYWxg==|216xw4kCZbqhVifzikzvzqLY2Er35tiYo+gl+hgf9dmLrPMf5vYcFgMe8IdTHXZCdUEuyEdpQeoAwGT8zG8d9GcwdKKOktccl04lE39Cb6XqKEr1PA3d4R8iPYTpeeFSm/cFLQlod5iymUkW4wxHTSIVn9KO/y0F8LWyKX7XxAdCEJykatSoUcC9SmFTPxEtR7BBgfkLTCgSZ9AUE0suKoYIUR6sJSlDq3IHP/09T8w0bbahBkRzevj5+JXawxn1DvBld00bVzo6GgrGojHz+VNa/crpLSaPqyR/IlD66+bS1DdIZ4UBODpZVZTxNKbWd7mPhkCcHF+NchCb47MR442dVQD9QjXk8q7E3SoK76JkYdOZsd3FIH8fZNdYTSOZsvLOYans74RyX1qCD5w3QVaR1cwRYD+kwCe0eFlHmzCLCx3IAuTfH1QdXvIvqaevYKikuKE8tfaAhrPJ2N4MHoKyxdF801jqslZdWrUrZvWsovdBZhp2siQZiWpd/fteJTSpy19sJ+J49+4SYEAfYe3lbz2K7ypKia8duffnV4+eh5tsK24MkExHO3ZQzQVkQdsX6eeFJmdqK4wONunSgnXIDti5rw/bWNtjVvAYiDMX+DNULML/opp9TPZUvrTgFhMsFFwbVzIjTxwE/PS9w+lD3etP195QkD717F87dClpkIrvm+UfQrQwCgDxOQ9PTPcUBVugq9MEflsiSn4NjCXdjWL1siSgxm2eJQ3k0OKJoN5bUInwG9i9njLh5fjxc4aiuvOOGAkqgX/mr3MxuuV8luKWRy884Reu8DdnZq6Vdq+yHgs7o9Ipxrtr8t85yBeU90yqyJrtmwDgEJiLK0TpJ1bY9ZwnqhYrtJGRrzxWrfvAGcJzEsWJ98aq9T+r/CnnsInyRTyptOgmsjmPlw0rTZ8//KI2afwRQRL+yIZ4817T+DekyF18QnYD607njiJb5igEy9MzYw04osr9yyQikheyuPDvD2UnGgGYdy04sHKVNgt0/xtzsJvxhsmy0mXknRcajExsKe6wH1jzTq6IxWo+08+5lnMmr05gtE8Y6HN2nsOAVdGU6x26MQVI|ASjBD0/F6Z61WSWc++RXhA6iQv8AziJO+/EXrj7GSVY=" +} \ No newline at end of file diff --git a/tests/data/bitwarden_export.json b/tests/data/bitwarden_export.json new file mode 100644 index 000000000..7d6a5de21 --- /dev/null +++ b/tests/data/bitwarden_export.json @@ -0,0 +1,180 @@ +{ + "folders": [ + { + "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "name": "My Folder" + }, + { + "id": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy", + "name": "Second Folder" + } + ], + "items": [ + { + "id": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa", + "organizationId": null, + "folderId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "type": 2, + "name": "My Secure Note", + "notes": "1st line of secure note\n2nd line of secure note\n3rd line of secure note", + "favorite": false, + "fields": [ + { + "name": "Text Field", + "value": "text-field-value", + "type": 0 + }, + { + "name": "Hidden Field", + "value": "hidden-field-value", + "type": 1 + }, + { + "name": "Boolean Field", + "value": "false", + "type": 2 + } + ], + "secureNote": { + "type": 0 + }, + "collectionIds": [ + null + ] + }, + { + "id": "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", + "organizationId": null, + "folderId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy", + "type": 3, + "name": "Card Name", + "notes": "1st line of note text\n2nd line of note text", + "favorite": false, + "fields": [ + { + "name": "Text Field", + "value": "text-field-value", + "type": 0 + }, + { + "name": "Hidden Field", + "value": "hidden-field-value", + "type": 1 + }, + { + "name": "Boolean Field", + "value": "false", + "type": 2 + } + ], + "card": { + "cardholderName": "Jane Doe", + "brand": "Visa", + "number": "1234567891011121", + "expMonth": "10", + "expYear": "2021", + "code": "123" + }, + "collectionIds": [ + null + ] + }, + { + "id": "cccccccc-cccc-cccc-cccc-cccccccccccc", + "organizationId": null, + "folderId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "type": 4, + "name": "My Identity", + "notes": "1st line of a note\n2nd line of a note", + "favorite": false, + "fields": [ + { + "name": "Text Field", + "value": "text-field-value", + "type": 0 + }, + { + "name": "Hidden Field", + "value": "hidden-field-value", + "type": 1 + }, + { + "name": "Boolean Field", + "value": "true", + "type": 2 + } + ], + "identity": { + "title": "Mrs", + "firstName": "Jane", + "middleName": "A", + "lastName": "Doe", + "address1": " 1 North Calle Cesar Chavez ", + "address2": null, + "address3": null, + "city": "Santa Barbara", + "state": "CA", + "postalCode": "93103", + "country": "United States ", + "company": "My Employer", + "email": "myemail@gmail.com", + "phone": "123-123-1234", + "ssn": "123-12-1234", + "username": "myusername", + "passportNumber": "123456789", + "licenseNumber": "123456789" + }, + "collectionIds": [ + null + ] + }, + { + "id": "dddddddd-dddd-dddd-dddd-dddddddddddd", + "organizationId": null, + "folderId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "type": 1, + "name": "Login Name", + "notes": "1st line of note text\n2nd Line of note text", + "favorite": true, + "fields": [ + { + "name": "Text Field", + "value": "text-field-value", + "type": 0 + }, + { + "name": "Hidden Field", + "value": "hidden-field-value", + "type": 1 + }, + { + "name": "Boolean Field", + "value": "true", + "type": 2 + } + ], + "login": { + "uris": [ + { + "match": null, + "uri": "https://mail.google.com" + }, + { + "match": null, + "uri": "https://google.com" + }, + { + "match": null, + "uri": "https://gmail.com" + } + ], + "username": "myusername@gmail.com", + "password": "mypassword", + "totp": "otpauth://totp/Google:myusername%40gmail.com?secret=DFDFDEF%3D&period=30&digits=6&issuer=Google" + }, + "collectionIds": [ + null + ] + } + ] +} diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 3e6c7c800..e411f3693 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -1489,28 +1489,6 @@ void TestGui::testDatabaseSettings() checkSaveDatabase(); } -void TestGui::testKeePass1Import() -{ - fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/basic.kdb")); - triggerAction("actionImportKeePass1"); - - auto* keepass1OpenWidget = m_tabWidget->currentDatabaseWidget()->findChild("keepass1OpenWidget"); - auto* editPassword = - keepass1OpenWidget->findChild("editPassword")->findChild("passwordEdit"); - QVERIFY(editPassword); - - QTest::keyClicks(editPassword, "masterpw"); - QTest::keyClick(editPassword, Qt::Key_Enter); - - QTRY_COMPARE(m_tabWidget->count(), 2); - QTRY_COMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("basic [New Database]*")); - - // Close the KeePass1 Database - MessageBox::setNextAnswer(MessageBox::No); - triggerAction("actionDatabaseClose"); - QApplication::processEvents(); -} - void TestGui::testDatabaseLocking() { QString origDbName = m_tabWidget->tabText(0); diff --git a/tests/gui/TestGui.h b/tests/gui/TestGui.h index c631e5bdc..fa3d613f9 100644 --- a/tests/gui/TestGui.h +++ b/tests/gui/TestGui.h @@ -61,7 +61,6 @@ private slots: void testSaveBackupPath(); void testSaveBackupPath_data(); void testDatabaseSettings(); - void testKeePass1Import(); void testDatabaseLocking(); void testDragAndDropKdbxFiles(); void testSortGroups();