mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-25 15:29:44 -05:00
Release 2.5.3
Fixed - Fix a possible database lockout when removing a YubiKey from a KDBX 3.1 database [#4147] - Fix crash if Auto-Type is performed on a new entry [#4150] - Fix crash when all entries are deleted from a group [#4156] - Improve the reliability of clipboard clearing on Gnome [#4165] - Do not check cmd:// URLs for valid URL syntax anymore [#4172] - Prevent unnecessary merges for databases on network shares [#4153] - Browser: Prevent native messaging proxy from blocking application shutdown [#4155] - Browser: Improve website URL matching [#4134, #4177] Added - Browser: Enable support for Chromium-based Edge Browser [#3359]
This commit is contained in:
commit
f8c962bd25
17
CHANGELOG.md
17
CHANGELOG.md
@ -1,5 +1,22 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2.5.3 (2020-01-19)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix a possible database lockout when removing a YubiKey from a KDBX 3.1 database [#4147]
|
||||||
|
- Fix crash if Auto-Type is performed on a new entry [#4150]
|
||||||
|
- Fix crash when all entries are deleted from a group [#4156]
|
||||||
|
- Improve the reliability of clipboard clearing on Gnome [#4165]
|
||||||
|
- Do not check cmd:// URLs for valid URL syntax anymore [#4172]
|
||||||
|
- Prevent unnecessary merges for databases on network shares [#4153]
|
||||||
|
- Browser: Prevent native messaging proxy from blocking application shutdown [#4155]
|
||||||
|
- Browser: Improve website URL matching [#4134, #4177]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Browser: Enable support for Chromium-based Edge Browser [#3359]
|
||||||
|
|
||||||
## 2.5.2 (2020-01-04)
|
## 2.5.2 (2020-01-04)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -95,7 +95,7 @@ endif()
|
|||||||
|
|
||||||
set(KEEPASSXC_VERSION_MAJOR "2")
|
set(KEEPASSXC_VERSION_MAJOR "2")
|
||||||
set(KEEPASSXC_VERSION_MINOR "5")
|
set(KEEPASSXC_VERSION_MINOR "5")
|
||||||
set(KEEPASSXC_VERSION_PATCH "2")
|
set(KEEPASSXC_VERSION_PATCH "3")
|
||||||
set(KEEPASSXC_VERSION "${KEEPASSXC_VERSION_MAJOR}.${KEEPASSXC_VERSION_MINOR}.${KEEPASSXC_VERSION_PATCH}")
|
set(KEEPASSXC_VERSION "${KEEPASSXC_VERSION_MAJOR}.${KEEPASSXC_VERSION_MINOR}.${KEEPASSXC_VERSION_PATCH}")
|
||||||
set(OVERRIDE_VERSION "" CACHE STRING "Override the KeePassXC Version for Snapshot builds")
|
set(OVERRIDE_VERSION "" CACHE STRING "Override the KeePassXC Version for Snapshot builds")
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ so please check out your distribution's package list to see if KeePassXC is avai
|
|||||||
- Using website favicons as entry icons
|
- Using website favicons as entry icons
|
||||||
- Merging of databases
|
- Merging of databases
|
||||||
- Automatic reload when the database changed on disk
|
- Automatic reload when the database changed on disk
|
||||||
- Browser integration with KeePassXC-Browser using [native messaging](https://developer.chrome.com/extensions/nativeMessaging) for [Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) and [Google Chrome, Chromium, Vivaldi, or Brave](https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk)
|
- Browser integration with KeePassXC-Browser using [native messaging](https://developer.chrome.com/extensions/nativeMessaging) for [Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) and [Google Chrome, Chromium, Vivaldi, or Brave](https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk) and [Microsoft Edge](https://microsoftedge.microsoft.com/addons/detail/pdffhmdngciaglkoonimfcmckehcpafo)
|
||||||
- Synchronize passwords using KeeShare. See [Using Sharing](./docs/QUICKSTART.md#using-sharing) for more details.
|
- Synchronize passwords using KeeShare. See [Using Sharing](./docs/QUICKSTART.md#using-sharing) for more details.
|
||||||
- Many bug fixes
|
- Many bug fixes
|
||||||
|
|
||||||
|
@ -50,6 +50,20 @@
|
|||||||
</screenshots>
|
</screenshots>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="2.5.3" date="2020-01-19">
|
||||||
|
<description>
|
||||||
|
<ul>
|
||||||
|
<li>Fix a possible database lockout when removing a YubiKey from a KDBX 3.1 database [#4147]</li>
|
||||||
|
<li>Fix crash if Auto-Type is performed on a new entry [#4150]</li>
|
||||||
|
<li>Fix crash when all entries are deleted from a group [#4156]</li>
|
||||||
|
<li>Improve the reliability of clipboard clearing on Gnome [#4165]</li>
|
||||||
|
<li>Do not check cmd:// URLs for valid URL syntax anymore [#4172]</li>
|
||||||
|
<li>Prevent unnecessary merges for databases on network shares [#4153]</li>
|
||||||
|
<li>Browser: Prevent native messaging proxy from blocking application shutdown [#4155]</li>
|
||||||
|
<li>Browser: Improve website URL matching [#4134, #4177]</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
</release>
|
||||||
<release version="2.5.2" date="2020-01-04">
|
<release version="2.5.2" date="2020-01-04">
|
||||||
<description>
|
<description>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -1112,7 +1112,7 @@ Please consider generating a new key file.</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Select key file</source>
|
<source>Select key file</source>
|
||||||
<translation>Seleccioneu el fitxer de clau</translation>
|
<translation>Selecciona el fitxer de clau</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Failed to open key file: %1</source>
|
<source>Failed to open key file: %1</source>
|
||||||
@ -1195,7 +1195,7 @@ To prevent this error from appearing, you must go to "Database Settings / S
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Enter Additional Credentials (if any):</source>
|
<source>Enter Additional Credentials (if any):</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Introduïu credencials addionals (si cal):</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source><p>You can use a hardware security key such as a <strong>YubiKey</strong> or <strong>OnlyKey</strong> with slots configured for HMAC-SHA1.</p>
|
<source><p>You can use a hardware security key such as a <strong>YubiKey</strong> or <strong>OnlyKey</strong> with slots configured for HMAC-SHA1.</p>
|
||||||
@ -1216,7 +1216,7 @@ To prevent this error from appearing, you must go to "Database Settings / S
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Select key file...</source>
|
<source>Select key file...</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Selecciona el fitxer clau...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Cannot use database file as key file</source>
|
<source>Cannot use database file as key file</source>
|
||||||
@ -2541,7 +2541,7 @@ Voleu deshabilitar el desat segur i provar-ho un altre cop?</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Toggle password generator</source>
|
<source>Toggle password generator</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Commuta el generador de contrasenyes</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Password field</source>
|
<source>Password field</source>
|
||||||
@ -2829,7 +2829,7 @@ Supported extensions are: %1.</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Toggle password generator</source>
|
<source>Toggle password generator</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Commuta el generador de contrasenyes</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Clear fields</source>
|
<source>Clear fields</source>
|
||||||
@ -3468,7 +3468,7 @@ You can enable the DuckDuckGo website icon service in the security section of th
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Downloading...</source>
|
<source>Downloading...</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Descarregant...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Ok</source>
|
<source>Ok</source>
|
||||||
@ -3480,7 +3480,7 @@ You can enable the DuckDuckGo website icon service in the security section of th
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Download Failed</source>
|
<source>Download Failed</source>
|
||||||
<translation type="unfinished"/>
|
<translation>La descàrrega ha fallat</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Downloading favicons (%1/%2)...</source>
|
<source>Downloading favicons (%1/%2)...</source>
|
||||||
@ -3897,7 +3897,7 @@ Line %2, column %3</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Import KeePass1 Database</source>
|
<source>Import KeePass1 Database</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Importa una base de dades de KeePass 1</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@ -4093,7 +4093,7 @@ If this reoccurs, then your database file may be corrupt.</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Imported from</source>
|
<source>Imported from</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Importat de</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Exported to</source>
|
<source>Exported to</source>
|
||||||
@ -4195,11 +4195,11 @@ Message: %2</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Select a key file</source>
|
<source>Select a key file</source>
|
||||||
<translation>Seleccioneu un arxiu clau</translation>
|
<translation>Selecciona un fitxer clau</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Key file selection</source>
|
<source>Key file selection</source>
|
||||||
<translation>Selecció del fitxer clau</translation>
|
<translation>Selecciona el fitxer clau...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Browse for key file</source>
|
<source>Browse for key file</source>
|
||||||
@ -4267,7 +4267,7 @@ Are you sure you want to continue with this file?</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>&About</source>
|
<source>&About</source>
|
||||||
<translation>&Sobre</translation>
|
<translation>Quant &a</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>&Open database...</source>
|
<source>&Open database...</source>
|
||||||
@ -4412,7 +4412,7 @@ We recommend you use the AppImage available on our downloads page.</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>&Import</source>
|
<source>&Import</source>
|
||||||
<translation>& Importa</translation>
|
<translation>&Importa</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Copy att&ribute...</source>
|
<source>Copy att&ribute...</source>
|
||||||
@ -4480,7 +4480,7 @@ We recommend you use the AppImage available on our downloads page.</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Open &URL</source>
|
<source>Open &URL</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Obre la &URL</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>KeePass 1 database...</source>
|
<source>KeePass 1 database...</source>
|
||||||
@ -4488,7 +4488,7 @@ We recommend you use the AppImage available on our downloads page.</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Import a KeePass 1 database</source>
|
<source>Import a KeePass 1 database</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Importa una base de dades de KeePass 1</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>CSV file...</source>
|
<source>CSV file...</source>
|
||||||
@ -4530,7 +4530,7 @@ Podeu esperar alguns errors i incidències menors. Aquesta versió no està pens
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>&Check for Updates...</source>
|
<source>&Check for Updates...</source>
|
||||||
<translation type="unfinished"/>
|
<translation>&Comprova si hi ha actualitzacions...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Downlo&ad all favicons</source>
|
<source>Downlo&ad all favicons</source>
|
||||||
@ -4538,19 +4538,19 @@ Podeu esperar alguns errors i incidències menors. Aquesta versió no està pens
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Sort &A-Z</source>
|
<source>Sort &A-Z</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Ordena &A-Z</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Sort &Z-A</source>
|
<source>Sort &Z-A</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Ordena &Z-A</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>&Password Generator</source>
|
<source>&Password Generator</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Generador de contrasenyes</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Download favicon</source>
|
<source>Download favicon</source>
|
||||||
<translation>Descarregua el favicon</translation>
|
<translation>Descarrega el favicon</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>&Export to HTML file...</source>
|
<source>&Export to HTML file...</source>
|
||||||
@ -4566,15 +4566,15 @@ Podeu esperar alguns errors i incidències menors. Aquesta versió no està pens
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>&Getting Started</source>
|
<source>&Getting Started</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Primers passos</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Open Getting Started Guide PDF</source>
|
<source>Open Getting Started Guide PDF</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Obre el PDF de la guia Primers passos</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>&Online Help...</source>
|
<source>&Online Help...</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Ajuda &online...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Go to online documentation (opens browser)</source>
|
<source>Go to online documentation (opens browser)</source>
|
||||||
@ -4582,15 +4582,15 @@ Podeu esperar alguns errors i incidències menors. Aquesta versió no està pens
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>&User Guide</source>
|
<source>&User Guide</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Guia d'&Usuari</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Open User Guide PDF</source>
|
<source>Open User Guide PDF</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Obre el PDF de la Guia d'usuari</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>&Keyboard Shortcuts</source>
|
<source>&Keyboard Shortcuts</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Dreceres de teclat</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@ -4944,7 +4944,7 @@ Podeu esperar alguns errors i incidències menors. Aquesta versió no està pens
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Toggle password generator</source>
|
<source>Toggle password generator</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Commuta la generació de contrasenyes</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@ -6151,7 +6151,7 @@ Nucli: %3 %4</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Successfully imported database.</source>
|
<source>Successfully imported database.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>La base de dades s'ha importat correctament.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Unknown command %1</source>
|
<source>Unknown command %1</source>
|
||||||
@ -6438,7 +6438,7 @@ Nucli: %3 %4</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Enable KeepassXC Freedesktop.org Secret Service integration</source>
|
<source>Enable KeepassXC Freedesktop.org Secret Service integration</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Habilita la integració amb el Freedesktop.org Secret Service</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>General</source>
|
<source>General</source>
|
||||||
@ -6446,7 +6446,7 @@ Nucli: %3 %4</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Show notification when credentials are requested</source>
|
<source>Show notification when credentials are requested</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Mostra una notificació quan es demanen credencials</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source><html><head/><body><p>If recycle bin is enabled for the database, entries will be moved to recycle bin directly. Otherwise, they will be deleted without confirmation.</p><p>You will still be prompted if any entries are referenced by others.</p></body></html></source>
|
<source><html><head/><body><p>If recycle bin is enabled for the database, entries will be moved to recycle bin directly. Otherwise, they will be deleted without confirmation.</p><p>You will still be prompted if any entries are referenced by others.</p></body></html></source>
|
||||||
@ -6454,7 +6454,7 @@ Nucli: %3 %4</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Don't confirm when entries are deleted by clients.</source>
|
<source>Don't confirm when entries are deleted by clients.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>No confirmar quan les entrades són esborrades pel clients.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Exposed database groups:</source>
|
<source>Exposed database groups:</source>
|
||||||
@ -6470,19 +6470,19 @@ Nucli: %3 %4</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Manage</source>
|
<source>Manage</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Gestiona</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Authorization</source>
|
<source>Authorization</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Autorització</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>These applications are currently connected:</source>
|
<source>These applications are currently connected:</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Aquestes aplicacions estan ara connectades:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Application</source>
|
<source>Application</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Aplicació</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Disconnect</source>
|
<source>Disconnect</source>
|
||||||
@ -6650,7 +6650,7 @@ Nucli: %3 %4</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Only show warnings and errors</source>
|
<source>Only show warnings and errors</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Mostra només els avisos i els errors</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Key</source>
|
<source>Key</source>
|
||||||
|
@ -7052,7 +7052,7 @@ Example: JBSWY3DPEHPK3PXP</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>You're up-to-date!</source>
|
<source>You're up-to-date!</source>
|
||||||
<translation>Version aktuel</translation>
|
<translation>Version aktuell</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>KeePassXC %1 is currently the newest version available</source>
|
<source>KeePassXC %1 is currently the newest version available</source>
|
||||||
|
@ -739,10 +739,6 @@ Please select the correct database for saving credentials.</translation>
|
|||||||
<source>Please see special instructions for browser extension use below</source>
|
<source>Please see special instructions for browser extension use below</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<source>KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2. %3</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
<message>
|
||||||
<source>&Brave</source>
|
<source>&Brave</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
@ -787,6 +783,14 @@ Please select the correct database for saving credentials.</translation>
|
|||||||
<source><b>Warning</b>, the keepassxc-proxy application was not found!<br />Please check the KeePassXC installation directory or confirm the custom path in advanced options.<br />Browser integration WILL NOT WORK without the proxy application.<br />Expected Path: %1</source>
|
<source><b>Warning</b>, the keepassxc-proxy application was not found!<br />Please check the KeePassXC installation directory or confirm the custom path in advanced options.<br />Browser integration WILL NOT WORK without the proxy application.<br />Expected Path: %1</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>&Edge</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2 and %3. %4</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>BrowserService</name>
|
<name>BrowserService</name>
|
||||||
|
@ -4519,7 +4519,7 @@ Wij raden je aan om de AppImage te gebruiken welke beschikbaar is op onze downlo
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Perform &Auto-Type</source>
|
<source>Perform &Auto-Type</source>
|
||||||
<translation>Uitvoeren &Auto-Type</translation>
|
<translation>&Auto-type uitvoeren</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Open &URL</source>
|
<source>Open &URL</source>
|
||||||
|
@ -878,7 +878,11 @@ Mevcut ayarlarınızı şimdi taşımak ister misiniz?</translation>
|
|||||||
|
|
||||||
Give the connection a unique name or ID, for example:
|
Give the connection a unique name or ID, for example:
|
||||||
chrome-laptop.</source>
|
chrome-laptop.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Aşağıdaki veritabanı için bir ilişkilendirme isteği aldınız:
|
||||||
|
%1
|
||||||
|
|
||||||
|
Bağlantıya benzersiz bir ad veya kimlik verin, örneğin:
|
||||||
|
linux-laptop.</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@ -990,7 +994,7 @@ chrome-laptop.</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Text qualification</source>
|
<source>Text qualification</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Metin niteliği</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Field separation</source>
|
<source>Field separation</source>
|
||||||
@ -1227,7 +1231,7 @@ To prevent this error from appearing, you must go to "Database Settings / S
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Cannot use database file as key file</source>
|
<source>Cannot use database file as key file</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Veritabanı dosyası anahtar dosyası olarak kullanılamaz</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>You cannot use your database file as a key file.
|
<source>You cannot use your database file as a key file.
|
||||||
@ -1389,11 +1393,11 @@ Tarayıcı eklentisiyle uyumluluğu korumak için bu gereklidir.</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Stored browser keys</source>
|
<source>Stored browser keys</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Saklanan tarayıcı tuşları</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Remove selected key</source>
|
<source>Remove selected key</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Seçili anahtarı kaldır</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@ -1539,11 +1543,11 @@ Eğer bu sayı ile devam ederseniz, veritabanınız çok kolay çözülerek kır
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Change existing decryption time</source>
|
<source>Change existing decryption time</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Mevcut şifre çözme süresini değiştir</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Decryption time in seconds</source>
|
<source>Decryption time in seconds</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Saniyede şifre çözme süresi</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Database format</source>
|
<source>Database format</source>
|
||||||
@ -1551,11 +1555,11 @@ Eğer bu sayı ile devam ederseniz, veritabanınız çok kolay çözülerek kır
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Encryption algorithm</source>
|
<source>Encryption algorithm</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Şifreleme algoritması</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Key derivation function</source>
|
<source>Key derivation function</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Anahtar türetme işlevi</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Transform rounds</source>
|
<source>Transform rounds</source>
|
||||||
@ -1567,14 +1571,14 @@ Eğer bu sayı ile devam ederseniz, veritabanınız çok kolay çözülerek kır
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Parallelism</source>
|
<source>Parallelism</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Benzerlik</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>DatabaseSettingsWidgetFdoSecrets</name>
|
<name>DatabaseSettingsWidgetFdoSecrets</name>
|
||||||
<message>
|
<message>
|
||||||
<source>Exposed Entries</source>
|
<source>Exposed Entries</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Maruz Kalan Girdiler</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Don't e&xpose this database</source>
|
<source>Don't e&xpose this database</source>
|
||||||
@ -1582,7 +1586,7 @@ Eğer bu sayı ile devam ederseniz, veritabanınız çok kolay çözülerek kır
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Expose entries &under this group:</source>
|
<source>Expose entries &under this group:</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Bu kümenin &altındaki girdileri göster:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Enable fd.o Secret Service to access these settings.</source>
|
<source>Enable fd.o Secret Service to access these settings.</source>
|
||||||
@ -1653,11 +1657,11 @@ Eğer bu sayı ile devam ederseniz, veritabanınız çok kolay çözülerek kır
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Maximum size of history per entry</source>
|
<source>Maximum size of history per entry</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Girdi başına azami geçmiş boyutu</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Delete Recycle Bin</source>
|
<source>Delete Recycle Bin</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Geri Dönüşüm Kutusunu Sil</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Do you want to delete the current recycle bin and all its contents?
|
<source>Do you want to delete the current recycle bin and all its contents?
|
||||||
@ -1767,7 +1771,7 @@ Parola olmadan devam etmek istediğinize emin misiniz?</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Hover over lines with error icons for further information.</source>
|
<source>Hover over lines with error icons for further information.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Daha fazla bilgi için farenizi hata simgeli satırların üzerine getirin.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Name</source>
|
<source>Name</source>
|
||||||
@ -1803,7 +1807,7 @@ Parola olmadan devam etmek istediğinize emin misiniz?</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>no</source>
|
<source>no</source>
|
||||||
<translation type="unfinished"/>
|
<translation>hayır</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>The database was modified, but the changes have not yet been saved to disk.</source>
|
<source>The database was modified, but the changes have not yet been saved to disk.</source>
|
||||||
@ -1811,15 +1815,15 @@ Parola olmadan devam etmek istediğinize emin misiniz?</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Number of groups</source>
|
<source>Number of groups</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Küme sayısı</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Number of entries</source>
|
<source>Number of entries</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Girdilerin sayısı</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Number of expired entries</source>
|
<source>Number of expired entries</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Süresi dolmuş girdi sayısı</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>The database contains entries that have expired.</source>
|
<source>The database contains entries that have expired.</source>
|
||||||
@ -1827,35 +1831,35 @@ Parola olmadan devam etmek istediğinize emin misiniz?</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Unique passwords</source>
|
<source>Unique passwords</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Benzersiz parolalar</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Non-unique passwords</source>
|
<source>Non-unique passwords</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Benzersiz olmayan parolalar</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>More than 10% of passwords are reused. Use unique passwords when possible.</source>
|
<source>More than 10% of passwords are reused. Use unique passwords when possible.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Parolaların %10'undan fazlası yeniden kullanılır. Mümkünse benzersiz parolalar kullanın.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Maximum password reuse</source>
|
<source>Maximum password reuse</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Azami parola kullanımı</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Some passwords are used more than three times. Use unique passwords when possible.</source>
|
<source>Some passwords are used more than three times. Use unique passwords when possible.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Bazı parolalar üç kereden fazla kullanılır. Mümkünse benzersiz parolalar kullanın.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Number of short passwords</source>
|
<source>Number of short passwords</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Kısa parola sayısı</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Recommended minimum password length is at least 8 characters.</source>
|
<source>Recommended minimum password length is at least 8 characters.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Önerilen asgari parola uzunluğu en az 8 karakterdir.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Number of weak passwords</source>
|
<source>Number of weak passwords</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Zayıf parola sayısı</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Recommend using long, randomized passwords with a rating of 'good' or 'excellent'.</source>
|
<source>Recommend using long, randomized passwords with a rating of 'good' or 'excellent'.</source>
|
||||||
@ -1971,7 +1975,7 @@ Bu kesinlikle bir hatadır, lütfen geliştiricilere bildirin.</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>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?</source>
|
<source>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?</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Veritabanınızı şifrelenmemiş bir dosyaya vermek üzeresiniz. Bu, parolalarınızı ve hassas bilgilerinizi savunmasız bırakacaktır! Devam etmek istediğine emin misin?</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@ -2350,7 +2354,7 @@ Güvenli kaydetme devre dışı bırakılsın ve tekrar denensin mi?</translatio
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Show a protected attribute</source>
|
<source>Show a protected attribute</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Korumalı bir özelliği göster</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Foreground color selection</source>
|
<source>Foreground color selection</source>
|
||||||
@ -2429,7 +2433,7 @@ Güvenli kaydetme devre dışı bırakılsın ve tekrar denensin mi?</translatio
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Custom Auto-Type sequence for this window</source>
|
<source>Custom Auto-Type sequence for this window</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Bu pencere için özel Otomatik Yazım sırası</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@ -2578,7 +2582,7 @@ Güvenli kaydetme devre dışı bırakılsın ve tekrar denensin mi?</translatio
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Expiration Presets</source>
|
<source>Expiration Presets</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Son Kullanma Önayarları</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Expiration presets</source>
|
<source>Expiration presets</source>
|
||||||
@ -2678,11 +2682,11 @@ Güvenli kaydetme devre dışı bırakılsın ve tekrar denensin mi?</translatio
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Remove key from agent after specified seconds</source>
|
<source>Remove key from agent after specified seconds</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Belirtilen saniye sonra anahtarı aracıdan kaldır</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Browser for key file</source>
|
<source>Browser for key file</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Anahtar dosyasına göz at</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>External key file</source>
|
<source>External key file</source>
|
||||||
@ -2690,7 +2694,7 @@ Güvenli kaydetme devre dışı bırakılsın ve tekrar denensin mi?</translatio
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Select attachment file</source>
|
<source>Select attachment file</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Ek dosyasını seç</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@ -3070,7 +3074,7 @@ Bu etkilenen eklentilerin bozulmasına neden olabilir.</translation>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Unique ID</source>
|
<source>Unique ID</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Benzersiz ID</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Plugin data</source>
|
<source>Plugin data</source>
|
||||||
@ -4124,11 +4128,11 @@ If this reoccurs, then your database file may be corrupt.</source>
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Exported to</source>
|
<source>Exported to</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Dışa aktarıldı</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Synchronized with</source>
|
<source>Synchronized with</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Eşitlendi</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
@ -4803,7 +4807,7 @@ Bazı hatalar ve küçük sorunlar olabilir, bu sürüm şu an dağıtımda değ
|
|||||||
<name>OpVaultReader</name>
|
<name>OpVaultReader</name>
|
||||||
<message>
|
<message>
|
||||||
<source>Directory .opvault must exist</source>
|
<source>Directory .opvault must exist</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Dizin .opvault mevcut olmalıdır</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Directory .opvault must be readable</source>
|
<source>Directory .opvault must be readable</source>
|
||||||
@ -6069,7 +6073,7 @@ MİB mimarisi: %2
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Cannot generate a password and prompt at the same time!</source>
|
<source>Cannot generate a password and prompt at the same time!</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Parola ve komut istemi aynı anda oluşturulamaz!</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Adds a new group to a database.</source>
|
<source>Adds a new group to a database.</source>
|
||||||
@ -6117,7 +6121,7 @@ MİB mimarisi: %2
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Display this help.</source>
|
<source>Display this help.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Bu yardımı görüntüle.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Yubikey slot used to encrypt the database.</source>
|
<source>Yubikey slot used to encrypt the database.</source>
|
||||||
@ -6189,7 +6193,7 @@ MİB mimarisi: %2
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Successfully imported database.</source>
|
<source>Successfully imported database.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Veritabanı başarıyla içe aktarıldı.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Unknown command %1</source>
|
<source>Unknown command %1</source>
|
||||||
@ -6245,7 +6249,7 @@ MİB mimarisi: %2
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Path of the group to remove.</source>
|
<source>Path of the group to remove.</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Kaldırılacak kümenin yolu.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Cannot remove root group from database.</source>
|
<source>Cannot remove root group from database.</source>
|
||||||
@ -6285,7 +6289,7 @@ MİB mimarisi: %2
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Enter password to encrypt database (optional): </source>
|
<source>Enter password to encrypt database (optional): </source>
|
||||||
<translation type="unfinished"/>
|
<translation>Veritabanını şifrelemek için parola gir (isteğe bağlı):</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>HIBP file, line %1: parse error</source>
|
<source>HIBP file, line %1: parse error</source>
|
||||||
@ -6496,7 +6500,7 @@ MİB mimarisi: %2
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Exposed database groups:</source>
|
<source>Exposed database groups:</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Maruz kalan veritabanı kümeleri:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>File Name</source>
|
<source>File Name</source>
|
||||||
@ -6532,7 +6536,7 @@ MİB mimarisi: %2
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Edit database settings</source>
|
<source>Edit database settings</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Veritabanı ayarlarını düzenle</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Unlock database</source>
|
<source>Unlock database</source>
|
||||||
@ -6700,7 +6704,7 @@ MİB mimarisi: %2
|
|||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Generate new certificate</source>
|
<source>Generate new certificate</source>
|
||||||
<translation type="unfinished"/>
|
<translation>Yeni sertifika oluştur</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<source>Import existing certificate</source>
|
<source>Import existing certificate</source>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name: keepassxc
|
name: keepassxc
|
||||||
version: 2.5.2
|
version: 2.5.3
|
||||||
grade: stable
|
grade: stable
|
||||||
summary: Community-driven port of the Windows application “KeePass Password Safe”
|
summary: Community-driven port of the Windows application “KeePass Password Safe”
|
||||||
description: |
|
description: |
|
||||||
|
@ -588,12 +588,12 @@ QList<AutoTypeAction*> AutoType::createActionFromTemplate(const QString& tmpl, c
|
|||||||
QList<QString> AutoType::autoTypeSequences(const Entry* entry, const QString& windowTitle)
|
QList<QString> AutoType::autoTypeSequences(const Entry* entry, const QString& windowTitle)
|
||||||
{
|
{
|
||||||
QList<QString> sequenceList;
|
QList<QString> sequenceList;
|
||||||
|
const Group* group = entry->group();
|
||||||
|
|
||||||
if (!entry->autoTypeEnabled()) {
|
if (!group || !entry->autoTypeEnabled()) {
|
||||||
return sequenceList;
|
return sequenceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Group* group = entry->group();
|
|
||||||
do {
|
do {
|
||||||
if (group->autoTypeEnabled() == Group::Disable) {
|
if (group->autoTypeEnabled() == Group::Disable) {
|
||||||
return sequenceList;
|
return sequenceList;
|
||||||
|
@ -44,10 +44,11 @@ BrowserOptionDialog::BrowserOptionDialog(QWidget* parent)
|
|||||||
|
|
||||||
m_ui->extensionLabel->setOpenExternalLinks(true);
|
m_ui->extensionLabel->setOpenExternalLinks(true);
|
||||||
m_ui->extensionLabel->setText(
|
m_ui->extensionLabel->setText(
|
||||||
tr("KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2. %3")
|
tr("KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2 and %3. %4")
|
||||||
.arg("<a href=\"https://addons.mozilla.org/firefox/addon/keepassxc-browser/\">Firefox</a>",
|
.arg("<a href=\"https://addons.mozilla.org/firefox/addon/keepassxc-browser/\">Firefox</a>",
|
||||||
"<a href=\"https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk\">"
|
"<a href=\"https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk\">"
|
||||||
"Google Chrome / Chromium / Vivaldi / Brave</a>",
|
"Google Chrome / Chromium / Vivaldi / Brave</a>",
|
||||||
|
"<a href=\"https://microsoftedge.microsoft.com/addons/detail/pdffhmdngciaglkoonimfcmckehcpafo\">Microsoft Edge</a>",
|
||||||
snapInstructions));
|
snapInstructions));
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@ -123,6 +124,7 @@ void BrowserOptionDialog::loadSettings()
|
|||||||
m_ui->chromeSupport->setChecked(settings->chromeSupport());
|
m_ui->chromeSupport->setChecked(settings->chromeSupport());
|
||||||
m_ui->chromiumSupport->setChecked(settings->chromiumSupport());
|
m_ui->chromiumSupport->setChecked(settings->chromiumSupport());
|
||||||
m_ui->firefoxSupport->setChecked(settings->firefoxSupport());
|
m_ui->firefoxSupport->setChecked(settings->firefoxSupport());
|
||||||
|
m_ui->edgeSupport->setChecked(settings->edgeSupport());
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
m_ui->braveSupport->setChecked(settings->braveSupport());
|
m_ui->braveSupport->setChecked(settings->braveSupport());
|
||||||
m_ui->vivaldiSupport->setChecked(settings->vivaldiSupport());
|
m_ui->vivaldiSupport->setChecked(settings->vivaldiSupport());
|
||||||
@ -132,6 +134,12 @@ void BrowserOptionDialog::loadSettings()
|
|||||||
m_ui->snapWarningLabel->setVisible(false);
|
m_ui->snapWarningLabel->setVisible(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// TODO: Enable when Linux version is released
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
m_ui->edgeSupport->setChecked(false);
|
||||||
|
m_ui->edgeSupport->setEnabled(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(KEEPASSXC_DIST_APPIMAGE)
|
#if defined(KEEPASSXC_DIST_APPIMAGE)
|
||||||
m_ui->supportBrowserProxy->setChecked(true);
|
m_ui->supportBrowserProxy->setChecked(true);
|
||||||
m_ui->supportBrowserProxy->setEnabled(false);
|
m_ui->supportBrowserProxy->setEnabled(false);
|
||||||
@ -194,6 +202,7 @@ void BrowserOptionDialog::saveSettings()
|
|||||||
settings->setChromeSupport(m_ui->chromeSupport->isChecked());
|
settings->setChromeSupport(m_ui->chromeSupport->isChecked());
|
||||||
settings->setChromiumSupport(m_ui->chromiumSupport->isChecked());
|
settings->setChromiumSupport(m_ui->chromiumSupport->isChecked());
|
||||||
settings->setFirefoxSupport(m_ui->firefoxSupport->isChecked());
|
settings->setFirefoxSupport(m_ui->firefoxSupport->isChecked());
|
||||||
|
settings->setEdgeSupport(m_ui->edgeSupport->isChecked());
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
settings->setBraveSupport(m_ui->braveSupport->isChecked());
|
settings->setBraveSupport(m_ui->braveSupport->isChecked());
|
||||||
settings->setVivaldiSupport(m_ui->vivaldiSupport->isChecked());
|
settings->setVivaldiSupport(m_ui->vivaldiSupport->isChecked());
|
||||||
|
@ -167,6 +167,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QCheckBox" name="edgeSupport">
|
||||||
|
<property name="text">
|
||||||
|
<string>&Edge</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -935,6 +935,12 @@ int BrowserService::sortPriority(const Entry* entry,
|
|||||||
if (url.scheme().isEmpty()) {
|
if (url.scheme().isEmpty()) {
|
||||||
url.setScheme("https");
|
url.setScheme("https");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the empty path to the URL if it's missing
|
||||||
|
if (url.path().isEmpty() && !url.hasFragment() && !url.hasQuery()) {
|
||||||
|
url.setPath("/");
|
||||||
|
}
|
||||||
|
|
||||||
const QString entryURL = url.toString(QUrl::StripTrailingSlash);
|
const QString entryURL = url.toString(QUrl::StripTrailingSlash);
|
||||||
const QString baseEntryURL =
|
const QString baseEntryURL =
|
||||||
url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment);
|
url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment);
|
||||||
@ -1046,7 +1052,12 @@ bool BrowserService::handleURL(const QString& entryUrl, const QString& url, cons
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter to match hostname in URL field
|
// Match the base domain
|
||||||
|
if (baseDomain(siteQUrl.host()) != baseDomain(entryQUrl.host())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match the subdomains with the limited wildcard
|
||||||
if (siteQUrl.host().endsWith(entryQUrl.host())) {
|
if (siteQUrl.host().endsWith(entryQUrl.host())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -280,6 +280,17 @@ void BrowserSettings::setTorBrowserSupport(bool enabled)
|
|||||||
HostInstaller::SupportedBrowsers::TOR_BROWSER, enabled, supportBrowserProxy(), customProxyLocation());
|
HostInstaller::SupportedBrowsers::TOR_BROWSER, enabled, supportBrowserProxy(), customProxyLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BrowserSettings::edgeSupport()
|
||||||
|
{
|
||||||
|
return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::EDGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrowserSettings::setEdgeSupport(bool enabled)
|
||||||
|
{
|
||||||
|
m_hostInstaller.installBrowser(
|
||||||
|
HostInstaller::SupportedBrowsers::EDGE, enabled, supportBrowserProxy(), customProxyLocation());
|
||||||
|
}
|
||||||
|
|
||||||
bool BrowserSettings::passwordUseNumbers()
|
bool BrowserSettings::passwordUseNumbers()
|
||||||
{
|
{
|
||||||
return config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool();
|
return config()->get("generator/Numbers", PasswordGenerator::DefaultNumbers).toBool();
|
||||||
|
@ -80,6 +80,8 @@ public:
|
|||||||
void setBraveSupport(bool enabled);
|
void setBraveSupport(bool enabled);
|
||||||
bool torBrowserSupport();
|
bool torBrowserSupport();
|
||||||
void setTorBrowserSupport(bool enabled);
|
void setTorBrowserSupport(bool enabled);
|
||||||
|
bool edgeSupport();
|
||||||
|
void setEdgeSupport(bool enabled);
|
||||||
|
|
||||||
bool passwordUseNumbers();
|
bool passwordUseNumbers();
|
||||||
void setPasswordUseNumbers(bool useNumbers);
|
void setPasswordUseNumbers(bool useNumbers);
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
HostInstaller::HostInstaller()
|
HostInstaller::HostInstaller()
|
||||||
: HOST_NAME("org.keepassxc.keepassxc_browser")
|
: HOST_NAME("org.keepassxc.keepassxc_browser")
|
||||||
, ALLOWED_EXTENSIONS(QStringList() << "keepassxc-browser@keepassxc.org")
|
, ALLOWED_EXTENSIONS(QStringList() << "keepassxc-browser@keepassxc.org")
|
||||||
, ALLOWED_ORIGINS(QStringList() << "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/"
|
, ALLOWED_ORIGINS(QStringList() << "chrome-extension://pdffhmdngciaglkoonimfcmckehcpafo/"
|
||||||
<< "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/")
|
<< "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/")
|
||||||
#if defined(Q_OS_MACOS)
|
#if defined(Q_OS_MACOS)
|
||||||
, TARGET_DIR_CHROME("/Library/Application Support/Google/Chrome/NativeMessagingHosts")
|
, TARGET_DIR_CHROME("/Library/Application Support/Google/Chrome/NativeMessagingHosts")
|
||||||
@ -40,6 +40,7 @@ HostInstaller::HostInstaller()
|
|||||||
, TARGET_DIR_VIVALDI("/Library/Application Support/Vivaldi/NativeMessagingHosts")
|
, TARGET_DIR_VIVALDI("/Library/Application Support/Vivaldi/NativeMessagingHosts")
|
||||||
, TARGET_DIR_TOR_BROWSER("/Library/Application Support/TorBrowser-Data/Browser/Mozilla/NativeMessagingHosts")
|
, TARGET_DIR_TOR_BROWSER("/Library/Application Support/TorBrowser-Data/Browser/Mozilla/NativeMessagingHosts")
|
||||||
, TARGET_DIR_BRAVE("/Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts")
|
, TARGET_DIR_BRAVE("/Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts")
|
||||||
|
, TARGET_DIR_EDGE("/Library/Application Support/Microsoft Edge/NativeMessagingHosts")
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
// clang-format off
|
// clang-format off
|
||||||
, TARGET_DIR_CHROME("HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser")
|
, TARGET_DIR_CHROME("HKEY_CURRENT_USER\\Software\\Google\\Chrome\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser")
|
||||||
@ -49,6 +50,8 @@ HostInstaller::HostInstaller()
|
|||||||
, TARGET_DIR_VIVALDI(TARGET_DIR_CHROME)
|
, TARGET_DIR_VIVALDI(TARGET_DIR_CHROME)
|
||||||
, TARGET_DIR_TOR_BROWSER(TARGET_DIR_FIREFOX)
|
, TARGET_DIR_TOR_BROWSER(TARGET_DIR_FIREFOX)
|
||||||
, TARGET_DIR_BRAVE(TARGET_DIR_CHROME)
|
, TARGET_DIR_BRAVE(TARGET_DIR_CHROME)
|
||||||
|
, TARGET_DIR_EDGE(
|
||||||
|
"HKEY_CURRENT_USER\\Software\\Microsoft\\Edge\\NativeMessagingHosts\\org.keepassxc.keepassxc_browser")
|
||||||
#else
|
#else
|
||||||
, TARGET_DIR_CHROME("/.config/google-chrome/NativeMessagingHosts")
|
, TARGET_DIR_CHROME("/.config/google-chrome/NativeMessagingHosts")
|
||||||
, TARGET_DIR_CHROMIUM("/.config/chromium/NativeMessagingHosts")
|
, TARGET_DIR_CHROMIUM("/.config/chromium/NativeMessagingHosts")
|
||||||
@ -56,6 +59,7 @@ HostInstaller::HostInstaller()
|
|||||||
, TARGET_DIR_VIVALDI("/.config/vivaldi/NativeMessagingHosts")
|
, TARGET_DIR_VIVALDI("/.config/vivaldi/NativeMessagingHosts")
|
||||||
, TARGET_DIR_TOR_BROWSER("/.tor-browser/app/Browser/TorBrowser/Data/Browser/.mozilla/native-messaging-hosts")
|
, TARGET_DIR_TOR_BROWSER("/.tor-browser/app/Browser/TorBrowser/Data/Browser/.mozilla/native-messaging-hosts")
|
||||||
, TARGET_DIR_BRAVE("/.config/BraveSoftware/Brave-Browser/NativeMessagingHosts")
|
, TARGET_DIR_BRAVE("/.config/BraveSoftware/Brave-Browser/NativeMessagingHosts")
|
||||||
|
, TARGET_DIR_EDGE("/.config/microsoftedge/NativeMessagingHosts")
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -139,8 +143,7 @@ void HostInstaller::installBrowser(SupportedBrowsers browser,
|
|||||||
*/
|
*/
|
||||||
void HostInstaller::updateBinaryPaths(const bool& proxy, const QString& location)
|
void HostInstaller::updateBinaryPaths(const bool& proxy, const QString& location)
|
||||||
{
|
{
|
||||||
// Where 6 is the number of entries in the SupportedBrowsers enum declared in HostInstaller.h
|
for (int i = 0; i <= SupportedBrowsers::EDGE; ++i) {
|
||||||
for (int i = 0; i < 6; ++i) {
|
|
||||||
if (checkIfInstalled(static_cast<SupportedBrowsers>(i))) {
|
if (checkIfInstalled(static_cast<SupportedBrowsers>(i))) {
|
||||||
installBrowser(static_cast<SupportedBrowsers>(i), true, proxy, location);
|
installBrowser(static_cast<SupportedBrowsers>(i), true, proxy, location);
|
||||||
}
|
}
|
||||||
@ -168,6 +171,8 @@ QString HostInstaller::getTargetPath(SupportedBrowsers browser) const
|
|||||||
return TARGET_DIR_TOR_BROWSER;
|
return TARGET_DIR_TOR_BROWSER;
|
||||||
case SupportedBrowsers::BRAVE:
|
case SupportedBrowsers::BRAVE:
|
||||||
return TARGET_DIR_BRAVE;
|
return TARGET_DIR_BRAVE;
|
||||||
|
case SupportedBrowsers::EDGE:
|
||||||
|
return TARGET_DIR_EDGE;
|
||||||
default:
|
default:
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
@ -195,6 +200,8 @@ QString HostInstaller::getBrowserName(SupportedBrowsers browser) const
|
|||||||
return "tor-browser";
|
return "tor-browser";
|
||||||
case SupportedBrowsers::BRAVE:
|
case SupportedBrowsers::BRAVE:
|
||||||
return "brave";
|
return "brave";
|
||||||
|
case SupportedBrowsers::EDGE:
|
||||||
|
return "edge";
|
||||||
default:
|
default:
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,8 @@ public:
|
|||||||
FIREFOX = 2,
|
FIREFOX = 2,
|
||||||
VIVALDI = 3,
|
VIVALDI = 3,
|
||||||
TOR_BROWSER = 4,
|
TOR_BROWSER = 4,
|
||||||
BRAVE = 5
|
BRAVE = 5,
|
||||||
|
EDGE = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -68,6 +69,7 @@ private:
|
|||||||
const QString TARGET_DIR_VIVALDI;
|
const QString TARGET_DIR_VIVALDI;
|
||||||
const QString TARGET_DIR_TOR_BROWSER;
|
const QString TARGET_DIR_TOR_BROWSER;
|
||||||
const QString TARGET_DIR_BRAVE;
|
const QString TARGET_DIR_BRAVE;
|
||||||
|
const QString TARGET_DIR_EDGE;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HOSTINSTALLER_H
|
#endif // HOSTINSTALLER_H
|
||||||
|
@ -106,9 +106,9 @@ void NativeMessagingBase::readNativeMessages()
|
|||||||
quint32 length = 0;
|
quint32 length = 0;
|
||||||
while (m_running.load() != 0 && !std::cin.eof()) {
|
while (m_running.load() != 0 && !std::cin.eof()) {
|
||||||
length = 0;
|
length = 0;
|
||||||
std::cin.read(reinterpret_cast<char*>(&length), 4);
|
std::cin.readsome(reinterpret_cast<char*>(&length), 4);
|
||||||
readStdIn(length);
|
readStdIn(length);
|
||||||
QThread::msleep(1);
|
QThread::msleep(100);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -651,6 +651,9 @@ bool Database::challengeMasterSeed(const QByteArray& masterSeed)
|
|||||||
bool ok = m_data.key->challenge(masterSeed, response);
|
bool ok = m_data.key->challenge(masterSeed, response);
|
||||||
if (ok && !response.isEmpty()) {
|
if (ok && !response.isEmpty()) {
|
||||||
m_data.challengeResponseKey->setHash(response);
|
m_data.challengeResponseKey->setHash(response);
|
||||||
|
} else if (ok && response.isEmpty()) {
|
||||||
|
// no CR key present, make sure buffer is empty
|
||||||
|
m_data.challengeResponseKey.reset(new PasswordKey);
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,9 @@ QByteArray FileWatcher::calculateChecksum()
|
|||||||
}
|
}
|
||||||
return hash.result();
|
return hash.result();
|
||||||
}
|
}
|
||||||
return {};
|
// If we fail to open the file return the last known checksum, this
|
||||||
|
// prevents unnecessary merge requests on intermittent network shares
|
||||||
|
return m_fileChecksum;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ namespace Tools
|
|||||||
|
|
||||||
bool checkUrlValid(const QString& urlField)
|
bool checkUrlValid(const QString& urlField)
|
||||||
{
|
{
|
||||||
if (urlField.isEmpty()) {
|
if (urlField.isEmpty() || urlField.startsWith("cmd://", Qt::CaseInsensitive)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,20 +44,22 @@ Clipboard::Clipboard(QObject* parent)
|
|||||||
connect(qApp, SIGNAL(aboutToQuit()), SLOT(clearCopiedText()));
|
connect(qApp, SIGNAL(aboutToQuit()), SLOT(clearCopiedText()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clipboard::setText(const QString& text)
|
void Clipboard::setText(const QString& text, bool clear)
|
||||||
{
|
{
|
||||||
QClipboard* clipboard = QApplication::clipboard();
|
auto* clipboard = QApplication::clipboard();
|
||||||
|
if (!clipboard) {
|
||||||
|
qWarning("Unable to access the clipboard.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QMimeData* mime = new QMimeData;
|
auto* mime = new QMimeData;
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
mime->setText(text);
|
mime->setText(text);
|
||||||
mime->setData("application/x-nspasteboard-concealed-type", text.toUtf8());
|
mime->setData("application/x-nspasteboard-concealed-type", text.toUtf8());
|
||||||
clipboard->setMimeData(mime, QClipboard::Clipboard);
|
clipboard->setMimeData(mime, QClipboard::Clipboard);
|
||||||
#else
|
#else
|
||||||
const QString secretStr = "secret";
|
|
||||||
QByteArray secretBa = secretStr.toUtf8();
|
|
||||||
mime->setText(text);
|
mime->setText(text);
|
||||||
mime->setData("x-kde-passwordManagerHint", secretBa);
|
mime->setData("x-kde-passwordManagerHint", QByteArrayLiteral("secret"));
|
||||||
clipboard->setMimeData(mime, QClipboard::Clipboard);
|
clipboard->setMimeData(mime, QClipboard::Clipboard);
|
||||||
|
|
||||||
if (clipboard->supportsSelection()) {
|
if (clipboard->supportsSelection()) {
|
||||||
@ -65,7 +67,7 @@ void Clipboard::setText(const QString& text)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (config()->get("security/clearclipboard").toBool()) {
|
if (clear && config()->get("security/clearclipboard").toBool()) {
|
||||||
int timeout = config()->get("security/clearclipboardtimeout").toInt();
|
int timeout = config()->get("security/clearclipboardtimeout").toInt();
|
||||||
if (timeout > 0) {
|
if (timeout > 0) {
|
||||||
m_lastCopied = text;
|
m_lastCopied = text;
|
||||||
@ -84,19 +86,15 @@ void Clipboard::clearCopiedText()
|
|||||||
|
|
||||||
void Clipboard::clearClipboard()
|
void Clipboard::clearClipboard()
|
||||||
{
|
{
|
||||||
QClipboard* clipboard = QApplication::clipboard();
|
auto* clipboard = QApplication::clipboard();
|
||||||
|
|
||||||
if (!clipboard) {
|
if (!clipboard) {
|
||||||
qWarning("Unable to access the clipboard.");
|
qWarning("Unable to access the clipboard.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clipboard->text(QClipboard::Clipboard) == m_lastCopied) {
|
if (m_lastCopied == clipboard->text(QClipboard::Clipboard)
|
||||||
clipboard->clear(QClipboard::Clipboard);
|
|| m_lastCopied == clipboard->text(QClipboard::Selection)) {
|
||||||
}
|
setText("", false);
|
||||||
|
|
||||||
if (clipboard->supportsSelection() && (clipboard->text(QClipboard::Selection) == m_lastCopied)) {
|
|
||||||
clipboard->clear(QClipboard::Selection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastCopied.clear();
|
m_lastCopied.clear();
|
||||||
|
@ -32,7 +32,7 @@ class Clipboard : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void setText(const QString& text);
|
void setText(const QString& text, bool clear = true);
|
||||||
|
|
||||||
static Clipboard* instance();
|
static Clipboard* instance();
|
||||||
|
|
||||||
|
@ -154,6 +154,7 @@ DatabaseWidget::DatabaseWidget(QSharedPointer<Database> db, QWidget* parent)
|
|||||||
m_shareLabel->setVisible(false);
|
m_shareLabel->setVisible(false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
m_previewView->setObjectName("previewWidget");
|
||||||
m_previewView->hide();
|
m_previewView->hide();
|
||||||
m_previewSplitter->addWidget(m_entryView);
|
m_previewSplitter->addWidget(m_entryView);
|
||||||
m_previewSplitter->addWidget(m_previewView);
|
m_previewSplitter->addWidget(m_previewView);
|
||||||
@ -552,6 +553,14 @@ void DatabaseWidget::deleteEntries(QList<Entry*> selectedEntries)
|
|||||||
}
|
}
|
||||||
|
|
||||||
refreshSearch();
|
refreshSearch();
|
||||||
|
|
||||||
|
m_entryView->setFirstEntryActive();
|
||||||
|
auto* currentEntry = currentSelectedEntry();
|
||||||
|
if (currentEntry) {
|
||||||
|
m_previewView->setEntry(currentEntry);
|
||||||
|
} else {
|
||||||
|
m_previewView->setGroup(groupView()->currentGroup());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DatabaseWidget::confirmDeleteEntries(QList<Entry*> entries, bool permanent)
|
bool DatabaseWidget::confirmDeleteEntries(QList<Entry*> entries, bool permanent)
|
||||||
|
@ -145,10 +145,12 @@ void EntryPreviewWidget::setDatabaseMode(DatabaseWidget::Mode mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mode == DatabaseWidget::Mode::ViewMode) {
|
if (mode == DatabaseWidget::Mode::ViewMode) {
|
||||||
if (m_ui->stackedWidget->currentWidget() == m_ui->pageGroup) {
|
if (m_currentGroup && m_ui->stackedWidget->currentWidget() == m_ui->pageGroup) {
|
||||||
setGroup(m_currentGroup);
|
setGroup(m_currentGroup);
|
||||||
} else {
|
} else if (m_currentEntry) {
|
||||||
setEntry(m_currentEntry);
|
setEntry(m_currentEntry);
|
||||||
|
} else {
|
||||||
|
hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,8 +77,8 @@ private:
|
|||||||
|
|
||||||
const QScopedPointer<Ui::EntryPreviewWidget> m_ui;
|
const QScopedPointer<Ui::EntryPreviewWidget> m_ui;
|
||||||
bool m_locked;
|
bool m_locked;
|
||||||
Entry* m_currentEntry;
|
QPointer<Entry> m_currentEntry;
|
||||||
Group* m_currentGroup;
|
QPointer<Group> m_currentGroup;
|
||||||
QTimer m_totpTimer;
|
QTimer m_totpTimer;
|
||||||
quint8 m_selectedTabEntry;
|
quint8 m_selectedTabEntry;
|
||||||
quint8 m_selectedTabGroup;
|
quint8 m_selectedTabGroup;
|
||||||
|
@ -104,7 +104,7 @@ add_unit_test(NAME testgroup SOURCES TestGroup.cpp
|
|||||||
add_unit_test(NAME testkdbx2 SOURCES TestKdbx2.cpp
|
add_unit_test(NAME testkdbx2 SOURCES TestKdbx2.cpp
|
||||||
LIBS ${TEST_LIBRARIES})
|
LIBS ${TEST_LIBRARIES})
|
||||||
|
|
||||||
add_unit_test(NAME testkdbx3 SOURCES TestKeePass2Format.cpp FailDevice.cpp TestKdbx3.cpp
|
add_unit_test(NAME testkdbx3 SOURCES TestKeePass2Format.cpp FailDevice.cpp mock/MockChallengeResponseKey.cpp TestKdbx3.cpp
|
||||||
LIBS testsupport ${TEST_LIBRARIES})
|
LIBS testsupport ${TEST_LIBRARIES})
|
||||||
|
|
||||||
add_unit_test(NAME testkdbx4 SOURCES TestKeePass2Format.cpp FailDevice.cpp mock/MockChallengeResponseKey.cpp TestKdbx4.cpp
|
add_unit_test(NAME testkdbx4 SOURCES TestKeePass2Format.cpp FailDevice.cpp mock/MockChallengeResponseKey.cpp TestKdbx4.cpp
|
||||||
|
@ -298,7 +298,8 @@ void TestBrowser::testSubdomainsAndPaths()
|
|||||||
"http://login.github.com/pathtonowhere",
|
"http://login.github.com/pathtonowhere",
|
||||||
".github.com", // Invalid URL
|
".github.com", // Invalid URL
|
||||||
"www.github.com/",
|
"www.github.com/",
|
||||||
"https://github" // Invalid URL
|
"https://github", // Invalid URL
|
||||||
|
"https://hub.com" // Should not return
|
||||||
};
|
};
|
||||||
|
|
||||||
createEntries(urls, root);
|
createEntries(urls, root);
|
||||||
|
@ -31,6 +31,8 @@ QTEST_GUILESS_MAIN(TestKdbx3)
|
|||||||
|
|
||||||
void TestKdbx3::initTestCaseImpl()
|
void TestKdbx3::initTestCaseImpl()
|
||||||
{
|
{
|
||||||
|
m_xmlDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX3)));
|
||||||
|
m_kdbxSourceDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<Database> TestKdbx3::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString)
|
QSharedPointer<Database> TestKdbx3::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString)
|
||||||
|
@ -29,15 +29,25 @@
|
|||||||
#include "keys/PasswordKey.h"
|
#include "keys/PasswordKey.h"
|
||||||
#include "mock/MockChallengeResponseKey.h"
|
#include "mock/MockChallengeResponseKey.h"
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(TestKdbx4)
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
QCoreApplication app(argc, argv);
|
||||||
|
QCoreApplication::setAttribute(Qt::AA_Use96Dpi, true);
|
||||||
|
QTEST_SET_MAIN_SOURCE_PATH
|
||||||
|
|
||||||
void TestKdbx4::initTestCaseImpl()
|
TestKdbx4Argon2 argon2Test;
|
||||||
|
TestKdbx4AesKdf aesKdfTest;
|
||||||
|
return QTest::qExec(&argon2Test, argc, argv) | QTest::qExec(&aesKdfTest, argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestKdbx4Argon2::initTestCaseImpl()
|
||||||
{
|
{
|
||||||
m_xmlDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)));
|
m_xmlDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)));
|
||||||
m_kdbxSourceDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)));
|
m_kdbxSourceDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<Database> TestKdbx4::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString)
|
QSharedPointer<Database>
|
||||||
|
TestKdbx4Argon2::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString)
|
||||||
{
|
{
|
||||||
KdbxXmlReader reader(KeePass2::FILE_VERSION_4);
|
KdbxXmlReader reader(KeePass2::FILE_VERSION_4);
|
||||||
reader.setStrictMode(strictMode);
|
reader.setStrictMode(strictMode);
|
||||||
@ -47,7 +57,7 @@ QSharedPointer<Database> TestKdbx4::readXml(const QString& path, bool strictMode
|
|||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<Database> TestKdbx4::readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString)
|
QSharedPointer<Database> TestKdbx4Argon2::readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString)
|
||||||
{
|
{
|
||||||
KdbxXmlReader reader(KeePass2::FILE_VERSION_4);
|
KdbxXmlReader reader(KeePass2::FILE_VERSION_4);
|
||||||
reader.setStrictMode(strictMode);
|
reader.setStrictMode(strictMode);
|
||||||
@ -57,7 +67,7 @@ QSharedPointer<Database> TestKdbx4::readXml(QBuffer* buf, bool strictMode, bool&
|
|||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKdbx4::writeXml(QBuffer* buf, Database* db, bool& hasError, QString& errorString)
|
void TestKdbx4Argon2::writeXml(QBuffer* buf, Database* db, bool& hasError, QString& errorString)
|
||||||
{
|
{
|
||||||
KdbxXmlWriter writer(KeePass2::FILE_VERSION_4);
|
KdbxXmlWriter writer(KeePass2::FILE_VERSION_4);
|
||||||
writer.writeDatabase(buf, db);
|
writer.writeDatabase(buf, db);
|
||||||
@ -65,7 +75,7 @@ void TestKdbx4::writeXml(QBuffer* buf, Database* db, bool& hasError, QString& er
|
|||||||
errorString = writer.errorString();
|
errorString = writer.errorString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKdbx4::readKdbx(QIODevice* device,
|
void TestKdbx4Argon2::readKdbx(QIODevice* device,
|
||||||
QSharedPointer<const CompositeKey> key,
|
QSharedPointer<const CompositeKey> key,
|
||||||
QSharedPointer<Database> db,
|
QSharedPointer<Database> db,
|
||||||
bool& hasError,
|
bool& hasError,
|
||||||
@ -80,7 +90,7 @@ void TestKdbx4::readKdbx(QIODevice* device,
|
|||||||
QCOMPARE(reader.version(), KeePass2::FILE_VERSION_4);
|
QCOMPARE(reader.version(), KeePass2::FILE_VERSION_4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKdbx4::readKdbx(const QString& path,
|
void TestKdbx4Argon2::readKdbx(const QString& path,
|
||||||
QSharedPointer<const CompositeKey> key,
|
QSharedPointer<const CompositeKey> key,
|
||||||
QSharedPointer<Database> db,
|
QSharedPointer<Database> db,
|
||||||
bool& hasError,
|
bool& hasError,
|
||||||
@ -95,7 +105,7 @@ void TestKdbx4::readKdbx(const QString& path,
|
|||||||
QCOMPARE(reader.version(), KeePass2::FILE_VERSION_4);
|
QCOMPARE(reader.version(), KeePass2::FILE_VERSION_4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKdbx4::writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString)
|
void TestKdbx4Argon2::writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString)
|
||||||
{
|
{
|
||||||
if (db->kdf()->uuid() == KeePass2::KDF_AES_KDBX3) {
|
if (db->kdf()->uuid() == KeePass2::KDF_AES_KDBX3) {
|
||||||
db->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)));
|
db->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)));
|
||||||
@ -110,7 +120,7 @@ void TestKdbx4::writeKdbx(QIODevice* device, Database* db, bool& hasError, QStri
|
|||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QUuid)
|
Q_DECLARE_METATYPE(QUuid)
|
||||||
void TestKdbx4::testFormat400()
|
void TestKdbx4Argon2::testFormat400()
|
||||||
{
|
{
|
||||||
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/Format400.kdbx");
|
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/Format400.kdbx");
|
||||||
auto key = QSharedPointer<CompositeKey>::create();
|
auto key = QSharedPointer<CompositeKey>::create();
|
||||||
@ -135,7 +145,7 @@ void TestKdbx4::testFormat400()
|
|||||||
QCOMPARE(entry->attachments()->value("Format400"), QByteArray("Format400\n"));
|
QCOMPARE(entry->attachments()->value("Format400"), QByteArray("Format400\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKdbx4::testFormat400Upgrade()
|
void TestKdbx4Argon2::testFormat400Upgrade()
|
||||||
{
|
{
|
||||||
QFETCH(QUuid, kdfUuid);
|
QFETCH(QUuid, kdfUuid);
|
||||||
QFETCH(QUuid, cipherUuid);
|
QFETCH(QUuid, cipherUuid);
|
||||||
@ -193,7 +203,7 @@ void TestKdbx4::testFormat400Upgrade()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
void TestKdbx4::testFormat400Upgrade_data()
|
void TestKdbx4Argon2::testFormat400Upgrade_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QUuid>("kdfUuid");
|
QTest::addColumn<QUuid>("kdfUuid");
|
||||||
QTest::addColumn<QUuid>("cipherUuid");
|
QTest::addColumn<QUuid>("cipherUuid");
|
||||||
@ -226,7 +236,7 @@ void TestKdbx4::testFormat400Upgrade_data()
|
|||||||
}
|
}
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
void TestKdbx4::testUpgradeMasterKeyIntegrity()
|
void TestKdbx4Argon2::testUpgradeMasterKeyIntegrity()
|
||||||
{
|
{
|
||||||
QFETCH(QString, upgradeAction);
|
QFETCH(QString, upgradeAction);
|
||||||
QFETCH(quint32, expectedVersion);
|
QFETCH(quint32, expectedVersion);
|
||||||
@ -249,6 +259,7 @@ void TestKdbx4::testUpgradeMasterKeyIntegrity()
|
|||||||
|
|
||||||
QScopedPointer<Database> db(new Database());
|
QScopedPointer<Database> db(new Database());
|
||||||
db->changeKdf(fastKdf(db->kdf()));
|
db->changeKdf(fastKdf(db->kdf()));
|
||||||
|
QCOMPARE(db->kdf()->uuid(), KeePass2::KDF_AES_KDBX3); // default is legacy AES-KDF
|
||||||
db->setKey(compositeKey);
|
db->setKey(compositeKey);
|
||||||
|
|
||||||
// upgrade the database by a specific method
|
// upgrade the database by a specific method
|
||||||
@ -309,9 +320,12 @@ void TestKdbx4::testUpgradeMasterKeyIntegrity()
|
|||||||
QFAIL(qPrintable(reader.errorString()));
|
QFAIL(qPrintable(reader.errorString()));
|
||||||
}
|
}
|
||||||
QCOMPARE(reader.version(), expectedVersion & KeePass2::FILE_VERSION_CRITICAL_MASK);
|
QCOMPARE(reader.version(), expectedVersion & KeePass2::FILE_VERSION_CRITICAL_MASK);
|
||||||
|
if (expectedVersion != KeePass2::FILE_VERSION_3) {
|
||||||
|
QVERIFY(db2->kdf()->uuid() != KeePass2::KDF_AES_KDBX3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKdbx4::testUpgradeMasterKeyIntegrity_data()
|
void TestKdbx4Argon2::testUpgradeMasterKeyIntegrity_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("upgradeAction");
|
QTest::addColumn<QString>("upgradeAction");
|
||||||
QTest::addColumn<quint32>("expectedVersion");
|
QTest::addColumn<quint32>("expectedVersion");
|
||||||
@ -330,7 +344,7 @@ void TestKdbx4::testUpgradeMasterKeyIntegrity_data()
|
|||||||
QTest::newRow("Upgrade (implicit): entry-customdata") << QString("entry-customdata") << KeePass2::FILE_VERSION_4;
|
QTest::newRow("Upgrade (implicit): entry-customdata") << QString("entry-customdata") << KeePass2::FILE_VERSION_4;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKdbx4::testCustomData()
|
void TestKdbx4Argon2::testCustomData()
|
||||||
{
|
{
|
||||||
Database db;
|
Database db;
|
||||||
|
|
||||||
@ -424,13 +438,8 @@ void TestKdbx4::testCustomData()
|
|||||||
QCOMPARE(newEntry->customData()->value(customDataKey2), customData2);
|
QCOMPARE(newEntry->customData()->value(customDataKey2), customData2);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<Kdf> TestKdbx4::fastKdf(QSharedPointer<Kdf> kdf)
|
void TestKdbx4AesKdf::initTestCaseImpl()
|
||||||
{
|
{
|
||||||
kdf->setRounds(1);
|
m_xmlDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX4)));
|
||||||
|
m_kdbxSourceDb->changeKdf(fastKdf(KeePass2::uuidToKdf(KeePass2::KDF_AES_KDBX4)));
|
||||||
if (kdf->uuid() == KeePass2::KDF_ARGON2) {
|
|
||||||
kdf->processParameters({{KeePass2::KDFPARAM_ARGON2_MEMORY, 1024}, {KeePass2::KDFPARAM_ARGON2_PARALLELISM, 1}});
|
|
||||||
}
|
|
||||||
|
|
||||||
return kdf;
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "TestKeePass2Format.h"
|
#include "TestKeePass2Format.h"
|
||||||
|
|
||||||
class TestKdbx4 : public TestKeePass2Format
|
class TestKdbx4Argon2 : public TestKeePass2Format
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -51,8 +51,14 @@ protected:
|
|||||||
bool& hasError,
|
bool& hasError,
|
||||||
QString& errorString) override;
|
QString& errorString) override;
|
||||||
void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) override;
|
void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) override;
|
||||||
|
};
|
||||||
|
|
||||||
QSharedPointer<Kdf> fastKdf(QSharedPointer<Kdf> kdf);
|
class TestKdbx4AesKdf : public TestKdbx4Argon2
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void initTestCaseImpl() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEPASSXC_TEST_KDBX4_H
|
#endif // KEEPASSXC_TEST_KDBX4_H
|
||||||
|
@ -22,7 +22,9 @@
|
|||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
#include "crypto/Crypto.h"
|
#include "crypto/Crypto.h"
|
||||||
#include "format/KdbxXmlReader.h"
|
#include "format/KdbxXmlReader.h"
|
||||||
|
#include "keys/FileKey.h"
|
||||||
#include "keys/PasswordKey.h"
|
#include "keys/PasswordKey.h"
|
||||||
|
#include "mock/MockChallengeResponseKey.h"
|
||||||
|
|
||||||
#include "FailDevice.h"
|
#include "FailDevice.h"
|
||||||
#include "config-keepassx-tests.h"
|
#include "config-keepassx-tests.h"
|
||||||
@ -566,6 +568,168 @@ void TestKeePass2Format::testKdbxDeviceFailure()
|
|||||||
QCOMPARE(errorString, QString("FAILDEVICE"));
|
QCOMPARE(errorString, QString("FAILDEVICE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(QSharedPointer<CompositeKey>)
|
||||||
|
|
||||||
|
void TestKeePass2Format::testKdbxKeyChange()
|
||||||
|
{
|
||||||
|
QFETCH(QSharedPointer<CompositeKey>, key1);
|
||||||
|
QFETCH(QSharedPointer<CompositeKey>, key2);
|
||||||
|
|
||||||
|
bool hasError;
|
||||||
|
QString errorString;
|
||||||
|
|
||||||
|
// write new database
|
||||||
|
QBuffer buffer;
|
||||||
|
buffer.open(QBuffer::ReadWrite);
|
||||||
|
buffer.seek(0);
|
||||||
|
QSharedPointer<Database> db(new Database());
|
||||||
|
db->changeKdf(fastKdf(KeePass2::uuidToKdf(m_kdbxSourceDb->kdf()->uuid())));
|
||||||
|
db->setRootGroup(m_kdbxSourceDb->rootGroup()->clone(Entry::CloneNoFlags, Group::CloneIncludeEntries));
|
||||||
|
|
||||||
|
db->setKey(key1);
|
||||||
|
writeKdbx(&buffer, db.data(), hasError, errorString);
|
||||||
|
QVERIFY(!hasError);
|
||||||
|
|
||||||
|
// read database
|
||||||
|
db = QSharedPointer<Database>::create();
|
||||||
|
buffer.seek(0);
|
||||||
|
readKdbx(&buffer, key1, db, hasError, errorString);
|
||||||
|
if (hasError) {
|
||||||
|
QFAIL(qPrintable(QStringLiteral("Error while reading database: ").append(errorString)));
|
||||||
|
}
|
||||||
|
QVERIFY(db.data());
|
||||||
|
|
||||||
|
// change key
|
||||||
|
db->setKey(key2);
|
||||||
|
|
||||||
|
// write database
|
||||||
|
buffer.seek(0);
|
||||||
|
writeKdbx(&buffer, db.data(), hasError, errorString);
|
||||||
|
QVERIFY(!hasError);
|
||||||
|
|
||||||
|
// read database
|
||||||
|
db = QSharedPointer<Database>::create();
|
||||||
|
buffer.seek(0);
|
||||||
|
readKdbx(&buffer, key2, db, hasError, errorString);
|
||||||
|
if (hasError) {
|
||||||
|
QFAIL(qPrintable(QStringLiteral("Error while reading database: ").append(errorString)));
|
||||||
|
}
|
||||||
|
QVERIFY(db.data());
|
||||||
|
QVERIFY(db->rootGroup() != m_kdbxSourceDb->rootGroup());
|
||||||
|
QVERIFY(db->rootGroup()->uuid() == m_kdbxSourceDb->rootGroup()->uuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestKeePass2Format::testKdbxKeyChange_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QSharedPointer<CompositeKey>>("key1");
|
||||||
|
QTest::addColumn<QSharedPointer<CompositeKey>>("key2");
|
||||||
|
|
||||||
|
auto passwordKey1 = QSharedPointer<PasswordKey>::create("abc");
|
||||||
|
auto passwordKey2 = QSharedPointer<PasswordKey>::create("def");
|
||||||
|
|
||||||
|
QByteArray fileKeyBytes1("uvw");
|
||||||
|
QBuffer fileKeyBuffer1(&fileKeyBytes1);
|
||||||
|
fileKeyBuffer1.open(QBuffer::ReadOnly);
|
||||||
|
auto fileKey1 = QSharedPointer<FileKey>::create();
|
||||||
|
fileKey1->load(&fileKeyBuffer1);
|
||||||
|
|
||||||
|
QByteArray fileKeyBytes2("xzy");
|
||||||
|
QBuffer fileKeyBuffer2(&fileKeyBytes1);
|
||||||
|
fileKeyBuffer2.open(QBuffer::ReadOnly);
|
||||||
|
auto fileKey2 = QSharedPointer<FileKey>::create();
|
||||||
|
fileKey2->load(&fileKeyBuffer2);
|
||||||
|
|
||||||
|
auto crKey1 = QSharedPointer<MockChallengeResponseKey>::create(QByteArray("123"));
|
||||||
|
auto crKey2 = QSharedPointer<MockChallengeResponseKey>::create(QByteArray("456"));
|
||||||
|
|
||||||
|
// empty key
|
||||||
|
auto compositeKey0 = QSharedPointer<CompositeKey>::create();
|
||||||
|
|
||||||
|
// all in
|
||||||
|
auto compositeKey1_1 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey1_1->addKey(passwordKey1);
|
||||||
|
compositeKey1_1->addKey(fileKey1);
|
||||||
|
compositeKey1_1->addChallengeResponseKey(crKey1);
|
||||||
|
auto compositeKey1_2 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey1_2->addKey(passwordKey2);
|
||||||
|
compositeKey1_2->addKey(fileKey2);
|
||||||
|
compositeKey1_2->addChallengeResponseKey(crKey2);
|
||||||
|
|
||||||
|
QTest::newRow("Change: Empty Key -> Full Key") << compositeKey0 << compositeKey1_1;
|
||||||
|
QTest::newRow("Change: Full Key -> Empty Key") << compositeKey1_1 << compositeKey0;
|
||||||
|
QTest::newRow("Change: Full Key 1 -> Full Key 2") << compositeKey1_1 << compositeKey1_2;
|
||||||
|
|
||||||
|
// only password
|
||||||
|
auto compositeKey2_1 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey2_1->addKey(passwordKey1);
|
||||||
|
auto compositeKey2_2 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey2_2->addKey(passwordKey2);
|
||||||
|
|
||||||
|
QTest::newRow("Change: Password -> Empty Key") << compositeKey2_1 << compositeKey0;
|
||||||
|
QTest::newRow("Change: Empty Key -> Password") << compositeKey0 << compositeKey2_1;
|
||||||
|
QTest::newRow("Change: Full Key -> Password 1") << compositeKey1_1 << compositeKey2_1;
|
||||||
|
QTest::newRow("Change: Full Key -> Password 2") << compositeKey1_1 << compositeKey2_2;
|
||||||
|
QTest::newRow("Change: Password 1 -> Full Key") << compositeKey2_1 << compositeKey1_1;
|
||||||
|
QTest::newRow("Change: Password 2 -> Full Key") << compositeKey2_2 << compositeKey1_1;
|
||||||
|
QTest::newRow("Change: Password 1 -> Password 2") << compositeKey2_1 << compositeKey2_2;
|
||||||
|
|
||||||
|
// only key file
|
||||||
|
auto compositeKey3_1 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey3_1->addKey(fileKey1);
|
||||||
|
auto compositeKey3_2 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey3_2->addKey(fileKey2);
|
||||||
|
|
||||||
|
QTest::newRow("Change: Key File -> Empty Key") << compositeKey3_1 << compositeKey0;
|
||||||
|
QTest::newRow("Change: Empty Key -> Key File") << compositeKey0 << compositeKey3_1;
|
||||||
|
QTest::newRow("Change: Full Key -> Key File 1") << compositeKey1_1 << compositeKey3_1;
|
||||||
|
QTest::newRow("Change: Full Key -> Key File 2") << compositeKey1_1 << compositeKey3_2;
|
||||||
|
QTest::newRow("Change: Key File 1 -> Full Key") << compositeKey3_1 << compositeKey1_1;
|
||||||
|
QTest::newRow("Change: Key File 2 -> Full Key") << compositeKey3_2 << compositeKey1_1;
|
||||||
|
QTest::newRow("Change: Key File 1 -> Key File 2") << compositeKey3_1 << compositeKey3_2;
|
||||||
|
|
||||||
|
// only cr key
|
||||||
|
auto compositeKey4_1 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey4_1->addChallengeResponseKey(crKey1);
|
||||||
|
auto compositeKey4_2 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey4_2->addChallengeResponseKey(crKey2);
|
||||||
|
|
||||||
|
QTest::newRow("Change: CR Key -> Empty Key") << compositeKey4_1 << compositeKey0;
|
||||||
|
QTest::newRow("Change: Empty Key -> CR Key") << compositeKey0 << compositeKey4_1;
|
||||||
|
QTest::newRow("Change: Full Key -> CR Key 1") << compositeKey1_1 << compositeKey4_1;
|
||||||
|
QTest::newRow("Change: Full Key -> CR Key 2") << compositeKey1_1 << compositeKey4_2;
|
||||||
|
QTest::newRow("Change: CR Key 1 -> Full Key") << compositeKey4_1 << compositeKey1_1;
|
||||||
|
QTest::newRow("Change: CR Key 2 -> Full Key") << compositeKey4_2 << compositeKey1_1;
|
||||||
|
QTest::newRow("Change: CR Key 1 -> CR Key 2") << compositeKey4_1 << compositeKey4_2;
|
||||||
|
|
||||||
|
// rotate
|
||||||
|
QTest::newRow("Change: Password -> Key File") << compositeKey2_1 << compositeKey3_1;
|
||||||
|
QTest::newRow("Change: Key File -> Password") << compositeKey3_1 << compositeKey2_1;
|
||||||
|
QTest::newRow("Change: Password -> Key File") << compositeKey2_1 << compositeKey3_1;
|
||||||
|
QTest::newRow("Change: Key File -> Password") << compositeKey3_1 << compositeKey2_1;
|
||||||
|
QTest::newRow("Change: Password -> CR Key") << compositeKey2_1 << compositeKey4_1;
|
||||||
|
QTest::newRow("Change: CR Key -> Password") << compositeKey4_1 << compositeKey2_1;
|
||||||
|
QTest::newRow("Change: Key File -> CR Key") << compositeKey3_1 << compositeKey4_1;
|
||||||
|
QTest::newRow("Change: CR Key -> Key File") << compositeKey4_1 << compositeKey3_1;
|
||||||
|
|
||||||
|
// leave one out
|
||||||
|
auto compositeKey5_1 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey5_1->addKey(fileKey1);
|
||||||
|
compositeKey5_1->addChallengeResponseKey(crKey1);
|
||||||
|
auto compositeKey5_2 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey5_2->addKey(passwordKey1);
|
||||||
|
compositeKey5_2->addChallengeResponseKey(crKey1);
|
||||||
|
auto compositeKey5_3 = QSharedPointer<CompositeKey>::create();
|
||||||
|
compositeKey5_3->addKey(passwordKey1);
|
||||||
|
compositeKey5_3->addKey(fileKey1);
|
||||||
|
|
||||||
|
QTest::newRow("Change: Full Key -> No Password") << compositeKey1_1 << compositeKey5_1;
|
||||||
|
QTest::newRow("Change: No Password -> Full Key") << compositeKey5_1 << compositeKey1_1;
|
||||||
|
QTest::newRow("Change: Full Key -> No Key File") << compositeKey1_1 << compositeKey5_2;
|
||||||
|
QTest::newRow("Change: No Key File -> Full Key") << compositeKey5_2 << compositeKey1_1;
|
||||||
|
QTest::newRow("Change: Full Key -> No CR Key") << compositeKey1_1 << compositeKey5_3;
|
||||||
|
QTest::newRow("Change: No CR Key -> Full Key") << compositeKey5_3 << compositeKey1_1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for catching mapping errors with duplicate attachments.
|
* Test for catching mapping errors with duplicate attachments.
|
||||||
*/
|
*/
|
||||||
@ -637,3 +801,17 @@ void TestKeePass2Format::testDuplicateAttachments()
|
|||||||
QCOMPARE(db->rootGroup()->entries()[2]->attachments()->value("c2"), attachment2);
|
QCOMPARE(db->rootGroup()->entries()[2]->attachments()->value("c2"), attachment2);
|
||||||
QCOMPARE(db->rootGroup()->entries()[2]->attachments()->value("c3"), attachment3);
|
QCOMPARE(db->rootGroup()->entries()[2]->attachments()->value("c3"), attachment3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return fast "dummy" KDF
|
||||||
|
*/
|
||||||
|
QSharedPointer<Kdf> TestKeePass2Format::fastKdf(QSharedPointer<Kdf> kdf) const
|
||||||
|
{
|
||||||
|
kdf->setRounds(1);
|
||||||
|
|
||||||
|
if (kdf->uuid() == KeePass2::KDF_ARGON2) {
|
||||||
|
kdf->processParameters({{KeePass2::KDFPARAM_ARGON2_MEMORY, 1024}, {KeePass2::KDFPARAM_ARGON2_PARALLELISM, 1}});
|
||||||
|
}
|
||||||
|
|
||||||
|
return kdf;
|
||||||
|
}
|
||||||
|
@ -62,6 +62,8 @@ private slots:
|
|||||||
void testKdbxAttachments();
|
void testKdbxAttachments();
|
||||||
void testKdbxNonAsciiPasswords();
|
void testKdbxNonAsciiPasswords();
|
||||||
void testKdbxDeviceFailure();
|
void testKdbxDeviceFailure();
|
||||||
|
void testKdbxKeyChange();
|
||||||
|
void testKdbxKeyChange_data();
|
||||||
void testDuplicateAttachments();
|
void testDuplicateAttachments();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -84,6 +86,8 @@ protected:
|
|||||||
QString& errorString) = 0;
|
QString& errorString) = 0;
|
||||||
virtual void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) = 0;
|
virtual void writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) = 0;
|
||||||
|
|
||||||
|
QSharedPointer<Kdf> fastKdf(QSharedPointer<Kdf> kdf) const;
|
||||||
|
|
||||||
QSharedPointer<Database> m_xmlDb;
|
QSharedPointer<Database> m_xmlDb;
|
||||||
QSharedPointer<Database> m_kdbxSourceDb;
|
QSharedPointer<Database> m_kdbxSourceDb;
|
||||||
QSharedPointer<Database> m_kdbxTargetDb;
|
QSharedPointer<Database> m_kdbxTargetDb;
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#include "gui/CloneDialog.h"
|
#include "gui/CloneDialog.h"
|
||||||
#include "gui/DatabaseTabWidget.h"
|
#include "gui/DatabaseTabWidget.h"
|
||||||
#include "gui/DatabaseWidget.h"
|
#include "gui/DatabaseWidget.h"
|
||||||
|
#include "gui/EntryPreviewWidget.h"
|
||||||
#include "gui/FileDialog.h"
|
#include "gui/FileDialog.h"
|
||||||
#include "gui/MessageBox.h"
|
#include "gui/MessageBox.h"
|
||||||
#include "gui/PasswordEdit.h"
|
#include "gui/PasswordEdit.h"
|
||||||
@ -967,6 +968,7 @@ void TestGui::testDeleteEntry()
|
|||||||
QWidget* entryDeleteWidget = toolBar->widgetForAction(entryDeleteAction);
|
QWidget* entryDeleteWidget = toolBar->widgetForAction(entryDeleteAction);
|
||||||
entryView->setFocus();
|
entryView->setFocus();
|
||||||
|
|
||||||
|
// Move one entry to the recycling bin
|
||||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode);
|
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::ViewMode);
|
||||||
clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton);
|
clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton);
|
||||||
QVERIFY(entryDeleteWidget->isVisible());
|
QVERIFY(entryDeleteWidget->isVisible());
|
||||||
@ -979,6 +981,7 @@ void TestGui::testDeleteEntry()
|
|||||||
QCOMPARE(entryView->model()->rowCount(), 3);
|
QCOMPARE(entryView->model()->rowCount(), 3);
|
||||||
QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 1);
|
QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 1);
|
||||||
|
|
||||||
|
// Select multiple entries and move them to the recycling bin
|
||||||
clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton);
|
clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton);
|
||||||
clickIndex(entryView->model()->index(2, 1), entryView, Qt::LeftButton, Qt::ControlModifier);
|
clickIndex(entryView->model()->index(2, 1), entryView, Qt::LeftButton, Qt::ControlModifier);
|
||||||
QCOMPARE(entryView->selectionModel()->selectedRows().size(), 2);
|
QCOMPARE(entryView->selectionModel()->selectedRows().size(), 2);
|
||||||
@ -993,6 +996,7 @@ void TestGui::testDeleteEntry()
|
|||||||
QCOMPARE(entryView->model()->rowCount(), 1);
|
QCOMPARE(entryView->model()->rowCount(), 1);
|
||||||
QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 3);
|
QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 3);
|
||||||
|
|
||||||
|
// Go to the recycling bin
|
||||||
QCOMPARE(groupView->currentGroup(), m_db->rootGroup());
|
QCOMPARE(groupView->currentGroup(), m_db->rootGroup());
|
||||||
QModelIndex rootGroupIndex = groupView->model()->index(0, 0);
|
QModelIndex rootGroupIndex = groupView->model()->index(0, 0);
|
||||||
clickIndex(groupView->model()->index(groupView->model()->rowCount(rootGroupIndex) - 1, 0, rootGroupIndex),
|
clickIndex(groupView->model()->index(groupView->model()->rowCount(rootGroupIndex) - 1, 0, rootGroupIndex),
|
||||||
@ -1000,6 +1004,7 @@ void TestGui::testDeleteEntry()
|
|||||||
Qt::LeftButton);
|
Qt::LeftButton);
|
||||||
QCOMPARE(groupView->currentGroup()->name(), m_db->metadata()->recycleBin()->name());
|
QCOMPARE(groupView->currentGroup()->name(), m_db->metadata()->recycleBin()->name());
|
||||||
|
|
||||||
|
// Delete one entry from the bin
|
||||||
clickIndex(entryView->model()->index(0, 1), entryView, Qt::LeftButton);
|
clickIndex(entryView->model()->index(0, 1), entryView, Qt::LeftButton);
|
||||||
MessageBox::setNextAnswer(MessageBox::Cancel);
|
MessageBox::setNextAnswer(MessageBox::Cancel);
|
||||||
QTest::mouseClick(entryDeleteWidget, Qt::LeftButton);
|
QTest::mouseClick(entryDeleteWidget, Qt::LeftButton);
|
||||||
@ -1011,6 +1016,7 @@ void TestGui::testDeleteEntry()
|
|||||||
QCOMPARE(entryView->model()->rowCount(), 2);
|
QCOMPARE(entryView->model()->rowCount(), 2);
|
||||||
QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 2);
|
QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 2);
|
||||||
|
|
||||||
|
// Select the remaining entries and delete them
|
||||||
clickIndex(entryView->model()->index(0, 1), entryView, Qt::LeftButton);
|
clickIndex(entryView->model()->index(0, 1), entryView, Qt::LeftButton);
|
||||||
clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton, Qt::ControlModifier);
|
clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton, Qt::ControlModifier);
|
||||||
MessageBox::setNextAnswer(MessageBox::Delete);
|
MessageBox::setNextAnswer(MessageBox::Delete);
|
||||||
@ -1018,6 +1024,16 @@ void TestGui::testDeleteEntry()
|
|||||||
QCOMPARE(entryView->model()->rowCount(), 0);
|
QCOMPARE(entryView->model()->rowCount(), 0);
|
||||||
QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 0);
|
QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 0);
|
||||||
|
|
||||||
|
// Ensure the entry preview widget shows the recycling group since all entries are deleted
|
||||||
|
auto* previewWidget = m_dbWidget->findChild<EntryPreviewWidget*>("previewWidget");
|
||||||
|
QVERIFY(previewWidget);
|
||||||
|
auto* groupTitleLabel = previewWidget->findChild<QLabel*>("groupTitleLabel");
|
||||||
|
QVERIFY(groupTitleLabel);
|
||||||
|
|
||||||
|
QTRY_VERIFY(groupTitleLabel->isVisible());
|
||||||
|
QVERIFY(groupTitleLabel->text().contains(m_db->metadata()->recycleBin()->name()));
|
||||||
|
|
||||||
|
// Go back to the root group
|
||||||
clickIndex(groupView->model()->index(0, 0), groupView, Qt::LeftButton);
|
clickIndex(groupView->model()->index(0, 0), groupView, Qt::LeftButton);
|
||||||
QCOMPARE(groupView->currentGroup(), m_db->rootGroup());
|
QCOMPARE(groupView->currentGroup(), m_db->rootGroup());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user