Release 2.5.0

Added

- Add 'Paper Backup' aka 'Export to HTML file' to the 'Database' menu [[#3277](https://github.com/keepassxreboot/keepassxc/pull/3277)]
- Add statistics panel with information about the database (number of entries, number of unique passwords, etc.) to the Database Settings dialog [[#2034](https://github.com/keepassxreboot/keepassxc/issues/2034)]
- Add offline user manual accessible via the 'Help' menu [[#3274](https://github.com/keepassxreboot/keepassxc/issues/3274)]
- Add support for importing 1Password OpVault files [[#2292](https://github.com/keepassxreboot/keepassxc/issues/2292)]
- Implement Freedesktop.org secret storage DBus protocol so that KeePassXC can be used as a vault service by libsecret [[#2726](https://github.com/keepassxreboot/keepassxc/issues/2726)]
- Add support for OnlyKey as an alternative to YubiKeys (requires yubikey-personalization >= 1.20.0) [[#3352](https://github.com/keepassxreboot/keepassxc/issues/3352)]
- Add group sorting feature [[#3282](https://github.com/keepassxreboot/keepassxc/issues/3282)]
- Add feature to download favicons for all entries at once [[#3169](https://github.com/keepassxreboot/keepassxc/issues/3169)]
- Add word case option to passphrase generator [[#3172](https://github.com/keepassxreboot/keepassxc/issues/3172)]
- Add support for RFC6238-compliant TOTP hashes [[#2972](https://github.com/keepassxreboot/keepassxc/issues/2972)]
- Add UNIX man page for main program [[#3665](https://github.com/keepassxreboot/keepassxc/issues/3665)]
- Add 'Monospaced font' option to the notes field [[#3321](https://github.com/keepassxreboot/keepassxc/issues/3321)]
- Add support for key files in auto open [[#3504](https://github.com/keepassxreboot/keepassxc/issues/3504)]
- Add search field for filtering entries in Auto-Type dialog [[#2955](https://github.com/keepassxreboot/keepassxc/issues/2955)]
- Complete usernames based on known usernames from other entries [[#3300](https://github.com/keepassxreboot/keepassxc/issues/3300)]
- Parse hyperlinks in the notes field of the entry preview pane [[#3596](https://github.com/keepassxreboot/keepassxc/issues/3596)]
- Allow abbreviation of field names in entry search [[#3440](https://github.com/keepassxreboot/keepassxc/issues/3440)]
- Allow setting group icons recursively [[#3273](https://github.com/keepassxreboot/keepassxc/issues/3273)]
- Add copy context menu for username and password in Auto-Type dialog [[#3038](https://github.com/keepassxreboot/keepassxc/issues/3038)]
- Drop to background after copying a password to the clipboard [[#3253](https://github.com/keepassxreboot/keepassxc/issues/3253)]
- Add 'Lock databases' entry to tray icon menu [[#2896](https://github.com/keepassxreboot/keepassxc/issues/2896)]
- Add option to minimize window after unlocking [[#3439](https://github.com/keepassxreboot/keepassxc/issues/3439)]
- Add option to minimize window after opening a URL [[#3302](https://github.com/keepassxreboot/keepassxc/issues/3302)]
- Request accessibility permissions for Auto-Type on macOS [[#3624](https://github.com/keepassxreboot/keepassxc/issues/3624)]
- Browser: Add initial support for multiple URLs [[#3558](https://github.com/keepassxreboot/keepassxc/issues/3558)]
- Browser: Add entry-specific browser integration settings [[#3444](https://github.com/keepassxreboot/keepassxc/issues/3444)]
- CLI: Add offline HIBP checker (requires a downloaded HIBP dump) [[#2707](https://github.com/keepassxreboot/keepassxc/issues/2707)]
- CLI: Add 'flatten' option to the 'ls' command [[#3276](https://github.com/keepassxreboot/keepassxc/issues/3276)]
- CLI: Add password generation options to `Add` and `Edit` commands [[#3275](https://github.com/keepassxreboot/keepassxc/issues/3275)]
- CLI: Add XML import [[#3572](https://github.com/keepassxreboot/keepassxc/issues/3572)]
- CLI: Add CSV export to the 'export' command [[#3278](https://github.com/keepassxreboot/keepassxc/issues/3278)]
- CLI: Add `-y --yubikey` option for YubiKey [[#3416](https://github.com/keepassxreboot/keepassxc/issues/3416)]
- CLI: Add `--dry-run` option for merging databases [[#3254](https://github.com/keepassxreboot/keepassxc/issues/3254)]
- CLI: Add group commands (mv, mkdir and rmdir) [[#3313](https://github.com/keepassxreboot/keepassxc/issues/3313)].
- CLI: Add interactive shell mode command `open` [[#3224](https://github.com/keepassxreboot/keepassxc/issues/3224)]

Changed

- Redesign database unlock dialog [ [#3287](https://github.com/keepassxreboot/keepassxc/issues/3287)]
- Rework the entry preview panel [ [#3306](https://github.com/keepassxreboot/keepassxc/issues/3306)]
- Move notes to General tab on Group Preview Panel [[#3336](https://github.com/keepassxreboot/keepassxc/issues/3336)]
- Enable entry actions when editing an entry and cleanup entry context menu  [[#3641](https://github.com/keepassxreboot/keepassxc/issues/3641)]
- Improve detection of external database changes  [[#2389](https://github.com/keepassxreboot/keepassxc/issues/2389)]
- Warn if user is trying to use a KDBX file as a key file [[#3625](https://github.com/keepassxreboot/keepassxc/issues/3625)]
- Add option to disable KeePassHTTP settings migrations prompt [[#3349](https://github.com/keepassxreboot/keepassxc/issues/3349), [#3344](https://github.com/keepassxreboot/keepassxc/issues/3344)]
- Re-enabled Wayland support (no Auto-Type yet) [[#3520](https://github.com/keepassxreboot/keepassxc/issues/3520), [#3341](https://github.com/keepassxreboot/keepassxc/issues/3341)]
- Add icon to 'Toggle Window' action in tray icon menu [[3244](https://github.com/keepassxreboot/keepassxc/issues/3244)]
- Merge custom data between databases only when necessary [[#3475](https://github.com/keepassxreboot/keepassxc/issues/3475)]
- Improve various file-handling related issues when picking files using the system's file dialog [[#3473](https://github.com/keepassxreboot/keepassxc/issues/3473)]
- Add 'New Entry' context menu when no entries are selected [[#3671](https://github.com/keepassxreboot/keepassxc/issues/3671)]
- Reduce default Argon2 settings from 128 MiB and one thread per CPU core to 64 MiB and two threads to account for lower-spec mobile hardware [ [#3672](https://github.com/keepassxreboot/keepassxc/issues/3672)]
- Browser: Remove unused 'Remember' checkbox for HTTP Basic Auth [[#3371](https://github.com/keepassxreboot/keepassxc/issues/3371)]
- Browser: Show database name when pairing with a new browser [[#3638](https://github.com/keepassxreboot/keepassxc/issues/3638)]
- Browser: Show URL in allow access dialog [[#3639](https://github.com/keepassxreboot/keepassxc/issues/3639)]
- CLI: The password length option `-l` for the CLI commands `Add` and `Edit` is now `-L` [[#3275](https://github.com/keepassxreboot/keepassxc/issues/3275)]
- CLI: The `-u` shorthand for the `--upper` password generation option has been renamed to `-U` [[#3275](https://github.com/keepassxreboot/keepassxc/issues/3275)]
- CLI: Rename command `extract` to `export`. [[#3277](https://github.com/keepassxreboot/keepassxc/issues/3277)]

Fixed

- Improve accessibility for assistive technologies [[#3409](https://github.com/keepassxreboot/keepassxc/issues/3409)]
- Correctly unlock all databases if `--pw-stdin` is provided [[#2916](https://github.com/keepassxreboot/keepassxc/issues/2916)]
- Fix password generator issues with special characters [[#3303](https://github.com/keepassxreboot/keepassxc/issues/3303)]
- Fix KeePassXC interrupting shutdown procedure [[#3666](https://github.com/keepassxreboot/keepassxc/issues/3666)]
- Fix password visibility toggle button state on unlock dialog [[#3312](https://github.com/keepassxreboot/keepassxc/issues/3312)]
- Fix potential data loss if database is reloaded while user is editing an entry [[#3656](https://github.com/keepassxreboot/keepassxc/issues/3656)]
- Fix hard-coded background color in search help popup [[#3001](https://github.com/keepassxreboot/keepassxc/issues/3001)]
- Fix font choice for password preview [[#3425](https://github.com/keepassxreboot/keepassxc/issues/3425)]
- Fix handling of read-only files when autosave is enabled [[#3408](https://github.com/keepassxreboot/keepassxc/issues/3408)]
- Handle symlinks correctly when atomic saves are disabled [[#3463](https://github.com/keepassxreboot/keepassxc/issues/3463)]
- Enable HighDPI icon scaling on Linux [[#3332](https://github.com/keepassxreboot/keepassxc/issues/3332)]
- Make Auto-Type on macOS more robust and remove old Carbon API calls [[#3634](https://github.com/keepassxreboot/keepassxc/issues/3634), [[#3347](https://github.com/keepassxreboot/keepassxc/issues/3347))]
- Hide Share tab if KeePassXC is compiled without KeeShare support and other minor KeeShare improvements [[#3654](https://github.com/keepassxreboot/keepassxc/issues/3654), [[#3291](https://github.com/keepassxreboot/keepassxc/issues/3291), [#3029](https://github.com/keepassxreboot/keepassxc/issues/3029), [#3031](https://github.com/keepassxreboot/keepassxc/issues/3031), [#3236](https://github.com/keepassxreboot/keepassxc/issues/3236)]
- Correctly bring window to the front when clicking tray icon on macOS [[#3576](https://github.com/keepassxreboot/keepassxc/issues/3576)]
- Correct application shortcut created by MSI Installer on Windows [[#3296](https://github.com/keepassxreboot/keepassxc/issues/3296)]
- Fix crash when removing custom data [[#3508](https://github.com/keepassxreboot/keepassxc/issues/3508)]
- Fix placeholder resolution in URLs [[#3281](https://github.com/keepassxreboot/keepassxc/issues/3281)]
- Fix various inconsistencies and platform-dependent compilation bugs [[#3664](https://github.com/keepassxreboot/keepassxc/issues/3664), [#3662](https://github.com/keepassxreboot/keepassxc/issues/3662), [#3660](https://github.com/keepassxreboot/keepassxc/issues/3660), [#3655](https://github.com/keepassxreboot/keepassxc/issues/3655), [#3649](https://github.com/keepassxreboot/keepassxc/issues/3649), [#3417](https://github.com/keepassxreboot/keepassxc/issues/3417), [#3357](https://github.com/keepassxreboot/keepassxc/issues/3357), [#3319](https://github.com/keepassxreboot/keepassxc/issues/3319), [#3318](https://github.com/keepassxreboot/keepassxc/issues/3318), [#3304](https://github.com/keepassxreboot/keepassxc/issues/3304)]
- Browser: Fix potential leaking of entries through the browser integration API if multiple databases are opened [[#3480](https://github.com/keepassxreboot/keepassxc/issues/3480)]
- Browser: Fix password entropy calculation [[#3107](https://github.com/keepassxreboot/keepassxc/issues/3107)]
- Browser: Fix Windows registry settings for portable installation [[#3603](https://github.com/keepassxreboot/keepassxc/issues/3603)]
This commit is contained in:
Janek Bevendorff 2019-10-26 21:34:32 +02:00
commit 1ab8a9f42c
No known key found for this signature in database
GPG Key ID: 2FDEB0D40BCA5E11
430 changed files with 89353 additions and 21987 deletions

View File

@ -125,7 +125,7 @@ For **C++ files** (*.cpp .h*): 4 spaces
For **Qt-UI files** (*.ui*): 2 spaces For **Qt-UI files** (*.ui*): 2 spaces
#### Includes #### Includes
```c ```cpp
// Class includes // Class includes
#include "MyWidget.h" #include "MyWidget.h"
#include "ui_MyWidget.h" #include "ui_MyWidget.h"
@ -140,7 +140,7 @@ For **Qt-UI files** (*.ui*): 2 spaces
``` ```
#### Classes #### Classes
```c ```cpp
// Note: order is important, stay organized! // Note: order is important, stay organized!
class MyWidget : public QWidget class MyWidget : public QWidget
{ {
@ -174,13 +174,13 @@ MyWidget::MyWidget(QWidget* parent)
``` ```
#### Pointers / References #### Pointers / References
```c ```cpp
int* count; int* count;
const QString& string; const QString& string;
``` ```
#### Braces #### Braces
```c ```cpp
if (condition) { if (condition) {
doSomething(); doSomething();
} else { } else {
@ -194,7 +194,7 @@ void ExampleClass::exampleFunction()
``` ```
#### Switch statement #### Switch statement
```c ```cpp
// Note: avoid declaring variables in a switch statement // Note: avoid declaring variables in a switch statement
switch (a) { switch (a) {
case 1: case 1:
@ -221,6 +221,6 @@ Example: `<widget class="QCheckBox" name="rememberCheckBox">`
[beginner]:https://github.com/keepassxreboot/keepassx/issues?q=is%3Aopen+is%3Aissue+label%3Abeginner+label%3A%22help+wanted%22+sort%3Acomments-desc [beginner]:https://github.com/keepassxreboot/keepassxc/issues?utf8=%E2%9C%93&q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22+sort%3Acomments-desc+
[help-wanted]:https://github.com/keepassxreboot/keepassx/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+sort%3Acomments-desc [help-wanted]:https://github.com/keepassxreboot/keepassx/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22+sort%3Acomments-desc
[issues-section]:https://github.com/keepassxreboot/keepassxc/issues [issues-section]:https://github.com/keepassxreboot/keepassxc/issues

482
CHANGELOG
View File

@ -1,482 +0,0 @@
2.4.3 (2019-06-12)
=========================
- Fix library loading issues in the Snap and macOS releases [#3247]
- Fix various keyboard navigation issues [#3248]
- Fix main window toggling regression when clicking the tray icon on KDE [#3258]
- Add documentation for keyboard shortcuts to source code distribution [#3215]
2.4.2 (2019-05-31)
=========================
- Improve resilience against memory attacks - overwrite memory before free [#3020]
- Prevent infinite save loop when location is unavailable [#3026]
- Attempt to fix quitting application when shutdown or logout issued [#3199]
- Support merging database custom data [#3002]
- Fix opening URL's with non-http schemes [#3153]
- Fix data loss due to not reading all database attachments if duplicates exist [#3180]
- Fix entry context menu disabling when using keyboard navigation [#3199]
- Fix behaviors when canceling an entry edit [#3199]
- Fix processing of tray icon click and doubleclick [#3112]
- Update group in preview widget when focused [#3199]
- Prefer DuckDuckGo service over direct icon download (increases resolution) [#2996]
- Remove apply button in application settings [#3019]
- Use winqtdeploy on Windows to correct deployment issues [#3025]
- Don't mark entry edit as modified when attribute selection changes [#3041]
- Use console code page CP_UTF8 on Windows if supported [#3050]
- Snap: Fix locking database with session lock [#3046]
- Snap: Fix theming across Linux distributions [#3057]
- Snap: Use SNAP_USER_COMMON and SNAP_USER_DATA directories [#3131]
- KeeShare: Automatically enable WITH_XC_KEESHARE_SECURE if quazip is found [#3088]
- macOS: Fix toolbar text when in dark mode [#2998]
- macOS: Lock database on switching user [#3097]
- macOS: Fix global Auto-Type when the database is locked [#3138]
- Browser: Close popups when database is locked [#3093]
- Browser: Add tests [#3016]
- Browser: Don't create default group if custom group is enabled [#3127]
2.4.1 (2019-04-12)
=========================
- Fix database deletion when using unsafe saves to a different file system [#2889]
- Fix opening databases with legacy key files that contain '/' [#2872]
- Fix opening database files from the command line [#2919]
- Fix crash when editing master key [#2836]
- Fix multiple issues with apply button behavior [#2947]
- Fix issues on application startup (tab order, --pw-stdin, etc.) [#2830]
- Fix building without WITH_XC_KEESHARE
- Fix reference entry coloring on macOS dark mode [#2984]
- Hide window when performing entry auto-type on macOS [#2969]
- Improve UX of update checker; reduce checks to every 7 days [#2968]
- KeeShare improvements [#2946, #2978, #2824]
- Re-enable Ctrl+C to copy password from search box [#2947]
- Add KeePassXC-Browser integration for Brave browser [#2933]
- SSH Agent: Re-Add keys on database unlock [#2982]
- SSH Agent: Only remove keys on app exit if they are removed on lock [#2985]
- CLI: Add --no-password option [#2708]
- CLI: Improve database extraction to XML [#2698]
- CLI: Don't call mandb on build [#2774]
- CLI: Add debug info [#2714]
- Improve support for Snap theming [#2832]
- Add support for building on Haiku OS [#2859]
- Ctrl+PgDn now goes to the next tab and Ctrl+PgUp to the previous
- Fix compiling on GCC 5 / Xenial [#2990]
- Add .gitrev output to tarball for third-party builds [#2970]
- Add WITH_XC_UPDATECHECK compile flag to toggle the update checker [#2968]
2.4.0 (2019-03-19)
=========================
- New Database Wizard [#1952]
- Advanced Search [#1797]
- Automatic update checker [#2648]
- KeeShare database synchronization [#2109, #1992, #2738, #2742, #2746, #2739]
- Improve favicon fetching; transition to Duck-Duck-Go [#2795, #2011, #2439]
- Remove KeePassHttp support [#1752]
- CLI: output info to stderr for easier scripting [#2558]
- CLI: Add --quiet option [#2507]
- CLI: Add create command [#2540]
- CLI: Add recursive listing of entries [#2345]
- CLI: Fix stdin/stdout encoding on Windows [#2425]
- SSH Agent: Support OpenSSH for Windows [#1994]
- macOS: TouchID Quick Unlock [#1851]
- macOS: Multiple improvements; include CLI in DMG [#2165, #2331, #2583]
- Linux: Prevent Klipper from storing secrets in clipboard [#1969]
- Linux: Use polling based file watching for NFS [#2171]
- Linux: Enable use of browser plugin in Snap build [#2802]
- TOTP QR Code Generator [#1167]
- High-DPI Scaling for 4k screens [#2404]
- Make keyboard shortcuts more consistent [#2431]
- Warn user if deleting referenced entries [#1744]
- Allow toolbar to be hidden and repositioned [#1819, #2357]
- Increase max allowed database timeout to 12 hours [#2173]
- Password generator uses existing password length by default [#2318]
- Improve alert message box button labels [#2376]
- Show message when a database merge makes no changes [#2551]
- Browser Integration Enhancements [#1497, #2253, #1904, #2232, #1850, #2218, #2391, #2396, #2542, #2622, #2637, #2790]
- Overall Code Improvements [#2316, #2284, #2351, #2402, #2410, #2419, #2422, #2443, #2491, #2506, #2610, #2667, #2709, #2731]
2.3.4 (2018-08-21)
=========================
- Show all URL schemes in entry view [#1768]
- Disable merge when database is locked [#1975]
- Fix intermittent crashes with favorite icon downloads [#1980]
- Provide potential crash warning to Qt 5.5.x users [#2211]
- Disable apply button when creating new entry/group to prevent data loss [#2204]
- Allow for 12 hour timeout to lock idle database [#2173]
- Multiple SSH Agent fixes [#1981, #2117]
- Multiple Browser Integration enhancements [#1993, #2003, #2055, #2116, #2159, #2174, #2185]
- Fix browser proxy application not closing properly [#2142]
- Add real names and Patreon supporters to about dialog [#2214]
- Add settings button to toolbar, Donate button, and Report a Bug button to help menu [#2214]
- Enhancements to release-tool to appsign intermediate build products [#2101]
2.3.3 (2018-05-09)
=========================
- Fix crash when browser integration is enabled [#1923]
2.3.2 (2018-05-07)
=========================
- Enable high entropy ASLR on Windows [#1747]
- Enhance favicon fetching [#1786]
- Fix crash on Windows due to autotype [#1691]
- Fix dark tray icon changing all icons [#1680]
- Fix --pw-stdin not using getPassword function [#1686]
- Fix placeholders being resolved in notes [#1907]
- Enable auto-type start delay to be configurable [#1908]
- Browser: Fix native messaging reply size [#1719]
- Browser: Increase maximum buffer size [#1720]
- Browser: Enhance usability and functionality [#1810, #1822, #1830, #1884, #1906]
- SSH Agent: Parse aes-256-cbc/ctr keys [#1682]
- SSH Agent: Enhance usability and functionality [#1677, #1679, #1681, #1787]
2.3.1 (2018-03-06)
=========================
- Fix unnecessary automatic upgrade to KDBX 4.0 and prevent challenge-response key being stripped [#1568]
- Abort saving and show an error message when challenge-response fails [#1659]
- Support inner stream protection on all string attributes [#1646]
- Fix favicon downloads not finishing on some websites [#1657]
- Fix freeze due to invalid STDIN data [#1628]
- Correct issue with encrypted RSA SSH keys [#1587]
- Fix crash on macOS due to QTBUG-54832 [#1607]
- Show error message if ssh-agent communication fails [#1614]
- Fix --pw-stdin and filename parameters being ignored [#1608]
- Fix Auto-Type syntax check not allowing spaces and special characters [#1626]
- Fix reference placeholders in combination with Auto-Type [#1649]
- Fix qtbase translations not being loaded [#1611]
- Fix startup crash on Windows due to missing SVG libraries [#1662]
- Correct database tab order regression [#1610]
- Fix GCC 8 compilation error [#1612]
- Fix copying of advanced attributes on KDE [#1640]
- Fix member initialization of CategoryListWidgetDelegate [#1613]
- Fix inconsistent toolbar icon sizes and provide higher-quality icons [#1616]
- Improve preview panel geometry [#1609]
2.3.0 (2018-02-27)
=========================
- Add support for KDBX 4.0, Argon2 and ChaCha20 [#148, #1179, #1230, #1494]
- Add SSH Agent feature [#1098, #1450, #1463]
- Add preview panel with details of the selected entry [#879, #1338]
- Add more and configurable columns to entry table and allow copying of values by double click [#1305]
- Add KeePassXC-Browser API as a replacement for KeePassHTTP [#608]
- Deprecate KeePassHTTP [#1392]
- Add support for Steam one-time passwords [#1206]
- Add support for multiple Auto-Type sequences for a single entry [#1390]
- Adjust YubiKey HMAC-SHA1 challenge-response key generation for KDBX 4.0 [#1060]
- Replace qHttp with cURL for website icon downloads [#1460]
- Remove lock file [#1231]
- Add option to create backup file before saving [#1385]
- Ask to save a generated password before closing the entry password generator [#1499]
- Resolve placeholders recursively [#1078]
- Add Auto-Type button to the toolbar [#1056]
- Improve window focus handling for Auto-Type dialogs [#1204, #1490]
- Auto-Type dialog and password generator can now be exited with ESC [#1252, #1412]
- Add optional dark tray icon [#1154]
- Add new "Unsafe saving" option to work around saving problems with file sync services [#1385]
- Add IBus support to AppImage and additional image formats to Windows builds [#1534, #1537]
- Add diceware password generator to CLI [#1406]
- Add --key-file option to CLI [#816, #824]
- Add DBus interface for opening and closing KeePassXC databases [#283]
- Add KDBX compression options to database settings [#1419]
- Discourage use of old fixed-length key files in favor of arbitrary files [#1326, #1327]
- Correct reference resolution in entry fields [#1486]
- Fix window state and recent databases not being remembered on exit [#1453]
- Correct history item generation when configuring TOTP for an entry [#1446]
- Correct multiple TOTP bugs [#1414]
- Automatic saving after every change is now a default [#279]
- Allow creation of new entries during search [#1398]
- Correct menu issues on macOS [#1335]
- Allow compilation on OpenBSD [#1328]
- Improve entry attachments view [#1139, #1298]
- Fix auto lock for Gnome and Xfce [#910, #1249]
- Don't remember key files in file dialogs when the setting is disabled [#1188]
- Improve database merging and conflict resolution [#807, #1165]
- Fix macOS pasteboard issues [#1202]
- Improve startup times on some platforms [#1205]
- Hide the notes field by default [#1124]
- Toggle main window by clicking tray icon with the middle mouse button [#992]
- Fix custom icons not copied over when databases are merged [#1008]
- Allow use of DEL key to delete entries [#914]
- Correct intermittent crash due to stale history items [#1527]
- Sanitize newline characters in title, username and URL fields [#1502]
- Reopen previously opened databases in correct order [#774]
- Use system's zxcvbn library if available [#701]
- Implement various i18n improvements [#690, #875, #1436]
2.2.4 (2017-12-13)
=========================
- Prevent database corruption when locked [#1219]
- Fixes apply button not saving new entries [#1141]
- Switch to Consolas font on Windows for password edit [#1229]
- Multiple fixes to AppImage deployment [#1115, #1228]
- Fixes multiple memory leaks [#1213]
- Resize message close to 16x16 pixels [#1253]
2.2.2 (2017-10-22)
=========================
- Fixed entries with empty URLs being reported to KeePassHTTP clients [#1031]
- Fixed YubiKey detection and enabled CLI tool for AppImage binary [#1100]
- Added AppStream description [#1082]
- Improved TOTP compatibility and added new Base32 implementation [#1069]
- Fixed error handling when processing invalid cipher stream [#1099]
- Fixed double warning display when opening a database [#1037]
- Fixed unlocking databases with --pw-stdin [#1087]
- Added ability to override QT_PLUGIN_PATH environment variable for AppImages [#1079]
- Fixed transform seed not being regenerated when saving the database [#1068]
- Fixed only one YubiKey slot being polled [#1048]
- Corrected an issue with entry icons while merging [#1008]
- Corrected desktop and tray icons in Snap package [#1030]
- Fixed screen lock and Google fallback settings [#1029]
2.2.1 (2017-10-01)
=========================
- Corrected multiple snap issues [#934, #1011]
- Corrected multiple custom icon issues [#708, #719, #994]
- Corrected multiple Yubikey issues [#880]
- Fixed single instance preventing load on occasion [#997]
- Keep entry history when merging databases [#970]
- Prevent data loss if passwords were mismatched [#1007]
- Fixed crash after merge [#941]
- Added configurable auto-type default delay [#703]
- Unlock database dialog window comes to front [#663]
- Translation and compiling fixes
2.2.0 (2017-06-23)
=========================
- Added YubiKey 2FA integration for unlocking databases [#127]
- Added TOTP support [#519]
- Added CSV import tool [#146, #490]
- Added KeePassXC CLI tool [#254]
- Added diceware password generator [#373]
- Added support for entry references [#370, #378]
- Added support for Twofish encryption [#167]
- Enabled DEP and ASLR for in-memory protection [#371]
- Enabled single instance mode [#510]
- Enabled portable mode [#645]
- Enabled database lock on screensaver and session lock [#545]
- Redesigned welcome screen with common features and recent databases [#292]
- Multiple updates to search behavior [#168, #213, #374, #471, #603, #654]
- Added auto-type fields {CLEARFIELD}, {SPACE}, {{}, {}} [#267, #427, #480]
- Fixed auto-type errors on Linux [#550]
- Prompt user prior to executing a cmd:// URL [#235]
- Entry attributes can be protected (hidden) [#220]
- Added extended ascii to password generator [#538]
- Added new database icon to toolbar [#289]
- Added context menu entry to empty recycle bin in databases [#520]
- Added "apply" button to entry and group edit windows [#624]
- Added macOS tray icon and enabled minimize on close [#583]
- Fixed issues with unclean shutdowns [#170, #580]
- Changed keyboard shortcut to create new database to CTRL+SHIFT+N [#515]
- Compare window title to entry URLs [#556]
- Implemented inline error messages [#162]
- Ignore group expansion and other minor changes when making database "dirty" [#464]
- Updated license and copyright information on souce files [#632]
- Added contributors list to about dialog [#629]
2.1.4 (2017-04-09)
=========================
- Bumped KeePassHTTP version to 1.8.4.2
- KeePassHTTP confirmation window comes to foreground [#466]
2.1.3 (2017-03-03)
=========================
- Fix possible overflow in zxcvbn library [#363]
- Revert HiDPI setting to avoid problems on laptop screens [#332]
- Set file meta properties in Windows executable [#330]
- Suppress error message when auto-reloading a locked database [#345]
- Improve usability of question dialog when database is already locked by a different instance [#346]
- Fix compiler warnings in QHttp library [#351]
- Use unified toolbar on Mac OS X [#361]
- Fix an issue on X11 where the main window would be raised instead of closed on Alt+F4 [#362]
2.1.2 (2017-02-17)
=========================
- Ask for save location when creating a new database [#302]
- Remove Libmicrohttpd dependency to clean up the code and ensure better OS X compatibility [#317, #265]
- Prevent Qt from degrading Wifi network performance on certain platforms [#318]
- Visually refine user interface on OS X and other platforms [#299]
- Remove unusable tray icon setting on OS X [#293]
- Fix compositing glitches on Ubuntu and prevent flashing when minimizing to the tray at startup [#307]
- Fix AppImage tray icon on Ubuntu [#277, #273]
- Fix global menu disappearing after restoring KeePassXC from the tray on Ubuntu [#276]
- Fix result order in entry search [#320]
- Enable HiDPI scaling on supported platforms [#315]
- Remove empty directories from installation target [#282]
2.1.1 (2017-02-06)
=========================
- Enabled HTTP plugin build; plugin is disabled by default and limited to localhost [#147]
- Escape HTML in dialog boxes [#247]
- Corrected crashes in favicon download and password generator [#233, #226]
- Increase font size of password meter [#228]
- Fixed compatibility with Qt 5.8 [#211]
- Use consistent button heights in password generator [#229]
2.1.0 (2017-01-22)
=========================
- Show unlock dialog when using autotype on a closed database [#10, #89]
- Show different tray icon when database is locked [#37, #46]
- Support autotype on Windows and OS X [#42, #60, #63]
- Add delay feature to autotype [#76, #77]
- Add password strength meter [#84, #92]
- Add option for automatically locking the database when minimizing
the window [#57]
- Add feature to download favicons and use them as entry icons [#30]
- Automatically reload and merge database when the file changed on
disk [#22, #33, #93]
- Add tool for merging two databases [#22, #47, #143]
- Add --pw-stdin commandline option to unlock the database by providing
a password on STDIN [#54]
- Add utility script for reading the database password from KWallet [#55]
- Fix some KeePassHTTP settings not being remembered [#34, #65]
- Make search box persistent [#15, #67, #157]
- Enhance search feature by scoping the search to selected group [#16, #118]
- Improve interaction between search field and entry list [#131, #141]
- Add stand-alone password-generator [#18, #92]
- Don't require password repetition when password is visible [#27, #92]
- Add support for entry attributes in autotype sequences [#107]
- Always focus password field when opening the database unlock widget [#116, #117]
- Fix compilation errors on various platforms [#53, #126, #130]
- Restructure and improve kdbx-extract utility [#160]
2.0.3 (2016-09-04)
=========================
- Improved error reporting when reading / writing databases fails. [#450, #462]
- Display an error message when opening a custom icon fails.
- Detect custom icon format based on contents instead of the filename. [#512]
- Keep symlink intact when saving databases. [#442].
- Fix a crash when deleting parent group of recycle bin. [#520]
- Display a confirm dialog before moving an entry to the recycle bin. [#447]
- Repair UUIDs of inconsistent history items. [#130]
- Only include top-level windows in auto-type window list when using gnome-shell.
- Update translations.
2.0.2 (2016-02-02)
=========================
- Fix regression in database writer that caused it to strip certain special
characters (characters from Unicode plane > 0).
- Fix bug in repair function that caused it to strip non-ASCII characters.
2.0.1 (2016-01-31)
=========================
- Flush temporary file before opening attachment. [#390]
- Disable password generator when showing entry in history mode. [#422]
- Strip invalid XML chars when writing databases. [#392]
- Add repair function to fix databases with invalid XML chars. [#392]
- Display custom icons scaled. [#322]
- Allow opening databases that have no password and keyfile. [#391]
- Fix crash when importing .kdb files with invalid icon ids. [#425]
- Update translations.
2.0 (2015-12-06)
=========================
- Improve UI of the search edit.
- Clear clipboard when locking databases. [#342]
- Enable Ctrl+M shortcut to minimize the window on all platforms. [#329]
- Show a better message when trying to open an old database format. [#338]
- Fix global auto-type behavior with some window managers.
- Show global auto-type window on the active desktop. [#359]
- Disable systray on OS X. [#326]
- Restore main window when clicking on the OS X docker icon. [#326]
2.0 Beta 2 (2015-09-06)
=========================
- Fix crash when locking with search UI open [#309]
- Fix file locking on Mac OS X [#327]
- Set default extension when saving a database [#79, #308]
2.0 Beta 1 (2015-07-18)
=========================
- Remember entry column sizes [#159]
- Add translations
- Support opening attachments directly
- Support cmd:// URLs [#244]
- Protect opened databases with a file lock [#18]
- Export to csv files [#57]
- Add optional tray icon [#153]
- Allow setting the default auto-type sequence for groups [#175]
- Make the kdbx parser more lenient
- Remove --password command line option [#285]
2.0 Alpha 6 (2014-04-12)
=========================
- Add option to lock databases after user inactivity [#62]
- Add compatibility with libgcrypt 1.6 [#129]
- Display passwords in monospace font [#51]
- Use an icon for the button that shows/masks passwords [#38]
- Add an option to show passwords by default [#93]
- Improve password generator design [#122]
- On Linux link .kdbx files with KeePassX
- Remember window size [#154]
- Disallow global auto-typing when the database is locked
2.0 Alpha 5 (2013-12-20)
=========================
- Support copying entries and groups using drag'n'drop [#74]
- Open last used databases on startup [#36]
- Made the kdbx file parser more robust
- Only edit entries on doubleclick (not single) or with enter key
- Allow removing multiple entries
- Added option to minimize window when copying data to clipboard
- Save password generator settings
- Fixed auto-type producing wrong chars in some keyboard configurations [#116]
- Added some more actions to the toolbar
2.0 Alpha 4 (2013-03-29)
=========================
- Add random password generator [#52]
- Merge the 'Description' tab into the 'Entry' tab [#59]
- Fix crash when deleting history items [#56]
- Fix crash on Mac OS X Mountain Lion during startup [#50]
- Improved KeePassX application icon [#58]
2.0 Alpha 3 (2012-10-27)
=========================
- Auto-Type on Linux / X11
- Database locking
- Fix database corruption when changing key transformation rounds [#34]
- Verify header data of kdbx files
- Add menu entry to open URLs in the browser
- Add menu entry to copy an entry attribute to clipboard
2.0 Alpha 2 (2012-07-02)
=========================
- Import kdb (KeePass 1) files [#2]
- Display history items [#23]
- Implement history item limits [#16]
- Group and entry icons can be set [#22]
- Add keyboard shortcuts
- Search in databases [#24]
- Sortable entry view
- Support building Mac OS X bundles
2.0 Alpha 1 (2012-05-07)
=========================
- First release.

546
CHANGELOG.md Normal file
View File

@ -0,0 +1,546 @@
# Changelog
## 2.5.0 (2019-10-26)
### Added
- Add 'Paper Backup' aka 'Export to HTML file' to the 'Database' menu [[#3277](https://github.com/keepassxreboot/keepassxc/pull/3277)]
- Add statistics panel with information about the database (number of entries, number of unique passwords, etc.) to the Database Settings dialog [[#2034](https://github.com/keepassxreboot/keepassxc/issues/2034)]
- Add offline user manual accessible via the 'Help' menu [[#3274](https://github.com/keepassxreboot/keepassxc/issues/3274)]
- Add support for importing 1Password OpVault files [[#2292](https://github.com/keepassxreboot/keepassxc/issues/2292)]
- Implement Freedesktop.org secret storage DBus protocol so that KeePassXC can be used as a vault service by libsecret [[#2726](https://github.com/keepassxreboot/keepassxc/issues/2726)]
- Add support for OnlyKey as an alternative to YubiKeys (requires yubikey-personalization >= 1.20.0) [[#3352](https://github.com/keepassxreboot/keepassxc/issues/3352)]
- Add group sorting feature [[#3282](https://github.com/keepassxreboot/keepassxc/issues/3282)]
- Add feature to download favicons for all entries at once [[#3169](https://github.com/keepassxreboot/keepassxc/issues/3169)]
- Add word case option to passphrase generator [[#3172](https://github.com/keepassxreboot/keepassxc/issues/3172)]
- Add support for RFC6238-compliant TOTP hashes [[#2972](https://github.com/keepassxreboot/keepassxc/issues/2972)]
- Add UNIX man page for main program [[#3665](https://github.com/keepassxreboot/keepassxc/issues/3665)]
- Add 'Monospaced font' option to the notes field [[#3321](https://github.com/keepassxreboot/keepassxc/issues/3321)]
- Add support for key files in auto open [[#3504](https://github.com/keepassxreboot/keepassxc/issues/3504)]
- Add search field for filtering entries in Auto-Type dialog [[#2955](https://github.com/keepassxreboot/keepassxc/issues/2955)]
- Complete usernames based on known usernames from other entries [[#3300](https://github.com/keepassxreboot/keepassxc/issues/3300)]
- Parse hyperlinks in the notes field of the entry preview pane [[#3596](https://github.com/keepassxreboot/keepassxc/issues/3596)]
- Allow abbreviation of field names in entry search [[#3440](https://github.com/keepassxreboot/keepassxc/issues/3440)]
- Allow setting group icons recursively [[#3273](https://github.com/keepassxreboot/keepassxc/issues/3273)]
- Add copy context menu for username and password in Auto-Type dialog [[#3038](https://github.com/keepassxreboot/keepassxc/issues/3038)]
- Drop to background after copying a password to the clipboard [[#3253](https://github.com/keepassxreboot/keepassxc/issues/3253)]
- Add 'Lock databases' entry to tray icon menu [[#2896](https://github.com/keepassxreboot/keepassxc/issues/2896)]
- Add option to minimize window after unlocking [[#3439](https://github.com/keepassxreboot/keepassxc/issues/3439)]
- Add option to minimize window after opening a URL [[#3302](https://github.com/keepassxreboot/keepassxc/issues/3302)]
- Request accessibility permissions for Auto-Type on macOS [[#3624](https://github.com/keepassxreboot/keepassxc/issues/3624)]
- Browser: Add initial support for multiple URLs [[#3558](https://github.com/keepassxreboot/keepassxc/issues/3558)]
- Browser: Add entry-specific browser integration settings [[#3444](https://github.com/keepassxreboot/keepassxc/issues/3444)]
- CLI: Add offline HIBP checker (requires a downloaded HIBP dump) [[#2707](https://github.com/keepassxreboot/keepassxc/issues/2707)]
- CLI: Add 'flatten' option to the 'ls' command [[#3276](https://github.com/keepassxreboot/keepassxc/issues/3276)]
- CLI: Add password generation options to `Add` and `Edit` commands [[#3275](https://github.com/keepassxreboot/keepassxc/issues/3275)]
- CLI: Add XML import [[#3572](https://github.com/keepassxreboot/keepassxc/issues/3572)]
- CLI: Add CSV export to the 'export' command [[#3278](https://github.com/keepassxreboot/keepassxc/issues/3278)]
- CLI: Add `-y --yubikey` option for YubiKey [[#3416](https://github.com/keepassxreboot/keepassxc/issues/3416)]
- CLI: Add `--dry-run` option for merging databases [[#3254](https://github.com/keepassxreboot/keepassxc/issues/3254)]
- CLI: Add group commands (mv, mkdir and rmdir) [[#3313](https://github.com/keepassxreboot/keepassxc/issues/3313)].
- CLI: Add interactive shell mode command `open` [[#3224](https://github.com/keepassxreboot/keepassxc/issues/3224)]
### Changed
- Redesign database unlock dialog [ [#3287](https://github.com/keepassxreboot/keepassxc/issues/3287)]
- Rework the entry preview panel [ [#3306](https://github.com/keepassxreboot/keepassxc/issues/3306)]
- Move notes to General tab on Group Preview Panel [[#3336](https://github.com/keepassxreboot/keepassxc/issues/3336)]
- Enable entry actions when editing an entry and cleanup entry context menu [[#3641](https://github.com/keepassxreboot/keepassxc/issues/3641)]
- Improve detection of external database changes [[#2389](https://github.com/keepassxreboot/keepassxc/issues/2389)]
- Warn if user is trying to use a KDBX file as a key file [[#3625](https://github.com/keepassxreboot/keepassxc/issues/3625)]
- Add option to disable KeePassHTTP settings migrations prompt [[#3349](https://github.com/keepassxreboot/keepassxc/issues/3349), [#3344](https://github.com/keepassxreboot/keepassxc/issues/3344)]
- Re-enabled Wayland support (no Auto-Type yet) [[#3520](https://github.com/keepassxreboot/keepassxc/issues/3520), [#3341](https://github.com/keepassxreboot/keepassxc/issues/3341)]
- Add icon to 'Toggle Window' action in tray icon menu [[3244](https://github.com/keepassxreboot/keepassxc/issues/3244)]
- Merge custom data between databases only when necessary [[#3475](https://github.com/keepassxreboot/keepassxc/issues/3475)]
- Improve various file-handling related issues when picking files using the system's file dialog [[#3473](https://github.com/keepassxreboot/keepassxc/issues/3473)]
- Add 'New Entry' context menu when no entries are selected [[#3671](https://github.com/keepassxreboot/keepassxc/issues/3671)]
- Reduce default Argon2 settings from 128 MiB and one thread per CPU core to 64 MiB and two threads to account for lower-spec mobile hardware [ [#3672](https://github.com/keepassxreboot/keepassxc/issues/3672)]
- Browser: Remove unused 'Remember' checkbox for HTTP Basic Auth [[#3371](https://github.com/keepassxreboot/keepassxc/issues/3371)]
- Browser: Show database name when pairing with a new browser [[#3638](https://github.com/keepassxreboot/keepassxc/issues/3638)]
- Browser: Show URL in allow access dialog [[#3639](https://github.com/keepassxreboot/keepassxc/issues/3639)]
- CLI: The password length option `-l` for the CLI commands `Add` and `Edit` is now `-L` [[#3275](https://github.com/keepassxreboot/keepassxc/issues/3275)]
- CLI: The `-u` shorthand for the `--upper` password generation option has been renamed to `-U` [[#3275](https://github.com/keepassxreboot/keepassxc/issues/3275)]
- CLI: Rename command `extract` to `export`. [[#3277](https://github.com/keepassxreboot/keepassxc/issues/3277)]
### Fixed
- Improve accessibility for assistive technologies [[#3409](https://github.com/keepassxreboot/keepassxc/issues/3409)]
- Correctly unlock all databases if `--pw-stdin` is provided [[#2916](https://github.com/keepassxreboot/keepassxc/issues/2916)]
- Fix password generator issues with special characters [[#3303](https://github.com/keepassxreboot/keepassxc/issues/3303)]
- Fix KeePassXC interrupting shutdown procedure [[#3666](https://github.com/keepassxreboot/keepassxc/issues/3666)]
- Fix password visibility toggle button state on unlock dialog [[#3312](https://github.com/keepassxreboot/keepassxc/issues/3312)]
- Fix potential data loss if database is reloaded while user is editing an entry [[#3656](https://github.com/keepassxreboot/keepassxc/issues/3656)]
- Fix hard-coded background color in search help popup [[#3001](https://github.com/keepassxreboot/keepassxc/issues/3001)]
- Fix font choice for password preview [[#3425](https://github.com/keepassxreboot/keepassxc/issues/3425)]
- Fix handling of read-only files when autosave is enabled [[#3408](https://github.com/keepassxreboot/keepassxc/issues/3408)]
- Handle symlinks correctly when atomic saves are disabled [[#3463](https://github.com/keepassxreboot/keepassxc/issues/3463)]
- Enable HighDPI icon scaling on Linux [[#3332](https://github.com/keepassxreboot/keepassxc/issues/3332)]
- Make Auto-Type on macOS more robust and remove old Carbon API calls [[#3634](https://github.com/keepassxreboot/keepassxc/issues/3634), [[#3347](https://github.com/keepassxreboot/keepassxc/issues/3347))]
- Hide Share tab if KeePassXC is compiled without KeeShare support and other minor KeeShare improvements [[#3654](https://github.com/keepassxreboot/keepassxc/issues/3654), [[#3291](https://github.com/keepassxreboot/keepassxc/issues/3291), [#3029](https://github.com/keepassxreboot/keepassxc/issues/3029), [#3031](https://github.com/keepassxreboot/keepassxc/issues/3031), [#3236](https://github.com/keepassxreboot/keepassxc/issues/3236)]
- Correctly bring window to the front when clicking tray icon on macOS [[#3576](https://github.com/keepassxreboot/keepassxc/issues/3576)]
- Correct application shortcut created by MSI Installer on Windows [[#3296](https://github.com/keepassxreboot/keepassxc/issues/3296)]
- Fix crash when removing custom data [[#3508](https://github.com/keepassxreboot/keepassxc/issues/3508)]
- Fix placeholder resolution in URLs [[#3281](https://github.com/keepassxreboot/keepassxc/issues/3281)]
- Fix various inconsistencies and platform-dependent compilation bugs [[#3664](https://github.com/keepassxreboot/keepassxc/issues/3664), [#3662](https://github.com/keepassxreboot/keepassxc/issues/3662), [#3660](https://github.com/keepassxreboot/keepassxc/issues/3660), [#3655](https://github.com/keepassxreboot/keepassxc/issues/3655), [#3649](https://github.com/keepassxreboot/keepassxc/issues/3649), [#3417](https://github.com/keepassxreboot/keepassxc/issues/3417), [#3357](https://github.com/keepassxreboot/keepassxc/issues/3357), [#3319](https://github.com/keepassxreboot/keepassxc/issues/3319), [#3318](https://github.com/keepassxreboot/keepassxc/issues/3318), [#3304](https://github.com/keepassxreboot/keepassxc/issues/3304)]
- Browser: Fix potential leaking of entries through the browser integration API if multiple databases are opened [[#3480](https://github.com/keepassxreboot/keepassxc/issues/3480)]
- Browser: Fix password entropy calculation [[#3107](https://github.com/keepassxreboot/keepassxc/issues/3107)]
- Browser: Fix Windows registry settings for portable installation [[#3603](https://github.com/keepassxreboot/keepassxc/issues/3603)]
## 2.4.3 (2019-06-12)
### Added
- Add documentation for keyboard shortcuts to source code distribution [[#3215](https://github.com/keepassxreboot/keepassxc/issues/3215)]
### Fixed
- Fix library loading issues in the Snap and macOS releases [[#3247](https://github.com/keepassxreboot/keepassxc/issues/3247)]
- Fix various keyboard navigation issues [[#3248](https://github.com/keepassxreboot/keepassxc/issues/3248)]
- Fix main window toggling regression when clicking the tray icon on KDE [[#3258](https://github.com/keepassxreboot/keepassxc/issues/3258)]
## 2.4.2 (2019-05-31)
- Improve resilience against memory attacks - overwrite memory before free [[#3020](https://github.com/keepassxreboot/keepassxc/issues/3020)]
- Prevent infinite save loop when location is unavailable [[#3026](https://github.com/keepassxreboot/keepassxc/issues/3026)]
- Attempt to fix quitting application when shutdown or logout issued [[#3199](https://github.com/keepassxreboot/keepassxc/issues/3199)]
- Support merging database custom data [[#3002](https://github.com/keepassxreboot/keepassxc/issues/3002)]
- Fix opening URL's with non-http schemes [[#3153](https://github.com/keepassxreboot/keepassxc/issues/3153)]
- Fix data loss due to not reading all database attachments if duplicates exist [[#3180](https://github.com/keepassxreboot/keepassxc/issues/3180)]
- Fix entry context menu disabling when using keyboard navigation [[#3199](https://github.com/keepassxreboot/keepassxc/issues/3199)]
- Fix behaviors when canceling an entry edit [[#3199](https://github.com/keepassxreboot/keepassxc/issues/3199)]
- Fix processing of tray icon click and doubleclick [[#3112](https://github.com/keepassxreboot/keepassxc/issues/3112)]
- Update group in preview widget when focused [[#3199](https://github.com/keepassxreboot/keepassxc/issues/3199)]
- Prefer DuckDuckGo service over direct icon download (increases resolution) [#2996](https://github.com/keepassxreboot/keepassxc/issues/2996)]
- Remove apply button in application settings [[#3019](https://github.com/keepassxreboot/keepassxc/issues/3019)]
- Use winqtdeploy on Windows to correct deployment issues [[#3025](https://github.com/keepassxreboot/keepassxc/issues/3025)]
- Don't mark entry edit as modified when attribute selection changes [[#3041](https://github.com/keepassxreboot/keepassxc/issues/3041)]
- Use console code page CP_UTF8 on Windows if supported [[#3050](https://github.com/keepassxreboot/keepassxc/issues/3050)]
- Snap: Fix locking database with session lock [[#3046](https://github.com/keepassxreboot/keepassxc/issues/3046)]
- Snap: Fix theming across Linux distributions [[#3057](https://github.com/keepassxreboot/keepassxc/issues/3057)]
- Snap: Use SNAP_USER_COMMON and SNAP_USER_DATA directories [[#3131](https://github.com/keepassxreboot/keepassxc/issues/3131)]
- KeeShare: Automatically enable WITH_XC_KEESHARE_SECURE if quazip is found [[#3088](https://github.com/keepassxreboot/keepassxc/issues/3088)]
- macOS: Fix toolbar text when in dark mode [[#2998](https://github.com/keepassxreboot/keepassxc/issues/2998)]
- macOS: Lock database on switching user [[#3097](https://github.com/keepassxreboot/keepassxc/issues/3097)]
- macOS: Fix global Auto-Type when the database is locked[ [#3138](https://github.com/keepassxreboot/keepassxc/issues/3138)]
- Browser: Close popups when database is locked [[#3093](https://github.com/keepassxreboot/keepassxc/issues/3093)]
- Browser: Add tests [[#3016](https://github.com/keepassxreboot/keepassxc/issues/3016)]
- Browser: Don't create default group if custom group is enabled [[#3127](https://github.com/keepassxreboot/keepassxc/issues/3127)]
## 2.4.1 (2019-04-12)
- Fix database deletion when using unsafe saves to a different file system [#2889](https://github.com/keepassxreboot/keepassxc/issues/2889)
- Fix opening databases with legacy key files that contain '/' [#2872](https://github.com/keepassxreboot/keepassxc/issues/2872)
- Fix opening database files from the command line [#2919](https://github.com/keepassxreboot/keepassxc/issues/2919)
- Fix crash when editing master key [#2836](https://github.com/keepassxreboot/keepassxc/issues/2836)
- Fix multiple issues with apply button behavior [#2947](https://github.com/keepassxreboot/keepassxc/issues/2947)
- Fix issues on application startup (tab order, --pw-stdin, etc.) [#2830](https://github.com/keepassxreboot/keepassxc/issues/2830)
- Fix building without WITH_XC_KEESHARE
- Fix reference entry coloring on macOS dark mode [#2984](https://github.com/keepassxreboot/keepassxc/issues/2984)
- Hide window when performing entry auto-type on macOS [#2969](https://github.com/keepassxreboot/keepassxc/issues/2969)
- Improve UX of update checker; reduce checks to every 7 days [#2968](https://github.com/keepassxreboot/keepassxc/issues/2968)
- KeeShare improvements [[#2946](https://github.com/keepassxreboot/keepassxc/issues/2946), [#2978](https://github.com/keepassxreboot/keepassxc/issues/2978), [#2824](https://github.com/keepassxreboot/keepassxc/issues/2824)]
- Re-enable Ctrl+C to copy password from search box [#2947](https://github.com/keepassxreboot/keepassxc/issues/2947)
- Add KeePassXC-Browser integration for Brave browser [#2933](https://github.com/keepassxreboot/keepassxc/issues/2933)
- SSH Agent: Re-Add keys on database unlock [#2982](https://github.com/keepassxreboot/keepassxc/issues/2982)
- SSH Agent: Only remove keys on app exit if they are removed on lock [#2985](https://github.com/keepassxreboot/keepassxc/issues/2985)
- CLI: Add --no-password option [#2708](https://github.com/keepassxreboot/keepassxc/issues/2708)
- CLI: Improve database extraction to XML [#2698](https://github.com/keepassxreboot/keepassxc/issues/2698)
- CLI: Don't call mandb on build [#2774](https://github.com/keepassxreboot/keepassxc/issues/2774)
- CLI: Add debug info [#2714](https://github.com/keepassxreboot/keepassxc/issues/2714)
- Improve support for Snap theming [#2832](https://github.com/keepassxreboot/keepassxc/issues/2832)
- Add support for building on Haiku OS [#2859](https://github.com/keepassxreboot/keepassxc/issues/2859)
- Ctrl+PgDn now goes to the next tab and Ctrl+PgUp to the previous
- Fix compiling on GCC 5 / Xenial [#2990](https://github.com/keepassxreboot/keepassxc/issues/2990)
- Add .gitrev output to tarball for third-party builds [#2970](https://github.com/keepassxreboot/keepassxc/issues/2970)
- Add WITH_XC_UPDATECHECK compile flag to toggle the update checker [#2968](https://github.com/keepassxreboot/keepassxc/issues/2968)
## 2.4.0 (2019-03-19)
- New Database Wizard [#1952](https://github.com/keepassxreboot/keepassxc/issues/1952)
- Advanced Search [#1797](https://github.com/keepassxreboot/keepassxc/issues/1797)
- Automatic update checker [#2648](https://github.com/keepassxreboot/keepassxc/issues/2648)
- KeeShare database synchronization [[#2109](https://github.com/keepassxreboot/keepassxc/issues/2109), [#1992](https://github.com/keepassxreboot/keepassxc/issues/1992), [#2738](https://github.com/keepassxreboot/keepassxc/issues/2738), [#2742](https://github.com/keepassxreboot/keepassxc/issues/2742), [#2746](https://github.com/keepassxreboot/keepassxc/issues/2746), [#2739](https://github.com/keepassxreboot/keepassxc/issues/2739)]
- Improve favicon fetching; transition to Duck-Duck-Go [[#2795](https://github.com/keepassxreboot/keepassxc/issues/2795), [#2011](https://github.com/keepassxreboot/keepassxc/issues/2011), [#2439](https://github.com/keepassxreboot/keepassxc/issues/2439)]
- Remove KeePassHttp support [#1752](https://github.com/keepassxreboot/keepassxc/issues/1752)
- CLI: output info to stderr for easier scripting [#2558](https://github.com/keepassxreboot/keepassxc/issues/2558)
- CLI: Add --quiet option [#2507](https://github.com/keepassxreboot/keepassxc/issues/2507)
- CLI: Add create command [#2540](https://github.com/keepassxreboot/keepassxc/issues/2540)
- CLI: Add recursive listing of entries [#2345](https://github.com/keepassxreboot/keepassxc/issues/2345)
- CLI: Fix stdin/stdout encoding on Windows [#2425](https://github.com/keepassxreboot/keepassxc/issues/2425)
- SSH Agent: Support OpenSSH for Windows [#1994](https://github.com/keepassxreboot/keepassxc/issues/1994)
- macOS: TouchID Quick Unlock [#1851](https://github.com/keepassxreboot/keepassxc/issues/1851)
- macOS: Multiple improvements; include CLI in DMG [[#2165](https://github.com/keepassxreboot/keepassxc/issues/2165), [#2331](https://github.com/keepassxreboot/keepassxc/issues/2331), [#2583](https://github.com/keepassxreboot/keepassxc/issues/2583)]
- Linux: Prevent Klipper from storing secrets in clipboard [#1969](https://github.com/keepassxreboot/keepassxc/issues/1969)
- Linux: Use polling based file watching for NFS [#2171](https://github.com/keepassxreboot/keepassxc/issues/2171)
- Linux: Enable use of browser plugin in Snap build [#2802](https://github.com/keepassxreboot/keepassxc/issues/2802)
- TOTP QR Code Generator [#1167](https://github.com/keepassxreboot/keepassxc/issues/1167)
- High-DPI Scaling for 4k screens [#2404](https://github.com/keepassxreboot/keepassxc/issues/2404)
- Make keyboard shortcuts more consistent [#2431](https://github.com/keepassxreboot/keepassxc/issues/2431)
- Warn user if deleting referenced entries [#1744](https://github.com/keepassxreboot/keepassxc/issues/1744)
- Allow toolbar to be hidden and repositioned [[#1819](https://github.com/keepassxreboot/keepassxc/issues/1819), [#2357](https://github.com/keepassxreboot/keepassxc/issues/2357)]
- Increase max allowed database timeout to 12 hours [#2173](https://github.com/keepassxreboot/keepassxc/issues/2173)
- Password generator uses existing password length by default [#2318](https://github.com/keepassxreboot/keepassxc/issues/2318)
- Improve alert message box button labels [#2376](https://github.com/keepassxreboot/keepassxc/issues/2376)
- Show message when a database merge makes no changes [#2551](https://github.com/keepassxreboot/keepassxc/issues/2551)
- Browser Integration Enhancements [[#1497](https://github.com/keepassxreboot/keepassxc/issues/1497), [#2253](https://github.com/keepassxreboot/keepassxc/issues/2253), [#1904](https://github.com/keepassxreboot/keepassxc/issues/1904), [#2232](https://github.com/keepassxreboot/keepassxc/issues/2232), [#1850](https://github.com/keepassxreboot/keepassxc/issues/1850), [#2218](https://github.com/keepassxreboot/keepassxc/issues/2218), [#2391](https://github.com/keepassxreboot/keepassxc/issues/2391), [#2396](https://github.com/keepassxreboot/keepassxc/issues/2396), [#2542](https://github.com/keepassxreboot/keepassxc/issues/2542), [#2622](https://github.com/keepassxreboot/keepassxc/issues/2622), [#2637](https://github.com/keepassxreboot/keepassxc/issues/2637), [#2790](https://github.com/keepassxreboot/keepassxc/issues/2790)]
- Overall Code Improvements [[#2316](https://github.com/keepassxreboot/keepassxc/issues/2316), [#2284](https://github.com/keepassxreboot/keepassxc/issues/2284), [#2351](https://github.com/keepassxreboot/keepassxc/issues/2351), [#2402](https://github.com/keepassxreboot/keepassxc/issues/2402), [#2410](https://github.com/keepassxreboot/keepassxc/issues/2410), [#2419](https://github.com/keepassxreboot/keepassxc/issues/2419), [#2422](https://github.com/keepassxreboot/keepassxc/issues/2422), [#2443](https://github.com/keepassxreboot/keepassxc/issues/2443), [#2491](https://github.com/keepassxreboot/keepassxc/issues/2491), [#2506](https://github.com/keepassxreboot/keepassxc/issues/2506), [#2610](https://github.com/keepassxreboot/keepassxc/issues/2610), [#2667](https://github.com/keepassxreboot/keepassxc/issues/2667), [#2709](https://github.com/keepassxreboot/keepassxc/issues/2709), [#2731](https://github.com/keepassxreboot/keepassxc/issues/2731)]
## 2.3.4 (2018-08-21)
- Show all URL schemes in entry view [#1768](https://github.com/keepassxreboot/keepassxc/issues/1768)
- Disable merge when database is locked [#1975](https://github.com/keepassxreboot/keepassxc/issues/1975)
- Fix intermittent crashes with favorite icon downloads [#1980](https://github.com/keepassxreboot/keepassxc/issues/1980)
- Provide potential crash warning to Qt 5.5.x users [#2211](https://github.com/keepassxreboot/keepassxc/issues/2211)
- Disable apply button when creating new entry/group to prevent data loss [#2204](https://github.com/keepassxreboot/keepassxc/issues/2204)
- Allow for 12 hour timeout to lock idle database [#2173](https://github.com/keepassxreboot/keepassxc/issues/2173)
- Multiple SSH Agent fixes [[#1981](https://github.com/keepassxreboot/keepassxc/issues/1981), [#2117](https://github.com/keepassxreboot/keepassxc/issues/2117)]
- Multiple Browser Integration enhancements [[#1993](https://github.com/keepassxreboot/keepassxc/issues/1993), [#2003](https://github.com/keepassxreboot/keepassxc/issues/2003), [#2055](https://github.com/keepassxreboot/keepassxc/issues/2055), [#2116](https://github.com/keepassxreboot/keepassxc/issues/2116), [#2159](https://github.com/keepassxreboot/keepassxc/issues/2159), [#2174](https://github.com/keepassxreboot/keepassxc/issues/2174), [#2185](https://github.com/keepassxreboot/keepassxc/issues/2185)]
- Fix browser proxy application not closing properly [#2142](https://github.com/keepassxreboot/keepassxc/issues/2142)
- Add real names and Patreon supporters to about dialog [#2214](https://github.com/keepassxreboot/keepassxc/issues/2214)
- Add settings button to toolbar, Donate button, and Report a Bug button to help menu [#2214](https://github.com/keepassxreboot/keepassxc/issues/2214)
- Enhancements to release-tool to appsign intermediate build products [#2101](https://github.com/keepassxreboot/keepassxc/issues/2101)
## 2.3.3 (2018-05-09)
- Fix crash when browser integration is enabled [#1923](https://github.com/keepassxreboot/keepassxc/issues/1923)
## 2.3.2 (2018-05-07)
- Enable high entropy ASLR on Windows [#1747](https://github.com/keepassxreboot/keepassxc/issues/1747)
- Enhance favicon fetching [#1786](https://github.com/keepassxreboot/keepassxc/issues/1786)
- Fix crash on Windows due to autotype [#1691](https://github.com/keepassxreboot/keepassxc/issues/1691)
- Fix dark tray icon changing all icons [#1680](https://github.com/keepassxreboot/keepassxc/issues/1680)
- Fix --pw-stdin not using getPassword function [#1686](https://github.com/keepassxreboot/keepassxc/issues/1686)
- Fix placeholders being resolved in notes [#1907](https://github.com/keepassxreboot/keepassxc/issues/1907)
- Enable auto-type start delay to be configurable [#1908](https://github.com/keepassxreboot/keepassxc/issues/1908)
- Browser: Fix native messaging reply size [#1719](https://github.com/keepassxreboot/keepassxc/issues/1719)
- Browser: Increase maximum buffer size [#1720](https://github.com/keepassxreboot/keepassxc/issues/1720)
- Browser: Enhance usability and functionality [[#1810](https://github.com/keepassxreboot/keepassxc/issues/1810), [#1822](https://github.com/keepassxreboot/keepassxc/issues/1822), [#1830](https://github.com/keepassxreboot/keepassxc/issues/1830), [#1884](https://github.com/keepassxreboot/keepassxc/issues/1884), [#1906](https://github.com/keepassxreboot/keepassxc/issues/1906)]
- SSH Agent: Parse aes-256-cbc/ctr keys [#1682](https://github.com/keepassxreboot/keepassxc/issues/1682)
- SSH Agent: Enhance usability and functionality [[#1677](https://github.com/keepassxreboot/keepassxc/issues/1677), [#1679](https://github.com/keepassxreboot/keepassxc/issues/1679), [#1681](https://github.com/keepassxreboot/keepassxc/issues/1681), [#1787](https://github.com/keepassxreboot/keepassxc/issues/1787)]
## 2.3.1 (2018-03-06)
- Fix unnecessary automatic upgrade to KDBX 4.0 and prevent challenge-response key being stripped [#1568](https://github.com/keepassxreboot/keepassxc/issues/1568)
- Abort saving and show an error message when challenge-response fails [#1659](https://github.com/keepassxreboot/keepassxc/issues/1659)
- Support inner stream protection on all string attributes [#1646](https://github.com/keepassxreboot/keepassxc/issues/1646)
- Fix favicon downloads not finishing on some websites [#1657](https://github.com/keepassxreboot/keepassxc/issues/1657)
- Fix freeze due to invalid STDIN data [#1628](https://github.com/keepassxreboot/keepassxc/issues/1628)
- Correct issue with encrypted RSA SSH keys [#1587](https://github.com/keepassxreboot/keepassxc/issues/1587)
- Fix crash on macOS due to QTBUG-54832 [#1607](https://github.com/keepassxreboot/keepassxc/issues/1607)
- Show error message if ssh-agent communication fails [#1614](https://github.com/keepassxreboot/keepassxc/issues/1614)
- Fix --pw-stdin and filename parameters being ignored [#1608](https://github.com/keepassxreboot/keepassxc/issues/1608)
- Fix Auto-Type syntax check not allowing spaces and special characters [#1626](https://github.com/keepassxreboot/keepassxc/issues/1626)
- Fix reference placeholders in combination with Auto-Type [#1649](https://github.com/keepassxreboot/keepassxc/issues/1649)
- Fix qtbase translations not being loaded [#1611](https://github.com/keepassxreboot/keepassxc/issues/1611)
- Fix startup crash on Windows due to missing SVG libraries [#1662](https://github.com/keepassxreboot/keepassxc/issues/1662)
- Correct database tab order regression [#1610](https://github.com/keepassxreboot/keepassxc/issues/1610)
- Fix GCC 8 compilation error [#1612](https://github.com/keepassxreboot/keepassxc/issues/1612)
- Fix copying of advanced attributes on KDE [#1640](https://github.com/keepassxreboot/keepassxc/issues/1640)
- Fix member initialization of CategoryListWidgetDelegate [#1613](https://github.com/keepassxreboot/keepassxc/issues/1613)
- Fix inconsistent toolbar icon sizes and provide higher-quality icons [#1616](https://github.com/keepassxreboot/keepassxc/issues/1616)
- Improve preview panel geometry [#1609](https://github.com/keepassxreboot/keepassxc/issues/1609)
## 2.3.0 (2018-02-27)
- Add support for KDBX 4.0, Argon2 and ChaCha20 [[#148](https://github.com/keepassxreboot/keepassxc/issues/148), [#1179](https://github.com/keepassxreboot/keepassxc/issues/1179), [#1230](https://github.com/keepassxreboot/keepassxc/issues/1230), [#1494](https://github.com/keepassxreboot/keepassxc/issues/1494)]
- Add SSH Agent feature [[#1098](https://github.com/keepassxreboot/keepassxc/issues/1098), [#1450](https://github.com/keepassxreboot/keepassxc/issues/1450), [#1463](https://github.com/keepassxreboot/keepassxc/issues/1463)]
- Add preview panel with details of the selected entry [[#879](https://github.com/keepassxreboot/keepassxc/issues/879), [#1338](https://github.com/keepassxreboot/keepassxc/issues/1338)]
- Add more and configurable columns to entry table and allow copying of values by double click [#1305](https://github.com/keepassxreboot/keepassxc/issues/1305)
- Add KeePassXC-Browser API as a replacement for KeePassHTTP [#608](https://github.com/keepassxreboot/keepassxc/issues/608)
- Deprecate KeePassHTTP [#1392](https://github.com/keepassxreboot/keepassxc/issues/1392)
- Add support for Steam one-time passwords [#1206](https://github.com/keepassxreboot/keepassxc/issues/1206)
- Add support for multiple Auto-Type sequences for a single entry [#1390](https://github.com/keepassxreboot/keepassxc/issues/1390)
- Adjust YubiKey HMAC-SHA1 challenge-response key generation for KDBX 4.0 [#1060](https://github.com/keepassxreboot/keepassxc/issues/1060)
- Replace qHttp with cURL for website icon downloads [#1460](https://github.com/keepassxreboot/keepassxc/issues/1460)
- Remove lock file [#1231](https://github.com/keepassxreboot/keepassxc/issues/1231)
- Add option to create backup file before saving [#1385](https://github.com/keepassxreboot/keepassxc/issues/1385)
- Ask to save a generated password before closing the entry password generator [#1499](https://github.com/keepassxreboot/keepassxc/issues/1499)
- Resolve placeholders recursively [#1078](https://github.com/keepassxreboot/keepassxc/issues/1078)
- Add Auto-Type button to the toolbar [#1056](https://github.com/keepassxreboot/keepassxc/issues/1056)
- Improve window focus handling for Auto-Type dialogs [[#1204](https://github.com/keepassxreboot/keepassxc/issues/1204), [#1490](https://github.com/keepassxreboot/keepassxc/issues/1490)]
- Auto-Type dialog and password generator can now be exited with ESC [[#1252](https://github.com/keepassxreboot/keepassxc/issues/1252), [#1412](https://github.com/keepassxreboot/keepassxc/issues/1412)]
- Add optional dark tray icon [#1154](https://github.com/keepassxreboot/keepassxc/issues/1154)
- Add new "Unsafe saving" option to work around saving problems with file sync services [#1385](https://github.com/keepassxreboot/keepassxc/issues/1385)
- Add IBus support to AppImage and additional image formats to Windows builds [[#1534](https://github.com/keepassxreboot/keepassxc/issues/1534), [#1537](https://github.com/keepassxreboot/keepassxc/issues/1537)]
- Add diceware password generator to CLI [#1406](https://github.com/keepassxreboot/keepassxc/issues/1406)
- Add --key-file option to CLI [[#816](https://github.com/keepassxreboot/keepassxc/issues/816), [#824](https://github.com/keepassxreboot/keepassxc/issues/824)]
- Add DBus interface for opening and closing KeePassXC databases [#283](https://github.com/keepassxreboot/keepassxc/issues/283)
- Add KDBX compression options to database settings [#1419](https://github.com/keepassxreboot/keepassxc/issues/1419)
- Discourage use of old fixed-length key files in favor of arbitrary files [[#1326](https://github.com/keepassxreboot/keepassxc/issues/1326), [#1327](https://github.com/keepassxreboot/keepassxc/issues/1327)]
- Correct reference resolution in entry fields [#1486](https://github.com/keepassxreboot/keepassxc/issues/1486)
- Fix window state and recent databases not being remembered on exit [#1453](https://github.com/keepassxreboot/keepassxc/issues/1453)
- Correct history item generation when configuring TOTP for an entry [#1446](https://github.com/keepassxreboot/keepassxc/issues/1446)
- Correct multiple TOTP bugs [#1414](https://github.com/keepassxreboot/keepassxc/issues/1414)
- Automatic saving after every change is now a default [#279](https://github.com/keepassxreboot/keepassxc/issues/279)
- Allow creation of new entries during search [#1398](https://github.com/keepassxreboot/keepassxc/issues/1398)
- Correct menu issues on macOS [#1335](https://github.com/keepassxreboot/keepassxc/issues/1335)
- Allow compilation on OpenBSD [#1328](https://github.com/keepassxreboot/keepassxc/issues/1328)
- Improve entry attachments view [[#1139](https://github.com/keepassxreboot/keepassxc/issues/1139), [#1298](https://github.com/keepassxreboot/keepassxc/issues/1298)]
- Fix auto lock for Gnome and Xfce [[#910](https://github.com/keepassxreboot/keepassxc/issues/910), [#1249](https://github.com/keepassxreboot/keepassxc/issues/1249)]
- Don't remember key files in file dialogs when the setting is disabled [#1188](https://github.com/keepassxreboot/keepassxc/issues/1188)
- Improve database merging and conflict resolution [[#807](https://github.com/keepassxreboot/keepassxc/issues/807), [#1165](https://github.com/keepassxreboot/keepassxc/issues/1165)]
- Fix macOS pasteboard issues [#1202](https://github.com/keepassxreboot/keepassxc/issues/1202)
- Improve startup times on some platforms [#1205](https://github.com/keepassxreboot/keepassxc/issues/1205)
- Hide the notes field by default [#1124](https://github.com/keepassxreboot/keepassxc/issues/1124)
- Toggle main window by clicking tray icon with the middle mouse button [#992](https://github.com/keepassxreboot/keepassxc/issues/992)
- Fix custom icons not copied over when databases are merged [#1008](https://github.com/keepassxreboot/keepassxc/issues/1008)
- Allow use of DEL key to delete entries [#914](https://github.com/keepassxreboot/keepassxc/issues/914)
- Correct intermittent crash due to stale history items [#1527](https://github.com/keepassxreboot/keepassxc/issues/1527)
- Sanitize newline characters in title, username and URL fields [#1502](https://github.com/keepassxreboot/keepassxc/issues/1502)
- Reopen previously opened databases in correct order [#774](https://github.com/keepassxreboot/keepassxc/issues/774)
- Use system's zxcvbn library if available [#701](https://github.com/keepassxreboot/keepassxc/issues/701)
- Implement various i18n improvements [[#690](https://github.com/keepassxreboot/keepassxc/issues/690), [#875](https://github.com/keepassxreboot/keepassxc/issues/875), [#1436](https://github.com/keepassxreboot/keepassxc/issues/1436)]
## 2.2.4 (2017-12-13)
- Prevent database corruption when locked [#1219](https://github.com/keepassxreboot/keepassxc/issues/1219)
- Fixes apply button not saving new entries [#1141](https://github.com/keepassxreboot/keepassxc/issues/1141)
- Switch to Consolas font on Windows for password edit [#1229](https://github.com/keepassxreboot/keepassxc/issues/1229)
- Multiple fixes to AppImage deployment [[#1115](https://github.com/keepassxreboot/keepassxc/issues/1115), [#1228](https://github.com/keepassxreboot/keepassxc/issues/1228)]
- Fixes multiple memory leaks [#1213](https://github.com/keepassxreboot/keepassxc/issues/1213)
- Resize message close to 16x16 pixels [#1253](https://github.com/keepassxreboot/keepassxc/issues/1253)
## 2.2.2 (2017-10-22)
- Fixed entries with empty URLs being reported to KeePassHTTP clients [#1031](https://github.com/keepassxreboot/keepassxc/issues/1031)
- Fixed YubiKey detection and enabled CLI tool for AppImage binary [#1100](https://github.com/keepassxreboot/keepassxc/issues/1100)
- Added AppStream description [#1082](https://github.com/keepassxreboot/keepassxc/issues/1082)
- Improved TOTP compatibility and added new Base32 implementation [#1069](https://github.com/keepassxreboot/keepassxc/issues/1069)
- Fixed error handling when processing invalid cipher stream [#1099](https://github.com/keepassxreboot/keepassxc/issues/1099)
- Fixed double warning display when opening a database [#1037](https://github.com/keepassxreboot/keepassxc/issues/1037)
- Fixed unlocking databases with --pw-stdin [#1087](https://github.com/keepassxreboot/keepassxc/issues/1087)
- Added ability to override QT_PLUGIN_PATH environment variable for AppImages [#1079](https://github.com/keepassxreboot/keepassxc/issues/1079)
- Fixed transform seed not being regenerated when saving the database [#1068](https://github.com/keepassxreboot/keepassxc/issues/1068)
- Fixed only one YubiKey slot being polled [#1048](https://github.com/keepassxreboot/keepassxc/issues/1048)
- Corrected an issue with entry icons while merging [#1008](https://github.com/keepassxreboot/keepassxc/issues/1008)
- Corrected desktop and tray icons in Snap package [#1030](https://github.com/keepassxreboot/keepassxc/issues/1030)
- Fixed screen lock and Google fallback settings [#1029](https://github.com/keepassxreboot/keepassxc/issues/1029)
## 2.2.1 (2017-10-01)
- Corrected multiple snap issues [[#934](https://github.com/keepassxreboot/keepassxc/issues/934), [#1011](https://github.com/keepassxreboot/keepassxc/issues/1011)]
- Corrected multiple custom icon issues [[#708](https://github.com/keepassxreboot/keepassxc/issues/708), [#719](https://github.com/keepassxreboot/keepassxc/issues/719), [#994](https://github.com/keepassxreboot/keepassxc/issues/994)]
- Corrected multiple Yubikey issues [#880](https://github.com/keepassxreboot/keepassxc/issues/880)
- Fixed single instance preventing load on occasion [#997](https://github.com/keepassxreboot/keepassxc/issues/997)
- Keep entry history when merging databases [#970](https://github.com/keepassxreboot/keepassxc/issues/970)
- Prevent data loss if passwords were mismatched [#1007](https://github.com/keepassxreboot/keepassxc/issues/1007)
- Fixed crash after merge [#941](https://github.com/keepassxreboot/keepassxc/issues/941)
- Added configurable auto-type default delay [#703](https://github.com/keepassxreboot/keepassxc/issues/703)
- Unlock database dialog window comes to front [#663](https://github.com/keepassxreboot/keepassxc/issues/663)
- Translation and compiling fixes
## 2.2.0 (2017-06-23)
- Added YubiKey 2FA integration for unlocking databases [#127](https://github.com/keepassxreboot/keepassxc/issues/127)
- Added TOTP support [#519](https://github.com/keepassxreboot/keepassxc/issues/519)
- Added CSV import tool [[#146](https://github.com/keepassxreboot/keepassxc/issues/146), [#490](https://github.com/keepassxreboot/keepassxc/issues/490)]
- Added KeePassXC CLI tool [#254](https://github.com/keepassxreboot/keepassxc/issues/254)
- Added diceware password generator [#373](https://github.com/keepassxreboot/keepassxc/issues/373)
- Added support for entry references [[#370](https://github.com/keepassxreboot/keepassxc/issues/370), [#378](https://github.com/keepassxreboot/keepassxc/issues/378)]
- Added support for Twofish encryption [#167](https://github.com/keepassxreboot/keepassxc/issues/167)
- Enabled DEP and ASLR for in-memory protection [#371](https://github.com/keepassxreboot/keepassxc/issues/371)
- Enabled single instance mode [#510](https://github.com/keepassxreboot/keepassxc/issues/510)
- Enabled portable mode [#645](https://github.com/keepassxreboot/keepassxc/issues/645)
- Enabled database lock on screensaver and session lock [#545](https://github.com/keepassxreboot/keepassxc/issues/545)
- Redesigned welcome screen with common features and recent databases [#292](https://github.com/keepassxreboot/keepassxc/issues/292)
- Multiple updates to search behavior [[#168](https://github.com/keepassxreboot/keepassxc/issues/168), [#213](https://github.com/keepassxreboot/keepassxc/issues/213), [#374](https://github.com/keepassxreboot/keepassxc/issues/374), [#471](https://github.com/keepassxreboot/keepassxc/issues/471), [#603](https://github.com/keepassxreboot/keepassxc/issues/603), [#654](https://github.com/keepassxreboot/keepassxc/issues/654)]
- Added auto-type fields {CLEARFIELD}, {SPACE}, {{}, {}} [[#267](https://github.com/keepassxreboot/keepassxc/issues/267), [#427](https://github.com/keepassxreboot/keepassxc/issues/427), [#480](https://github.com/keepassxreboot/keepassxc/issues/480)]
- Fixed auto-type errors on Linux [#550](https://github.com/keepassxreboot/keepassxc/issues/550)
- Prompt user prior to executing a cmd:// URL [#235](https://github.com/keepassxreboot/keepassxc/issues/235)
- Entry attributes can be protected (hidden) [#220](https://github.com/keepassxreboot/keepassxc/issues/220)
- Added extended ascii to password generator [#538](https://github.com/keepassxreboot/keepassxc/issues/538)
- Added new database icon to toolbar [#289](https://github.com/keepassxreboot/keepassxc/issues/289)
- Added context menu entry to empty recycle bin in databases [#520](https://github.com/keepassxreboot/keepassxc/issues/520)
- Added "apply" button to entry and group edit windows [#624](https://github.com/keepassxreboot/keepassxc/issues/624)
- Added macOS tray icon and enabled minimize on close [#583](https://github.com/keepassxreboot/keepassxc/issues/583)
- Fixed issues with unclean shutdowns [[#170](https://github.com/keepassxreboot/keepassxc/issues/170), [#580](https://github.com/keepassxreboot/keepassxc/issues/580)]
- Changed keyboard shortcut to create new database to CTRL+SHIFT+N [#515](https://github.com/keepassxreboot/keepassxc/issues/515)
- Compare window title to entry URLs [#556](https://github.com/keepassxreboot/keepassxc/issues/556)
- Implemented inline error messages [#162](https://github.com/keepassxreboot/keepassxc/issues/162)
- Ignore group expansion and other minor changes when making database "dirty" [#464](https://github.com/keepassxreboot/keepassxc/issues/464)
- Updated license and copyright information on souce files [#632](https://github.com/keepassxreboot/keepassxc/issues/632)
- Added contributors list to about dialog [#629](https://github.com/keepassxreboot/keepassxc/issues/629)
## 2.1.4 (2017-04-09)
- Bumped KeePassHTTP version to 1.8.4.2
- KeePassHTTP confirmation window comes to foreground [#466](https://github.com/keepassxreboot/keepassxc/issues/466)
## 2.1.3 (2017-03-03)
- Fix possible overflow in zxcvbn library [#363](https://github.com/keepassxreboot/keepassxc/issues/363)
- Revert HiDPI setting to avoid problems on laptop screens [#332](https://github.com/keepassxreboot/keepassxc/issues/332)
- Set file meta properties in Windows executable [#330](https://github.com/keepassxreboot/keepassxc/issues/330)
- Suppress error message when auto-reloading a locked database [#345](https://github.com/keepassxreboot/keepassxc/issues/345)
- Improve usability of question dialog when database is already locked by a different instance [#346](https://github.com/keepassxreboot/keepassxc/issues/346)
- Fix compiler warnings in QHttp library [#351](https://github.com/keepassxreboot/keepassxc/issues/351)
- Use unified toolbar on Mac OS X [#361](https://github.com/keepassxreboot/keepassxc/issues/361)
- Fix an issue on X11 where the main window would be raised instead of closed on Alt+F4 [#362](https://github.com/keepassxreboot/keepassxc/issues/362)
## 2.1.2 (2017-02-17)
- Ask for save location when creating a new database [#302](https://github.com/keepassxreboot/keepassxc/issues/302)
- Remove Libmicrohttpd dependency to clean up the code and ensure better OS X compatibility [[#317](https://github.com/keepassxreboot/keepassxc/issues/317), [#265](https://github.com/keepassxreboot/keepassxc/issues/265)]
- Prevent Qt from degrading Wifi network performance on certain platforms [#318](https://github.com/keepassxreboot/keepassxc/issues/318)
- Visually refine user interface on OS X and other platforms [#299](https://github.com/keepassxreboot/keepassxc/issues/299)
- Remove unusable tray icon setting on OS X [#293](https://github.com/keepassxreboot/keepassxc/issues/293)
- Fix compositing glitches on Ubuntu and prevent flashing when minimizing to the tray at startup [#307](https://github.com/keepassxreboot/keepassxc/issues/307)
- Fix AppImage tray icon on Ubuntu [[#277](https://github.com/keepassxreboot/keepassxc/issues/277), [#273](https://github.com/keepassxreboot/keepassxc/issues/273)]
- Fix global menu disappearing after restoring KeePassXC from the tray on Ubuntu [#276](https://github.com/keepassxreboot/keepassxc/issues/276)
- Fix result order in entry search [#320](https://github.com/keepassxreboot/keepassxc/issues/320)
- Enable HiDPI scaling on supported platforms [#315](https://github.com/keepassxreboot/keepassxc/issues/315)
- Remove empty directories from installation target [#282](https://github.com/keepassxreboot/keepassxc/issues/282)
## 2.1.1 (2017-02-06)
- Enabled HTTP plugin build; plugin is disabled by default and limited to localhost [#147](https://github.com/keepassxreboot/keepassxc/issues/147)
- Escape HTML in dialog boxes [#247](https://github.com/keepassxreboot/keepassxc/issues/247)
- Corrected crashes in favicon download and password generator [[#233](https://github.com/keepassxreboot/keepassxc/issues/233), [#226](https://github.com/keepassxreboot/keepassxc/issues/226)]
- Increase font size of password meter [#228](https://github.com/keepassxreboot/keepassxc/issues/228)
- Fixed compatibility with Qt 5.8 [#211](https://github.com/keepassxreboot/keepassxc/issues/211)
- Use consistent button heights in password generator [#229](https://github.com/keepassxreboot/keepassxc/issues/229)
## 2.1.0 (2017-01-22)
- Show unlock dialog when using autotype on a closed database [[#10](https://github.com/keepassxreboot/keepassxc/issues/10), [#89](https://github.com/keepassxreboot/keepassxc/issues/89)]
- Show different tray icon when database is locked [[#37](https://github.com/keepassxreboot/keepassxc/issues/37), [#46](https://github.com/keepassxreboot/keepassxc/issues/46)]
- Support autotype on Windows and OS X [[#42](https://github.com/keepassxreboot/keepassxc/issues/42), [#60](https://github.com/keepassxreboot/keepassxc/issues/60), [#63](https://github.com/keepassxreboot/keepassxc/issues/63)]
- Add delay feature to autotype [[#76](https://github.com/keepassxreboot/keepassxc/issues/76), [#77](https://github.com/keepassxreboot/keepassxc/issues/77)]
- Add password strength meter [[#84](https://github.com/keepassxreboot/keepassxc/issues/84), [#92](https://github.com/keepassxreboot/keepassxc/issues/92)]
- Add option for automatically locking the database when minimizing
the window [#57](https://github.com/keepassxreboot/keepassxc/issues/57)
- Add feature to download favicons and use them as entry icons [#30](https://github.com/keepassxreboot/keepassxc/issues/30)
- Automatically reload and merge database when the file changed on
disk [[#22](https://github.com/keepassxreboot/keepassxc/issues/22), [#33](https://github.com/keepassxreboot/keepassxc/issues/33), [#93](https://github.com/keepassxreboot/keepassxc/issues/93)]
- Add tool for merging two databases [[#22](https://github.com/keepassxreboot/keepassxc/issues/22), [#47](https://github.com/keepassxreboot/keepassxc/issues/47), [#143](https://github.com/keepassxreboot/keepassxc/issues/143)]
- Add --pw-stdin commandline option to unlock the database by providing
a password on STDIN [#54](https://github.com/keepassxreboot/keepassxc/issues/54)
- Add utility script for reading the database password from KWallet [#55](https://github.com/keepassxreboot/keepassxc/issues/55)
- Fix some KeePassHTTP settings not being remembered [[#34](https://github.com/keepassxreboot/keepassxc/issues/34), [#65](https://github.com/keepassxreboot/keepassxc/issues/65)]
- Make search box persistent [[#15](https://github.com/keepassxreboot/keepassxc/issues/15), [#67](https://github.com/keepassxreboot/keepassxc/issues/67), [#157](https://github.com/keepassxreboot/keepassxc/issues/157)]
- Enhance search feature by scoping the search to selected group [[#16](https://github.com/keepassxreboot/keepassxc/issues/16), [#118](https://github.com/keepassxreboot/keepassxc/issues/118)]
- Improve interaction between search field and entry list [[#131](https://github.com/keepassxreboot/keepassxc/issues/131), [#141](https://github.com/keepassxreboot/keepassxc/issues/141)]
- Add stand-alone password-generator [[#18](https://github.com/keepassxreboot/keepassxc/issues/18), [#92](https://github.com/keepassxreboot/keepassxc/issues/92)]
- Don't require password repetition when password is visible [[#27](https://github.com/keepassxreboot/keepassxc/issues/27), [#92](https://github.com/keepassxreboot/keepassxc/issues/92)]
- Add support for entry attributes in autotype sequences [#107](https://github.com/keepassxreboot/keepassxc/issues/107)
- Always focus password field when opening the database unlock widget [[#116](https://github.com/keepassxreboot/keepassxc/issues/116), [#117](https://github.com/keepassxreboot/keepassxc/issues/117)]
- Fix compilation errors on various platforms [[#53](https://github.com/keepassxreboot/keepassxc/issues/53), [#126](https://github.com/keepassxreboot/keepassxc/issues/126), [#130](https://github.com/keepassxreboot/keepassxc/issues/130)]
- Restructure and improve kdbx-extract utility [#160](https://github.com/keepassxreboot/keepassxc/issues/160)
## 2.0.3 (2016-09-04)
- Improved error reporting when reading / writing databases fails. [[#450](https://github.com/keepassxreboot/keepassxc/issues/450), [#462](https://github.com/keepassxreboot/keepassxc/issues/462)]
- Display an error message when opening a custom icon fails.
- Detect custom icon format based on contents instead of the filename. [#512](https://github.com/keepassxreboot/keepassxc/issues/512)
- Keep symlink intact when saving databases. [#442](https://github.com/keepassxreboot/keepassxc/issues/442).
- Fix a crash when deleting parent group of recycle bin. [#520](https://github.com/keepassxreboot/keepassxc/issues/520)
- Display a confirm dialog before moving an entry to the recycle bin. [#447](https://github.com/keepassxreboot/keepassxc/issues/447)
- Repair UUIDs of inconsistent history items. [#130](https://github.com/keepassxreboot/keepassxc/issues/130)
- Only include top-level windows in auto-type window list when using gnome-shell.
- Update translations.
## 2.0.2 (2016-02-02)
- Fix regression in database writer that caused it to strip certain special
characters (characters from Unicode plane > 0).
- Fix bug in repair function that caused it to strip non-ASCII characters.
## 2.0.1 (2016-01-31)
- Flush temporary file before opening attachment. [#390](https://github.com/keepassxreboot/keepassxc/issues/390)
- Disable password generator when showing entry in history mode. [#422](https://github.com/keepassxreboot/keepassxc/issues/422)
- Strip invalid XML chars when writing databases. [#392](https://github.com/keepassxreboot/keepassxc/issues/392)
- Add repair function to fix databases with invalid XML chars. [#392](https://github.com/keepassxreboot/keepassxc/issues/392)
- Display custom icons scaled. [#322](https://github.com/keepassxreboot/keepassxc/issues/322)
- Allow opening databases that have no password and keyfile. [#391](https://github.com/keepassxreboot/keepassxc/issues/391)
- Fix crash when importing .kdb files with invalid icon ids. [#425](https://github.com/keepassxreboot/keepassxc/issues/425)
- Update translations.
## 2.0 (2015-12-06)
- Improve UI of the search edit.
- Clear clipboard when locking databases. [#342](https://github.com/keepassxreboot/keepassxc/issues/342)
- Enable Ctrl+M shortcut to minimize the window on all platforms. [#329](https://github.com/keepassxreboot/keepassxc/issues/329)
- Show a better message when trying to open an old database format. [#338](https://github.com/keepassxreboot/keepassxc/issues/338)
- Fix global auto-type behavior with some window managers.
- Show global auto-type window on the active desktop. [#359](https://github.com/keepassxreboot/keepassxc/issues/359)
- Disable systray on OS X. [#326](https://github.com/keepassxreboot/keepassxc/issues/326)
- Restore main window when clicking on the OS X docker icon. [#326](https://github.com/keepassxreboot/keepassxc/issues/326)
## 2.0 Beta 2 (2015-09-06)
- Fix crash when locking with search UI open [#309](https://github.com/keepassxreboot/keepassxc/issues/309)
- Fix file locking on Mac OS X [#327](https://github.com/keepassxreboot/keepassxc/issues/327)
- Set default extension when saving a database [[#79](https://github.com/keepassxreboot/keepassxc/issues/79), [#308](https://github.com/keepassxreboot/keepassxc/issues/308)]
## 2.0 Beta 1 (2015-07-18)
- Remember entry column sizes [#159](https://github.com/keepassxreboot/keepassxc/issues/159)
- Add translations
- Support opening attachments directly
- Support cmd:// URLs [#244](https://github.com/keepassxreboot/keepassxc/issues/244)
- Protect opened databases with a file lock [#18](https://github.com/keepassxreboot/keepassxc/issues/18)
- Export to csv files [#57](https://github.com/keepassxreboot/keepassxc/issues/57)
- Add optional tray icon [#153](https://github.com/keepassxreboot/keepassxc/issues/153)
- Allow setting the default auto-type sequence for groups [#175](https://github.com/keepassxreboot/keepassxc/issues/175)
- Make the kdbx parser more lenient
- Remove --password command line option [#285](https://github.com/keepassxreboot/keepassxc/issues/285)
## 2.0 Alpha 6 (2014-04-12)
- Add option to lock databases after user inactivity [#62](https://github.com/keepassxreboot/keepassxc/issues/62)
- Add compatibility with libgcrypt 1.6 [#129](https://github.com/keepassxreboot/keepassxc/issues/129)
- Display passwords in monospace font [#51](https://github.com/keepassxreboot/keepassxc/issues/51)
- Use an icon for the button that shows/masks passwords [#38](https://github.com/keepassxreboot/keepassxc/issues/38)
- Add an option to show passwords by default [#93](https://github.com/keepassxreboot/keepassxc/issues/93)
- Improve password generator design [#122](https://github.com/keepassxreboot/keepassxc/issues/122)
- On Linux link .kdbx files with KeePassX
- Remember window size [#154](https://github.com/keepassxreboot/keepassxc/issues/154)
- Disallow global auto-typing when the database is locked
## 2.0 Alpha 5 (2013-12-20)
- Support copying entries and groups using drag'n'drop [#74](https://github.com/keepassxreboot/keepassxc/issues/74)
- Open last used databases on startup [#36](https://github.com/keepassxreboot/keepassxc/issues/36)
- Made the kdbx file parser more robust
- Only edit entries on doubleclick (not single) or with enter key
- Allow removing multiple entries
- Added option to minimize window when copying data to clipboard
- Save password generator settings
- Fixed auto-type producing wrong chars in some keyboard configurations [#116](https://github.com/keepassxreboot/keepassxc/issues/116)
- Added some more actions to the toolbar
## 2.0 Alpha 4 (2013-03-29)
- Add random password generator [#52](https://github.com/keepassxreboot/keepassxc/issues/52)
- Merge the 'Description' tab into the 'Entry' tab [#59](https://github.com/keepassxreboot/keepassxc/issues/59)
- Fix crash when deleting history items [#56](https://github.com/keepassxreboot/keepassxc/issues/56)
- Fix crash on Mac OS X Mountain Lion during startup [#50](https://github.com/keepassxreboot/keepassxc/issues/50)
- Improved KeePassX application icon [#58](https://github.com/keepassxreboot/keepassxc/issues/58)
## 2.0 Alpha 3 (2012-10-27)
- Auto-Type on Linux / X11
- Database locking
- Fix database corruption when changing key transformation rounds [#34](https://github.com/keepassxreboot/keepassxc/issues/34)
- Verify header data of kdbx files
- Add menu entry to open URLs in the browser
- Add menu entry to copy an entry attribute to clipboard
## 2.0 Alpha 2 (2012-07-02)
- Import kdb (KeePass 1) files [#2](https://github.com/keepassxreboot/keepassxc/issues/2)
- Display history items [#23](https://github.com/keepassxreboot/keepassxc/issues/23)
- Implement history item limits [#16](https://github.com/keepassxreboot/keepassxc/issues/16)
- Group and entry icons can be set [#22](https://github.com/keepassxreboot/keepassxc/issues/22)
- Add keyboard shortcuts
- Search in databases [#24](https://github.com/keepassxreboot/keepassxc/issues/24)
- Sortable entry view
- Support building Mac OS X bundles
## 2.0 Alpha 1 (2012-05-07)
- First release.

View File

@ -27,6 +27,13 @@ string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# Use the Compiler Cache (ccache) if it is installed
# (install with: sudo apt get ccache)
find_program (CCACHE_FOUND ccache)
if (CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
endif (CCACHE_FOUND)
# Support Visual Studio Code # Support Visual Studio Code
include(CMakeToolsHelpers OPTIONAL) include(CMakeToolsHelpers OPTIONAL)
@ -50,6 +57,9 @@ option(WITH_XC_YUBIKEY "Include YubiKey support." OFF)
option(WITH_XC_SSHAGENT "Include SSH agent support." OFF) option(WITH_XC_SSHAGENT "Include SSH agent support." OFF)
option(WITH_XC_KEESHARE "Sharing integration with KeeShare (requires quazip5 for secure containers)" OFF) option(WITH_XC_KEESHARE "Sharing integration with KeeShare (requires quazip5 for secure containers)" OFF)
option(WITH_XC_UPDATECHECK "Include automatic update checks; disable for controlled distributions" ON) option(WITH_XC_UPDATECHECK "Include automatic update checks; disable for controlled distributions" ON)
if(UNIX AND NOT APPLE)
option(WITH_XC_FDOSECRETS "Implement freedesktop.org Secret Storage Spec server side API." OFF)
endif()
if(APPLE) if(APPLE)
option(WITH_XC_TOUCHID "Include TouchID support for macOS." OFF) option(WITH_XC_TOUCHID "Include TouchID support for macOS." OFF)
endif() endif()
@ -65,6 +75,9 @@ if(WITH_XC_ALL)
if(APPLE) if(APPLE)
set(WITH_XC_TOUCHID ON) set(WITH_XC_TOUCHID ON)
endif() endif()
if(UNIX AND NOT APPLE)
set(WITH_XC_FDOSECRETS ON)
endif()
endif() endif()
if(WITH_XC_SSHAGENT OR WITH_XC_KEESHARE) if(WITH_XC_SSHAGENT OR WITH_XC_KEESHARE)
@ -80,8 +93,8 @@ if(NOT WITH_XC_NETWORKING AND WITH_XC_UPDATECHECK)
endif() endif()
set(KEEPASSXC_VERSION_MAJOR "2") set(KEEPASSXC_VERSION_MAJOR "2")
set(KEEPASSXC_VERSION_MINOR "4") set(KEEPASSXC_VERSION_MINOR "5")
set(KEEPASSXC_VERSION_PATCH "3") set(KEEPASSXC_VERSION_PATCH "0")
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")
@ -160,15 +173,16 @@ if("${CMAKE_SIZEOF_VOID_P}" EQUAL "4")
set(IS_32BIT TRUE) set(IS_32BIT TRUE)
endif() endif()
set(CLANG_COMPILER_ID_REGEX "^(Apple)?[Cc]lang$")
if("${CMAKE_C_COMPILER}" MATCHES "clang$" if("${CMAKE_C_COMPILER}" MATCHES "clang$"
OR "${CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS}" MATCHES "__clang__" OR "${CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS}" MATCHES "__clang__"
OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR "${CMAKE_C_COMPILER_ID}" MATCHES ${CLANG_COMPILER_ID_REGEX})
set(CMAKE_COMPILER_IS_CLANG 1) set(CMAKE_COMPILER_IS_CLANG 1)
endif() endif()
if("${CMAKE_CXX_COMPILER}" MATCHES "clang(\\+\\+)?$" if("${CMAKE_CXX_COMPILER}" MATCHES "clang(\\+\\+)?$"
OR "${CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS}" MATCHES "__clang__" OR "${CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS}" MATCHES "__clang__"
OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") OR "${CMAKE_CXX_COMPILER_ID}" MATCHES ${CLANG_COMPILER_ID_REGEX})
set(CMAKE_COMPILER_IS_CLANGXX 1) set(CMAKE_COMPILER_IS_CLANGXX 1)
endif() endif()
@ -247,6 +261,15 @@ if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align")
endif() endif()
if(WITH_COVERAGE AND CMAKE_COMPILER_IS_CLANGXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping")
# then:
# $ llvm-profdata merge -sparse default.profraw -o default.profdata
# $ llvm-cov show ./tests/${the_test_binary} \
# -format=html -instr-profile=default.profdata -output-dir=./coverages \
# `find src -iname '*.h' -or -iname '*.cpp'`
endif()
if(CMAKE_COMPILER_IS_GNUCC) if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align")
endif() endif()
@ -270,7 +293,7 @@ if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9.
add_gcc_compiler_cxxflags("-fsized-deallocation") add_gcc_compiler_cxxflags("-fsized-deallocation")
endif() endif()
if(APPLE) if(APPLE AND CMAKE_COMPILER_IS_CLANGXX)
add_gcc_compiler_cxxflags("-stdlib=libc++") add_gcc_compiler_cxxflags("-stdlib=libc++")
endif() endif()

13
COPYING
View File

@ -1,5 +1,5 @@
KeePassXC - http://www.keepassxc.org/ KeePassXC - http://www.keepassxc.org/
Copyright (C) 2016-2017 KeePassXC Team <team@keepassxc.org> Copyright (C) 2016-2019 KeePassXC Team <team@keepassxc.org>
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -27,7 +27,7 @@ Copyright: 2010-2012, Felix Geyer <debfx@fobos.de>
2000-2008, Tom Sato <VEF00200@nifty.ne.jp> 2000-2008, Tom Sato <VEF00200@nifty.ne.jp>
2013, Laszlo Papp <lpapp@kde.org> 2013, Laszlo Papp <lpapp@kde.org>
2013, David Faure <faure@kde.org> 2013, David Faure <faure@kde.org>
2016-2018, KeePassXC Team <team@keepassxc.org> 2016-2019, KeePassXC Team <team@keepassxc.org>
License: GPL-2 or GPL-3 License: GPL-2 or GPL-3
Comment: The "KeePassXC Team" in every copyright notice is formed by the following people: Comment: The "KeePassXC Team" in every copyright notice is formed by the following people:
@ -160,11 +160,11 @@ Comment: based on Nuvola icon theme
Files: share/icons/application/*/actions/application-exit.png Files: share/icons/application/*/actions/application-exit.png
share/icons/application/*/actions/chronometer.png share/icons/application/*/actions/chronometer.png
share/icons/application/*/actions/configure.png share/icons/application/*/actions/configure.png
share/icons/application/*/actions/database-lock.png
share/icons/application/*/actions/dialog-close.png share/icons/application/*/actions/dialog-close.png
share/icons/application/*/actions/dialog-ok.png share/icons/application/*/actions/dialog-ok.png
share/icons/application/*/actions/document-close.png share/icons/application/*/actions/document-close.png
share/icons/application/*/actions/document-edit.png share/icons/application/*/actions/document-edit.png
share/icons/application/*/actions/document-encrypt.png
share/icons/application/*/actions/document-new.png share/icons/application/*/actions/document-new.png
share/icons/application/*/actions/document-open.png share/icons/application/*/actions/document-open.png
share/icons/application/*/actions/document-properties.png share/icons/application/*/actions/document-properties.png
@ -241,3 +241,10 @@ License: LGPL-2.1
Files: share/macosx/dmg-background.tiff Files: share/macosx/dmg-background.tiff
Copyright: 2008-2014, Andrey Tarantsov Copyright: 2008-2014, Andrey Tarantsov
License: MIT License: MIT
Files: share/icons/application/scalable/apps/freedesktop.svg
Copyright: GPL-2+
Comment: from Freedesktop.org website
Files: share/icons/application/32x32/actions/statistics.png
Copyright: Icon made by Freepik from https://www.flaticon.com/free-icon/bars-chart_265733

View File

@ -27,6 +27,8 @@ The following libraries are required:
* libxi, libxtst, qtx11extras (optional for auto-type on X11) * libxi, libxtst, qtx11extras (optional for auto-type on X11)
* libsodium (>= 1.0.12) * libsodium (>= 1.0.12)
* libargon2 * libargon2
* qrencode
* yubikey ykpers (optional to support YubiKey)
Prepare the Building Environment Prepare the Building Environment
================================ ================================
@ -100,6 +102,7 @@ These steps place the compiled KeePassXC binary inside the `./build/src/` direct
-DWITH_XC_NETWORKING=[ON|OFF] Enable/Disable Networking support (e.g., favicon downloading) (default: OFF) -DWITH_XC_NETWORKING=[ON|OFF] Enable/Disable Networking support (e.g., favicon downloading) (default: OFF)
-DWITH_XC_SSHAGENT=[ON|OFF] Enable/Disable SSHAgent support (default: OFF) -DWITH_XC_SSHAGENT=[ON|OFF] Enable/Disable SSHAgent support (default: OFF)
-DWITH_XC_TOUCHID=[ON|OFF] (macOS Only) Enable/Disable Touch ID unlock (default:OFF) -DWITH_XC_TOUCHID=[ON|OFF] (macOS Only) Enable/Disable Touch ID unlock (default:OFF)
-DWITH_XC_FDOSECRETS=[ON|OFF] (Linux Only) Enable/Disable Freedesktop.org Secrets Service support (default:OFF)
-DWITH_XC_KEESHARE=[ON|OFF] Enable/Disable KeeShare group synchronization extension (default: OFF) -DWITH_XC_KEESHARE=[ON|OFF] Enable/Disable KeeShare group synchronization extension (default: OFF)
-DWITH_XC_KEESHARE_SECURE=[ON|OFF] Enable/Disable KeeShare signed containers, requires libquazip5 (default: OFF) -DWITH_XC_KEESHARE_SECURE=[ON|OFF] Enable/Disable KeeShare signed containers, requires libquazip5 (default: OFF)
-DWITH_XC_ALL=[ON|OFF] Enable/Disable compiling all plugins above (default: OFF) -DWITH_XC_ALL=[ON|OFF] Enable/Disable compiling all plugins above (default: OFF)

View File

@ -22,7 +22,7 @@ so please check out your distribution's package list to see if KeePassXC is avai
- YubiKey challenge-response support - YubiKey challenge-response support
- TOTP generation - TOTP generation
- CSV import - CSV import
- Command line interface - A [Command Line Interface (keepassxc-cli)](./share/docs/man/keepassxc-cli.1)
- DEP and ASLR hardening - DEP and ASLR hardening
- Stand-alone password and passphrase generator - Stand-alone password and passphrase generator
- Password strength meter - Password strength meter
@ -33,7 +33,7 @@ so please check out your distribution's package list to see if KeePassXC is avai
- 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
For a full list of features and changes, read the [CHANGELOG](CHANGELOG) document. For a full list of features and changes, read the [CHANGELOG](CHANGELOG.md) document.
For a full list of keyboard shortcuts, see [KEYBINDS](./docs/KEYBINDS.md) For a full list of keyboard shortcuts, see [KEYBINDS](./docs/KEYBINDS.md)
## Building KeePassXC ## Building KeePassXC

50
cmake/FindReadline.cmake Normal file
View File

@ -0,0 +1,50 @@
# Code copied from sethhall@github
#
# - Try to find readline include dirs and libraries
#
# Usage of this module as follows:
#
# find_package(Readline)
#
# Variables used by this module, they can change the default behaviour and need
# to be set before calling find_package:
#
# Readline_ROOT_DIR Set this variable to the root installation of
# readline if the module has problems finding the
# proper installation path.
#
# Variables defined by this module:
#
# READLINE_FOUND System has readline, include and lib dirs found
# Readline_INCLUDE_DIR The readline include directories.
# Readline_LIBRARY The readline library.
find_path(Readline_ROOT_DIR
NAMES include/readline/readline.h
)
find_path(Readline_INCLUDE_DIR
NAMES readline/readline.h
HINTS ${Readline_ROOT_DIR}/include
)
find_library(Readline_LIBRARY
NAMES readline
HINTS ${Readline_ROOT_DIR}/lib
)
if(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
set(READLINE_FOUND TRUE)
else(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
find_library(Readline_LIBRARY NAMES readline)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Readline DEFAULT_MSG Readline_INCLUDE_DIR Readline_LIBRARY )
mark_as_advanced(Readline_INCLUDE_DIR Readline_LIBRARY)
endif(Readline_INCLUDE_DIR AND Readline_LIBRARY AND Ncurses_LIBRARY)
mark_as_advanced(
Readline_ROOT_DIR
Readline_INCLUDE_DIR
Readline_LIBRARY
)

View File

@ -1,188 +0,0 @@
# - Define GNU standard installation directories
# Provides install directory variables as defined for GNU software:
# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
# Inclusion of this module defines the following variables:
# CMAKE_INSTALL_<dir> - destination for files of a given type
# CMAKE_INSTALL_FULL_<dir> - corresponding absolute path
# where <dir> is one of:
# BINDIR - user executables (bin)
# SBINDIR - system admin executables (sbin)
# LIBEXECDIR - program executables (libexec)
# SYSCONFDIR - read-only single-machine data (etc)
# SHAREDSTATEDIR - modifiable architecture-independent data (com)
# LOCALSTATEDIR - modifiable single-machine data (var)
# LIBDIR - object code libraries (lib or lib64 or lib/<multiarch-tuple> on Debian)
# INCLUDEDIR - C header files (include)
# OLDINCLUDEDIR - C header files for non-gcc (/usr/include)
# DATAROOTDIR - read-only architecture-independent data root (share)
# DATADIR - read-only architecture-independent data (DATAROOTDIR)
# INFODIR - info documentation (DATAROOTDIR/info)
# LOCALEDIR - locale-dependent data (DATAROOTDIR/locale)
# MANDIR - man documentation (DATAROOTDIR/man)
# DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME)
# Each CMAKE_INSTALL_<dir> value may be passed to the DESTINATION options of
# install() commands for the corresponding file type. If the includer does
# not define a value the above-shown default will be used and the value will
# appear in the cache for editing by the user.
# Each CMAKE_INSTALL_FULL_<dir> value contains an absolute path constructed
# from the corresponding destination by prepending (if necessary) the value
# of CMAKE_INSTALL_PREFIX.
#=============================================================================
# Copyright 2011 Nikita Krupen'ko <krnekit@gmail.com>
# Copyright 2011 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# Installation directories
#
if(NOT DEFINED CMAKE_INSTALL_BINDIR)
set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SBINDIR)
set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR)
set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR)
set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR)
set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR)
set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(_LIBDIR_DEFAULT "lib")
# Override this default 'lib' with 'lib64' iff:
# - we are on Linux system but NOT cross-compiling
# - we are NOT on debian
# - we are on a 64 bits system
# reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
# For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if
# CMAKE_LIBRARY_ARCHITECTURE is set (which contains e.g. "i386-linux-gnu"
# See http://wiki.debian.org/Multiarch
if((CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU")
AND NOT CMAKE_CROSSCOMPILING)
if (EXISTS "/etc/debian_version") # is this a debian system ?
if(CMAKE_LIBRARY_ARCHITECTURE)
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
endif()
else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
message(AUTHOR_WARNING
"Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
"Please enable at least one language before including GNUInstallDirs.")
else()
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(_LIBDIR_DEFAULT "lib64")
endif()
endif()
endif()
endif()
set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})")
endif()
if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)")
endif()
if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR)
set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)")
endif()
if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR)
set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)")
endif()
#-----------------------------------------------------------------------------
# Values whose defaults are relative to DATAROOTDIR. Store empty values in
# the cache and store the defaults in local variables if the cache values are
# not set explicitly. This auto-updates the defaults as DATAROOTDIR changes.
if(NOT CMAKE_INSTALL_DATADIR)
set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)")
set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}")
endif()
if(NOT CMAKE_INSTALL_INFODIR)
set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)")
set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info")
endif()
if(NOT CMAKE_INSTALL_LOCALEDIR)
set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)")
set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale")
endif()
if(NOT CMAKE_INSTALL_MANDIR)
set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)")
set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man")
endif()
if(NOT CMAKE_INSTALL_DOCDIR)
set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}")
endif()
#-----------------------------------------------------------------------------
mark_as_advanced(
CMAKE_INSTALL_BINDIR
CMAKE_INSTALL_SBINDIR
CMAKE_INSTALL_LIBEXECDIR
CMAKE_INSTALL_SYSCONFDIR
CMAKE_INSTALL_SHAREDSTATEDIR
CMAKE_INSTALL_LOCALSTATEDIR
CMAKE_INSTALL_LIBDIR
CMAKE_INSTALL_INCLUDEDIR
CMAKE_INSTALL_OLDINCLUDEDIR
CMAKE_INSTALL_DATAROOTDIR
CMAKE_INSTALL_DATADIR
CMAKE_INSTALL_INFODIR
CMAKE_INSTALL_LOCALEDIR
CMAKE_INSTALL_MANDIR
CMAKE_INSTALL_DOCDIR
)
# Result directories
#
foreach(dir
BINDIR
SBINDIR
LIBEXECDIR
SYSCONFDIR
SHAREDSTATEDIR
LOCALSTATEDIR
LIBDIR
INCLUDEDIR
OLDINCLUDEDIR
DATAROOTDIR
DATADIR
INFODIR
LOCALEDIR
MANDIR
DOCDIR
)
if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
else()
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
endif()
endforeach()

View File

@ -28,6 +28,7 @@ Toggle Passwords Hidden | Ctrl + Shift + C
Toggle Usernames Hidden | Ctrl + Shift + B Toggle Usernames Hidden | Ctrl + Shift + B
Focus Search | Ctrl + F Focus Search | Ctrl + F
Clear Search | ESC Clear Search | ESC
Show Keyboard Shortcuts | Ctrl + /

View File

@ -1,51 +1,47 @@
# Quick Start for KeePassXC # Quick Start for KeePassXC
This procedure gets KeePassXC running on your computer with browser integration, This procedure gets KeePassXC running on your computer with browser integration, using the pre-built binaries available for [download](https://keepassxc.org/download) from [KeePassXC site](https://keepassxc.org).
using the pre-built binaries available for [download](https://keepassxc.org/download)
from [KeePassXC site](https://keepassxc.org).
**TL;DR** KeePassXC saves your passwords securely. **TL;DR** KeePassXC saves your passwords securely.
When you double-click a URL in KeePassXC, it launches your default browser to that URL. When you double-click a URL in KeePassXC, it launches your default browser to that URL.
With browser integration configured, KeePassXC automatically enters With browser integration configured, KeePassXC automatically enters username/password credentials into web page fields.
username/password credentials into web page fields.
## Installing and Starting KeePassXC ## Installing and Starting KeePassXC
* [Download the native installer](https://keepassxc.org/download) and install 1. [Download the native installer](https://keepassxc.org/download) and install KeePassXC for your Windows, macOS, or Linux computer in the usual way for your platform.
KeePassXC for your Windows, macOS, or Linux computer in the usual way for your platform. 1. Open the KeePassXC application.
* Open the KeePassXC application. 1. Create a new database and give it a master key that's used to unlock the database file.
* Create a new database and give it a master key that's used to unlock the database file. This database holds entries (usernames, passwords, account numbers, notes) for all your websites, programs, etc.
This database holds entries (usernames, passwords, account numbers, notes) 1. Create a few entries - enter the username, password, URL, and optionally notes about the entry.
for all your websites, programs, etc. 1. KeePassXC securely stores those entries in the database.
* Create a few entries - enter the username, password, URL, and optionally notes about the entry.
* KeePassXC securely stores those entries in the database.
## Setting up Browser Integration with KeePassXC ## Setting up Browser Integration with KeePassXC
* *Within KeePassXC*, go to **Tools->Settings** (on macOS, go to **KeePassXC->Preferences**.) 1. *Within KeePassXC*, go to **Tools &rarr; Settings** (on macOS, go to **KeePassXC &rarr; Preferences**).
* In **Browser Integration**, check **Enable KeePassXC browser integration** 1. In **Browser Integration**, check **Enable KeePassXC browser integration**.
* Right below that, click the checkbox for the browser(s) you use 1. Right below that, click the checkbox for the browser(s) you use.
Leave the other options at their defaults. Leave the other options at their defaults.
* *In your default web browser,* install the KeePassXC Browser extension/add-on. Instructions for [Firefox or Tor Browser](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) or [Chrome](https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk) 1. *In your default web browser,* install the KeePassXC Browser extension/add-on. Instructions for [Firefox or Tor Browser](https://addons.mozilla.org/firefox/addon/keepassxc-browser/) or [Chrome or Chromium](https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk).
* Click the KeePassXC icon in the upper-right corner. You'll see the dialog below. 1. Click the KeePassXC icon in the upper-right corner. You'll see the dialog below.
* Click the blue Connect button to make the browser extension connect to the KeePassXC application. 1. Click the blue Connect button to make the browser extension connect to the KeePassXC application.
<img src="./KeePassHTTP/KeePassXC-Connect.png" height="200" alt="KeePassXC Connect dialog">
* *Switch back to KeePassXC.* You'll see a dialog (below) indicating that a request to connect has arrived. &nbsp;<img src="./KeePassHTTP/KeePassXC-Connect.png" height="200" alt="KeePassXC Connect Dialog">
* Give the connection a name (perhaps *Keepass-Browsername*, any unique name will suffice) and click OK to accept it.
* This one-time operation connects KeePassXC and your browser. 7. *Switch back to KeePassXC.* You'll see a dialog (below) indicating that a request to connect has arrived.
<img src="./KeePassHTTP/KeePassXC-Accept-Button.png" height="200" alt="KeePassXC accept connection dialog"> 7. Give the connection a name (perhaps *Keepass-Browsername*, any unique name will suffice) and click OK to accept it.
7. This one-time operation connects KeePassXC and your browser.
<img src="./KeePassHTTP/KeePassXC-Accept-Button.png" height="200" alt="KeePassXC Accept Connection Dialog">
## Using Browser Integration ## Using Browser Integration
* *Within KeePassXC,* double-click the URL of an entry, 1. *Within KeePassXC,* double-click the URL of an entry, or select it and type Ctrl+U (Cmd+U on macOS).
or select it and type Ctrl+U (Cmd+U on macOS). 1. Your browser opens to that URL.
* Your browser opens to that URL. 1. If there are username/password fields on that page, you will see the dialog below.
* If there are username/password fields on that page, you will see the dialog below.
Click *Allow* to confirm that KeePassXC may access the credentials to auto-fill the fields. Click *Allow* to confirm that KeePassXC may access the credentials to auto-fill the fields.
* Check *Remember this decision* to allow this each time you visit the page. 1. Check *Remember this decision* to allow this each time you visit the page.
<img src="./KeePassHTTP/KeePassXC-Confirm.png" height="200" alt="KeePassCX Confirm Access dialog">
<img src="./KeePassHTTP/KeePassXC-Confirm.png" height="200" alt="KeePassCX Confirm Access Dialog">
## Using Sharing ## Using Sharing
@ -55,24 +51,24 @@ Sharing allows you to share a subset of your credentials with others and vice ve
To use sharing, you need to enable for the application. To use sharing, you need to enable for the application.
1. Go to Tools &rarr; Settings 1. Go to Tools &rarr; Settings.
2. Select the category KeeShare 1. Select the category KeeShare.
3. Check _Allow import_ if you want to import shared credentials 1. Check _Allow import_ if you want to import shared credentials.
4. Check _Allow export_ if you want to share credentials 1. Check _Allow export_ if you want to share credentials.
To make sure that your data is valid when im imported by another client, please _generate_ (or _import_) a public/private key pair and enter your _signer_ name. This way your client may verify that the imported data is valid. When Importing, you'll see the known sources with names and fingerprint in the list at the bottom. This is the place to _trust_ or _untrust_ signers. It is only possible to trust someone on application level. To make sure that your data is valid when imported by another client, please _generate_ (or _import_) a public/private key pair and enter your _signer_ name. This way your client may verify that the imported data is valid. When Importing, you'll see the known sources with names and fingerprint in the list at the bottom. This is the place to _trust_ or _untrust_ signers. It is only possible to trust someone on application level.
<img src="./KeeShare/AppSettings.png" height="600" width="800" alt="KeeShare Application Settings"> <img src="./KeeShare/AppSettings.png" height="600" width="800" alt="KeeShare Application Settings">
### Sharing Credentials ### Sharing Credentials
If you checked _Allow export_ in the Sharing settings you now are good to go to share some passwords with others. Sharing always is defined on a group. If you enable sharing on a group, every entry under this group or it's children is shared. If you enable sharing on the root node, **every password** inside your database gets shared! If you checked _Allow export_ in the Sharing settings you now are good to go to share some passwords with others. Sharing always is defined on a group. If you enable sharing on a group, every entry under this group or its children is shared. If you enable sharing on the root node, **every password** inside your database gets shared!
1. Open the edit sheet on a group you want to share 1. Open the edit sheet on a group you want to share.
1. Select the sharing section 1. Select the sharing section.
1. Choose _Export to path_ as the sharing method 1. Choose _Export to path_ as the sharing method.
1. Choose a path to store the shared credentials to 1. Choose a path to store the shared credentials to.
1. Generate a password for this share container 1. Generate a password for this share container.
The export file will not be generated automatically. Instead, each time the database is saved, the file gets written (so please deactivate the autosafe feature). If an old file is present, the old file will be overwritten! The file should be written to a location that is accessible by others. An easy setup is a network share or storing the file inside the cloud. The export file will not be generated automatically. Instead, each time the database is saved, the file gets written (so please deactivate the autosafe feature). If an old file is present, the old file will be overwritten! The file should be written to a location that is accessible by others. An easy setup is a network share or storing the file inside the cloud.
@ -82,12 +78,12 @@ The export file will not be generated automatically. Instead, each time the data
Checking _Allow import_ in the Sharing settings of the database enables you to receive credentials from others. KeePass will watch sharing sources and import any changes immediately into your database using the synchronization feature. Checking _Allow import_ in the Sharing settings of the database enables you to receive credentials from others. KeePass will watch sharing sources and import any changes immediately into your database using the synchronization feature.
1. Create a group for import 1. Create a group for import.
1. Open the edit sheet on that group 1. Open the edit sheet on that group.
1. Select the sharing section 1. Select the sharing section.
1. Choose _Import from path_ as the sharing method 1. Choose _Import from path_ as the sharing method.
1. Choose a share container that is shared with you 1. Choose a share container that is shared with you.
1. Enter the password for the shared container 1. Enter the password for the shared container.
KeeShare observes the container for changes and merges them into your database when necessary. Importing merges in time order, so older data is moved to the history, which should have a sufficient size to prevent loss of needed data. KeeShare observes the container for changes and merges them into your database when necessary. Importing merges in time order, so older data is moved to the history, which should have a sufficient size to prevent loss of needed data.
@ -99,11 +95,11 @@ Please note, that the import currently is not restricted to the configured group
Instead of using different groups for sharing and importing you can use a single group that acts as both. This way you can synchronize a number of credentials easily across many users without a lot of hassle. Instead of using different groups for sharing and importing you can use a single group that acts as both. This way you can synchronize a number of credentials easily across many users without a lot of hassle.
1. Open the edit sheet on a group you want to synchronize 1. Open the edit sheet on a group you want to synchronize.
1. Select the sharing section 1. Select the sharing section.
1. Choose _Synchronize with path_ as the sharing method 1. Choose _Synchronize with path_ as the sharing method.
1. Choose a database that you want to use a synchronization file 1. Choose a database that you want to use a synchronization file.
1. Enter the password for the database 1. Enter the password for the database.
<img src="./KeeShare/GroupSettings_Sync.png" height="600" width="800" alt="KeeShare Group Synchronization Settings"> <img src="./KeeShare/GroupSettings_Sync.png" height="600" width="800" alt="KeeShare Group Synchronization Settings">
@ -111,14 +107,14 @@ Instead of using different groups for sharing and importing you can use a single
In case you don't want to share (import or export) some credentials, it is possible to you can In case you don't want to share (import or export) some credentials, it is possible to you can
* use the application settings and uncheck the options or * use the application settings and uncheck the options or
* instead of selecting _Import from path_, _Export to path_ or _Synchronize with path_ you'll select _Inactive_ while leaving the path and the password untouched * instead of selecting _Import from path_, _Export to path_ or _Synchronize with path_ you'll select _Inactive_ while leaving the path and the password untouched.
### Sharing overview ### Sharing overview
There is a simple overview of shared groups to keep track of your data. There is a simple overview of shared groups to keep track of your data.
1. Open the Database Settings 1. Open the Database Settings.
1. Select the KeeShare category 1. Select the KeeShare category.
<img src="./KeeShare/DatabaseSettings.png" height="600" width="800" alt="KeeShare Group Sharing Ovewview"> <img src="./KeeShare/DatabaseSettings.png" height="600" width="800" alt="KeeShare Group Sharing Ovewview">
@ -128,4 +124,14 @@ Sharing relies on the combination of file exports and imports as well as the syn
KeeShare uses a custom certification mechanism to ensure that the source of the data is the expected one. This ensures that the data was exported by the signer but it is not possible to detect if someone replaced the data with an older version from a valid signer. To prevent this, the container could be placed at a location which is only writeable for valid signers. KeeShare uses a custom certification mechanism to ensure that the source of the data is the expected one. This ensures that the data was exported by the signer but it is not possible to detect if someone replaced the data with an older version from a valid signer. To prevent this, the container could be placed at a location which is only writeable for valid signers.
## Using Auto Open
The Auto Open feature automatically loads and unlocks additional databases when you unlock your main database.
In order to use this functionnality, do the following:
1. Create a group called **AutoOpen** at the root of your main database.
1. In this group, create a new entry for each database that should be opened automatically:
* Put the *password of the database* in the **Password** field
* Put the *path to the database's file* in the **URL** field* (it can be formatted either as **file://**, a **/path/to/the/file** form, or a relative file path.)
* If the extra database requires a keyfile to be unlocked, put the *path to the keyfile* in the **Username** field. The path options are the same as for the database's file in the URL field.
1. The next time you unlock your database these databases will be opened and unlocked automatically.

View File

@ -231,7 +231,7 @@ checkOutputDirDoesNotExist() {
} }
checkGitRepository() { checkGitRepository() {
if [ ! -d .git ] || [ ! -f CHANGELOG ]; then if [ ! -d .git ] || [ ! -f CHANGELOG.md ]; then
exitError "Source directory is not a valid Git repository!" exitError "Source directory is not a valid Git repository!"
fi fi
} }
@ -287,13 +287,13 @@ checkVersionInCMake() {
} }
checkChangeLog() { checkChangeLog() {
if [ ! -f CHANGELOG ]; then if [ ! -f CHANGELOG.md ]; then
exitError "No CHANGELOG file found!" exitError "No CHANGELOG file found!"
fi fi
grep -qPzo "${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n=+\n" CHANGELOG grep -qPzo "## ${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n" CHANGELOG.md
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
exitError "'CHANGELOG' has not been updated to the '${RELEASE_NAME}' release!" exitError "'CHANGELOG.md' has not been updated to the '${RELEASE_NAME}' release!"
fi fi
} }
@ -498,8 +498,8 @@ merge() {
fi fi
fi fi
CHANGELOG=$(grep -Pzo "(?<=${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n)=+\n\n?(?:.|\n)+?\n(?=\n)" \ CHANGELOG=$(grep -Pzo "(?<=${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n\n)\n?(?:.|\n)+?\n(?=## )" CHANGELOG.md \
CHANGELOG | grep -Pzo '(?<=\n\n)(.|\n)+' | tr -d \\0) | sed 's/^### //' | tr -d \\0)
COMMIT_MSG="Release ${RELEASE_NAME}" COMMIT_MSG="Release ${RELEASE_NAME}"
logInfo "Checking out target branch '${TARGET_BRANCH}'..." logInfo "Checking out target branch '${TARGET_BRANCH}'..."
@ -699,6 +699,10 @@ EOF
appimage_name="KeePassXC-${RELEASE_NAME}-x86_64.AppImage" appimage_name="KeePassXC-${RELEASE_NAME}-x86_64.AppImage"
fi fi
# Allow appimagetool to insert version information into the AppImage to allow
# desktop integration tools to display that in app launchers
export VERSION="${RELEASE_NAME}"
# Run appimagetool to package (and possibly sign) AppImage # Run appimagetool to package (and possibly sign) AppImage
# --no-appstream is required, since it may crash on newer systems # --no-appstream is required, since it may crash on newer systems
# see: https://github.com/AppImage/AppImageKit/issues/856 # see: https://github.com/AppImage/AppImageKit/issues/856

View File

@ -39,6 +39,8 @@ if(APPLE)
install(FILES macosx/keepassxc.icns DESTINATION ${DATA_INSTALL_DIR}) install(FILES macosx/keepassxc.icns DESTINATION ${DATA_INSTALL_DIR})
endif() endif()
install(DIRECTORY docs/ DESTINATION ${DATA_INSTALL_DIR}/docs FILES_MATCHING PATTERN "*.pdf")
install(DIRECTORY wizard/ DESTINATION ${DATA_INSTALL_DIR}/wizard FILES_MATCHING PATTERN "*.png") install(DIRECTORY wizard/ DESTINATION ${DATA_INSTALL_DIR}/wizard FILES_MATCHING PATTERN "*.png")
install(DIRECTORY icons/application/ DESTINATION ${DATA_INSTALL_DIR}/icons/application install(DIRECTORY icons/application/ DESTINATION ${DATA_INSTALL_DIR}/icons/application

BIN
share/demo.kdbx Normal file

Binary file not shown.

1
share/demo.key Normal file
View File

@ -0,0 +1 @@
secret

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,251 @@
.TH KEEPASSXC-CLI 1 "June 15, 2019"
.SH NAME
keepassxc-cli \- command line interface for the \fBKeePassXC\fP password manager.
.SH SYNOPSIS
.B keepassxc-cli
.I command
.B [
-I options
.B ]
.SH DESCRIPTION
\fBkeepassxc-cli\fP is the command line interface for the \fBKeePassXC\fP password manager. It provides the ability to query and modify the entries of a KeePass database, directly from the command line.
.SH COMMANDS
.IP "add [options] <database> <entry>"
Adds a new entry to a database. A password can be generated (\fI-g\fP option), or a prompt can be displayed to input the password (\fI-p\fP option).
The same password generation options as documented for the generate command can be used when the \fI-g\fP option is set.
.IP "analyze [options] <database>"
Analyzes passwords in a database for weaknesses.
.IP "clip [options] <database> <entry> [timeout]"
Copies the password or the current TOTP (\fI-t\fP option) of a database entry to the clipboard. If multiple entries with the same name exist in different groups, only the password for the first one is going to be copied. For copying the password of an entry in a specific group, the group path to the entry should be specified as well, instead of just the name. Optionally, a timeout in seconds can be specified to automatically clear the clipboard.
.IP "close"
In interactive mode, closes the currently opened database (see \fIopen\fP).
.IP "create [options] <database>"
Creates a new database with a key file and/or password. The key file will be created if the file that is referred to does not exist. If both the key file and password are empty, no database will be created.
.IP "diceware [options]"
Generates a random diceware passphrase.
.IP "edit [options] <database> <entry>"
Edits a database entry. A password can be generated (\fI-g\fP option), or a prompt can be displayed to input the password (\fI-p\fP option).
The same password generation options as documented for the generate command can be used when the \fI-g\fP option is set.
.IP "estimate [options] [password]"
Estimates the entropy of a password. The password to estimate can be provided as a positional argument, or using the standard input.
.IP "exit"
Exits interactive mode. Synonymous with \fIquit\fP.
.IP "export [options] <database>"
Exports the content of a database to standard output in the specified format (defaults to XML).
.IP "generate [options]"
Generates a random password.
.IP "help [command]"
Displays a list of available commands, or detailed information about the specified command.
.IP "import [options] <xml> <database>"
Imports the contents of an XML database to the target database.
.IP "locate [options] <database> <term>"
Locates all the entries that match a specific search term in a database.
.IP "ls [options] <database> [group]"
Lists the contents of a group in a database. If no group is specified, it will default to the root group.
.IP "merge [options] <database1> <database2>"
Merges two databases together. The first database file is going to be replaced by the result of the merge, for that reason it is advisable to keep a backup of the two database files before attempting a merge. In the case that both databases make use of the same credentials, the \fI--same-credentials\fP or \fI-s\fP option can be used.
.IP "mkdir [options] <database> <group>"
Adds a new group to a database.
.IP "mv [options] <database> <entry> <group>"
Moves an entry to a new group.
.IP "open [options] <database>"
Opens the given database in a shell-style interactive mode. This is useful for performing multiple operations on a single database (e.g. \fIls\fP followed by \fIshow\fP).
.IP "quit"
Exits interactive mode. Synonymous with \fIexit\fP.
.IP "rm [options] <database> <entry>"
Removes an entry from a database. If the database has a recycle bin, the entry will be moved there. If the entry is already in the recycle bin, it will be removed permanently.
.IP "rmdir [options] <database> <group>"
Removes a group from a database. If the database has a recycle bin, the group will be moved there. If the group is already in the recycle bin, it will be removed permanently.
.IP "show [options] <database> <entry>"
Shows the title, username, password, URL and notes of a database entry. Can also show the current TOTP. Regarding the occurrence of multiple entries with the same name in different groups, everything stated in the \fIclip\fP command section also applies here.
.SH OPTIONS
.SS "General options"
.IP "--debug-info"
Displays debugging information.
.IP "-k, --key-file <path>"
Specifies a path to a key file for unlocking the database. In a merge operation this option, is used to specify the key file path for the first database.
.IP "--no-password"
Deactivates the password key for the database.
.IP "-y, --yubikey <slot>"
Specifies a yubikey slot for unlocking the database. In a merge operation this option is used to specify the yubikey slot for the first database.
.IP "-q, --quiet <path>"
Silences password prompt and other secondary outputs.
.IP "-h, --help"
Displays help information.
.IP "-v, --version"
Displays the program version.
.SS "Merge options"
.IP "-d, --dry-run <path>"
Prints the changes detected by the merge operation without making any changes to the database.
.IP "-f, --key-file-from <path>"
Sets the path of the key file for the second database.
.IP "--no-password-from"
Deactivates password key for the database to merge from.
.IP "--yubikey-from <slot>"
Yubikey slot for the second database.
.IP "-s, --same-credentials"
Uses the same credentials for unlocking both databases.
.SS "Add and edit options"
The same password generation options as documented for the generate command can be used
with those 2 commands when the -g option is set.
.IP "-u, --username <username>"
Specifies the username of the entry.
.IP "--url <url>"
Specifies the URL of the entry.
.IP "-p, --password-prompt"
Uses a password prompt for the entry's password.
.IP "-g, --generate"
Generates a new password for the entry.
.SS "Edit options"
.IP "-t, --title <title>"
Specifies the title of the entry.
.SS "Estimate options"
.IP "-a, --advanced"
Performs advanced analysis on the password.
.SS "Analyze options"
.IP "-H, --hibp <filename>"
Checks if any passwords have been publicly leaked, by comparing against the given
list of password SHA-1 hashes, which must be in "Have I Been Pwned" format. Such
files are available from https://haveibeenpwned.com/Passwords; note that they
are large, and so this operation typically takes some time (minutes up to an
hour or so).
.SS "Clip options"
.IP "-t, --totp"
Copies the current TOTP instead of current password to clipboard. Will report
an error if no TOTP is configured for the entry.
.SS "Show options"
.IP "-a, --attributes <attribute>..."
Shows the named attributes. This option can be specified more than once,
with each attribute shown one-per-line in the given order. If no attributes are
specified and \fI-t\fP is not specified, a summary of the default attributes is given.
.IP "-t, --totp"
Also shows the current TOTP, reporting an error if no TOTP is configured for
the entry.
.SS "Diceware options"
.IP "-W, --words <count>"
Sets the desired number of words for the generated passphrase. [Default: 7]
.IP "-w, --word-list <path>"
Sets the Path of the wordlist for the diceware generator. The wordlist must
have > 1000 words, otherwise the program will fail. If the wordlist has < 4000
words a warning will be printed to STDERR.
.SS "Export options"
.IP "-f, --format"
Format to use when exporting. Available choices are xml or csv. Defaults to xml.
.SS "List options"
.IP "-R, --recursive"
Recursively lists the elements of the group.
.IP "-f, --flatten"
Flattens the output to single lines. When this option is enabled, subgroups and subentries will be displayed with a relative group path instead of indentation.
.SS "Generate options"
.IP "-L, --length <length>"
Sets the desired length for the generated password. [Default: 16]
.IP "-l --lower"
Uses lowercase characters for the generated password. [Default: Enabled]
.IP "-U --upper"
Uses uppercase characters for the generated password. [Default: Enabled]
.IP "-n --numeric"
Uses numbers characters for the generated password. [Default: Enabled]
.IP "-s --special"
Uses special characters for the generated password. [Default: Disabled]
.IP "-e --extended"
Uses extended ASCII characters for the generated password. [Default: Disabled]
.IP "-x --exclude <chars>"
Comma-separated list of characters to exclude from the generated password. None is excluded by default.
.IP "--exclude-similar"
Exclude similar looking characters. [Default: Disabled]
.IP "--every-group"
Include characters from every selected group. [Default: Disabled]
.SH REPORTING BUGS
Bugs and feature requests can be reported on GitHub at https://github.com/keepassxreboot/keepassxc/issues.
.SH AUTHOR
This manual page was originally written by Manolis Agkopian <m.agkopian@gmail.com>,
and is maintained by the KeePassXC Team <team@keepassxc.org>.

View File

@ -0,0 +1,39 @@
.TH KEEPASSXC 1 "Oct 25, 2019"
.SH NAME
keepassxc \- password manager
.SH SYNOPSIS
.B keepassxc
.B [
.I options
.B ] [
.I filename(s)
.B ]
.SH DESCRIPTION
\fBKeePassXC\fP is a free/open-source password manager or safe which helps you to manage your passwords in a secure way. The complete database is always encrypted with the industry-standard AES (alias Rijndael) encryption algorithm using a 256 bit key. KeePassXC uses a database format that is compatible with KeePass Password Safe. Your wallet works offline and requires no Internet connection.
.SH OPTIONS
.IP "-h, --help"
Displays this help.
.IP "-v, --version"
Displays version information.
.IP "--config <config>"
Path to a custom config file
.IP "--keyfile <keyfile>"
Key file of the database
.IP "--pw-stdin"
Read password of the database from stdin
.IP "--pw, --parent-window <handle>"
Parent window handle
.IP "--debug-info"
Displays debugging information.
.SH AUTHOR
This manual page is maintained by the KeePassXC Team <team@keepassxc.org>.

View File

Before

Width:  |  Height:  |  Size: 454 B

After

Width:  |  Height:  |  Size: 454 B

View File

Before

Width:  |  Height:  |  Size: 583 B

After

Width:  |  Height:  |  Size: 583 B

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="108.7505"
height="91.166321"
viewBox="0 0 87.000389 72.933061"
id="svg2"
sodipodi:docname="freedesktop.svg"
inkscape:version="0.92.4 5da689c313, 2019-01-14">
<defs
id="defs14" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="3840"
inkscape:window-height="2106"
id="namedview12"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.7980996"
inkscape:cx="-97.45169"
inkscape:cy="25.551539"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg2" />
<metadata
id="metadata57">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0.01402783,0.01402783)"
id="g37"
style="fill:#ffffff;fill-rule:nonzero;stroke:#3b80ae;stroke-width:2.45880008;stroke-miterlimit:4">
<g
id="g39">
<path
d="M 85.277,40.796 C 87.335,48.68 82.61,56.738 74.726,58.795 L 27.143,71.21 C 19.259,73.267 11.2,68.543 9.143,60.658 L 1.695,32.108 C -0.362,24.224 4.362,16.166 12.246,14.109 L 59.83,1.695 c 7.884,-2.057 15.942,2.667 17.999,10.551 l 7.449,28.55 z"
id="path41"
style="stroke:#bababa"
inkscape:connector-curvature="0" />
<path
d="m 80.444,39.778 c 1.749,7.854 -1.816,13.621 -9.504,15.447 L 28.704,66.245 C 21.135,68.641 14.615,65.064 12.866,57.409 L 6.53,33.127 C 4.781,24.982 7.239,20.238 16.033,17.68 L 58.27,6.661 c 8.144,-1.826 14.089,1.363 15.838,8.835 z"
id="path43"
style="fill:#3b80ae;stroke:none"
inkscape:connector-curvature="0" />
</g>
<path
d="M 45.542,51.793 24.104,31.102 62.204,26.709 Z"
id="path45"
style="opacity:0.5;fill:none;stroke:#ffffff"
inkscape:connector-curvature="0" />
<path
d="m 72.325,28.769 c 0.405,1.55 -0.525,3.136 -2.075,3.541 l -12.331,3.217 c -1.551,0.404 -3.137,-0.525 -3.542,-2.076 L 52.082,24.65 c -0.405,-1.551 0.524,-3.137 2.076,-3.542 l 12.33,-3.217 c 1.551,-0.405 3.137,0.525 3.542,2.076 l 2.295,8.801 z"
id="path47"
inkscape:connector-curvature="0" />
<path
d="m 36.51,33.625 c 0.496,1.9 -0.645,3.844 -2.545,4.34 l -15.112,3.943 c -1.901,0.496 -3.845,-0.644 -4.34,-2.544 L 11.699,28.578 c -0.496,-1.901 0.644,-3.844 2.544,-4.34 l 15.113,-3.942 c 1.901,-0.496 3.845,0.643 4.34,2.544 l 2.814,10.786 z"
id="path49"
inkscape:connector-curvature="0" />
<path
d="m 52.493,53.208 c 0.278,1.065 -0.36,2.154 -1.425,2.432 L 42.6,57.848 c -1.064,0.277 -2.153,-0.36 -2.431,-1.426 l -1.577,-6.043 c -0.277,-1.064 0.36,-2.153 1.425,-2.432 l 8.468,-2.209 c 1.064,-0.277 2.154,0.361 2.431,1.426 l 1.577,6.043 z"
id="path51"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -5,7 +5,10 @@ OpenPreviousDatabasesOnStartup=true
AutoSaveAfterEveryChange=false AutoSaveAfterEveryChange=false
AutoSaveOnExit=false AutoSaveOnExit=false
AutoReloadOnChange=true AutoReloadOnChange=true
MinimizeOnCopy=false HideWindowOnCopy=false
MinimizeOnCopy=true
DropToBackgroundOnCopy=false
MinimizeOnOpenUrl=false
UseGroupIconOnEntryCreation=true UseGroupIconOnEntryCreation=true
IgnoreGroupExpansion=false IgnoreGroupExpansion=false
AutoTypeEntryTitleMatch=true AutoTypeEntryTitleMatch=true
@ -20,6 +23,7 @@ DarkTrayIcon=false
MinimizeToTray=false MinimizeToTray=false
MinimizeOnClose=false MinimizeOnClose=false
MinimizeOnStartup=false MinimizeOnStartup=false
MonospaceNotes=false
MainWindowGeometry="@ByteArray(\x1\xd9\xd0\xcb\0\x2\0\0\0\0\x2(\0\0\0\xbd\0\0\x5W\0\0\x3;\0\0\x2\x30\0\0\0\xdc\0\0\x5O\0\0\x3\x33\0\0\0\0\0\0\0\0\a\x80)" MainWindowGeometry="@ByteArray(\x1\xd9\xd0\xcb\0\x2\0\0\0\0\x2(\0\0\0\xbd\0\0\x5W\0\0\x3;\0\0\x2\x30\0\0\0\xdc\0\0\x5O\0\0\x3\x33\0\0\0\0\0\0\0\0\a\x80)"
SplitterState=@Invalid() SplitterState=@Invalid()
EntryListColumnSizes=@Invalid() EntryListColumnSizes=@Invalid()

View File

@ -50,6 +50,87 @@
</screenshots> </screenshots>
<releases> <releases>
<release version="2.5.0" date="2019-10-26">
<description>
<ul>
<li>Add 'Paper Backup' aka 'Export to HTML file' to the 'Database' menu [#3277]</li>
<li>Add statistics panel with information about the database (number of entries, number of unique passwords, etc.) to the Database Settings dialog [#2034]</li>
<li>Add offline user manual accessible via the 'Help' menu [#3274]</li>
<li>Add support for importing 1Password OpVault files [#2292]</li>
<li>Implement Freedesktop.org secret storage DBus protocol so that KeePassXC can be used as a vault service by libsecret [#2726]</li>
<li>Add support for OnlyKey as an alternative to YubiKeys (requires yubikey-personalization >= 1.20.0) [#3352]</li>
<li>Add group sorting feature [#3282]</li>
<li>Add feature to download favicons for all entries at once [#3169]</li>
<li>Add word case option to passphrase generator [#3172]</li>
<li>Add support for RFC6238-compliant TOTP hashes [#2972]</li>
<li>Add UNIX man page for main program [#3665]</li>
<li>Add 'Monospaced font' option to the notes field [#3321]</li>
<li>Add support for key files in auto open [#3504]</li>
<li>Add search field for filtering entries in Auto-Type dialog [#2955]</li>
<li>Complete usernames based on known usernames from other entries [#3300]</li>
<li>Parse hyperlinks in the notes field of the entry preview pane [#3596]</li>
<li>Allow abbreviation of field names in entry search [#3440]</li>
<li>Allow setting group icons recursively [#3273]</li>
<li>Add copy context menu for username and password in Auto-Type dialog [#3038]</li>
<li>Drop to background after copying a password to the clipboard [#3253]</li>
<li>Add 'Lock databases' entry to tray icon menu [#2896]</li>
<li>Add option to minimize window after unlocking [#3439]</li>
<li>Add option to minimize window after opening a URL [#3302]</li>
<li>Request accessibility permissions for Auto-Type on macOS [#3624]</li>
<li>Browser: Add initial support for multiple URLs [#3558]</li>
<li>Browser: Add entry-specific browser integration settings [#3444]</li>
<li>Add offline HIBP checker (requires a downloaded HIBP dump) [#2707]</li>
<li>CLI: Add 'flatten' option to the 'ls' command [#3276]</li>
<li>CLI: Add password generation options to `Add` and `Edit` commands [#3275]</li>
<li>CLI: Add XML import [#3572]</li>
<li>CLI: Add CSV export to the 'export' command [#3278]</li>
<li>CLI: Add `-y --yubikey` option for YubiKey [#3416]</li>
<li>CLI: Add `--dry-run` option for merging databases [#3254]</li>
<li>CLI: Add group commands (mv, mkdir and rmdir) [#3313].</li>
<li>CLI: Add interactive shell mode command `open` [#3224]</li>
<li>Redesign database unlock dialog [ [#3287]</li>
<li>Rework the entry preview panel [ [#3306]</li>
<li>Move notes to General tab on Group Preview Panel [#3336]</li>
<li>Enable entry actions when editing an entry and cleanup entry context menu [#3641]</li>
<li>Improve detection of external database changes [#2389]</li>
<li>Warn if user is trying to use a KDBX file as a key file [#3625]</li>
<li>Add option to disable KeePassHTTP settings migrations prompt [#3349, #3344]</li>
<li>Re-enabled Wayland support (no Auto-Type yet) [#3520, #3341]</li>
<li>Add icon to 'Toggle Window' action in tray icon menu [[3244]</li>
<li>Merge custom data between databases only when necessary [#3475]</li>
<li>Improve various file-handling related issues when picking files using the system's file dialog [#3473]</li>
<li>Add 'New Entry' context menu when no entries are selected [#3671]</li>
<li>Reduce default Argon2 settings from 128 MiB and one thread per CPU core to 64 MiB and two threads to account for lower-spec mobile hardware [#3672]</li>
<li>Browser: Remove unused 'Remember' checkbox for HTTP Basic Auth [#3371]</li>
<li>Browser: Show database name when pairing with a new browser [#3638]</li>
<li>Browser: Show URL in allow access dialog [#3639]</li>
<li>CLI: The password length option `-l` for the CLI commands `Add` and `Edit` is now `-L` [#3275]</li>
<li>CLI: The `-u` shorthand for the `--upper` password generation option has been renamed to `-U` [#3275]</li>
<li>CLI: Rename command `extract` to `export`. [#3277]</li>
<li>Improve accessibility for assistive technologies [#3409]</li>
<li>Correctly unlock all databases if `--pw-stdin` is provided [#2916]</li>
<li>Fix password generator issues with special characters [#3303]</li>
<li>Fix KeePassXC interrupting shutdown procedure [#3666]</li>
<li>Fix password visibility toggle button state on unlock dialog [#3312]</li>
<li>Fix potential data loss if database is reloaded while user is editing an entry [#3656]</li>
<li>Fix hard-coded background color in search help popup [#3001]</li>
<li>Fix font choice for password preview [#3425]</li>
<li>Fix handling of read-only files when autosave is enabled [#3408]</li>
<li>Handle symlinks correctly when atomic saves are disabled [#3463]</li>
<li>Enable HighDPI icon scaling on Linux [#3332]</li>
<li>Make Auto-Type on macOS more robust and remove old Carbon API calls [#3634, #3347]</li>
<li>Hide Share tab if KeePassXC is compiled without KeeShare support and other minor KeeShare improvements [#3654, #3291, #3029, #3031, #3236]</li>
<li>Correctly bring window to the front when clicking tray icon on macOS [#3576]</li>
<li>Correct application shortcut created by MSI Installer on Windows [#3296]</li>
<li>Fix crash when removing custom data [#3508]</li>
<li>Fix placeholder resolution in URLs [#3281]</li>
<li>Fix various inconsistencies and platform-dependent compilation bugs [#3664, #3662, #3660, #3655, #3649, #3417, #3357, #3319, #3318, #3304]</li>
<li>Browser: Fix potential leaking of entries through the browser integration API if multiple databases are opened [#3480]</li>
<li>Browser: Fix password entropy calculation [#3107]</li>
<li>Browser: Fix Windows registry settings for portable installation [#3603]</li>
</ul>
</description>
</release>
<release version="2.4.3" date="2019-06-12"> <release version="2.4.3" date="2019-06-12">
<description> <description>
<ul> <ul>

View File

@ -1,11 +1,13 @@
[Desktop Entry] [Desktop Entry]
Name=KeePassXC Name=KeePassXC
GenericName=Password Manager GenericName=Password Manager
GenericName[da]=Adgangskodehåndtering
GenericName[de]=Passwortverwaltung GenericName[de]=Passwortverwaltung
GenericName[es]=Gestor de contraseñas GenericName[es]=Gestor de contraseñas
GenericName[fr]=Gestionnaire de mot de passe GenericName[fr]=Gestionnaire de mot de passe
GenericName[ru]=менеджер паролей GenericName[ru]=менеджер паролей
Comment=Community-driven port of the Windows application KeePass Password Safe Comment=Community-driven port of the Windows application KeePass Password Safe
Comment[da]=Fællesskabsdrevet port af Windows-programmet KeePass Password Safe
Exec=keepassxc %f Exec=keepassxc %f
TryExec=keepassxc TryExec=keepassxc
Icon=keepassxc Icon=keepassxc

View File

@ -8,8 +8,6 @@
<string>production</string> <string>production</string>
<key>com.apple.security.network.client</key> <key>com.apple.security.network.client</key>
<true/> <true/>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.print</key> <key>com.apple.security.print</key>
<true/> <true/>
<key>com.apple.security.app-sandbox</key> <key>com.apple.security.app-sandbox</key>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<CPackWiXPatch> <CPackWiXPatch>
<CPackWiXFragment Id="CM_FP_KeePassXC.exe">
<Shortcut Id="CM_SP_KeePassXC.exe" Directory="ProgramMenuFolder"
Name="KeePassXC" Icon="ProductIcon.ico"
WorkingDirectory="INSTALL_ROOT" Advertise="yes" />
</CPackWiXFragment>
<CPackWiXFragment Id="CM_CP_KeePassXC.exe"> <CPackWiXFragment Id="CM_CP_KeePassXC.exe">
<ProgId Id="KeePassXC.kdbx" Description="KeePass Password Database" Icon="CM_FP_KeePassXC.exe" IconIndex="1"> <ProgId Id="KeePassXC.kdbx" Description="KeePass Password Database" Icon="CM_FP_KeePassXC.exe" IconIndex="1">
<Extension Id="kdbx" ContentType="application/x-keepass2"> <Extension Id="kdbx" ContentType="application/x-keepass2">

View File

@ -38,28 +38,55 @@
<WixVariable Id="WixUIDialogBmp" Value="$(var.CPACK_WIX_UI_DIALOG)"/> <WixVariable Id="WixUIDialogBmp" Value="$(var.CPACK_WIX_UI_DIALOG)"/>
<?endif?> <?endif?>
<FeatureRef Id="ProductFeature"/> <FeatureRef Id="ProductFeature">
<ComponentRef Id="ApplicationShortcut" />
</FeatureRef>
<UIRef Id="$(var.CPACK_WIX_UI_REF)" /> <UI>
<UIRef Id="$(var.CPACK_WIX_UI_REF)" />
<Publish Dialog="ExitDialog"
Control="Finish"
Event="DoAction"
Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
</UI>
<?include "properties.wxi"?> <?include "properties.wxi"?>
<?include "product_fragment.wxi"?> <?include "product_fragment.wxi"?>
<DirectoryRef Id="TARGETDIR"> <DirectoryRef Id="TARGETDIR">
<Directory Id="ProgramMenuFolder" /> <Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="KeePassXC"/>
</Directory>
</DirectoryRef> </DirectoryRef>
<Property Id="WixSilentExecCmdLine" Value='"Taskkill" /IM KeePassXC.exe'/> <DirectoryRef Id="ApplicationProgramsFolder">
<CustomAction Id="KillKeePassXCInstall" BinaryKey="WixCA" DllEntry="WixSilentExec" Execute="immediate" Return="ignore"/> <Component Id="ApplicationShortcut" Guid="*">
<CustomAction Id="KillKeePassXCUninstall" BinaryKey="WixCA" DllEntry="WixSilentExec" Execute="immediate" Return="ignore"/> <Shortcut Id="ApplicationStartMenuShortcut"
Name="KeePassXC"
Target="[#CM_FP_KeePassXC.exe]"
Icon="ProductIcon.ico"
WorkingDirectory="INSTALL_ROOT"/>
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\KeePassXC" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</DirectoryRef>
<Property Id="WixQuietExecCmdLine" Value='"Taskkill" /IM keepassxc-proxy.exe /F'/> <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1" />
<CustomAction Id="KillProxyInstall" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="immediate" Return="ignore"/> <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Launch $(var.CPACK_PACKAGE_NAME)" />
<CustomAction Id="KillProxyUninstall" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="immediate" Return="ignore"/> <Property Id="WixShellExecTarget" Value="[#CM_FP_KeePassXC.exe]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<Property Id="WixSilentExecCmdLine" Value='"Taskkill" /IM KeePassXC.exe' />
<CustomAction Id="KillKeePassXCInstall" BinaryKey="WixCA" DllEntry="WixSilentExec" Execute="immediate" Return="ignore" />
<CustomAction Id="KillKeePassXCUninstall" BinaryKey="WixCA" DllEntry="WixSilentExec" Execute="immediate" Return="ignore" />
<Property Id="WixQuietExecCmdLine" Value='"Taskkill" /IM keepassxc-proxy.exe /F' />
<CustomAction Id="KillProxyInstall" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="immediate" Return="ignore" />
<CustomAction Id="KillProxyUninstall" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="immediate" Return="ignore" />
<InstallExecuteSequence> <InstallExecuteSequence>
<Custom Action="KillKeePassXCInstall" After="InstallInitialize"/> <Custom Action="KillKeePassXCInstall" After="InstallInitialize" />
<Custom Action="KillProxyInstall" After="InstallInitialize"/> <Custom Action="KillProxyInstall" After="InstallInitialize" />
<Custom Action="KillKeePassXCUninstall" Before="InstallValidate">Installed</Custom> <Custom Action="KillKeePassXCUninstall" Before="InstallValidate">Installed</Custom>
<Custom Action="KillProxyUninstall" Before="InstallValidate">Installed</Custom> <Custom Action="KillProxyUninstall" Before="InstallValidate">Installed</Custom>
</InstallExecuteSequence> </InstallExecuteSequence>

View File

@ -1,5 +1,5 @@
name: keepassxc name: keepassxc
version: 2.4.3 version: 2.5.0
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: |

View File

@ -27,6 +27,9 @@ set(keepassx_SOURCES
core/Alloc.cpp core/Alloc.cpp
core/AutoTypeAssociations.cpp core/AutoTypeAssociations.cpp
core/AutoTypeMatch.cpp core/AutoTypeMatch.cpp
core/Base32.cpp
core/Bootstrap.cpp
core/Clock.cpp
core/Compare.cpp core/Compare.cpp
core/Config.cpp core/Config.cpp
core/CsvParser.cpp core/CsvParser.cpp
@ -39,8 +42,8 @@ set(keepassx_SOURCES
core/EntrySearcher.cpp core/EntrySearcher.cpp
core/FilePath.cpp core/FilePath.cpp
core/FileWatcher.cpp core/FileWatcher.cpp
core/Bootstrap.cpp
core/Group.cpp core/Group.cpp
core/HibpOffline.cpp
core/InactivityTimer.cpp core/InactivityTimer.cpp
core/Merger.cpp core/Merger.cpp
core/Metadata.cpp core/Metadata.cpp
@ -51,10 +54,8 @@ set(keepassx_SOURCES
core/ScreenLockListenerPrivate.cpp core/ScreenLockListenerPrivate.cpp
core/TimeDelta.cpp core/TimeDelta.cpp
core/TimeInfo.cpp core/TimeInfo.cpp
core/Clock.cpp
core/Tools.cpp core/Tools.cpp
core/Translator.cpp core/Translator.cpp
core/Base32.cpp
cli/Utils.cpp cli/Utils.cpp
cli/TextStream.cpp cli/TextStream.cpp
crypto/Crypto.cpp crypto/Crypto.cpp
@ -66,6 +67,7 @@ set(keepassx_SOURCES
crypto/kdf/AesKdf.cpp crypto/kdf/AesKdf.cpp
crypto/kdf/Argon2Kdf.cpp crypto/kdf/Argon2Kdf.cpp
format/CsvExporter.cpp format/CsvExporter.cpp
format/HtmlExporter.cpp
format/KeePass1Reader.cpp format/KeePass1Reader.cpp
format/KeePass2.cpp format/KeePass2.cpp
format/KeePass2RandomStream.cpp format/KeePass2RandomStream.cpp
@ -79,6 +81,11 @@ set(keepassx_SOURCES
format/Kdbx4Reader.cpp format/Kdbx4Reader.cpp
format/Kdbx4Writer.cpp format/Kdbx4Writer.cpp
format/KdbxXmlWriter.cpp format/KdbxXmlWriter.cpp
format/OpData01.cpp
format/OpVaultReader.cpp
format/OpVaultReaderAttachments.cpp
format/OpVaultReaderBandEntry.cpp
format/OpVaultReaderSections.cpp
gui/AboutDialog.cpp gui/AboutDialog.cpp
gui/Application.cpp gui/Application.cpp
gui/CategoryListWidget.cpp gui/CategoryListWidget.cpp
@ -103,6 +110,7 @@ set(keepassx_SOURCES
gui/MainWindow.cpp gui/MainWindow.cpp
gui/MessageBox.cpp gui/MessageBox.cpp
gui/MessageWidget.cpp gui/MessageWidget.cpp
gui/OpVaultOpenWidget.cpp
gui/PasswordEdit.cpp gui/PasswordEdit.cpp
gui/PasswordGeneratorWidget.cpp gui/PasswordGeneratorWidget.cpp
gui/ApplicationSettingsWidget.cpp gui/ApplicationSettingsWidget.cpp
@ -140,6 +148,8 @@ set(keepassx_SOURCES
gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.cpp gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.cpp
gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp
gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp
gui/dbsettings/DatabaseSettingsWidgetStatistics.cpp
gui/dbsettings/DatabaseSettingsPageStatistics.cpp
gui/settings/SettingsWidget.cpp gui/settings/SettingsWidget.cpp
gui/widgets/ElidedLabel.cpp gui/widgets/ElidedLabel.cpp
gui/widgets/PopupHelpWidget.cpp gui/widgets/PopupHelpWidget.cpp
@ -152,6 +162,7 @@ set(keepassx_SOURCES
keys/FileKey.cpp keys/FileKey.cpp
keys/PasswordKey.cpp keys/PasswordKey.cpp
keys/YkChallengeResponseKey.cpp keys/YkChallengeResponseKey.cpp
keys/YkChallengeResponseKeyCLI.cpp
streams/HashedBlockStream.cpp streams/HashedBlockStream.cpp
streams/HmacBlockStream.cpp streams/HmacBlockStream.cpp
streams/LayeredStream.cpp streams/LayeredStream.cpp
@ -194,6 +205,9 @@ add_feature_info(SSHAgent WITH_XC_SSHAGENT "SSH agent integration compatible wit
add_feature_info(KeeShare WITH_XC_KEESHARE "Sharing integration with KeeShare (requires quazip5 for secure containers)") add_feature_info(KeeShare WITH_XC_KEESHARE "Sharing integration with KeeShare (requires quazip5 for secure containers)")
add_feature_info(YubiKey WITH_XC_YUBIKEY "YubiKey HMAC-SHA1 challenge-response") add_feature_info(YubiKey WITH_XC_YUBIKEY "YubiKey HMAC-SHA1 challenge-response")
add_feature_info(UpdateCheck WITH_XC_UPDATECHECK "Automatic update checking") add_feature_info(UpdateCheck WITH_XC_UPDATECHECK "Automatic update checking")
if(UNIX AND NOT APPLE)
add_feature_info(FdoSecrets WITH_XC_FDOSECRETS "Implement freedesktop.org Secret Storage Spec server side API.")
endif()
if(APPLE) if(APPLE)
add_feature_info(TouchID WITH_XC_TOUCHID "TouchID integration") add_feature_info(TouchID WITH_XC_TOUCHID "TouchID integration")
endif() endif()
@ -204,6 +218,7 @@ add_subdirectory(proxy)
if(WITH_XC_BROWSER) if(WITH_XC_BROWSER)
set(keepassxcbrowser_LIB keepassxcbrowser) set(keepassxcbrowser_LIB keepassxcbrowser)
set(keepassx_SOURCES ${keepassx_SOURCES} gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp) set(keepassx_SOURCES ${keepassx_SOURCES} gui/dbsettings/DatabaseSettingsWidgetBrowser.cpp)
set(keepassx_SOURCES ${keepassx_SOURCES} gui/entry/EntryURLModel.cpp)
endif() endif()
add_subdirectory(autotype) add_subdirectory(autotype)
@ -226,10 +241,16 @@ if(WITH_XC_SSHAGENT)
set(sshagent_LIB sshagent) set(sshagent_LIB sshagent)
endif() endif()
add_subdirectory(fdosecrets)
if(WITH_XC_FDOSECRETS)
set(fdosecrets_LIB fdosecrets)
endif()
set(autotype_SOURCES set(autotype_SOURCES
core/Tools.cpp core/Tools.cpp
autotype/AutoType.cpp autotype/AutoType.cpp
autotype/AutoTypeAction.cpp autotype/AutoTypeAction.cpp
autotype/AutoTypeFilterLineEdit.cpp
autotype/AutoTypeSelectDialog.cpp autotype/AutoTypeSelectDialog.cpp
autotype/AutoTypeSelectView.cpp autotype/AutoTypeSelectView.cpp
autotype/ShortcutWidget.cpp autotype/ShortcutWidget.cpp
@ -247,7 +268,12 @@ else()
endif() endif()
if(WITH_XC_NETWORKING) if(WITH_XC_NETWORKING)
list(APPEND keepassx_SOURCES updatecheck/UpdateChecker.cpp gui/UpdateCheckDialog.cpp) list(APPEND keepassx_SOURCES
core/IconDownloader.cpp
core/NetworkManager.cpp
gui/UpdateCheckDialog.cpp
gui/IconDownloaderDialog.cpp
updatecheck/UpdateChecker.cpp)
endif() endif()
if(WITH_XC_TOUCHID) if(WITH_XC_TOUCHID)
@ -269,6 +295,7 @@ target_link_libraries(keepassx_core
autotype autotype
${keepassxcbrowser_LIB} ${keepassxcbrowser_LIB}
${qrcode_LIB} ${qrcode_LIB}
${fdosecrets_LIB}
Qt5::Core Qt5::Core
Qt5::Concurrent Qt5::Concurrent
Qt5::Network Qt5::Network
@ -362,6 +389,10 @@ install(TARGETS ${PROGNAME}
BUNDLE DESTINATION . COMPONENT Runtime BUNDLE DESTINATION . COMPONENT Runtime
RUNTIME DESTINATION ${BIN_INSTALL_DIR} COMPONENT Runtime) RUNTIME DESTINATION ${BIN_INSTALL_DIR} COMPONENT Runtime)
if(APPLE OR UNIX)
install(FILES ../share/docs/man/keepassxc.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1/)
endif()
if(MINGW) if(MINGW)
if(${CMAKE_SIZEOF_VOID_P} EQUAL "8") if(${CMAKE_SIZEOF_VOID_P} EQUAL "8")
set(OUTPUT_FILE_POSTFIX "Win64") set(OUTPUT_FILE_POSTFIX "Win64")

View File

@ -37,6 +37,10 @@
#include "core/Tools.h" #include "core/Tools.h"
#include "gui/MessageBox.h" #include "gui/MessageBox.h"
#ifdef Q_OS_MAC
#include "gui/macutils/MacUtils.h"
#endif
AutoType* AutoType::m_instance = nullptr; AutoType* AutoType::m_instance = nullptr;
AutoType::AutoType(QObject* parent, bool test) AutoType::AutoType(QObject* parent, bool test)
@ -214,6 +218,7 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c
if (hideWindow) { if (hideWindow) {
#if defined(Q_OS_MACOS) #if defined(Q_OS_MACOS)
macUtils()->raiseLastActiveWindow();
m_plugin->hideOwnWindow(); m_plugin->hideOwnWindow();
#else #else
hideWindow->showMinimized(); hideWindow->showMinimized();
@ -631,9 +636,8 @@ bool AutoType::windowMatches(const QString& windowTitle, const QString& windowPa
if (windowPattern.startsWith("//") && windowPattern.endsWith("//") && windowPattern.size() >= 4) { if (windowPattern.startsWith("//") && windowPattern.endsWith("//") && windowPattern.size() >= 4) {
QRegExp regExp(windowPattern.mid(2, windowPattern.size() - 4), Qt::CaseInsensitive, QRegExp::RegExp2); QRegExp regExp(windowPattern.mid(2, windowPattern.size() - 4), Qt::CaseInsensitive, QRegExp::RegExp2);
return (regExp.indexIn(windowTitle) != -1); return (regExp.indexIn(windowTitle) != -1);
} else {
return WildcardMatcher(windowTitle).match(windowPattern);
} }
return WildcardMatcher(windowTitle).match(windowPattern);
} }
/** /**

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AutoTypeFilterLineEdit.h"
#include <QKeyEvent>
void AutoTypeFilterLineEdit::keyPressEvent(QKeyEvent* event)
{
if (event->key() == Qt::Key_Up) {
emit keyUpPressed();
} else if (event->key() == Qt::Key_Down) {
emit keyDownPressed();
} else {
QLineEdit::keyPressEvent(event);
}
}
void AutoTypeFilterLineEdit::keyReleaseEvent(QKeyEvent* event)
{
if (event->key() == Qt::Key_Escape) {
emit escapeReleased();
} else {
QLineEdit::keyReleaseEvent(event);
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEEPASSX_AUTOTYPEFILTERLINEEDIT_H
#define KEEPASSX_AUTOTYPEFILTERLINEEDIT_H
#include <QLineEdit>
class AutoTypeFilterLineEdit : public QLineEdit
{
Q_OBJECT
public:
AutoTypeFilterLineEdit(QWidget* widget)
: QLineEdit(widget)
{
}
protected:
virtual void keyPressEvent(QKeyEvent* event);
virtual void keyReleaseEvent(QKeyEvent* event);
signals:
void keyUpPressed();
void keyDownPressed();
void escapeReleased();
};
#endif // KEEPASSX_AUTOTYPEFILTERLINEEDIT_H

View File

@ -27,6 +27,8 @@
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QHeaderView> #include <QHeaderView>
#include <QLabel> #include <QLabel>
#include <QLineEdit>
#include <QSortFilterProxyModel>
#include <QVBoxLayout> #include <QVBoxLayout>
#include "autotype/AutoTypeSelectView.h" #include "autotype/AutoTypeSelectView.h"
@ -38,6 +40,7 @@
AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent)
: QDialog(parent) : QDialog(parent)
, m_view(new AutoTypeSelectView(this)) , m_view(new AutoTypeSelectView(this))
, m_filterLineEdit(new AutoTypeFilterLineEdit(this))
, m_matchActivatedEmitted(false) , m_matchActivatedEmitted(false)
, m_rejected(false) , m_rejected(false)
{ {
@ -72,13 +75,31 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent)
connect(m_view, SIGNAL(clicked(QModelIndex)), SLOT(emitMatchActivated(QModelIndex))); connect(m_view, SIGNAL(clicked(QModelIndex)), SLOT(emitMatchActivated(QModelIndex)));
connect(m_view->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(matchRemoved())); connect(m_view->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(matchRemoved()));
connect(m_view, SIGNAL(rejected()), SLOT(reject())); connect(m_view, SIGNAL(rejected()), SLOT(reject()));
connect(m_view, SIGNAL(matchTextCopied()), SLOT(reject()));
// clang-format on // clang-format on
QSortFilterProxyModel* proxy = qobject_cast<QSortFilterProxyModel*>(m_view->model());
if (proxy) {
proxy->setFilterKeyColumn(-1);
proxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
}
layout->addWidget(m_view); layout->addWidget(m_view);
connect(m_filterLineEdit, SIGNAL(textChanged(QString)), SLOT(filterList(QString)));
connect(m_filterLineEdit, SIGNAL(returnPressed()), SLOT(activateCurrentIndex()));
connect(m_filterLineEdit, SIGNAL(keyUpPressed()), SLOT(moveSelectionUp()));
connect(m_filterLineEdit, SIGNAL(keyDownPressed()), SLOT(moveSelectionDown()));
connect(m_filterLineEdit, SIGNAL(escapeReleased()), SLOT(reject()));
m_filterLineEdit->setPlaceholderText(tr("Search..."));
layout->addWidget(m_filterLineEdit);
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, Qt::Horizontal, this); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, Qt::Horizontal, this);
connect(buttonBox, SIGNAL(rejected()), SLOT(reject())); connect(buttonBox, SIGNAL(rejected()), SLOT(reject()));
layout->addWidget(buttonBox); layout->addWidget(buttonBox);
m_filterLineEdit->setFocus();
} }
void AutoTypeSelectDialog::setMatchList(const QList<AutoTypeMatch>& matchList) void AutoTypeSelectDialog::setMatchList(const QList<AutoTypeMatch>& matchList)
@ -121,7 +142,43 @@ void AutoTypeSelectDialog::matchRemoved()
return; return;
} }
if (m_view->model()->rowCount() == 0) { if (m_view->model()->rowCount() == 0 && m_filterLineEdit->text().isEmpty()) {
reject(); reject();
} }
} }
void AutoTypeSelectDialog::filterList(QString filterString)
{
QSortFilterProxyModel* proxy = qobject_cast<QSortFilterProxyModel*>(m_view->model());
if (proxy) {
proxy->setFilterWildcard(filterString);
if (!m_view->currentIndex().isValid()) {
m_view->setCurrentIndex(m_view->model()->index(0, 0));
}
}
}
void AutoTypeSelectDialog::moveSelectionUp()
{
auto current = m_view->currentIndex();
auto previous = current.sibling(current.row() - 1, 0);
if (previous.isValid()) {
m_view->setCurrentIndex(previous);
}
}
void AutoTypeSelectDialog::moveSelectionDown()
{
auto current = m_view->currentIndex();
auto next = current.sibling(current.row() + 1, 0);
if (next.isValid()) {
m_view->setCurrentIndex(next);
}
}
void AutoTypeSelectDialog::activateCurrentIndex()
{
emitMatchActivated(m_view->currentIndex());
}

View File

@ -22,6 +22,7 @@
#include <QDialog> #include <QDialog>
#include <QHash> #include <QHash>
#include "autotype/AutoTypeFilterLineEdit.h"
#include "core/AutoTypeMatch.h" #include "core/AutoTypeMatch.h"
class AutoTypeSelectView; class AutoTypeSelectView;
@ -44,9 +45,14 @@ public slots:
private slots: private slots:
void emitMatchActivated(const QModelIndex& index); void emitMatchActivated(const QModelIndex& index);
void matchRemoved(); void matchRemoved();
void filterList(QString filterString);
void moveSelectionUp();
void moveSelectionDown();
void activateCurrentIndex();
private: private:
AutoTypeSelectView* const m_view; AutoTypeSelectView* const m_view;
AutoTypeFilterLineEdit* const m_filterLineEdit;
bool m_matchActivatedEmitted; bool m_matchActivatedEmitted;
bool m_rejected; bool m_rejected;
}; };

View File

@ -17,47 +17,43 @@
*/ */
#include "AutoTypeMac.h" #include "AutoTypeMac.h"
#include "AutoTypeMacKeyCodes.h"
#include "gui/macutils/MacUtils.h" #include "gui/macutils/MacUtils.h"
#include <ApplicationServices/ApplicationServices.h>
#define HOTKEY_ID 1
#define MAX_WINDOW_TITLE_LENGTH 1024 #define MAX_WINDOW_TITLE_LENGTH 1024
#define INVALID_KEYCODE 0xFFFF #define INVALID_KEYCODE 0xFFFF
AutoTypePlatformMac::AutoTypePlatformMac() AutoTypePlatformMac::AutoTypePlatformMac()
: m_hotkeyRef(nullptr) : m_globalMonitor(nullptr)
, m_hotkeyId({ 'kpx2', HOTKEY_ID })
{ {
EventTypeSpec eventSpec;
eventSpec.eventClass = kEventClassKeyboard;
eventSpec.eventKind = kEventHotKeyPressed;
::InstallApplicationEventHandler(AutoTypePlatformMac::hotkeyHandler, 1, &eventSpec, this, nullptr);
} }
// /**
// Keepassx requires mac os 10.7 * Request accessibility permissions required for keyboard control
// *
* @return true on success
*/
bool AutoTypePlatformMac::isAvailable() bool AutoTypePlatformMac::isAvailable()
{ {
return true; return macUtils()->enableAccessibility();
} }
// /**
// Get list of visible window titles * Get a list of the currently open window titles
// see: Quartz Window Services *
// * @return list of window titles
*/
QStringList AutoTypePlatformMac::windowTitles() QStringList AutoTypePlatformMac::windowTitles()
{ {
QStringList list; QStringList list;
CFArrayRef windowList = ::CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); auto windowList = ::CGWindowListCopyWindowInfo(
if (windowList != nullptr) { kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
CFIndex count = ::CFArrayGetCount(windowList); if (windowList) {
auto count = ::CFArrayGetCount(windowList);
for (CFIndex i = 0; i < count; i++) { for (CFIndex i = 0; i < count; i++) {
CFDictionaryRef window = static_cast<CFDictionaryRef>(::CFArrayGetValueAtIndex(windowList, i)); auto window = static_cast<CFDictionaryRef>(::CFArrayGetValueAtIndex(windowList, i));
if (windowLayer(window) != 0) { if (windowLayer(window) != 0) {
continue; continue;
} }
@ -74,24 +70,28 @@ QStringList AutoTypePlatformMac::windowTitles()
return list; return list;
} }
// /**
// Get active window process id * Get active window ID
// *
* @return window ID
*/
WId AutoTypePlatformMac::activeWindow() WId AutoTypePlatformMac::activeWindow()
{ {
return macUtils()->activeWindow(); return macUtils()->activeWindow();
} }
// /**
// Get active window title * Get active window title
// see: Quartz Window Services *
// * @return window title
*/
QString AutoTypePlatformMac::activeWindowTitle() QString AutoTypePlatformMac::activeWindowTitle()
{ {
QString title; QString title;
CFArrayRef windowList = ::CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); CFArrayRef windowList = ::CGWindowListCopyWindowInfo(
if (windowList != nullptr) { kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
if (windowList) {
CFIndex count = ::CFArrayGetCount(windowList); CFIndex count = ::CFArrayGetCount(windowList);
for (CFIndex i = 0; i < count; i++) { for (CFIndex i = 0; i < count; i++) {
@ -111,41 +111,62 @@ QString AutoTypePlatformMac::activeWindowTitle()
return title; return title;
} }
// /**
// Register global hotkey * Register global hotkey using NS global event monitor.
// * Note that this hotkey is not trapped and may trigger
* actions in the local application where it is issued.
*
* @param key key used for hotkey
* @param modifiers modifiers required in addition to key
* @return true on success
*/
bool AutoTypePlatformMac::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) bool AutoTypePlatformMac::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
{ {
uint16 nativeKeyCode = qtToNativeKeyCode(key); auto nativeKeyCode = qtToNativeKeyCode(key);
if (nativeKeyCode == INVALID_KEYCODE) { if (nativeKeyCode == INVALID_KEYCODE) {
qWarning("Invalid key code"); qWarning("Invalid key code");
return false; return false;
} }
CGEventFlags nativeModifiers = qtToNativeModifiers(modifiers, false); auto nativeModifiers = qtToNativeModifiers(modifiers);
if (::RegisterEventHotKey(nativeKeyCode, nativeModifiers, m_hotkeyId, GetApplicationEventTarget(), 0, &m_hotkeyRef) != noErr) { m_globalMonitor =
qWarning("Register hotkey failed"); macUtils()->addGlobalMonitor(nativeKeyCode, nativeModifiers, this, AutoTypePlatformMac::hotkeyHandler);
return false;
}
return true; return true;
} }
// /**
// Unregister global hotkey * Handle global hotkey presses by emitting the trigger signal
// *
* @param userData pointer to AutoTypePlatform
*/
void AutoTypePlatformMac::hotkeyHandler(void* userData)
{
auto* self = static_cast<AutoTypePlatformMac*>(userData);
emit self->globalShortcutTriggered();
}
/**
* Unregister a previously registered global hotkey
*
* @param key unused
* @param modifiers unused
*/
void AutoTypePlatformMac::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) void AutoTypePlatformMac::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
{ {
Q_UNUSED(key); Q_UNUSED(key);
Q_UNUSED(modifiers); Q_UNUSED(modifiers);
if (m_globalMonitor) {
::UnregisterEventHotKey(m_hotkeyRef); macUtils()->removeGlobalMonitor(m_globalMonitor);
m_globalMonitor = nullptr;
}
} }
/**
* Unused
*/
int AutoTypePlatformMac::platformEventFilter(void* event) int AutoTypePlatformMac::platformEventFilter(void* event)
{ {
Q_UNUSED(event); Q_UNUSED(event);
Q_ASSERT(false); Q_ASSERT(false);
return -1; return -1;
} }
@ -154,17 +175,21 @@ AutoTypeExecutor* AutoTypePlatformMac::createExecutor()
return new AutoTypeExecutorMac(this); return new AutoTypeExecutorMac(this);
} }
// /**
// Activate window by process id * Raise the given window ID
// *
* @return true on success
*/
bool AutoTypePlatformMac::raiseWindow(WId pid) bool AutoTypePlatformMac::raiseWindow(WId pid)
{ {
return macUtils()->raiseWindow(pid); return macUtils()->raiseWindow(pid);
} }
// /**
// Activate last active window * Hide the KeePassXC window
// *
* @return true on success
*/
bool AutoTypePlatformMac::hideOwnWindow() bool AutoTypePlatformMac::hideOwnWindow()
{ {
return macUtils()->hideOwnWindow(); return macUtils()->hideOwnWindow();
@ -178,309 +203,293 @@ bool AutoTypePlatformMac::raiseOwnWindow()
return macUtils()->raiseOwnWindow(); return macUtils()->raiseOwnWindow();
} }
// /**
// Send unicode character to active window * Send provided character as key event to the active window
// see: Quartz Event Services *
// * @param ch unicode character
* @param isKeyDown whether the key is pressed
*/
void AutoTypePlatformMac::sendChar(const QChar& ch, bool isKeyDown) void AutoTypePlatformMac::sendChar(const QChar& ch, bool isKeyDown)
{ {
CGEventRef keyEvent = ::CGEventCreateKeyboardEvent(nullptr, 0, isKeyDown); auto keyEvent = ::CGEventCreateKeyboardEvent(nullptr, 0, isKeyDown);
if (keyEvent != nullptr) { if (keyEvent) {
UniChar unicode = ch.unicode(); auto unicode = ch.unicode();
::CGEventKeyboardSetUnicodeString(keyEvent, 1, &unicode); ::CGEventKeyboardSetUnicodeString(keyEvent, 1, &unicode);
::CGEventPost(kCGSessionEventTap, keyEvent); ::CGEventPost(kCGSessionEventTap, keyEvent);
::CFRelease(keyEvent); ::CFRelease(keyEvent);
} }
} }
// /**
// Send key code to active window * Send provided Qt key as key event to the active window
// see: Quartz Event Services *
// * @param key Qt key code
void AutoTypePlatformMac::sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers = 0) * @param isKeyDown whether the key is pressed
* @param modifiers any modifiers to apply to key
*/
void AutoTypePlatformMac::sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers)
{ {
uint16 keyCode = qtToNativeKeyCode(key); auto keyCode = qtToNativeKeyCode(key);
if (keyCode == INVALID_KEYCODE) { if (keyCode == INVALID_KEYCODE) {
return; return;
} }
CGEventRef keyEvent = ::CGEventCreateKeyboardEvent(nullptr, keyCode, isKeyDown); auto keyEvent = ::CGEventCreateKeyboardEvent(nullptr, keyCode, isKeyDown);
CGEventFlags nativeModifiers = qtToNativeModifiers(modifiers, true); auto nativeModifiers = qtToNativeModifiers(modifiers);
if (keyEvent != nullptr) { if (keyEvent) {
::CGEventSetFlags(keyEvent, nativeModifiers); ::CGEventSetFlags(keyEvent, nativeModifiers);
::CGEventPost(kCGSessionEventTap, keyEvent); ::CGEventPost(kCGSessionEventTap, keyEvent);
::CFRelease(keyEvent); ::CFRelease(keyEvent);
} }
} }
// /**
// Translate qt key code to mac os key code * Translate Qt key to macOS key code provided by
// see: HIToolbox/Events.h * AutoTypeMacKeyCodes.h which are derived from
// * legacy Carbon "HIToolbox/Events.h"
uint16 AutoTypePlatformMac::qtToNativeKeyCode(Qt::Key key) *
* @param key key to translate
* @returns macOS key code
*/
CGKeyCode AutoTypePlatformMac::qtToNativeKeyCode(Qt::Key key)
{ {
switch (key) { switch (key) {
case Qt::Key_A: case Qt::Key_A:
return kVK_ANSI_A; return kVK_ANSI_A;
case Qt::Key_B: case Qt::Key_B:
return kVK_ANSI_B; return kVK_ANSI_B;
case Qt::Key_C: case Qt::Key_C:
return kVK_ANSI_C; return kVK_ANSI_C;
case Qt::Key_D: case Qt::Key_D:
return kVK_ANSI_D; return kVK_ANSI_D;
case Qt::Key_E: case Qt::Key_E:
return kVK_ANSI_E; return kVK_ANSI_E;
case Qt::Key_F: case Qt::Key_F:
return kVK_ANSI_F; return kVK_ANSI_F;
case Qt::Key_G: case Qt::Key_G:
return kVK_ANSI_G; return kVK_ANSI_G;
case Qt::Key_H: case Qt::Key_H:
return kVK_ANSI_H; return kVK_ANSI_H;
case Qt::Key_I: case Qt::Key_I:
return kVK_ANSI_I; return kVK_ANSI_I;
case Qt::Key_J: case Qt::Key_J:
return kVK_ANSI_J; return kVK_ANSI_J;
case Qt::Key_K: case Qt::Key_K:
return kVK_ANSI_K; return kVK_ANSI_K;
case Qt::Key_L: case Qt::Key_L:
return kVK_ANSI_L; return kVK_ANSI_L;
case Qt::Key_M: case Qt::Key_M:
return kVK_ANSI_M; return kVK_ANSI_M;
case Qt::Key_N: case Qt::Key_N:
return kVK_ANSI_N; return kVK_ANSI_N;
case Qt::Key_O: case Qt::Key_O:
return kVK_ANSI_O; return kVK_ANSI_O;
case Qt::Key_P: case Qt::Key_P:
return kVK_ANSI_P; return kVK_ANSI_P;
case Qt::Key_Q: case Qt::Key_Q:
return kVK_ANSI_Q; return kVK_ANSI_Q;
case Qt::Key_R: case Qt::Key_R:
return kVK_ANSI_R; return kVK_ANSI_R;
case Qt::Key_S: case Qt::Key_S:
return kVK_ANSI_S; return kVK_ANSI_S;
case Qt::Key_T: case Qt::Key_T:
return kVK_ANSI_T; return kVK_ANSI_T;
case Qt::Key_U: case Qt::Key_U:
return kVK_ANSI_U; return kVK_ANSI_U;
case Qt::Key_V: case Qt::Key_V:
return kVK_ANSI_V; return kVK_ANSI_V;
case Qt::Key_W: case Qt::Key_W:
return kVK_ANSI_W; return kVK_ANSI_W;
case Qt::Key_X: case Qt::Key_X:
return kVK_ANSI_X; return kVK_ANSI_X;
case Qt::Key_Y: case Qt::Key_Y:
return kVK_ANSI_Y; return kVK_ANSI_Y;
case Qt::Key_Z: case Qt::Key_Z:
return kVK_ANSI_Z; return kVK_ANSI_Z;
case Qt::Key_0: case Qt::Key_0:
return kVK_ANSI_0; return kVK_ANSI_0;
case Qt::Key_1: case Qt::Key_1:
return kVK_ANSI_1; return kVK_ANSI_1;
case Qt::Key_2: case Qt::Key_2:
return kVK_ANSI_2; return kVK_ANSI_2;
case Qt::Key_3: case Qt::Key_3:
return kVK_ANSI_3; return kVK_ANSI_3;
case Qt::Key_4: case Qt::Key_4:
return kVK_ANSI_4; return kVK_ANSI_4;
case Qt::Key_5: case Qt::Key_5:
return kVK_ANSI_5; return kVK_ANSI_5;
case Qt::Key_6: case Qt::Key_6:
return kVK_ANSI_6; return kVK_ANSI_6;
case Qt::Key_7: case Qt::Key_7:
return kVK_ANSI_7; return kVK_ANSI_7;
case Qt::Key_8: case Qt::Key_8:
return kVK_ANSI_8; return kVK_ANSI_8;
case Qt::Key_9: case Qt::Key_9:
return kVK_ANSI_9; return kVK_ANSI_9;
case Qt::Key_Equal: case Qt::Key_Equal:
return kVK_ANSI_Equal; return kVK_ANSI_Equal;
case Qt::Key_Minus: case Qt::Key_Minus:
return kVK_ANSI_Minus; return kVK_ANSI_Minus;
case Qt::Key_BracketRight: case Qt::Key_BracketRight:
return kVK_ANSI_RightBracket; return kVK_ANSI_RightBracket;
case Qt::Key_BracketLeft: case Qt::Key_BracketLeft:
return kVK_ANSI_LeftBracket; return kVK_ANSI_LeftBracket;
case Qt::Key_QuoteDbl: case Qt::Key_QuoteDbl:
return kVK_ANSI_Quote; return kVK_ANSI_Quote;
case Qt::Key_Semicolon: case Qt::Key_Semicolon:
return kVK_ANSI_Semicolon; return kVK_ANSI_Semicolon;
case Qt::Key_Backslash: case Qt::Key_Backslash:
return kVK_ANSI_Backslash; return kVK_ANSI_Backslash;
case Qt::Key_Comma: case Qt::Key_Comma:
return kVK_ANSI_Comma; return kVK_ANSI_Comma;
case Qt::Key_Slash: case Qt::Key_Slash:
return kVK_ANSI_Slash; return kVK_ANSI_Slash;
case Qt::Key_Period: case Qt::Key_Period:
return kVK_ANSI_Period; return kVK_ANSI_Period;
case Qt::Key_Shift: case Qt::Key_Shift:
return kVK_Shift; return kVK_Shift;
case Qt::Key_Control: case Qt::Key_Control:
return kVK_Command; return kVK_Command;
case Qt::Key_Backspace: case Qt::Key_Backspace:
return kVK_Delete; return kVK_Delete;
case Qt::Key_Tab: case Qt::Key_Tab:
case Qt::Key_Backtab: case Qt::Key_Backtab:
return kVK_Tab; return kVK_Tab;
case Qt::Key_Enter: case Qt::Key_Enter:
case Qt::Key_Return: case Qt::Key_Return:
return kVK_Return; return kVK_Return;
case Qt::Key_CapsLock: case Qt::Key_CapsLock:
return kVK_CapsLock; return kVK_CapsLock;
case Qt::Key_Escape: case Qt::Key_Escape:
return kVK_Escape; return kVK_Escape;
case Qt::Key_Space: case Qt::Key_Space:
return kVK_Space; return kVK_Space;
case Qt::Key_PageUp: case Qt::Key_PageUp:
return kVK_PageUp; return kVK_PageUp;
case Qt::Key_PageDown: case Qt::Key_PageDown:
return kVK_PageDown; return kVK_PageDown;
case Qt::Key_End: case Qt::Key_End:
return kVK_End; return kVK_End;
case Qt::Key_Home: case Qt::Key_Home:
return kVK_Home; return kVK_Home;
case Qt::Key_Left: case Qt::Key_Left:
return kVK_LeftArrow; return kVK_LeftArrow;
case Qt::Key_Up: case Qt::Key_Up:
return kVK_UpArrow; return kVK_UpArrow;
case Qt::Key_Right: case Qt::Key_Right:
return kVK_RightArrow; return kVK_RightArrow;
case Qt::Key_Down: case Qt::Key_Down:
return kVK_DownArrow; return kVK_DownArrow;
case Qt::Key_Delete: case Qt::Key_Delete:
return kVK_ForwardDelete; return kVK_ForwardDelete;
case Qt::Key_Help: case Qt::Key_Help:
return kVK_Help; return kVK_Help;
case Qt::Key_F1: case Qt::Key_F1:
return kVK_F1; return kVK_F1;
case Qt::Key_F2: case Qt::Key_F2:
return kVK_F2; return kVK_F2;
case Qt::Key_F3: case Qt::Key_F3:
return kVK_F3; return kVK_F3;
case Qt::Key_F4: case Qt::Key_F4:
return kVK_F4; return kVK_F4;
case Qt::Key_F5: case Qt::Key_F5:
return kVK_F5; return kVK_F5;
case Qt::Key_F6: case Qt::Key_F6:
return kVK_F6; return kVK_F6;
case Qt::Key_F7: case Qt::Key_F7:
return kVK_F7; return kVK_F7;
case Qt::Key_F8: case Qt::Key_F8:
return kVK_F8; return kVK_F8;
case Qt::Key_F9: case Qt::Key_F9:
return kVK_F9; return kVK_F9;
case Qt::Key_F10: case Qt::Key_F10:
return kVK_F10; return kVK_F10;
case Qt::Key_F11: case Qt::Key_F11:
return kVK_F11; return kVK_F11;
case Qt::Key_F12: case Qt::Key_F12:
return kVK_F12; return kVK_F12;
case Qt::Key_F13: case Qt::Key_F13:
return kVK_F13; return kVK_F13;
case Qt::Key_F14: case Qt::Key_F14:
return kVK_F14; return kVK_F14;
case Qt::Key_F15: case Qt::Key_F15:
return kVK_F15; return kVK_F15;
case Qt::Key_F16: case Qt::Key_F16:
return kVK_F16; return kVK_F16;
default: default:
Q_ASSERT(false); return INVALID_KEYCODE;
return INVALID_KEYCODE;
} }
} }
// /**
// Translate qt key modifiers to mac os modifiers * Translate Qt key modifiers to macOS key modifiers
// see: https://doc.qt.io/qt-5/osx-issues.html#special-keys * provided by the Core Graphics component
// *
CGEventFlags AutoTypePlatformMac::qtToNativeModifiers(Qt::KeyboardModifiers modifiers, bool native) * @param modifiers Qt keyboard modifier(s)
* @returns macOS key modifier(s)
*/
CGEventFlags AutoTypePlatformMac::qtToNativeModifiers(Qt::KeyboardModifiers modifiers)
{ {
CGEventFlags nativeModifiers = CGEventFlags(0); auto nativeModifiers = CGEventFlags(0);
CGEventFlags shiftMod = CGEventFlags(shiftKey);
CGEventFlags cmdMod = CGEventFlags(cmdKey);
CGEventFlags optionMod = CGEventFlags(optionKey);
CGEventFlags controlMod = CGEventFlags(controlKey);
if (native) {
shiftMod = kCGEventFlagMaskShift;
cmdMod = kCGEventFlagMaskCommand;
optionMod = kCGEventFlagMaskAlternate;
controlMod = kCGEventFlagMaskControl;
}
if (modifiers & Qt::ShiftModifier) { if (modifiers & Qt::ShiftModifier) {
nativeModifiers = CGEventFlags(nativeModifiers | shiftMod); nativeModifiers = CGEventFlags(nativeModifiers | kCGEventFlagMaskShift);
} }
if (modifiers & Qt::ControlModifier) { if (modifiers & Qt::ControlModifier) {
nativeModifiers = CGEventFlags(nativeModifiers | cmdMod); nativeModifiers = CGEventFlags(nativeModifiers | kCGEventFlagMaskCommand);
} }
if (modifiers & Qt::AltModifier) { if (modifiers & Qt::AltModifier) {
nativeModifiers = CGEventFlags(nativeModifiers | optionMod); nativeModifiers = CGEventFlags(nativeModifiers | kCGEventFlagMaskAlternate);
} }
if (modifiers & Qt::MetaModifier) { if (modifiers & Qt::MetaModifier) {
nativeModifiers = CGEventFlags(nativeModifiers | controlMod); nativeModifiers = CGEventFlags(nativeModifiers | kCGEventFlagMaskControl);
} }
return nativeModifiers; return nativeModifiers;
} }
// /**
// Get window layer/level * Get window layer / level
// *
* @param window macOS window ref
* @returns layer number or -1 if window not found
*/
int AutoTypePlatformMac::windowLayer(CFDictionaryRef window) int AutoTypePlatformMac::windowLayer(CFDictionaryRef window)
{ {
int layer; int layer;
CFNumberRef layerRef = static_cast<CFNumberRef>(::CFDictionaryGetValue(window, kCGWindowLayer)); auto layerRef = static_cast<CFNumberRef>(::CFDictionaryGetValue(window, kCGWindowLayer));
if (layerRef != nullptr if (layerRef && ::CFNumberGetValue(layerRef, kCFNumberIntType, &layer)) {
&& ::CFNumberGetValue(layerRef, kCFNumberIntType, &layer)) {
return layer; return layer;
} }
return -1; return -1;
} }
// /**
// Get window title * Get window title for macOS window ref
// *
* @param window macOS window ref
* @returns window title if found
*/
QString AutoTypePlatformMac::windowTitle(CFDictionaryRef window) QString AutoTypePlatformMac::windowTitle(CFDictionaryRef window)
{ {
char buffer[MAX_WINDOW_TITLE_LENGTH]; char buffer[MAX_WINDOW_TITLE_LENGTH];
QString title; QString title;
CFStringRef titleRef = static_cast<CFStringRef>(::CFDictionaryGetValue(window, kCGWindowName)); auto titleRef = static_cast<CFStringRef>(::CFDictionaryGetValue(window, kCGWindowName));
if (titleRef != nullptr if (titleRef && ::CFStringGetCString(titleRef, buffer, MAX_WINDOW_TITLE_LENGTH, kCFStringEncodingUTF8)) {
&& ::CFStringGetCString(titleRef, buffer, MAX_WINDOW_TITLE_LENGTH, kCFStringEncodingUTF8)) {
title = QString::fromUtf8(buffer); title = QString::fromUtf8(buffer);
} }
return title; return title;
} }
//
// Carbon hotkey handler
//
OSStatus AutoTypePlatformMac::hotkeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
{
Q_UNUSED(nextHandler);
AutoTypePlatformMac *self = static_cast<AutoTypePlatformMac *>(userData);
EventHotKeyID hotkeyId;
if (::GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, nullptr, sizeof(hotkeyId), nullptr, &hotkeyId) == noErr
&& hotkeyId.id == HOTKEY_ID) {
emit self->globalShortcutTriggered();
}
return noErr;
}
// //
// ------------------------------ AutoTypeExecutorMac ------------------------------ // ------------------------------ AutoTypeExecutorMac ------------------------------
// //
@ -502,7 +511,7 @@ void AutoTypeExecutorMac::execKey(AutoTypeKey* action)
m_platform->sendKey(action->key, false); m_platform->sendKey(action->key, false);
} }
void AutoTypeExecutorMac::execClearField(AutoTypeClearField* action = nullptr) void AutoTypeExecutorMac::execClearField(AutoTypeClearField* action)
{ {
Q_UNUSED(action); Q_UNUSED(action);

View File

@ -19,12 +19,12 @@
#ifndef KEEPASSX_AUTOTYPEMAC_H #ifndef KEEPASSX_AUTOTYPEMAC_H
#define KEEPASSX_AUTOTYPEMAC_H #define KEEPASSX_AUTOTYPEMAC_H
#include <Carbon/Carbon.h> #include <ApplicationServices/ApplicationServices.h>
#include <QtPlugin> #include <QtPlugin>
#include <memory> #include <memory>
#include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeAction.h" #include "autotype/AutoTypeAction.h"
#include "autotype/AutoTypePlatformPlugin.h"
class AutoTypePlatformMac : public QObject, public AutoTypePlatformInterface class AutoTypePlatformMac : public QObject, public AutoTypePlatformInterface
{ {
@ -48,20 +48,19 @@ public:
bool raiseOwnWindow() override; bool raiseOwnWindow() override;
void sendChar(const QChar& ch, bool isKeyDown); void sendChar(const QChar& ch, bool isKeyDown);
void sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers); void sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers = 0);
signals: signals:
void globalShortcutTriggered(); void globalShortcutTriggered();
private: private:
EventHotKeyRef m_hotkeyRef; static void hotkeyHandler(void* userData);
EventHotKeyID m_hotkeyId; static CGKeyCode qtToNativeKeyCode(Qt::Key key);
static CGEventFlags qtToNativeModifiers(Qt::KeyboardModifiers modifiers);
static uint16 qtToNativeKeyCode(Qt::Key key);
static CGEventFlags qtToNativeModifiers(Qt::KeyboardModifiers modifiers, bool native);
static int windowLayer(CFDictionaryRef window); static int windowLayer(CFDictionaryRef window);
static QString windowTitle(CFDictionaryRef window); static QString windowTitle(CFDictionaryRef window);
static OSStatus hotkeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData);
void* m_globalMonitor;
}; };
class AutoTypeExecutorMac : public AutoTypeExecutor class AutoTypeExecutorMac : public AutoTypeExecutor
@ -77,4 +76,4 @@ private:
AutoTypePlatformMac* const m_platform; AutoTypePlatformMac* const m_platform;
}; };
#endif // KEEPASSX_AUTOTYPEMAC_H #endif // KEEPASSX_AUTOTYPEMAC_H

View File

@ -0,0 +1,160 @@
//
// Taken from HIToolbox/Events.h
//
/*
* Summary:
* Virtual keycodes
*
* Discussion:
* These constants are the virtual keycodes defined originally in
* Inside Mac Volume V, pg. V-191. They identify physical keys on a
* keyboard. Those constants with "ANSI" in the name are labeled
* according to the key position on an ANSI-standard US keyboard.
* For example, kVK_ANSI_A indicates the virtual keycode for the key
* with the letter 'A' in the US keyboard layout. Other keyboard
* layouts may have the 'A' key label on a different physical key;
* in this case, pressing 'A' will generate a different virtual
* keycode.
*/
#ifndef KEEPASSXC_AUTOTYPEMAC_KEYCODES_H
#define KEEPASSXC_AUTOTYPEMAC_KEYCODES_H
// clang-format off
enum {
kVK_ANSI_A = 0x00,
kVK_ANSI_S = 0x01,
kVK_ANSI_D = 0x02,
kVK_ANSI_F = 0x03,
kVK_ANSI_H = 0x04,
kVK_ANSI_G = 0x05,
kVK_ANSI_Z = 0x06,
kVK_ANSI_X = 0x07,
kVK_ANSI_C = 0x08,
kVK_ANSI_V = 0x09,
kVK_ANSI_B = 0x0B,
kVK_ANSI_Q = 0x0C,
kVK_ANSI_W = 0x0D,
kVK_ANSI_E = 0x0E,
kVK_ANSI_R = 0x0F,
kVK_ANSI_Y = 0x10,
kVK_ANSI_T = 0x11,
kVK_ANSI_1 = 0x12,
kVK_ANSI_2 = 0x13,
kVK_ANSI_3 = 0x14,
kVK_ANSI_4 = 0x15,
kVK_ANSI_6 = 0x16,
kVK_ANSI_5 = 0x17,
kVK_ANSI_Equal = 0x18,
kVK_ANSI_9 = 0x19,
kVK_ANSI_7 = 0x1A,
kVK_ANSI_Minus = 0x1B,
kVK_ANSI_8 = 0x1C,
kVK_ANSI_0 = 0x1D,
kVK_ANSI_RightBracket = 0x1E,
kVK_ANSI_O = 0x1F,
kVK_ANSI_U = 0x20,
kVK_ANSI_LeftBracket = 0x21,
kVK_ANSI_I = 0x22,
kVK_ANSI_P = 0x23,
kVK_ANSI_L = 0x25,
kVK_ANSI_J = 0x26,
kVK_ANSI_Quote = 0x27,
kVK_ANSI_K = 0x28,
kVK_ANSI_Semicolon = 0x29,
kVK_ANSI_Backslash = 0x2A,
kVK_ANSI_Comma = 0x2B,
kVK_ANSI_Slash = 0x2C,
kVK_ANSI_N = 0x2D,
kVK_ANSI_M = 0x2E,
kVK_ANSI_Period = 0x2F,
kVK_ANSI_Grave = 0x32,
kVK_ANSI_KeypadDecimal = 0x41,
kVK_ANSI_KeypadMultiply = 0x43,
kVK_ANSI_KeypadPlus = 0x45,
kVK_ANSI_KeypadClear = 0x47,
kVK_ANSI_KeypadDivide = 0x4B,
kVK_ANSI_KeypadEnter = 0x4C,
kVK_ANSI_KeypadMinus = 0x4E,
kVK_ANSI_KeypadEquals = 0x51,
kVK_ANSI_Keypad0 = 0x52,
kVK_ANSI_Keypad1 = 0x53,
kVK_ANSI_Keypad2 = 0x54,
kVK_ANSI_Keypad3 = 0x55,
kVK_ANSI_Keypad4 = 0x56,
kVK_ANSI_Keypad5 = 0x57,
kVK_ANSI_Keypad6 = 0x58,
kVK_ANSI_Keypad7 = 0x59,
kVK_ANSI_Keypad8 = 0x5B,
kVK_ANSI_Keypad9 = 0x5C
};
/* keycodes for keys that are independent of keyboard layout*/
enum {
kVK_Return = 0x24,
kVK_Tab = 0x30,
kVK_Space = 0x31,
kVK_Delete = 0x33,
kVK_Escape = 0x35,
kVK_Command = 0x37,
kVK_Shift = 0x38,
kVK_CapsLock = 0x39,
kVK_Option = 0x3A,
kVK_Control = 0x3B,
kVK_RightCommand = 0x36,
kVK_RightShift = 0x3C,
kVK_RightOption = 0x3D,
kVK_RightControl = 0x3E,
kVK_Function = 0x3F,
kVK_F17 = 0x40,
kVK_VolumeUp = 0x48,
kVK_VolumeDown = 0x49,
kVK_Mute = 0x4A,
kVK_F18 = 0x4F,
kVK_F19 = 0x50,
kVK_F20 = 0x5A,
kVK_F5 = 0x60,
kVK_F6 = 0x61,
kVK_F7 = 0x62,
kVK_F3 = 0x63,
kVK_F8 = 0x64,
kVK_F9 = 0x65,
kVK_F11 = 0x67,
kVK_F13 = 0x69,
kVK_F16 = 0x6A,
kVK_F14 = 0x6B,
kVK_F10 = 0x6D,
kVK_F12 = 0x6F,
kVK_F15 = 0x71,
kVK_Help = 0x72,
kVK_Home = 0x73,
kVK_PageUp = 0x74,
kVK_ForwardDelete = 0x75,
kVK_F4 = 0x76,
kVK_End = 0x77,
kVK_F2 = 0x78,
kVK_PageDown = 0x79,
kVK_F1 = 0x7A,
kVK_LeftArrow = 0x7B,
kVK_RightArrow = 0x7C,
kVK_DownArrow = 0x7D,
kVK_UpArrow = 0x7E
};
/* ISO keyboards only*/
enum {
kVK_ISO_Section = 0x0A
};
/* JIS keyboards only*/
enum {
kVK_JIS_Yen = 0x5D,
kVK_JIS_Underscore = 0x5E,
kVK_JIS_KeypadComma = 0x5F,
kVK_JIS_Eisu = 0x66,
kVK_JIS_Kana = 0x68
};
// clang-format on
#endif

View File

@ -1,7 +1,7 @@
set(autotype_mac_SOURCES AutoTypeMac.cpp) set(autotype_mac_SOURCES AutoTypeMac.cpp)
add_library(keepassx-autotype-cocoa MODULE ${autotype_mac_SOURCES}) add_library(keepassx-autotype-cocoa MODULE ${autotype_mac_SOURCES})
set_target_properties(keepassx-autotype-cocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit -framework Carbon") set_target_properties(keepassx-autotype-cocoa PROPERTIES LINK_FLAGS "-framework Foundation -framework AppKit")
target_link_libraries(keepassx-autotype-cocoa ${PROGNAME} Qt5::Core Qt5::Widgets) target_link_libraries(keepassx-autotype-cocoa ${PROGNAME} Qt5::Core Qt5::Widgets)
if(WITH_APP_BUNDLE) if(WITH_APP_BUNDLE)

View File

@ -59,3 +59,8 @@ void BrowserAccessControlDialog::setRemember(bool r)
{ {
m_ui->rememberDecisionCheckBox->setChecked(r); m_ui->rememberDecisionCheckBox->setChecked(r);
} }
void BrowserAccessControlDialog::setHTTPAuth(bool httpAuth)
{
m_ui->rememberDecisionCheckBox->setVisible(!httpAuth);
}

View File

@ -41,6 +41,7 @@ public:
void setItems(const QList<Entry*>& items); void setItems(const QList<Entry*>& items);
bool remember() const; bool remember() const;
void setRemember(bool r); void setRemember(bool r);
void setHTTPAuth(bool httpAuth);
private: private:
QScopedPointer<Ui::BrowserAccessControlDialog> m_ui; QScopedPointer<Ui::BrowserAccessControlDialog> m_ui;

View File

@ -48,6 +48,9 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="allowButton"> <widget class="QPushButton" name="allowButton">
<property name="accessibleName">
<string>Allow access</string>
</property>
<property name="text"> <property name="text">
<string>Allow</string> <string>Allow</string>
</property> </property>
@ -55,6 +58,9 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="denyButton"> <widget class="QPushButton" name="denyButton">
<property name="accessibleName">
<string>Deny access</string>
</property>
<property name="text"> <property name="text">
<string>Deny</string> <string>Deny</string>
</property> </property>

View File

@ -149,6 +149,16 @@ QJsonObject BrowserAction::handleGetDatabaseHash(const QJsonObject& json, const
QJsonObject message = buildMessage(newNonce); QJsonObject message = buildMessage(newNonce);
message["hash"] = hash; message["hash"] = hash;
// Update a legacy database hash if found
const QJsonArray hashes = decrypted.value("connectedKeys").toArray();
if (!hashes.isEmpty()) {
const QString legacyHash = getLegacyDatabaseHash();
if (hashes.contains(legacyHash)) {
message["oldHash"] = legacyHash;
}
}
return buildResponse(action, message, newNonce); return buildResponse(action, message, newNonce);
} }
@ -278,18 +288,18 @@ QJsonObject BrowserAction::handleGetLogins(const QJsonObject& json, const QStrin
QJsonObject BrowserAction::handleGeneratePassword(const QJsonObject& json, const QString& action) QJsonObject BrowserAction::handleGeneratePassword(const QJsonObject& json, const QString& action)
{ {
const QString nonce = json.value("nonce").toString(); auto nonce = json.value("nonce").toString();
const QString password = browserSettings()->generatePassword(); auto password = browserSettings()->generatePassword();
if (nonce.isEmpty() || password.isEmpty()) { if (nonce.isEmpty() || password.isEmpty()) {
return QJsonObject(); return QJsonObject();
} }
// For backwards compatibility
password["login"] = password["entropy"];
QJsonArray arr; QJsonArray arr;
QJsonObject passwd; arr.append(password);
passwd["login"] = QString::number(password.length() * 8); // bits;
passwd["password"] = password;
arr.append(passwd);
const QString newNonce = incrementNonce(nonce); const QString newNonce = incrementNonce(nonce);
@ -329,10 +339,11 @@ QJsonObject BrowserAction::handleSetLogin(const QJsonObject& json, const QString
const QString groupUuid = decrypted.value("groupUuid").toString(); const QString groupUuid = decrypted.value("groupUuid").toString();
const QString realm; const QString realm;
BrowserService::ReturnValue result = BrowserService::ReturnValue::Success;
if (uuid.isEmpty()) { if (uuid.isEmpty()) {
m_browserService.addEntry(id, login, password, url, submitUrl, realm, group, groupUuid); m_browserService.addEntry(id, login, password, url, submitUrl, realm, group, groupUuid);
} else { } else {
m_browserService.updateEntry(id, uuid, login, password, url, submitUrl); result = m_browserService.updateEntry(id, uuid, login, password, url, submitUrl);
} }
const QString newNonce = incrementNonce(nonce); const QString newNonce = incrementNonce(nonce);
@ -340,7 +351,7 @@ QJsonObject BrowserAction::handleSetLogin(const QJsonObject& json, const QString
QJsonObject message = buildMessage(newNonce); QJsonObject message = buildMessage(newNonce);
message["count"] = QJsonValue::Null; message["count"] = QJsonValue::Null;
message["entries"] = QJsonValue::Null; message["entries"] = QJsonValue::Null;
message["error"] = ""; message["error"] = getReturnValue(result);
message["hash"] = hash; message["hash"] = hash;
return buildResponse(action, message, newNonce); return buildResponse(action, message, newNonce);
@ -513,7 +524,28 @@ QString BrowserAction::getErrorMessage(const int errorCode) const
} }
} }
QString BrowserAction::getReturnValue(const BrowserService::ReturnValue returnValue) const
{
switch (returnValue) {
case BrowserService::ReturnValue::Success:
return QString("success");
case BrowserService::ReturnValue::Error:
return QString("error");
case BrowserService::ReturnValue::Canceled:
return QString("canceled");
}
return QString("error");
}
QString BrowserAction::getDatabaseHash() QString BrowserAction::getDatabaseHash()
{
QMutexLocker locker(&m_mutex);
QByteArray hash =
QCryptographicHash::hash(m_browserService.getDatabaseRootUuid().toUtf8(), QCryptographicHash::Sha256).toHex();
return QString(hash);
}
QString BrowserAction::getLegacyDatabaseHash()
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
QByteArray hash = QByteArray hash =

View File

@ -73,7 +73,9 @@ private:
QJsonObject buildResponse(const QString& action, const QJsonObject& message, const QString& nonce); QJsonObject buildResponse(const QString& action, const QJsonObject& message, const QString& nonce);
QJsonObject getErrorReply(const QString& action, const int errorCode) const; QJsonObject getErrorReply(const QString& action, const int errorCode) const;
QString getErrorMessage(const int errorCode) const; QString getErrorMessage(const int errorCode) const;
QString getReturnValue(const BrowserService::ReturnValue returnValue) const;
QString getDatabaseHash(); QString getDatabaseHash();
QString getLegacyDatabaseHash();
QString encryptMessage(const QJsonObject& message, const QString& nonce); QString encryptMessage(const QJsonObject& message, const QString& nonce);
QJsonObject decryptMessage(const QString& message, const QString& nonce); QJsonObject decryptMessage(const QString& message, const QString& nonce);

View File

@ -45,7 +45,7 @@ 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. %3")
.arg("<a href=\"https://addons.mozilla.org/en-US/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>",
snapInstructions)); snapInstructions));
@ -53,12 +53,6 @@ BrowserOptionDialog::BrowserOptionDialog(QWidget* parent)
m_ui->scriptWarningWidget->setVisible(false); m_ui->scriptWarningWidget->setVisible(false);
m_ui->scriptWarningWidget->setAutoHideTimeout(-1); m_ui->scriptWarningWidget->setAutoHideTimeout(-1);
m_ui->scriptWarningWidget->showMessage(
tr("<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: "),
MessageWidget::Warning);
m_ui->warningWidget->showMessage(tr("<b>Warning:</b> The following options can be dangerous!"), m_ui->warningWidget->showMessage(tr("<b>Warning:</b> The following options can be dangerous!"),
MessageWidget::Warning); MessageWidget::Warning);
@ -116,6 +110,7 @@ void BrowserOptionDialog::loadSettings()
m_ui->httpAuthPermission->setChecked(settings->httpAuthPermission()); m_ui->httpAuthPermission->setChecked(settings->httpAuthPermission());
m_ui->searchInAllDatabases->setChecked(settings->searchInAllDatabases()); m_ui->searchInAllDatabases->setChecked(settings->searchInAllDatabases());
m_ui->supportKphFields->setChecked(settings->supportKphFields()); m_ui->supportKphFields->setChecked(settings->supportKphFields());
m_ui->noMigrationPrompt->setChecked(settings->noMigrationPrompt());
m_ui->supportBrowserProxy->setChecked(settings->supportBrowserProxy()); m_ui->supportBrowserProxy->setChecked(settings->supportBrowserProxy());
m_ui->useCustomProxy->setChecked(settings->useCustomProxy()); m_ui->useCustomProxy->setChecked(settings->useCustomProxy());
m_ui->customProxyLocation->setText(settings->customProxyLocation()); m_ui->customProxyLocation->setText(settings->customProxyLocation());
@ -153,9 +148,13 @@ void BrowserOptionDialog::loadSettings()
// Check for native messaging host location errors // Check for native messaging host location errors
QString path; QString path;
if (!settings->checkIfProxyExists(path)) { if (!settings->checkIfProxyExists(path)) {
QString text = m_ui->scriptWarningWidget->text(); auto text =
text.append(path); tr("<b>Warning</b>, the keepassxc-proxy application was not found!"
m_ui->scriptWarningWidget->setText(text); "<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")
.arg(path);
m_ui->scriptWarningWidget->showMessage(text, MessageWidget::Warning);
m_ui->scriptWarningWidget->setVisible(true); m_ui->scriptWarningWidget->setVisible(true);
} else { } else {
m_ui->scriptWarningWidget->setVisible(false); m_ui->scriptWarningWidget->setVisible(false);
@ -183,6 +182,7 @@ void BrowserOptionDialog::saveSettings()
settings->setHttpAuthPermission(m_ui->httpAuthPermission->isChecked()); settings->setHttpAuthPermission(m_ui->httpAuthPermission->isChecked());
settings->setSearchInAllDatabases(m_ui->searchInAllDatabases->isChecked()); settings->setSearchInAllDatabases(m_ui->searchInAllDatabases->isChecked());
settings->setSupportKphFields(m_ui->supportKphFields->isChecked()); settings->setSupportKphFields(m_ui->supportKphFields->isChecked());
settings->setNoMigrationPrompt(m_ui->noMigrationPrompt->isChecked());
settings->setChromeSupport(m_ui->chromeSupport->isChecked()); settings->setChromeSupport(m_ui->chromeSupport->isChecked());
settings->setChromiumSupport(m_ui->chromiumSupport->isChecked()); settings->setChromiumSupport(m_ui->chromiumSupport->isChecked());

View File

@ -35,7 +35,7 @@
<string>This is required for accessing your databases with KeePassXC-Browser</string> <string>This is required for accessing your databases with KeePassXC-Browser</string>
</property> </property>
<property name="text"> <property name="text">
<string>Enable KeepassXC browser integration</string> <string>Enable browser integration</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -59,6 +59,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Browsers installed as snaps are currently not supported.</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QLabel" name="extensionLabel"/> <widget class="QLabel" name="extensionLabel"/>
</item> </item>
@ -297,7 +304,7 @@
<item> <item>
<widget class="QCheckBox" name="searchInAllDatabases"> <widget class="QCheckBox" name="searchInAllDatabases">
<property name="toolTip"> <property name="toolTip">
<string>Only the selected database has to be connected with a client.</string> <string>All databases connected to the extension will return matching credentials.</string>
</property> </property>
<property name="text"> <property name="text">
<string extracomment="Credentials mean login data requested via browser extension">Searc&amp;h in all opened databases for matching credentials</string> <string extracomment="Credentials mean login data requested via browser extension">Searc&amp;h in all opened databases for matching credentials</string>
@ -314,6 +321,16 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="noMigrationPrompt">
<property name="toolTip">
<string>Don't display the popup suggesting migration of legacy KeePassHTTP settings.</string>
</property>
<property name="text">
<string>&amp;Do not prompt for KeePassHTTP settings migration.</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="updateBinaryPath"> <widget class="QCheckBox" name="updateBinaryPath">
<property name="toolTip"> <property name="toolTip">
@ -348,6 +365,9 @@
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>
<widget class="QLineEdit" name="customProxyLocation"> <widget class="QLineEdit" name="customProxyLocation">
<property name="accessibleName">
<string>Custom proxy location field</string>
</property>
<property name="maxLength"> <property name="maxLength">
<number>999</number> <number>999</number>
</property> </property>
@ -358,6 +378,9 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="customProxyLocationBrowseButton"> <widget class="QPushButton" name="customProxyLocationBrowseButton">
<property name="accessibleName">
<string>Browser for custom proxy file</string>
</property>
<property name="text"> <property name="text">
<string extracomment="Button for opening file dialog">Browse...</string> <string extracomment="Button for opening file dialog">Browse...</string>
</property> </property>

View File

@ -17,6 +17,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <QCheckBox>
#include <QInputDialog> #include <QInputDialog>
#include <QJsonArray> #include <QJsonArray>
#include <QMessageBox> #include <QMessageBox>
@ -40,15 +41,20 @@
#include "gui/macutils/MacUtils.h" #include "gui/macutils/MacUtils.h"
#endif #endif
const char BrowserService::KEEPASSXCBROWSER_NAME[] = "KeePassXC-Browser Settings"; const QString BrowserService::KEEPASSXCBROWSER_NAME = QStringLiteral("KeePassXC-Browser Settings");
const char BrowserService::KEEPASSXCBROWSER_OLD_NAME[] = "keepassxc-browser Settings"; const QString BrowserService::KEEPASSXCBROWSER_OLD_NAME = QStringLiteral("keepassxc-browser Settings");
const char BrowserService::ASSOCIATE_KEY_PREFIX[] = "KPXC_BROWSER_"; const QString BrowserService::ASSOCIATE_KEY_PREFIX = QStringLiteral("KPXC_BROWSER_");
static const char KEEPASSXCBROWSER_GROUP_NAME[] = "KeePassXC-Browser Passwords"; static const QString KEEPASSXCBROWSER_GROUP_NAME = QStringLiteral("KeePassXC-Browser Passwords");
static int KEEPASSXCBROWSER_DEFAULT_ICON = 1; static int KEEPASSXCBROWSER_DEFAULT_ICON = 1;
// These are for the settings and password conversion // These are for the settings and password conversion
const char BrowserService::LEGACY_ASSOCIATE_KEY_PREFIX[] = "Public Key: "; const QString BrowserService::LEGACY_ASSOCIATE_KEY_PREFIX = QStringLiteral("Public Key: ");
static const char KEEPASSHTTP_NAME[] = "KeePassHttp Settings"; static const QString KEEPASSHTTP_NAME = QStringLiteral("KeePassHttp Settings");
static const char KEEPASSHTTP_GROUP_NAME[] = "KeePassHttp Passwords"; static const QString KEEPASSHTTP_GROUP_NAME = QStringLiteral("KeePassHttp Passwords");
// Extra entry related options saved in custom data
const QString BrowserService::OPTION_SKIP_AUTO_SUBMIT = QStringLiteral("BrowserSkipAutoSubmit");
const QString BrowserService::OPTION_HIDE_ENTRY = QStringLiteral("BrowserHideEntry");
// Multiple URL's
const QString BrowserService::ADDITIONAL_URL = QStringLiteral("KP2A_URL");
BrowserService::BrowserService(DatabaseTabWidget* parent) BrowserService::BrowserService(DatabaseTabWidget* parent)
: m_dbTabWidget(parent) : m_dbTabWidget(parent)
@ -298,9 +304,9 @@ QString BrowserService::storeKey(const QString& key)
QInputDialog keyDialog; QInputDialog keyDialog;
connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), &keyDialog, SLOT(reject())); connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), &keyDialog, SLOT(reject()));
keyDialog.setWindowTitle(tr("KeePassXC: New key association request")); keyDialog.setWindowTitle(tr("KeePassXC: New key association request"));
keyDialog.setLabelText(tr("You have received an association request for the above key.\n\n" keyDialog.setLabelText(tr("You have received an association request for the following database:\n%1\n\n"
"If you would like to allow it access to your KeePassXC database,\n" "Give the connection a unique name or ID, for example:\nchrome-laptop.")
"give it a unique name to identify and accept it.")); .arg(db->metadata()->name().toHtmlEscaped()));
keyDialog.setOkButtonText(tr("Save and allow access")); keyDialog.setOkButtonText(tr("Save and allow access"));
keyDialog.setWindowFlags(keyDialog.windowFlags() | Qt::WindowStaysOnTopHint); keyDialog.setWindowFlags(keyDialog.windowFlags() | Qt::WindowStaysOnTopHint);
raiseWindow(); raiseWindow();
@ -316,7 +322,7 @@ QString BrowserService::storeKey(const QString& key)
return {}; return {};
} }
contains = db->metadata()->customData()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + id); contains = db->metadata()->customData()->contains(ASSOCIATE_KEY_PREFIX + id);
if (contains) { if (contains) {
dialogResult = MessageBox::warning(nullptr, dialogResult = MessageBox::warning(nullptr,
tr("KeePassXC: Overwrite existing key?"), tr("KeePassXC: Overwrite existing key?"),
@ -329,7 +335,7 @@ QString BrowserService::storeKey(const QString& key)
} while (contains && dialogResult == MessageBox::Cancel); } while (contains && dialogResult == MessageBox::Cancel);
hideWindow(); hideWindow();
db->metadata()->customData()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + id, key); db->metadata()->customData()->set(ASSOCIATE_KEY_PREFIX + id, key);
return id; return id;
} }
@ -340,7 +346,7 @@ QString BrowserService::getKey(const QString& id)
return {}; return {};
} }
return db->metadata()->customData()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + id); return db->metadata()->customData()->value(ASSOCIATE_KEY_PREFIX + id);
} }
QJsonArray BrowserService::findMatchingEntries(const QString& id, QJsonArray BrowserService::findMatchingEntries(const QString& id,
@ -373,7 +379,12 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id,
// Check entries for authorization // Check entries for authorization
QList<Entry*> pwEntriesToConfirm; QList<Entry*> pwEntriesToConfirm;
QList<Entry*> pwEntries; QList<Entry*> pwEntries;
for (Entry* entry : searchEntries(url, keyList)) { for (auto* entry : searchEntries(url, keyList)) {
if (entry->customData()->contains(BrowserService::OPTION_HIDE_ENTRY)
&& entry->customData()->value(BrowserService::OPTION_HIDE_ENTRY) == "true") {
continue;
}
// HTTP Basic Auth always needs a confirmation // HTTP Basic Auth always needs a confirmation
if (!ignoreHttpAuth && httpAuth) { if (!ignoreHttpAuth && httpAuth) {
pwEntriesToConfirm.append(entry); pwEntriesToConfirm.append(entry);
@ -399,7 +410,7 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id,
} }
// Confirm entries // Confirm entries
if (confirmEntries(pwEntriesToConfirm, url, host, submitHost, realm)) { if (confirmEntries(pwEntriesToConfirm, url, host, submitUrl, realm, httpAuth)) {
pwEntries.append(pwEntriesToConfirm); pwEntries.append(pwEntriesToConfirm);
} }
@ -416,8 +427,8 @@ QJsonArray BrowserService::findMatchingEntries(const QString& id,
pwEntries = sortEntries(pwEntries, host, submitUrl); pwEntries = sortEntries(pwEntries, host, submitUrl);
// Fill the list // Fill the list
for (Entry* entry : pwEntries) { for (auto* entry : pwEntries) {
result << prepareEntry(entry); result.append(prepareEntry(entry));
} }
return result; return result;
@ -489,17 +500,19 @@ void BrowserService::addEntry(const QString& id,
config.save(entry); config.save(entry);
} }
void BrowserService::updateEntry(const QString& id, BrowserService::ReturnValue BrowserService::updateEntry(const QString& id,
const QString& uuid, const QString& uuid,
const QString& login, const QString& login,
const QString& password, const QString& password,
const QString& url, const QString& url,
const QString& submitUrl) const QString& submitUrl)
{ {
ReturnValue result = ReturnValue::Error;
if (thread() != QThread::currentThread()) { if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(this, QMetaObject::invokeMethod(this,
"updateEntry", "updateEntry",
Qt::BlockingQueuedConnection, Qt::BlockingQueuedConnection,
Q_RETURN_ARG(ReturnValue, result),
Q_ARG(QString, id), Q_ARG(QString, id),
Q_ARG(QString, uuid), Q_ARG(QString, uuid),
Q_ARG(QString, login), Q_ARG(QString, login),
@ -510,14 +523,14 @@ void BrowserService::updateEntry(const QString& id,
auto db = selectedDatabase(); auto db = selectedDatabase();
if (!db) { if (!db) {
return; return ReturnValue::Error;
} }
Entry* entry = db->rootGroup()->findEntryByUuid(Tools::hexToUuid(uuid)); Entry* entry = db->rootGroup()->findEntryByUuid(Tools::hexToUuid(uuid));
if (!entry) { if (!entry) {
// If entry is not found for update, add a new one to the selected database // If entry is not found for update, add a new one to the selected database
addEntry(id, login, password, url, submitUrl, "", "", "", db); addEntry(id, login, password, url, submitUrl, "", "", "", db);
return; return ReturnValue::Success;
} }
// Check if the entry password is a reference. If so, update the original entry instead // Check if the entry password is a reference. If so, update the original entry instead
@ -526,14 +539,14 @@ void BrowserService::updateEntry(const QString& id,
if (!referenceUuid.isNull()) { if (!referenceUuid.isNull()) {
entry = db->rootGroup()->findEntryByUuid(referenceUuid); entry = db->rootGroup()->findEntryByUuid(referenceUuid);
if (!entry) { if (!entry) {
return; return ReturnValue::Error;
} }
} }
} }
QString username = entry->username(); QString username = entry->username();
if (username.isEmpty()) { if (username.isEmpty()) {
return; return ReturnValue::Error;
} }
if (username.compare(login, Qt::CaseSensitive) != 0 if (username.compare(login, Qt::CaseSensitive) != 0
@ -557,10 +570,15 @@ void BrowserService::updateEntry(const QString& id,
} }
entry->setPassword(password); entry->setPassword(password);
entry->endUpdate(); entry->endUpdate();
result = ReturnValue::Success;
} else {
result = ReturnValue::Canceled;
} }
hideWindow(); hideWindow();
} }
return result;
} }
QList<Entry*> QList<Entry*>
@ -572,22 +590,30 @@ BrowserService::searchEntries(const QSharedPointer<Database>& db, const QString&
return entries; return entries;
} }
for (Entry* entry : EntrySearcher().search(baseDomain(hostname), rootGroup)) { for (const auto& group : rootGroup->groupsRecursive(true)) {
QString entryUrl = entry->url(); if (group->isRecycled() || !group->resolveSearchingEnabled()) {
QUrl entryQUrl(entryUrl);
QString entryScheme = entryQUrl.scheme();
QUrl qUrl(url);
// Ignore entry if port or scheme defined in the URL doesn't match
if ((entryQUrl.port() > 0 && entryQUrl.port() != qUrl.port())
|| (browserSettings()->matchUrlScheme() && !entryScheme.isEmpty()
&& entryScheme.compare(qUrl.scheme()) != 0)) {
continue; continue;
} }
// Filter to match hostname in URL field for (auto* entry : group->entries()) {
if ((!entryUrl.isEmpty() && hostname.contains(entryUrl)) if (entry->isRecycled()) {
|| (matchUrlScheme(entryUrl) && hostname.endsWith(entryQUrl.host()))) { continue;
}
// Search for additional URL's starting with KP2A_URL
if (entry->attributes()->keys().contains(ADDITIONAL_URL)) {
for (const auto& key : entry->attributes()->keys()) {
if (key.startsWith(ADDITIONAL_URL) && handleURL(entry->attributes()->value(key), hostname, url)) {
entries.append(entry);
continue;
}
}
}
if (!handleURL(entry->url(), hostname, url)) {
continue;
}
entries.append(entry); entries.append(entry);
} }
} }
@ -597,6 +623,17 @@ BrowserService::searchEntries(const QSharedPointer<Database>& db, const QString&
QList<Entry*> BrowserService::searchEntries(const QString& url, const StringPairList& keyList) QList<Entry*> BrowserService::searchEntries(const QString& url, const StringPairList& keyList)
{ {
// Check if database is connected with KeePassXC-Browser
auto databaseConnected = [&](const QSharedPointer<Database>& db) {
for (const StringPair& keyPair : keyList) {
QString key = db->metadata()->customData()->value(ASSOCIATE_KEY_PREFIX + keyPair.first);
if (!key.isEmpty() && keyPair.second == key) {
return true;
}
}
return false;
};
// Get the list of databases to search // Get the list of databases to search
QList<QSharedPointer<Database>> databases; QList<QSharedPointer<Database>> databases;
if (browserSettings()->searchInAllDatabases()) { if (browserSettings()->searchInAllDatabases()) {
@ -604,19 +641,16 @@ QList<Entry*> BrowserService::searchEntries(const QString& url, const StringPair
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
if (auto* dbWidget = qobject_cast<DatabaseWidget*>(m_dbTabWidget->widget(i))) { if (auto* dbWidget = qobject_cast<DatabaseWidget*>(m_dbTabWidget->widget(i))) {
if (const auto& db = dbWidget->database()) { if (const auto& db = dbWidget->database()) {
// Check if database is connected with KeePassXC-Browser if (databaseConnected(db)) {
for (const StringPair& keyPair : keyList) { databases << db;
QString key =
db->metadata()->customData()->value(QLatin1String(ASSOCIATE_KEY_PREFIX) + keyPair.first);
if (!key.isEmpty() && keyPair.second == key) {
databases << db;
}
} }
} }
} }
} }
} else if (const auto& db = getDatabase()) { } else if (const auto& db = getDatabase()) {
databases << db; if (databaseConnected(db)) {
databases << db;
}
} }
// Search entries matching the hostname // Search entries matching the hostname
@ -644,7 +678,7 @@ void BrowserService::convertAttributesToCustomData(const QSharedPointer<Database
int counter = 0; int counter = 0;
int keyCounter = 0; int keyCounter = 0;
for (Entry* entry : entries) { for (auto* entry : entries) {
if (progress.wasCanceled()) { if (progress.wasCanceled()) {
return; return;
} }
@ -697,12 +731,9 @@ void BrowserService::convertAttributesToCustomData(const QSharedPointer<Database
return; return;
} }
const QString keePassBrowserGroupName = QLatin1String(KEEPASSXCBROWSER_GROUP_NAME); for (auto* g : rootGroup->groupsRecursive(true)) {
const QString keePassHttpGroupName = QLatin1String(KEEPASSHTTP_GROUP_NAME); if (g->name() == KEEPASSHTTP_GROUP_NAME) {
g->setName(KEEPASSXCBROWSER_GROUP_NAME);
for (Group* g : rootGroup->groupsRecursive(true)) {
if (g->name() == keePassHttpGroupName) {
g->setName(keePassBrowserGroupName);
break; break;
} }
} }
@ -721,7 +752,7 @@ QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QStrin
// Build map of prioritized entries // Build map of prioritized entries
QMultiMap<int, Entry*> priorities; QMultiMap<int, Entry*> priorities;
for (Entry* entry : pwEntries) { for (auto* entry : pwEntries) {
priorities.insert(sortPriority(entry, host, submitUrl, baseSubmitUrl), entry); priorities.insert(sortPriority(entry, host, submitUrl, baseSubmitUrl), entry);
} }
@ -755,8 +786,9 @@ QList<Entry*> BrowserService::sortEntries(QList<Entry*>& pwEntries, const QStrin
bool BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm, bool BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm,
const QString& url, const QString& url,
const QString& host, const QString& host,
const QString& submitHost, const QString& submitUrl,
const QString& realm) const QString& realm,
const bool httpAuth)
{ {
if (pwEntriesToConfirm.isEmpty() || m_dialogActive) { if (pwEntriesToConfirm.isEmpty() || m_dialogActive) {
return false; return false;
@ -765,17 +797,19 @@ bool BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm,
m_dialogActive = true; m_dialogActive = true;
BrowserAccessControlDialog accessControlDialog; BrowserAccessControlDialog accessControlDialog;
connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), &accessControlDialog, SLOT(reject())); connect(m_dbTabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), &accessControlDialog, SLOT(reject()));
accessControlDialog.setUrl(url); accessControlDialog.setUrl(!submitUrl.isEmpty() ? submitUrl : url);
accessControlDialog.setItems(pwEntriesToConfirm); accessControlDialog.setItems(pwEntriesToConfirm);
accessControlDialog.setHTTPAuth(httpAuth);
raiseWindow(); raiseWindow();
accessControlDialog.show(); accessControlDialog.show();
accessControlDialog.activateWindow(); accessControlDialog.activateWindow();
accessControlDialog.raise(); accessControlDialog.raise();
const QString submitHost = QUrl(submitUrl).host();
int res = accessControlDialog.exec(); int res = accessControlDialog.exec();
if (accessControlDialog.remember()) { if (accessControlDialog.remember()) {
for (Entry* entry : pwEntriesToConfirm) { for (auto* entry : pwEntriesToConfirm) {
BrowserEntryConfig config; BrowserEntryConfig config;
config.load(entry); config.load(entry);
if (res == QDialog::Accepted) { if (res == QDialog::Accepted) {
@ -820,14 +854,18 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry)
res["expired"] = "true"; res["expired"] = "true";
} }
if (entry->customData()->contains(BrowserService::OPTION_SKIP_AUTO_SUBMIT)) {
res["skipAutoSubmit"] = entry->customData()->value(BrowserService::OPTION_SKIP_AUTO_SUBMIT);
}
if (browserSettings()->supportKphFields()) { if (browserSettings()->supportKphFields()) {
const EntryAttributes* attr = entry->attributes(); const EntryAttributes* attr = entry->attributes();
QJsonArray stringFields; QJsonArray stringFields;
for (const QString& key : attr->keys()) { for (const auto& key : attr->keys()) {
if (key.startsWith(QLatin1String("KPH: "))) { if (key.startsWith("KPH: ")) {
QJsonObject sField; QJsonObject sField;
sField[key] = entry->resolveMultiplePlaceholders(attr->value(key)); sField[key] = entry->resolveMultiplePlaceholders(attr->value(key));
stringFields << sField; stringFields.append(sField);
} }
} }
res["stringFields"] = stringFields; res["stringFields"] = stringFields;
@ -869,18 +907,15 @@ Group* BrowserService::getDefaultEntryGroup(const QSharedPointer<Database>& sele
return nullptr; return nullptr;
} }
const QString groupName =
QLatin1String(KEEPASSXCBROWSER_GROUP_NAME);
for (auto* g : rootGroup->groupsRecursive(true)) { for (auto* g : rootGroup->groupsRecursive(true)) {
if (g->name() == groupName && !g->isRecycled()) { if (g->name() == KEEPASSXCBROWSER_GROUP_NAME && !g->isRecycled()) {
return db->rootGroup()->findGroupByUuid(g->uuid()); return db->rootGroup()->findGroupByUuid(g->uuid());
} }
} }
auto* group = new Group(); auto* group = new Group();
group->setUuid(QUuid::createUuid()); group->setUuid(QUuid::createUuid());
group->setName(groupName); group->setName(KEEPASSXCBROWSER_GROUP_NAME);
group->setIcon(KEEPASSXCBROWSER_DEFAULT_ICON); group->setIcon(KEEPASSXCBROWSER_DEFAULT_ICON);
group->setParent(rootGroup); group->setParent(rootGroup);
return group; return group;
@ -958,6 +993,26 @@ bool BrowserService::removeFirstDomain(QString& hostname)
return false; return false;
} }
bool BrowserService::handleURL(const QString& entryUrl, const QString& hostname, const QString& url)
{
QUrl entryQUrl(entryUrl);
QString entryScheme = entryQUrl.scheme();
QUrl qUrl(url);
// Ignore entry if port or scheme defined in the URL doesn't match
if ((entryQUrl.port() > 0 && entryQUrl.port() != qUrl.port())
|| (browserSettings()->matchUrlScheme() && !entryScheme.isEmpty() && entryScheme.compare(qUrl.scheme()) != 0)) {
return false;
}
// Filter to match hostname in URL field
if ((!entryUrl.isEmpty() && hostname.contains(entryUrl))
|| (matchUrlScheme(entryUrl) && hostname.endsWith(entryQUrl.host()))) {
return true;
}
return false;
};
/** /**
* Gets the base domain of URL. * Gets the base domain of URL.
* *
@ -1051,9 +1106,8 @@ int BrowserService::moveKeysToCustomData(Entry* entry, const QSharedPointer<Data
publicKey.remove(LEGACY_ASSOCIATE_KEY_PREFIX); publicKey.remove(LEGACY_ASSOCIATE_KEY_PREFIX);
// Add key to database custom data // Add key to database custom data
if (db && !db->metadata()->customData()->contains(QLatin1String(ASSOCIATE_KEY_PREFIX) + publicKey)) { if (db && !db->metadata()->customData()->contains(ASSOCIATE_KEY_PREFIX + publicKey)) {
db->metadata()->customData()->set(QLatin1String(ASSOCIATE_KEY_PREFIX) + publicKey, db->metadata()->customData()->set(ASSOCIATE_KEY_PREFIX + publicKey, entry->attributes()->value(key));
entry->attributes()->value(key));
++keyCounter; ++keyCounter;
} }
} }
@ -1064,6 +1118,10 @@ int BrowserService::moveKeysToCustomData(Entry* entry, const QSharedPointer<Data
bool BrowserService::checkLegacySettings() bool BrowserService::checkLegacySettings()
{ {
if (!browserSettings()->isEnabled() || browserSettings()->noMigrationPrompt()) {
return false;
}
auto db = getDatabase(); auto db = getDatabase();
if (!db) { if (!db) {
return false; return false;
@ -1083,13 +1141,21 @@ bool BrowserService::checkLegacySettings()
return false; return false;
} }
auto* checkbox = new QCheckBox(tr("Don't show this warning again"));
QObject::connect(checkbox, &QCheckBox::stateChanged, [&](int state) {
browserSettings()->setNoMigrationPrompt(static_cast<Qt::CheckState>(state) == Qt::CheckState::Checked);
});
auto dialogResult = auto dialogResult =
MessageBox::warning(nullptr, MessageBox::warning(nullptr,
tr("KeePassXC: Legacy browser integration settings detected"), tr("KeePassXC: Legacy browser integration settings detected"),
tr("Your KeePassXC-Browser settings need to be moved into the database settings.\n" tr("Your KeePassXC-Browser settings need to be moved into the database settings.\n"
"This is necessary to maintain your current browser connections.\n" "This is necessary to maintain your current browser connections.\n"
"Would you like to migrate your existing settings now?"), "Would you like to migrate your existing settings now?"),
MessageBox::Yes | MessageBox::No); MessageBox::Yes | MessageBox::No,
MessageBox::NoButton,
MessageBox::Raise,
checkbox);
return dialogResult == MessageBox::Yes; return dialogResult == MessageBox::Yes;
} }

View File

@ -38,6 +38,13 @@ class BrowserService : public QObject
Q_OBJECT Q_OBJECT
public: public:
enum ReturnValue
{
Success,
Error,
Canceled
};
explicit BrowserService(DatabaseTabWidget* parent); explicit BrowserService(DatabaseTabWidget* parent);
bool isDatabaseOpened() const; bool isDatabaseOpened() const;
@ -61,10 +68,13 @@ public:
void convertAttributesToCustomData(const QSharedPointer<Database>& currentDb = {}); void convertAttributesToCustomData(const QSharedPointer<Database>& currentDb = {});
public: public:
static const char KEEPASSXCBROWSER_NAME[]; static const QString KEEPASSXCBROWSER_NAME;
static const char KEEPASSXCBROWSER_OLD_NAME[]; static const QString KEEPASSXCBROWSER_OLD_NAME;
static const char ASSOCIATE_KEY_PREFIX[]; static const QString ASSOCIATE_KEY_PREFIX;
static const char LEGACY_ASSOCIATE_KEY_PREFIX[]; static const QString LEGACY_ASSOCIATE_KEY_PREFIX;
static const QString OPTION_SKIP_AUTO_SUBMIT;
static const QString OPTION_HIDE_ENTRY;
static const QString ADDITIONAL_URL;
public slots: public slots:
QJsonArray findMatchingEntries(const QString& id, QJsonArray findMatchingEntries(const QString& id,
@ -74,12 +84,12 @@ public slots:
const StringPairList& keyList, const StringPairList& keyList,
const bool httpAuth = false); const bool httpAuth = false);
QString storeKey(const QString& key); QString storeKey(const QString& key);
void updateEntry(const QString& id, ReturnValue updateEntry(const QString& id,
const QString& uuid, const QString& uuid,
const QString& login, const QString& login,
const QString& password, const QString& password,
const QString& url, const QString& url,
const QString& submitUrl); const QString& submitUrl);
void databaseLocked(DatabaseWidget* dbWidget); void databaseLocked(DatabaseWidget* dbWidget);
void databaseUnlocked(DatabaseWidget* dbWidget); void databaseUnlocked(DatabaseWidget* dbWidget);
void activateDatabaseChanged(DatabaseWidget* dbWidget); void activateDatabaseChanged(DatabaseWidget* dbWidget);
@ -110,8 +120,9 @@ private:
bool confirmEntries(QList<Entry*>& pwEntriesToConfirm, bool confirmEntries(QList<Entry*>& pwEntriesToConfirm,
const QString& url, const QString& url,
const QString& host, const QString& host,
const QString& submitHost, const QString& submitUrl,
const QString& realm); const QString& realm,
const bool httpAuth);
QJsonObject prepareEntry(const Entry* entry); QJsonObject prepareEntry(const Entry* entry);
Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm); Access checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm);
Group* getDefaultEntryGroup(const QSharedPointer<Database>& selectedDb = {}); Group* getDefaultEntryGroup(const QSharedPointer<Database>& selectedDb = {});
@ -119,6 +130,7 @@ private:
sortPriority(const Entry* entry, const QString& host, const QString& submitUrl, const QString& baseSubmitUrl) const; sortPriority(const Entry* entry, const QString& host, const QString& submitUrl, const QString& baseSubmitUrl) const;
bool matchUrlScheme(const QString& url); bool matchUrlScheme(const QString& url);
bool removeFirstDomain(QString& hostname); bool removeFirstDomain(QString& hostname);
bool handleURL(const QString& entryUrl, const QString& hostname, const QString& url);
QString baseDomain(const QString& url) const; QString baseDomain(const QString& url) const;
QSharedPointer<Database> getDatabase(); QSharedPointer<Database> getDatabase();
QSharedPointer<Database> selectedDatabase(); QSharedPointer<Database> selectedDatabase();

View File

@ -151,6 +151,16 @@ void BrowserSettings::setSupportKphFields(bool supportKphFields)
config()->set("Browser/SupportKphFields", supportKphFields); config()->set("Browser/SupportKphFields", supportKphFields);
} }
bool BrowserSettings::noMigrationPrompt()
{
return config()->get("Browser/NoMigrationPrompt", false).toBool();
}
void BrowserSettings::setNoMigrationPrompt(bool prompt)
{
config()->set("Browser/NoMigrationPrompt", prompt);
}
bool BrowserSettings::supportBrowserProxy() bool BrowserSettings::supportBrowserProxy()
{ {
return config()->get("Browser/SupportBrowserProxy", true).toBool(); return config()->get("Browser/SupportBrowserProxy", true).toBool();
@ -250,13 +260,13 @@ void BrowserSettings::setVivaldiSupport(bool enabled)
bool BrowserSettings::braveSupport() bool BrowserSettings::braveSupport()
{ {
return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::BRAVE); return m_hostInstaller.checkIfInstalled(HostInstaller::SupportedBrowsers::BRAVE);
} }
void BrowserSettings::setBraveSupport(bool enabled) void BrowserSettings::setBraveSupport(bool enabled)
{ {
m_hostInstaller.installBrowser( m_hostInstaller.installBrowser(
HostInstaller::SupportedBrowsers::BRAVE, enabled, supportBrowserProxy(), customProxyLocation()); HostInstaller::SupportedBrowsers::BRAVE, enabled, supportBrowserProxy(), customProxyLocation());
} }
bool BrowserSettings::torBrowserSupport() bool BrowserSettings::torBrowserSupport()
@ -512,19 +522,23 @@ PasswordGenerator::GeneratorFlags BrowserSettings::passwordGeneratorFlags()
return flags; return flags;
} }
QString BrowserSettings::generatePassword() QJsonObject BrowserSettings::generatePassword()
{ {
QJsonObject password;
if (generatorType() == 0) { if (generatorType() == 0) {
m_passwordGenerator.setLength(passwordLength()); m_passwordGenerator.setLength(passwordLength());
m_passwordGenerator.setCharClasses(passwordCharClasses()); m_passwordGenerator.setCharClasses(passwordCharClasses());
m_passwordGenerator.setFlags(passwordGeneratorFlags()); m_passwordGenerator.setFlags(passwordGeneratorFlags());
return m_passwordGenerator.generatePassword(); const QString pw = m_passwordGenerator.generatePassword();
password["entropy"] = m_passwordGenerator.estimateEntropy(pw);
password["password"] = pw;
} else { } else {
m_passPhraseGenerator.setDefaultWordList();
m_passPhraseGenerator.setWordCount(passPhraseWordCount()); m_passPhraseGenerator.setWordCount(passPhraseWordCount());
m_passPhraseGenerator.setWordSeparator(passPhraseWordSeparator()); m_passPhraseGenerator.setWordSeparator(passPhraseWordSeparator());
return m_passPhraseGenerator.generatePassphrase(); password["entropy"] = m_passPhraseGenerator.estimateEntropy();
password["password"] = m_passPhraseGenerator.generatePassphrase();
} }
return password;
} }
void BrowserSettings::updateBinaryPaths(const QString& customProxyLocation) void BrowserSettings::updateBinaryPaths(const QString& customProxyLocation)

View File

@ -55,6 +55,8 @@ public:
void setHttpAuthPermission(bool httpAuthPermission); void setHttpAuthPermission(bool httpAuthPermission);
bool supportKphFields(); bool supportKphFields();
void setSupportKphFields(bool supportKphFields); void setSupportKphFields(bool supportKphFields);
bool noMigrationPrompt();
void setNoMigrationPrompt(bool prompt);
bool supportBrowserProxy(); bool supportBrowserProxy();
void setSupportBrowserProxy(bool enabled); void setSupportBrowserProxy(bool enabled);
@ -119,7 +121,7 @@ public:
void setPasswordLength(int length); void setPasswordLength(int length);
PasswordGenerator::CharClasses passwordCharClasses(); PasswordGenerator::CharClasses passwordCharClasses();
PasswordGenerator::GeneratorFlags passwordGeneratorFlags(); PasswordGenerator::GeneratorFlags passwordGeneratorFlags();
QString generatePassword(); QJsonObject generatePassword();
void updateBinaryPaths(const QString& customProxyLocation = QString()); void updateBinaryPaths(const QString& customProxyLocation = QString());
bool checkIfProxyExists(QString& path); bool checkIfProxyExists(QString& path);

View File

@ -40,13 +40,6 @@ 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")
#elif defined(Q_OS_LINUX)
, TARGET_DIR_CHROME("/.config/google-chrome/NativeMessagingHosts")
, TARGET_DIR_CHROMIUM("/.config/chromium/NativeMessagingHosts")
, TARGET_DIR_FIREFOX("/.mozilla/native-messaging-hosts")
, TARGET_DIR_VIVALDI("/.config/vivaldi/NativeMessagingHosts")
, TARGET_DIR_TOR_BROWSER("/.tor-browser/app/Browser/TorBrowser/Data/Browser/.mozilla/native-messaging-hosts")
, TARGET_DIR_BRAVE("/.config/BraveSoftware/Brave-Browser/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")
@ -56,6 +49,13 @@ 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)
#else
, TARGET_DIR_CHROME("/.config/google-chrome/NativeMessagingHosts")
, TARGET_DIR_CHROMIUM("/.config/chromium/NativeMessagingHosts")
, TARGET_DIR_FIREFOX("/.mozilla/native-messaging-hosts")
, TARGET_DIR_VIVALDI("/.config/vivaldi/NativeMessagingHosts")
, TARGET_DIR_TOR_BROWSER("/.tor-browser/app/Browser/TorBrowser/Data/Browser/.mozilla/native-messaging-hosts")
, TARGET_DIR_BRAVE("/.config/BraveSoftware/Brave-Browser/NativeMessagingHosts")
#endif #endif
{ {
} }
@ -109,9 +109,7 @@ void HostInstaller::installBrowser(SupportedBrowsers browser,
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Create a registry key // Create a registry key
QSettings settings(getTargetPath(browser), QSettings::NativeFormat); QSettings settings(getTargetPath(browser), QSettings::NativeFormat);
if (!registryEntryFound(settings)) { settings.setValue("Default", getPath(browser));
settings.setValue("Default", getPath(browser));
}
#endif #endif
// Always create the script file // Always create the script file
QJsonObject script = constructFile(browser, proxy, location); QJsonObject script = constructFile(browser, proxy, location);
@ -128,9 +126,7 @@ void HostInstaller::installBrowser(SupportedBrowsers browser,
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Remove the registry entry // Remove the registry entry
QSettings settings(getTargetPath(browser), QSettings::NativeFormat); QSettings settings(getTargetPath(browser), QSettings::NativeFormat);
if (registryEntryFound(settings)) { settings.remove("Default");
settings.remove("Default");
}
#endif #endif
} }
} }
@ -171,7 +167,7 @@ QString HostInstaller::getTargetPath(SupportedBrowsers browser) const
case SupportedBrowsers::TOR_BROWSER: case SupportedBrowsers::TOR_BROWSER:
return TARGET_DIR_TOR_BROWSER; return TARGET_DIR_TOR_BROWSER;
case SupportedBrowsers::BRAVE: case SupportedBrowsers::BRAVE:
return TARGET_DIR_BRAVE; return TARGET_DIR_BRAVE;
default: default:
return QString(); return QString();
} }
@ -194,11 +190,11 @@ QString HostInstaller::getBrowserName(SupportedBrowsers browser) const
case SupportedBrowsers::FIREFOX: case SupportedBrowsers::FIREFOX:
return "firefox"; return "firefox";
case SupportedBrowsers::VIVALDI: case SupportedBrowsers::VIVALDI:
return "vivaldi"; return "vivaldi";
case SupportedBrowsers::TOR_BROWSER: case SupportedBrowsers::TOR_BROWSER:
return "tor-browser"; return "tor-browser";
case SupportedBrowsers::BRAVE: case SupportedBrowsers::BRAVE:
return "brave"; return "brave";
default: default:
return QString(); return QString();
} }
@ -299,9 +295,9 @@ QJsonObject HostInstaller::constructFile(SupportedBrowsers browser, const bool&
QJsonObject script; QJsonObject script;
script["name"] = HOST_NAME; script["name"] = HOST_NAME;
script["description"] = "KeePassXC integration with native messaging support"; script["description"] = QString("KeePassXC integration with native messaging support");
script["path"] = path; script["path"] = path;
script["type"] = "stdio"; script["type"] = QString("stdio");
QJsonArray arr; QJsonArray arr;
if (browser == SupportedBrowsers::FIREFOX || browser == SupportedBrowsers::TOR_BROWSER) { if (browser == SupportedBrowsers::FIREFOX || browser == SupportedBrowsers::TOR_BROWSER) {

View File

@ -104,7 +104,7 @@ void NativeMessagingBase::readNativeMessages()
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
quint32 length = 0; quint32 length = 0;
while (m_running.load() && !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.read(reinterpret_cast<char*>(&length), 4);
readStdIn(length); readStdIn(length);

View File

@ -19,7 +19,7 @@
#ifndef NATIVEMESSAGINGBASE_H #ifndef NATIVEMESSAGINGBASE_H
#define NATIVEMESSAGINGBASE_H #define NATIVEMESSAGINGBASE_H
#include <QAtomicInteger> #include <QAtomicInt>
#include <QFuture> #include <QFuture>
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
@ -60,7 +60,7 @@ protected:
QString getLocalServerPath() const; QString getLocalServerPath() const;
protected: protected:
QAtomicInteger<quint8> m_running; QAtomicInt m_running;
QSharedPointer<QSocketNotifier> m_notifier; QSharedPointer<QSocketNotifier> m_notifier;
QFuture<void> m_future; QFuture<void> m_future;
}; };

View File

@ -35,9 +35,9 @@ NativeMessagingHost::NativeMessagingHost(DatabaseTabWidget* parent, const bool e
{ {
m_localServer.reset(new QLocalServer(this)); m_localServer.reset(new QLocalServer(this));
m_localServer->setSocketOptions(QLocalServer::UserAccessOption); m_localServer->setSocketOptions(QLocalServer::UserAccessOption);
m_running.store(false); m_running.store(0);
if (browserSettings()->isEnabled() && !m_running) { if (browserSettings()->isEnabled() && m_running.load() == 0) {
run(); run();
} }
@ -59,7 +59,7 @@ int NativeMessagingHost::init()
void NativeMessagingHost::run() void NativeMessagingHost::run()
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
if (!m_running.load() && init() == -1) { if (m_running.load() == 0 && init() == -1) {
return; return;
} }
@ -69,7 +69,7 @@ void NativeMessagingHost::run()
browserSettings()->useCustomProxy() ? browserSettings()->customProxyLocation() : ""); browserSettings()->useCustomProxy() ? browserSettings()->customProxyLocation() : "");
} }
m_running.store(true); m_running.store(1);
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
m_future = m_future =
QtConcurrent::run(this, static_cast<void (NativeMessagingHost::*)()>(&NativeMessagingHost::readNativeMessages)); QtConcurrent::run(this, static_cast<void (NativeMessagingHost::*)()>(&NativeMessagingHost::readNativeMessages));
@ -100,7 +100,7 @@ void NativeMessagingHost::stop()
databaseLocked(); databaseLocked();
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
m_socketList.clear(); m_socketList.clear();
m_running.testAndSetOrdered(true, false); m_running.testAndSetOrdered(1, 0);
m_future.waitForFinished(); m_future.waitForFinished();
m_localServer->close(); m_localServer->close();
} }
@ -210,13 +210,13 @@ void NativeMessagingHost::disconnectSocket()
void NativeMessagingHost::databaseLocked() void NativeMessagingHost::databaseLocked()
{ {
QJsonObject response; QJsonObject response;
response["action"] = "database-locked"; response["action"] = QString("database-locked");
sendReplyToAllClients(response); sendReplyToAllClients(response);
} }
void NativeMessagingHost::databaseUnlocked() void NativeMessagingHost::databaseUnlocked()
{ {
QJsonObject response; QJsonObject response;
response["action"] = "database-unlocked"; response["action"] = QString("database-unlocked");
sendReplyToAllClients(response); sendReplyToAllClients(response);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,8 +20,7 @@
#include "Add.h" #include "Add.h"
#include <QCommandLineParser> #include "cli/Generate.h"
#include "cli/TextStream.h" #include "cli/TextStream.h"
#include "cli/Utils.h" #include "cli/Utils.h"
#include "core/Database.h" #include "core/Database.h"
@ -29,127 +28,102 @@
#include "core/Group.h" #include "core/Group.h"
#include "core/PasswordGenerator.h" #include "core/PasswordGenerator.h"
const QCommandLineOption Add::UsernameOption = QCommandLineOption(QStringList() << "u"
<< "username",
QObject::tr("Username for the entry."),
QObject::tr("username"));
const QCommandLineOption Add::UrlOption =
QCommandLineOption(QStringList() << "url", QObject::tr("URL for the entry."), QObject::tr("URL"));
const QCommandLineOption Add::PasswordPromptOption =
QCommandLineOption(QStringList() << "p"
<< "password-prompt",
QObject::tr("Prompt for the entry's password."));
const QCommandLineOption Add::GenerateOption = QCommandLineOption(QStringList() << "g"
<< "generate",
QObject::tr("Generate a password for the entry."));
Add::Add() Add::Add()
{ {
name = QString("add"); name = QString("add");
description = QObject::tr("Add a new entry to a database."); description = QObject::tr("Add a new entry to a database.");
options.append(Add::UsernameOption);
options.append(Add::UrlOption);
options.append(Add::PasswordPromptOption);
positionalArguments.append({QString("entry"), QObject::tr("Path of the entry to add."), QString("")});
// Password generation options.
options.append(Add::GenerateOption);
options.append(Generate::PasswordLengthOption);
options.append(Generate::LowerCaseOption);
options.append(Generate::UpperCaseOption);
options.append(Generate::NumbersOption);
options.append(Generate::SpecialCharsOption);
options.append(Generate::ExtendedAsciiOption);
options.append(Generate::ExcludeCharsOption);
options.append(Generate::ExcludeSimilarCharsOption);
options.append(Generate::IncludeEveryGroupOption);
} }
Add::~Add() int Add::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<QCommandLineParser> parser)
{
}
int Add::execute(const QStringList& arguments)
{ {
TextStream inputTextStream(Utils::STDIN, QIODevice::ReadOnly); TextStream inputTextStream(Utils::STDIN, QIODevice::ReadOnly);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly); TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly); TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QCommandLineParser parser; const QStringList args = parser->positionalArguments();
parser.setApplicationDescription(description); auto& entryPath = args.at(1);
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
parser.addOption(Command::QuietOption);
parser.addOption(Command::KeyFileOption);
parser.addOption(Command::NoPasswordOption);
QCommandLineOption username(QStringList() << "u" // Cannot use those 2 options at the same time!
<< "username", if (parser->isSet(Add::GenerateOption) && parser->isSet(Add::PasswordPromptOption)) {
QObject::tr("Username for the entry."), errorTextStream << QObject::tr("Cannot generate a password and prompt at the same time!") << endl;
QObject::tr("username"));
parser.addOption(username);
QCommandLineOption url(QStringList() << "url", QObject::tr("URL for the entry."), QObject::tr("URL"));
parser.addOption(url);
QCommandLineOption prompt(QStringList() << "p"
<< "password-prompt",
QObject::tr("Prompt for the entry's password."));
parser.addOption(prompt);
QCommandLineOption generate(QStringList() << "g"
<< "generate",
QObject::tr("Generate a password for the entry."));
parser.addOption(generate);
QCommandLineOption length(QStringList() << "l"
<< "password-length",
QObject::tr("Length for the generated password."),
QObject::tr("length"));
parser.addOption(length);
parser.addPositionalArgument("entry", QObject::tr("Path of the entry to add."));
parser.addHelpOption();
parser.process(arguments);
const QStringList args = parser.positionalArguments();
if (args.size() != 2) {
errorTextStream << parser.helpText().replace("[options]", "add [options]");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
const QString& databasePath = args.at(0); // Validating the password generator here, before we actually create
const QString& entryPath = args.at(1);
auto db = Utils::unlockDatabase(databasePath,
!parser.isSet(Command::NoPasswordOption),
parser.value(Command::KeyFileOption),
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
Utils::STDERR);
if (!db) {
return EXIT_FAILURE;
}
// Validating the password length here, before we actually create
// the entry. // the entry.
QString passwordLength = parser.value(length); QSharedPointer<PasswordGenerator> passwordGenerator;
if (!passwordLength.isEmpty() && !passwordLength.toInt()) { if (parser->isSet(Add::GenerateOption)) {
errorTextStream << QObject::tr("Invalid value for password length %1.").arg(passwordLength) << endl; passwordGenerator = Generate::createGenerator(parser);
return EXIT_FAILURE; if (passwordGenerator.isNull()) {
return EXIT_FAILURE;
}
} }
Entry* entry = db->rootGroup()->addEntryWithPath(entryPath); Entry* entry = database->rootGroup()->addEntryWithPath(entryPath);
if (!entry) { if (!entry) {
errorTextStream << QObject::tr("Could not create entry with path %1.").arg(entryPath) << endl; errorTextStream << QObject::tr("Could not create entry with path %1.").arg(entryPath) << endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!parser.value("username").isEmpty()) { if (!parser->value(Add::UsernameOption).isEmpty()) {
entry->setUsername(parser.value("username")); entry->setUsername(parser->value(Add::UsernameOption));
} }
if (!parser.value("url").isEmpty()) { if (!parser->value(Add::UrlOption).isEmpty()) {
entry->setUrl(parser.value("url")); entry->setUrl(parser->value(Add::UrlOption));
} }
if (parser.isSet(prompt)) { if (parser->isSet(Add::PasswordPromptOption)) {
if (!parser.isSet(Command::QuietOption)) { if (!parser->isSet(Command::QuietOption)) {
outputTextStream << QObject::tr("Enter password for new entry: ") << flush; outputTextStream << QObject::tr("Enter password for new entry: ") << flush;
} }
QString password = Utils::getPassword(parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT); QString password = Utils::getPassword(parser->isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT);
entry->setPassword(password); entry->setPassword(password);
} else if (parser.isSet(generate)) { } else if (parser->isSet(Add::GenerateOption)) {
PasswordGenerator passwordGenerator; QString password = passwordGenerator->generatePassword();
if (passwordLength.isEmpty()) {
passwordGenerator.setLength(PasswordGenerator::DefaultLength);
} else {
passwordGenerator.setLength(passwordLength.toInt());
}
passwordGenerator.setCharClasses(PasswordGenerator::DefaultCharset);
passwordGenerator.setFlags(PasswordGenerator::DefaultFlags);
QString password = passwordGenerator.generatePassword();
entry->setPassword(password); entry->setPassword(password);
} }
QString errorMessage; QString errorMessage;
if (!db->save(databasePath, &errorMessage, true, false)) { if (!database->save(&errorMessage, true, false)) {
errorTextStream << QObject::tr("Writing the database failed %1.").arg(errorMessage) << endl; errorTextStream << QObject::tr("Writing the database failed %1.").arg(errorMessage) << endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!parser.isSet(Command::QuietOption)) { if (!parser->isSet(Command::QuietOption)) {
outputTextStream << QObject::tr("Successfully added entry %1.").arg(entry->title()) << endl; outputTextStream << QObject::tr("Successfully added entry %1.").arg(entry->title()) << endl;
} }
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -18,14 +18,20 @@
#ifndef KEEPASSXC_ADD_H #ifndef KEEPASSXC_ADD_H
#define KEEPASSXC_ADD_H #define KEEPASSXC_ADD_H
#include "Command.h" #include "DatabaseCommand.h"
class Add : public Command class Add : public DatabaseCommand
{ {
public: public:
Add(); Add();
~Add();
int execute(const QStringList& arguments) override; int executeWithDatabase(QSharedPointer<Database> db, QSharedPointer<QCommandLineParser> parser) override;
static const QCommandLineOption UsernameOption;
static const QCommandLineOption UrlOption;
static const QCommandLineOption PasswordPromptOption;
static const QCommandLineOption GenerateOption;
static const QCommandLineOption PasswordLengthOption;
}; };
#endif // KEEPASSXC_ADD_H #endif // KEEPASSXC_ADD_H

79
src/cli/AddGroup.cpp Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstdlib>
#include <stdio.h>
#include "AddGroup.h"
#include "cli/TextStream.h"
#include "cli/Utils.h"
#include "core/Database.h"
#include "core/Entry.h"
#include "core/Group.h"
AddGroup::AddGroup()
{
name = QString("mkdir");
description = QObject::tr("Adds a new group to a database.");
positionalArguments.append({QString("group"), QObject::tr("Path of the group to add."), QString("")});
}
AddGroup::~AddGroup()
{
}
int AddGroup::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<QCommandLineParser> parser)
{
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
const QStringList args = parser->positionalArguments();
const QString& groupPath = args.at(1);
QStringList pathParts = groupPath.split("/");
QString groupName = pathParts.takeLast();
QString parentGroupPath = pathParts.join("/");
Group* group = database->rootGroup()->findGroupByPath(groupPath);
if (group) {
errorTextStream << QObject::tr("Group %1 already exists!").arg(groupPath) << endl;
return EXIT_FAILURE;
}
Group* parentGroup = database->rootGroup()->findGroupByPath(parentGroupPath);
if (!parentGroup) {
errorTextStream << QObject::tr("Group %1 not found.").arg(parentGroupPath) << endl;
return EXIT_FAILURE;
}
Group* newGroup = new Group();
newGroup->setUuid(QUuid::createUuid());
newGroup->setName(groupName);
newGroup->setParent(parentGroup);
QString errorMessage;
if (!database->save(&errorMessage, true, false)) {
errorTextStream << QObject::tr("Writing the database failed %1.").arg(errorMessage) << endl;
return EXIT_FAILURE;
}
if (!parser->isSet(Command::QuietOption)) {
outputTextStream << QObject::tr("Successfully added group %1.").arg(groupName) << endl;
}
return EXIT_SUCCESS;
}

32
src/cli/AddGroup.h Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEEPASSXC_ADDGROUP_H
#define KEEPASSXC_ADDGROUP_H
#include "DatabaseCommand.h"
class AddGroup : public DatabaseCommand
{
public:
AddGroup();
~AddGroup();
int executeWithDatabase(QSharedPointer<Database> db, QSharedPointer<QCommandLineParser> parser);
};
#endif // KEEPASSXC_ADDGROUP_H

82
src/cli/Analyze.cpp Normal file
View File

@ -0,0 +1,82 @@
/*
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Analyze.h"
#include "cli/Utils.h"
#include "core/HibpOffline.h"
#include <QCommandLineParser>
#include <QFile>
#include <QString>
#include "cli/TextStream.h"
#include "core/Group.h"
#include "core/Tools.h"
const QCommandLineOption Analyze::HIBPDatabaseOption = QCommandLineOption(
{"H", "hibp"},
QObject::tr("Check if any passwords have been publicly leaked. FILENAME must be the path of a file listing "
"SHA-1 hashes of leaked passwords in HIBP format, as available from "
"https://haveibeenpwned.com/Passwords."),
QObject::tr("FILENAME"));
Analyze::Analyze()
{
name = QString("analyze");
description = QObject::tr("Analyze passwords for weaknesses and problems.");
options.append(Analyze::HIBPDatabaseOption);
}
int Analyze::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<QCommandLineParser> parser)
{
TextStream inputTextStream(Utils::STDIN, QIODevice::ReadOnly);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
QString hibpDatabase = parser->value(Analyze::HIBPDatabaseOption);
QFile hibpFile(hibpDatabase);
if (!hibpFile.open(QFile::ReadOnly)) {
errorTextStream << QObject::tr("Failed to open HIBP file %1: %2").arg(hibpDatabase).arg(hibpFile.errorString())
<< endl;
return EXIT_FAILURE;
}
outputTextStream << QObject::tr("Evaluating database entries against HIBP file, this will take a while...");
QList<QPair<const Entry*, int>> findings;
QString error;
if (!HibpOffline::report(database, hibpFile, findings, &error)) {
errorTextStream << error << endl;
return EXIT_FAILURE;
}
for (auto& finding : findings) {
printHibpFinding(finding.first, finding.second, outputTextStream);
}
return EXIT_SUCCESS;
}
void Analyze::printHibpFinding(const Entry* entry, int count, QTextStream& out)
{
QString path = entry->title();
for (auto g = entry->group(); g && g != g->database()->rootGroup(); g = g->parentGroup()) {
path.prepend("/").prepend(g->name());
}
out << QObject::tr("Password for '%1' has been leaked %2 time(s)!", "", count).arg(path).arg(count) << endl;
}

35
src/cli/Analyze.h Normal file
View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEEPASSXC_ANALYZE_H
#define KEEPASSXC_ANALYZE_H
#include "DatabaseCommand.h"
class Analyze : public DatabaseCommand
{
public:
Analyze();
int executeWithDatabase(QSharedPointer<Database> db, QSharedPointer<QCommandLineParser> parser) override;
static const QCommandLineOption HIBPDatabaseOption;
private:
void printHibpFinding(const Entry* entry, int count, QTextStream& out);
};
#endif // KEEPASSXC_HIBP_H

View File

@ -1,4 +1,4 @@
# Copyright (C) 2017 KeePassXC Team # Copyright (C) 2019 KeePassXC Team
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -15,23 +15,40 @@
set(cli_SOURCES set(cli_SOURCES
Add.cpp Add.cpp
AddGroup.cpp
Analyze.cpp
Clip.cpp Clip.cpp
Close.cpp
Create.cpp Create.cpp
Command.cpp Command.cpp
DatabaseCommand.cpp
Diceware.cpp Diceware.cpp
Edit.cpp Edit.cpp
Estimate.cpp Estimate.cpp
Extract.cpp Exit.cpp
Export.cpp
Generate.cpp Generate.cpp
Help.cpp
Import.cpp
List.cpp List.cpp
Locate.cpp Locate.cpp
Merge.cpp Merge.cpp
Move.cpp
Open.cpp
Remove.cpp Remove.cpp
RemoveGroup.cpp
Show.cpp) Show.cpp)
add_library(cli STATIC ${cli_SOURCES}) add_library(cli STATIC ${cli_SOURCES})
target_link_libraries(cli Qt5::Core Qt5::Widgets) target_link_libraries(cli Qt5::Core Qt5::Widgets)
find_package(Readline)
if (READLINE_FOUND)
target_compile_definitions(cli PUBLIC USE_READLINE)
target_link_libraries(cli readline)
endif()
add_executable(keepassxc-cli keepassxc-cli.cpp) add_executable(keepassxc-cli keepassxc-cli.cpp)
target_link_libraries(keepassxc-cli target_link_libraries(keepassxc-cli
cli cli
@ -48,6 +65,12 @@ install(TARGETS keepassxc-cli
BUNDLE DESTINATION . COMPONENT Runtime BUNDLE DESTINATION . COMPONENT Runtime
RUNTIME DESTINATION ${CLI_INSTALL_DIR} COMPONENT Runtime) RUNTIME DESTINATION ${CLI_INSTALL_DIR} COMPONENT Runtime)
if(MINGW)
install(CODE "include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/keepassxc-cli.exe\" \"\" \"\")"
COMPONENT Runtime)
endif()
if(APPLE AND WITH_APP_BUNDLE) if(APPLE AND WITH_APP_BUNDLE)
add_custom_command(TARGET keepassxc-cli add_custom_command(TARGET keepassxc-cli
POST_BUILD POST_BUILD
@ -82,6 +105,8 @@ if(APPLE AND WITH_APP_BUNDLE)
"@executable_path/../Frameworks/libyubikey.0.dylib" "@executable_path/../Frameworks/libyubikey.0.dylib"
-change /usr/local/opt/ykpers/lib/libykpers-1.1.dylib -change /usr/local/opt/ykpers/lib/libykpers-1.1.dylib
"@executable_path/../Frameworks/libykpers-1.1.dylib" "@executable_path/../Frameworks/libykpers-1.1.dylib"
-change /usr/local/opt/quazip/lib/libquazip.1.dylib
"@executable_path/../Frameworks/libquazip.1.dylib"
keepassxc-cli keepassxc-cli
COMMENT "Changing linking of keepassxc-cli") COMMENT "Changing linking of keepassxc-cli")
@ -94,5 +119,5 @@ if(APPLE AND WITH_APP_BUNDLE)
endif() endif()
if(APPLE OR UNIX) if(APPLE OR UNIX)
install(FILES keepassxc-cli.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1/) install(FILES ../../share/docs/man/keepassxc-cli.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1/)
endif() endif()

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -22,80 +22,48 @@
#include "Clip.h" #include "Clip.h"
#include <QCommandLineParser>
#include "cli/TextStream.h" #include "cli/TextStream.h"
#include "cli/Utils.h" #include "cli/Utils.h"
#include "core/Database.h" #include "core/Database.h"
#include "core/Entry.h" #include "core/Entry.h"
#include "core/Group.h" #include "core/Group.h"
const QCommandLineOption Clip::TotpOption = QCommandLineOption(QStringList() << "t"
<< "totp",
QObject::tr("Copy the current TOTP to the clipboard."));
Clip::Clip() Clip::Clip()
{ {
name = QString("clip"); name = QString("clip");
description = QObject::tr("Copy an entry's password to the clipboard."); description = QObject::tr("Copy an entry's password to the clipboard.");
options.append(Clip::TotpOption);
positionalArguments.append(
{QString("entry"), QObject::tr("Path of the entry to clip.", "clip = copy to clipboard"), QString("")});
optionalArguments.append(
{QString("timeout"), QObject::tr("Timeout in seconds before clearing the clipboard."), QString("[timeout]")});
} }
Clip::~Clip() int Clip::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<QCommandLineParser> parser)
{ {
} const QStringList args = parser->positionalArguments();
QString entryPath = args.at(1);
int Clip::execute(const QStringList& arguments) QString timeout;
{ if (args.size() == 3) {
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly); timeout = args.at(2);
QCommandLineParser parser;
parser.setApplicationDescription(description);
parser.addPositionalArgument("database", QObject::tr("Path of the database."));
parser.addOption(Command::QuietOption);
parser.addOption(Command::KeyFileOption);
parser.addOption(Command::NoPasswordOption);
QCommandLineOption totp(QStringList() << "t"
<< "totp",
QObject::tr("Copy the current TOTP to the clipboard."));
parser.addOption(totp);
parser.addPositionalArgument("entry", QObject::tr("Path of the entry to clip.", "clip = copy to clipboard"));
parser.addPositionalArgument(
"timeout", QObject::tr("Timeout in seconds before clearing the clipboard."), "[timeout]");
parser.addHelpOption();
parser.process(arguments);
const QStringList args = parser.positionalArguments();
if (args.size() != 2 && args.size() != 3) {
errorTextStream << parser.helpText().replace("[options]", "clip [options]");
return EXIT_FAILURE;
} }
bool clipTotp = parser->isSet(Clip::TotpOption);
auto db = Utils::unlockDatabase(args.at(0),
!parser.isSet(Command::NoPasswordOption),
parser.value(Command::KeyFileOption),
parser.isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
Utils::STDERR);
if (!db) {
return EXIT_FAILURE;
}
return clipEntry(db, args.at(1), args.value(2), parser.isSet(totp), parser.isSet(Command::QuietOption));
}
int Clip::clipEntry(const QSharedPointer<Database>& database,
const QString& entryPath,
const QString& timeout,
bool clipTotp,
bool silent)
{
TextStream errorTextStream(Utils::STDERR); TextStream errorTextStream(Utils::STDERR);
int timeoutSeconds = 0; int timeoutSeconds = 0;
if (!timeout.isEmpty() && !timeout.toInt()) { if (!timeout.isEmpty() && timeout.toInt() <= 0) {
errorTextStream << QObject::tr("Invalid timeout value %1.").arg(timeout) << endl; errorTextStream << QObject::tr("Invalid timeout value %1.").arg(timeout) << endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} else if (!timeout.isEmpty()) { } else if (!timeout.isEmpty()) {
timeoutSeconds = timeout.toInt(); timeoutSeconds = timeout.toInt();
} }
TextStream outputTextStream(silent ? Utils::DEVNULL : Utils::STDOUT, QIODevice::WriteOnly); TextStream outputTextStream(parser->isSet(Command::QuietOption) ? Utils::DEVNULL : Utils::STDOUT,
QIODevice::WriteOnly);
Entry* entry = database->rootGroup()->findEntryByPath(entryPath); Entry* entry = database->rootGroup()->findEntryByPath(entryPath);
if (!entry) { if (!entry) {
errorTextStream << QObject::tr("Entry %1 not found.").arg(entryPath) << endl; errorTextStream << QObject::tr("Entry %1 not found.").arg(entryPath) << endl;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -18,19 +18,16 @@
#ifndef KEEPASSXC_CLIP_H #ifndef KEEPASSXC_CLIP_H
#define KEEPASSXC_CLIP_H #define KEEPASSXC_CLIP_H
#include "Command.h" #include "DatabaseCommand.h"
class Clip : public Command class Clip : public DatabaseCommand
{ {
public: public:
Clip(); Clip();
~Clip();
int execute(const QStringList& arguments) override; int executeWithDatabase(QSharedPointer<Database> db, QSharedPointer<QCommandLineParser> parser) override;
int clipEntry(const QSharedPointer<Database>& database,
const QString& entryPath, static const QCommandLineOption TotpOption;
const QString& timeout,
bool clipTotp,
bool silent);
}; };
#endif // KEEPASSXC_CLIP_H #endif // KEEPASSXC_CLIP_H

38
src/cli/Close.cpp Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Close.h"
#include <QCommandLineParser>
#include <QtGlobal>
#include "DatabaseCommand.h"
#include "TextStream.h"
#include "Utils.h"
Close::Close()
{
name = QString("close");
description = QObject::tr("Close the currently opened database.");
}
int Close::execute(const QStringList& arguments)
{
Q_UNUSED(arguments)
currentDatabase.reset(nullptr);
return EXIT_SUCCESS;
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -15,17 +15,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef KEEPASSXC_EXTRACT_H #ifndef KEEPASSXC_CLOSE_H
#define KEEPASSXC_EXTRACT_H #define KEEPASSXC_CLOSE_H
#include <QStringList>
#include "Command.h" #include "Command.h"
class Extract : public Command class Close : public Command
{ {
public: public:
Extract(); Close();
~Extract();
int execute(const QStringList& arguments) override; int execute(const QStringList& arguments) override;
}; };
#endif // KEEPASSXC_EXTRACT_H #endif // KEEPASSXC_CLOSE_H

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -15,26 +15,45 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <stdio.h> #include <utility>
#include <QMap> #include <QMap>
#include "Command.h" #include "Command.h"
#include "Add.h" #include "Add.h"
#include "AddGroup.h"
#include "Analyze.h"
#include "Clip.h" #include "Clip.h"
#include "Close.h"
#include "Create.h" #include "Create.h"
#include "Diceware.h" #include "Diceware.h"
#include "Edit.h" #include "Edit.h"
#include "Estimate.h" #include "Estimate.h"
#include "Extract.h" #include "Exit.h"
#include "Export.h"
#include "Generate.h" #include "Generate.h"
#include "Help.h"
#include "Import.h"
#include "List.h" #include "List.h"
#include "Locate.h" #include "Locate.h"
#include "Merge.h" #include "Merge.h"
#include "Move.h"
#include "Open.h"
#include "Remove.h" #include "Remove.h"
#include "RemoveGroup.h"
#include "Show.h" #include "Show.h"
#include "TextStream.h"
#include "Utils.h"
const QCommandLineOption Command::HelpOption = QCommandLineOption(QStringList()
#ifdef Q_OS_WIN
<< QStringLiteral("?")
#endif
<< QStringLiteral("h") << QStringLiteral("help"),
QObject::tr("Display this help."));
const QCommandLineOption Command::QuietOption = const QCommandLineOption Command::QuietOption =
QCommandLineOption(QStringList() << "q" QCommandLineOption(QStringList() << "q"
@ -47,10 +66,42 @@ const QCommandLineOption Command::KeyFileOption = QCommandLineOption(QStringList
QObject::tr("path")); QObject::tr("path"));
const QCommandLineOption Command::NoPasswordOption = const QCommandLineOption Command::NoPasswordOption =
QCommandLineOption(QStringList() << "no-password", QCommandLineOption(QStringList() << "no-password", QObject::tr("Deactivate password key for the database."));
QObject::tr("Deactivate password key for the database."));
QMap<QString, Command*> commands; const QCommandLineOption Command::YubiKeyOption =
QCommandLineOption(QStringList() << "y"
<< "yubikey",
QObject::tr("Yubikey slot used to encrypt the database."),
QObject::tr("slot"));
namespace
{
QSharedPointer<QCommandLineParser> buildParser(Command* command)
{
auto parser = QSharedPointer<QCommandLineParser>(new QCommandLineParser());
parser->setApplicationDescription(command->description);
for (const CommandLineArgument& positionalArgument : command->positionalArguments) {
parser->addPositionalArgument(
positionalArgument.name, positionalArgument.description, positionalArgument.syntax);
}
for (const CommandLineArgument& optionalArgument : command->optionalArguments) {
parser->addPositionalArgument(optionalArgument.name, optionalArgument.description, optionalArgument.syntax);
}
for (const QCommandLineOption& option : command->options) {
parser->addOption(option);
}
parser->addOption(Command::HelpOption);
return parser;
}
} // namespace
Command::Command()
: currentDatabase(nullptr)
{
options.append(Command::QuietOption);
}
Command::~Command() Command::~Command()
{ {
@ -58,7 +109,6 @@ Command::~Command()
QString Command::getDescriptionLine() QString Command::getDescriptionLine()
{ {
QString response = name; QString response = name;
QString space(" "); QString space(" ");
QString spaces = space.repeated(15 - name.length()); QString spaces = space.repeated(15 - name.length());
@ -68,36 +118,80 @@ QString Command::getDescriptionLine()
return response; return response;
} }
void populateCommands() QString Command::getHelpText()
{ {
if (commands.isEmpty()) { return buildParser(this)->helpText().replace("[options]", name + " [options]");
commands.insert(QString("add"), new Add());
commands.insert(QString("clip"), new Clip());
commands.insert(QString("create"), new Create());
commands.insert(QString("diceware"), new Diceware());
commands.insert(QString("edit"), new Edit());
commands.insert(QString("estimate"), new Estimate());
commands.insert(QString("extract"), new Extract());
commands.insert(QString("generate"), new Generate());
commands.insert(QString("locate"), new Locate());
commands.insert(QString("ls"), new List());
commands.insert(QString("merge"), new Merge());
commands.insert(QString("rm"), new Remove());
commands.insert(QString("show"), new Show());
}
} }
Command* Command::getCommand(const QString& commandName) QSharedPointer<QCommandLineParser> Command::getCommandLineParser(const QStringList& arguments)
{ {
populateCommands(); TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
if (commands.contains(commandName)) { QSharedPointer<QCommandLineParser> parser = buildParser(this);
return commands[commandName];
if (!parser->parse(arguments)) {
errorTextStream << parser->errorText() << "\n\n";
errorTextStream << getHelpText();
return {};
} }
return nullptr; if (parser->positionalArguments().size() < positionalArguments.size()) {
errorTextStream << getHelpText();
return {};
}
if (parser->positionalArguments().size() > (positionalArguments.size() + optionalArguments.size())) {
errorTextStream << getHelpText();
return {};
}
if (parser->isSet(HelpOption)) {
errorTextStream << getHelpText();
return {};
}
return parser;
} }
QList<Command*> Command::getCommands() namespace Commands
{ {
populateCommands(); QMap<QString, QSharedPointer<Command>> s_commands;
return commands.values();
} void setupCommands(bool interactive)
{
s_commands.clear();
s_commands.insert(QStringLiteral("add"), QSharedPointer<Command>(new Add()));
s_commands.insert(QStringLiteral("analyze"), QSharedPointer<Command>(new Analyze()));
s_commands.insert(QStringLiteral("clip"), QSharedPointer<Command>(new Clip()));
s_commands.insert(QStringLiteral("close"), QSharedPointer<Command>(new Close()));
s_commands.insert(QStringLiteral("create"), QSharedPointer<Command>(new Create()));
s_commands.insert(QStringLiteral("diceware"), QSharedPointer<Command>(new Diceware()));
s_commands.insert(QStringLiteral("edit"), QSharedPointer<Command>(new Edit()));
s_commands.insert(QStringLiteral("estimate"), QSharedPointer<Command>(new Estimate()));
s_commands.insert(QStringLiteral("generate"), QSharedPointer<Command>(new Generate()));
s_commands.insert(QStringLiteral("help"), QSharedPointer<Command>(new Help()));
s_commands.insert(QStringLiteral("locate"), QSharedPointer<Command>(new Locate()));
s_commands.insert(QStringLiteral("ls"), QSharedPointer<Command>(new List()));
s_commands.insert(QStringLiteral("merge"), QSharedPointer<Command>(new Merge()));
s_commands.insert(QStringLiteral("mkdir"), QSharedPointer<Command>(new AddGroup()));
s_commands.insert(QStringLiteral("mv"), QSharedPointer<Command>(new Move()));
s_commands.insert(QStringLiteral("open"), QSharedPointer<Command>(new Open()));
s_commands.insert(QStringLiteral("rm"), QSharedPointer<Command>(new Remove()));
s_commands.insert(QStringLiteral("rmdir"), QSharedPointer<Command>(new RemoveGroup()));
s_commands.insert(QStringLiteral("show"), QSharedPointer<Command>(new Show()));
if (interactive) {
s_commands.insert(QStringLiteral("exit"), QSharedPointer<Command>(new Exit("exit")));
s_commands.insert(QStringLiteral("quit"), QSharedPointer<Command>(new Exit("quit")));
} else {
s_commands.insert(QStringLiteral("export"), QSharedPointer<Command>(new Export()));
s_commands.insert(QStringLiteral("import"), QSharedPointer<Command>(new Import()));
}
}
QList<QSharedPointer<Command>> getCommands()
{
return s_commands.values();
}
QSharedPointer<Command> getCommand(const QString& commandName)
{
return s_commands.value(commandName);
}
} // namespace Commands

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> * Copyright (C) 2019 KeePassXC Team <team@keepassxc.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,6 +19,7 @@
#define KEEPASSXC_COMMAND_H #define KEEPASSXC_COMMAND_H
#include <QCommandLineOption> #include <QCommandLineOption>
#include <QCommandLineParser>
#include <QList> #include <QList>
#include <QObject> #include <QObject>
#include <QString> #include <QString>
@ -26,21 +27,44 @@
#include "core/Database.h" #include "core/Database.h"
// At the moment, there's no QT class for the positional arguments
// like there is for the options (QCommandLineOption).
struct CommandLineArgument
{
QString name;
QString description;
QString syntax;
};
class Command class Command
{ {
public: public:
Command();
virtual ~Command(); virtual ~Command();
virtual int execute(const QStringList& arguments) = 0; virtual int execute(const QStringList& arguments) = 0;
QString name; QString name;
QString description; QString description;
QSharedPointer<Database> currentDatabase;
QList<CommandLineArgument> positionalArguments;
QList<CommandLineArgument> optionalArguments;
QList<QCommandLineOption> options;
QString getDescriptionLine(); QString getDescriptionLine();
QSharedPointer<QCommandLineParser> getCommandLineParser(const QStringList& arguments);
QString getHelpText();
static QList<Command*> getCommands(); static const QCommandLineOption HelpOption;
static Command* getCommand(const QString& commandName);
static const QCommandLineOption QuietOption; static const QCommandLineOption QuietOption;
static const QCommandLineOption KeyFileOption; static const QCommandLineOption KeyFileOption;
static const QCommandLineOption NoPasswordOption; static const QCommandLineOption NoPasswordOption;
static const QCommandLineOption YubiKeyOption;
}; };
namespace Commands
{
void setupCommands(bool interactive);
QList<QSharedPointer<Command>> getCommands();
QSharedPointer<Command> getCommand(const QString& commandName);
} // namespace Commands
#endif // KEEPASSXC_COMMAND_H #endif // KEEPASSXC_COMMAND_H

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