diff --git a/CHANGELOG.md b/CHANGELOG.md index 697146498..fe0d2f6b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,80 @@ # Changelog -## 2.6.0 (unreleased) +## 2.6.0 (2020-07-06) ### Added -- Added CLI db-info command [#4231] -- Switch application icons to Material Design [#4066] -- Health Check report [#551] -- HIBP report: Check passwords against the HIBP online service [#1083] + +- Custom Light and Dark themes [#4110, #4769, #4791, #4796, #4892, #4915] +- Compact mode to use classic Group and Entry line height [#4910] +- View menu to quickly switch themes, compact mode, and toggle UI elements [#4910] +- Search for groups and scope search to matched groups [#4705] +- Save Database Backup feature [#4550] +- Sort entries by "natural order" and move lines up/down [#4357] +- Option to launch KeePassXC on system startup/login [#4675] +- Caps Lock warning on password input fields [#3646] +- Add "Size" column to entry view [#4588] +- Browser-like tab experience using Ctrl+[Num] (Alt+[Num] on Linux) [#4063, #4305] +- Password Generator: Define additional characters to choose from [#3876] +- Reports: Database password health check (offline) [#3993] +- Reports: HIBP online service to check for breached passwords [#4438] +- Auto-Type: DateTime placeholders [#4409] +- Browser: Show group name in results sent to browser extension [#4111] +- Browser: Ability to define a custom browser location (macOS and Linux only) [#4148] +- Browser: Ability to change root group UUID and inline edit connection ID [#4315, #4591] +- CLI: `db-info` command [#4231] +- CLI: Use wl-clipboard if xclip is not available (Linux) [#4323] +- CLI: Incorporate xclip into snap builds [#4697] +- SSH Agent: Key file path env substitution, SSH_AUTH_SOCK override, and connection test [#3769, #3801, #4545] +- SSH Agent: Context menu actions to add/remove keys [#4290] ### Changed -- Renamed CLI create command to db-create [#4231] -- Added --set-password option for CLI db-create command -- Added --set-key-file option for CLI db-create command (replacing --key-file option) + +- Complete replacement of default database icons [#4699] +- Complete replacement of application icons [#4066, #4161, #4203, #4411] +- Complete rewrite of documentation and manpages using Asciidoctor [#4937] +- Complete refactor of config files; separate between local and roaming [#4665] +- Complete refactor of browser integration and proxy code [#4680] +- Complete refactor of hardware key integration (YubiKey and OnlyKey) [#4584, #4843] +- Significantly improve performance when saving and opening databases [#4309, #4833] +- Remove read-only detection for database files [#4508] +- Overhaul of password fields and password generator [#4367] +- Replace instances of "Master Key" with "Database Credentials" [#4929] +- Change settings checkboxes to positive phrasing for consistency [#4715] +- Improve UX of using entry actions (focus fix) [#3893] +- Set expiration time to Now when enabling entry expiration [#4406] +- Always show "New Entry" in context menu [#4617] +- Issue warning before adding large attachments [#4651] +- Improve importing OPVault [#4630] +- Improve AutoOpen capability [#3901, #4752] +- Check for updates every 7 days even while still running [#4752] +- Improve Windows installer UI/UX [#4675] +- Improve config file handling of portable distribution [#4131, #4752] +- macOS: Hide dock icon when application is hidden to tray [#4782] +- Browser: Use unlock dialog to improve UX of opening a locked database [#3698] +- Browser: Improve database and entry settings experience [#4392, #4591] +- Browser: Improve confirm access dialog [#2143, #4660] +- KeeShare: Improve monitoring file changes of shares [#4720] +- CLI: Rename `create` command to `db-create` [#4231] +- CLI: Cleanup `db-create` options (`--set-key-file` and `--set-password`) [#4313] +- CLI: Use stderr for help text and password prompts [#4086, #4623] +- FdoSecrets: Display existing secret service process [#4128] + +### Fixed + +- Fix changing focus around the main window using tab key [#4641] +- Fix search field clearing while still using the application [#4368] +- Improve search help widget displaying on macOS and Linux [#4236] +- Return keyboard focus after editing an entry [#4287] +- Reset database path after failed "Save As" [#4526] +- Use SHA256 Digest for Windows code signing [#4129] +- Improve handling of ccache when building [#4104, #4335] +- macOS: Properly re-hide application window after browser integration and Auto-Type usage [#4909] +- Auto-Type: Fix crash when performing on new entry [#4132] +- Browser: Send legacy HTTP settings to recycle bin [#4589] +- Browser: Fix merging browser keys [#4685] +- CLI: Fix encoding when exporting database [#3921] +- SSH Agent: Improve reliability and underlying code [#3833, #4256, #4549, #4595] +- FdoSecrets: Fix crash when editing settings before service is enabled [#4332] ## 2.5.4 (2020-04-09) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b2cbde92..b0244d648 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -cmake_minimum_required(VERSION 3.1.0) +cmake_minimum_required(VERSION 3.3.0) project(KeePassXC) @@ -58,6 +58,7 @@ endif() if(APPLE) option(WITH_XC_TOUCHID "Include TouchID support for macOS." OFF) endif() +option(WITH_XC_DOCS "Enable building of documentation" ON) if(WITH_CCACHE) # Use the Compiler Cache (ccache) program @@ -71,7 +72,7 @@ if(WITH_CCACHE) endif() if(WITH_XC_ALL) - # Enable all options (except update check) + # Enable all options (except update check and docs) set(WITH_XC_AUTOTYPE ON) set(WITH_XC_NETWORKING ON) set(WITH_XC_BROWSER ON) @@ -225,10 +226,22 @@ macro(check_add_gcc_compiler_cflag FLAG FLAGNAME) endif() endmacro(check_add_gcc_compiler_cflag) +# This is the "front-end" for the above macros +# Optionally takes additional parameter(s) with language to check (currently "C" or "CXX") macro(check_add_gcc_compiler_flag FLAG) string(REGEX REPLACE "[-=]" "_" FLAGNAME "${FLAG}") - check_add_gcc_compiler_cxxflag("${FLAG}" "${FLAGNAME}") - check_add_gcc_compiler_cflag("${FLAG}" "${FLAGNAME}") + set(check_lang_spec ${ARGN}) + list(LENGTH check_lang_spec num_extra_args) + set(langs C CXX) + if(num_extra_args GREATER 0) + set(langs "${check_lang_spec}") + endif() + if("C" IN_LIST langs) + check_add_gcc_compiler_cflag("${FLAG}" "${FLAGNAME}") + endif() + if("CXX" IN_LIST langs) + check_add_gcc_compiler_cxxflag("${FLAG}" "${FLAGNAME}") + endif() endmacro(check_add_gcc_compiler_flag) add_definitions(-DQT_NO_EXCEPTIONS -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII) @@ -281,7 +294,7 @@ if(CMAKE_BUILD_TYPE_LOWER MATCHES "(release|relwithdebinfo|minsizerel)") endif() check_add_gcc_compiler_flag("-Werror=format-security") -check_add_gcc_compiler_flag("-Werror=implicit-function-declaration") +check_add_gcc_compiler_flag("-Werror=implicit-function-declaration" C) check_add_gcc_compiler_flag("-Wcast-align") if(WITH_COVERAGE AND CMAKE_COMPILER_IS_CLANGXX) @@ -305,7 +318,7 @@ endif() add_gcc_compiler_cflags("-std=c99") add_gcc_compiler_cxxflags("-std=c++11") -check_add_gcc_compiler_flag("-fsized-deallocation") +check_add_gcc_compiler_flag("-fsized-deallocation" CXX) if(APPLE AND CMAKE_COMPILER_IS_CLANGXX) add_gcc_compiler_cxxflags("-stdlib=libc++") @@ -489,6 +502,10 @@ if(WITH_TESTS) add_subdirectory(tests) endif(WITH_TESTS) +if(WITH_XC_DOCS) + add_subdirectory(docs) +endif() + if(PRINT_SUMMARY) # This will print ENABLED, REQUIRED and DISABLED feature_summary(WHAT ALL) diff --git a/INSTALL.md b/INSTALL.md index f452d84dd..44d63c2af 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -4,8 +4,7 @@ Build and Install KeePassXC This document will guide you through the steps to build and install KeePassXC from source. For more information, see also the [_Building KeePassXC_](https://github.com/keepassxreboot/keepassxc/wiki/Building-KeePassXC) page on the wiki. -The [KeePassXC QuickStart](./docs/QUICKSTART.md) gets you started using KeePassXC on your -Windows, Mac, or Linux computer using the pre-built binaries. +The [QuickStart Guide](https://keepassxc.org/docs/KeePassXC_GettingStarted.html) gets you started using KeePassXC on your Windows, macOS, or Linux computer using pre-compiled binaries from the [downloads page](https://keepassxc.org/download). Build Dependencies ================== @@ -15,6 +14,7 @@ The following tools must exist within your PATH: * make * cmake (>= 2.8.12) * g++ (>= 4.7) or clang++ (>= 3.0) +* asciidoctor (on Linux/MacOS) The following libraries are required: diff --git a/README.md b/README.md index d5070b8b7..4d5248a66 100644 --- a/README.md +++ b/README.md @@ -3,56 +3,52 @@ [![codecov](https://codecov.io/gh/keepassxreboot/keepassxc/branch/develop/graph/badge.svg)](https://codecov.io/gh/keepassxreboot/keepassxc) [![GitHub release](https://img.shields.io/github/release/keepassxreboot/keepassxc)](https://github.com/keepassxreboot/keepassxc/releases/) -[KeePassXC](https://keepassxc.org) is a cross-platform community fork of -[KeePassX](https://www.keepassx.org/). -Our goal is to extend and improve it with new features and bugfixes -to provide a feature-rich, fully cross-platform and modern -open-source password manager. +[KeePassXC](https://keepassxc.org) is a modern open-source password manager. It is used to store and manage information such as URLs, usernames, passwords, and so on for various accounts on your web and desktop applications. KeePassXC stores all data in an encrypted database format while still providing secure access to that information. KeePassXC is helpful for people with extremely high demands of secure personal data management. -## Installation -The [KeePassXC QuickStart](./docs/QUICKSTART.md) gets you started using -KeePassXC on your Windows, Mac, or Linux computer using pre-compiled binaries -from the [downloads page](https://keepassxc.org/download). +## Quick Start +The [QuickStart Guide](https://keepassxc.org/docs/KeePassXC_GettingStarted.html) gets you started using KeePassXC on your Windows, macOS, or Linux computer using pre-compiled binaries from the [downloads page](https://keepassxc.org/download). Additionally, individual Linux distributions may ship their own versions, so please check your distribution's package list to see if KeePassXC is available. Detailed documentation is available in the [User Guide](https://keepassxc.org/docs/KeePassXC_UserGuide.html). -Additionally, individual Linux distributions may ship their own versions, -so please check out your distribution's package list to see if KeePassXC is available. +## Features List +KeePassXC has numerous features for novice and power users alike. This guide will go over the basic features to get you up and running quickly. The User Guide contains more in-depth discussions on the major features in the application. -## Additional features compared to KeePassX -- Auto-Type on all three major platforms (Linux, Windows, macOS) -- Twofish encryption -- YubiKey challenge-response support -- TOTP generation -- CSV import -- A [Command Line Interface (keepassxc-cli)](./share/docs/man/keepassxc-cli.1) -- DEP and ASLR hardening -- Stand-alone password and passphrase generator -- Password strength meter -- Using website favicons as entry icons -- Merging of databases -- Automatic reload when the database changed on disk -- Browser integration with KeePassXC-Browser using [native messaging](https://developer.chrome.com/extensions/nativeMessaging) for [Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/) and [Google Chrome, Chromium, Vivaldi, or Brave](https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk) and [Microsoft Edge](https://microsoftedge.microsoft.com/addons/detail/pdffhmdngciaglkoonimfcmckehcpafo) -- Synchronize passwords using KeeShare. See [Using Sharing](./docs/QUICKSTART.md#using-sharing) for more details. -- Many bug fixes +### Basic +* Create, open, and save databases in the KDBX format (KeePass Compatible) +* Store sensitive information in entries that are organized by groups +* Search for entries +* Password generator +* Auto-Type passwords into applications +* Browser integration with Google Chrome, Mozilla Firefox, Microsoft Edge, Chromium, Vivaldi, Brave, and Tor-Browser +* Entry icon download +* Import databases from CSV, 1Password, and KeePass1 formats -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) +### Advanced +* Database reports (password health, HIBP, and statistics) +* Database export to CSV and HTML formats +* TOTP storage and generation +* Field references between entries +* File attachments and custom attributes +* Entry history and data restoration +* YubiKey/OnlyKey challenge-response support +* Command line interface (keepassxc-cli) +* Auto-Open databases +* KeeShare shared databases (import, export, and synchronize) +* SSH Agent +* FreeDesktop.org Secret Service (replace Gnome keyring, etc.) +* Additional encryption choices: Twofish and ChaCha20 + +For a full list of changes, read the [CHANGELOG](CHANGELOG.md) document. \ +For a full list of keyboard shortcuts, see [KeyboardShortcuts.adoc](./docs/topics/KeyboardShortcuts.adoc) ## Building KeePassXC -Detailed instructions are available in the [Build and Install](./INSTALL.md) -page or on the [Wiki page](https://github.com/keepassxreboot/keepassxc/wiki/Building-KeePassXC). +Detailed instructions are available in the [Build and Install](./INSTALL.md) page and in the [Wiki](https://github.com/keepassxreboot/keepassxc/wiki/Building-KeePassXC). ## Contributing -We are always looking for suggestions how to improve our application. -If you find any bugs or have an idea for a new feature, please let us know by -opening a report in our [issue tracker](https://github.com/keepassxreboot/keepassxc/issues) -on GitHub or join us on IRC on freenode channels #keepassxc or #keepassxc-dev. +We are always looking for suggestions on how to improve KeePassXC. If you find any bugs or have an idea for a new feature, please let us know by opening a report in the [issue tracker](https://github.com/keepassxreboot/keepassxc/issues) on GitHub or join us on IRC in [freenode](https://webchat.freenode.net/) channels #keepassxc and #keepassxc-dev. -You can of course also directly contribute your own code. We are happy to accept your pull requests. - -Please read the [CONTRIBUTING document](.github/CONTRIBUTING.md) for further information. +You may directly contribute your own code by submitting a pull request. Please read the [CONTRIBUTING](.github/CONTRIBUTING.md) document for further information. ## License -GPL-2 or GPL-3 +KeePassXC code is licensed under GPL-2 or GPL-3. Additional licensing for third-party files is detailed in [COPYING](./COPYING). diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 000000000..8a64701cc --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,65 @@ +# Copyright (C) 2020 KeePassXC Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 or (at your option) +# version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +find_program(ASCIIDOCTOR_EXE asciidoctor) +if(NOT ASCIIDOCTOR_EXE) + message(FATAL_ERROR "asciidoctor is required to build documentation") +else() + message(STATUS "Using asciidoctor: ${ASCIIDOCTOR_EXE}") +endif() + +set(DOC_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(OUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) + +# Build html documentation on all platforms +add_custom_command(OUTPUT KeePassXC_GettingStarted.html + COMMAND ${ASCIIDOCTOR_EXE} -D ${OUT_DIR} -o KeePassXC_GettingStarted.html ${DOC_DIR}/GettingStarted.adoc + DEPENDS ${DOC_DIR}/topics/* ${DOC_DIR}/styles/* ${DOC_DIR}/images/* ${DOC_DIR}/GettingStarted.adoc + VERBATIM) +add_custom_command(OUTPUT KeePassXC_UserGuide.html + COMMAND ${ASCIIDOCTOR_EXE} -D ${OUT_DIR} -o KeePassXC_UserGuide.html ${DOC_DIR}/UserGuide.adoc + DEPENDS ${DOC_DIR}/topics/* ${DOC_DIR}/styles/* ${DOC_DIR}/images/* ${DOC_DIR}/UserGuide.adoc + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + VERBATIM) +add_custom_command(OUTPUT KeePassXC_KeyboardShortcuts.html + COMMAND ${ASCIIDOCTOR_EXE} -D ${OUT_DIR} -o KeePassXC_KeyboardShortcuts.html ${DOC_DIR}/topics/KeyboardShortcuts.adoc + DEPENDS ${DOC_DIR}/topics/KeyboardShortcuts.adoc ${DOC_DIR}/styles/* + VERBATIM) + +add_custom_target(docs ALL DEPENDS KeePassXC_GettingStarted.html KeePassXC_UserGuide.html KeePassXC_KeyboardShortcuts.html) + +install(FILES + ${OUT_DIR}/KeePassXC_GettingStarted.html + ${OUT_DIR}/KeePassXC_UserGuide.html + ${OUT_DIR}/KeePassXC_KeyboardShortcuts.html + DESTINATION ${DATA_INSTALL_DIR}/docs) + +# Build Man Pages on Linux and macOS +if(APPLE OR UNIX) + add_custom_command(OUTPUT keepassxc.1 + COMMAND ${ASCIIDOCTOR_EXE} -D ${OUT_DIR} -b manpage ${DOC_DIR}/man/keepassxc.1.adoc + DEPENDS ${DOC_DIR}/man/* + VERBATIM) + add_custom_command(OUTPUT keepassxc-cli.1 + COMMAND ${ASCIIDOCTOR_EXE} -D ${OUT_DIR} -b manpage ${DOC_DIR}/man/keepassxc-cli.1.adoc + DEPENDS ${DOC_DIR}/man/* + VERBATIM) + add_custom_target(manpages ALL DEPENDS keepassxc.1 keepassxc-cli.1) + + install(FILES + ${OUT_DIR}/keepassxc.1 + ${OUT_DIR}/keepassxc-cli.1 + DESTINATION ${CMAKE_INSTALL_MANDIR}/man1/) +endif() diff --git a/docs/GettingStarted.adoc b/docs/GettingStarted.adoc new file mode 100644 index 000000000..8235ed3b9 --- /dev/null +++ b/docs/GettingStarted.adoc @@ -0,0 +1,34 @@ += KeePassXC: Getting Started Guide +KeePassXC Team +v2.6.0 +:data-uri: +:linkcss!: +:homepage: https://keepassxc.org +:icons: font +:imagesdir: images +:stylesheet: styles/dark.css +:toc: left +ifdef::backend-pdf[] +:title-page: +:title-logo-image: {imagesdir}/kpxc_logo.png +:pdf-theme: styles/pdf_theme.yml +:compress: +endif::[] + +include::topics/Disclaimers.adoc[] + +<<< + +// Include various topics, excluding advanced sections + +include::topics/Welcome.adoc[tags=*;!advanced] + +include::topics/DownloadInstall.adoc[tags=*;!advanced] + +include::topics/UserInterface.adoc[tags=*;!advanced] + +include::topics/PasswordGenerator.adoc[tags=*;!advanced] + +include::topics/DatabaseOperations.adoc[tags=*;!advanced] + +include::topics/BrowserPlugin.adoc[tags=*;!advanced] diff --git a/docs/KEYBINDS.md b/docs/KEYBINDS.md deleted file mode 100644 index 24f85f68e..000000000 --- a/docs/KEYBINDS.md +++ /dev/null @@ -1,33 +0,0 @@ -# List of Keyboard Shortcuts for KeePassXC - -Actions | Keyboard Shortcuts ------------------------------|---------------------------- -New Database | Ctrl + Shift + N -Open Database | Ctrl + O -Save Database | Ctrl + S -Save Database As | Ctrl + Shift + S -Close Database | Ctrl + W -Lock Databases | Ctrl + L -Quit | Ctrl + Q -New Entry | Ctrl + N -Edit Entry | Ctrl + E -Delete Entry | Ctrl + D -Clone Entry | Ctrl + K -Show TOTP | Ctrl + Shift + T -Copy TOTP | Ctrl + T -Copy Username | Ctrl + B -Copy Password | Ctrl + C -Trigger AutoType | Ctrl + Shift - V -Open URL | Ctrl + Shift - U -Copy URL | Ctrl + U -Add key to SSH Agent | Ctrl + H -Remove key from SSH Agent | Ctrl + Shift + H -Show Minimized | Ctrl + M -Hide Window | Ctrl + Shift - M -Select Next Database Tab | Ctrl + Tab *OR* Ctrl + PGDN -Select Previous Database Tab | Ctrl + Shift + Tab *OR* Ctrl + PGUP -Toggle Passwords Hidden | Ctrl + Shift + C -Toggle Usernames Hidden | Ctrl + Shift + B -Focus Search | Ctrl + F -Clear Search | ESC -Show Keyboard Shortcuts | Ctrl + / diff --git a/docs/KeePassHTTP/KeePassXC-Accept-Button.png b/docs/KeePassHTTP/KeePassXC-Accept-Button.png deleted file mode 100644 index 8c736c213..000000000 Binary files a/docs/KeePassHTTP/KeePassXC-Accept-Button.png and /dev/null differ diff --git a/docs/KeePassHTTP/KeePassXC-Confirm.png b/docs/KeePassHTTP/KeePassXC-Confirm.png deleted file mode 100644 index e0b0f084e..000000000 Binary files a/docs/KeePassHTTP/KeePassXC-Confirm.png and /dev/null differ diff --git a/docs/KeePassHTTP/KeePassXC-Connect.png b/docs/KeePassHTTP/KeePassXC-Connect.png deleted file mode 100644 index a2d756712..000000000 Binary files a/docs/KeePassHTTP/KeePassXC-Connect.png and /dev/null differ diff --git a/docs/KeeShare/AppSettings.png b/docs/KeeShare/AppSettings.png deleted file mode 100644 index b12e6a04d..000000000 Binary files a/docs/KeeShare/AppSettings.png and /dev/null differ diff --git a/docs/KeeShare/DatabaseSettings.png b/docs/KeeShare/DatabaseSettings.png deleted file mode 100644 index ec89b51d5..000000000 Binary files a/docs/KeeShare/DatabaseSettings.png and /dev/null differ diff --git a/docs/KeeShare/GroupSettings_Export.png b/docs/KeeShare/GroupSettings_Export.png deleted file mode 100644 index 1cfd3f331..000000000 Binary files a/docs/KeeShare/GroupSettings_Export.png and /dev/null differ diff --git a/docs/KeeShare/GroupSettings_Import.png b/docs/KeeShare/GroupSettings_Import.png deleted file mode 100644 index 3824c0158..000000000 Binary files a/docs/KeeShare/GroupSettings_Import.png and /dev/null differ diff --git a/docs/KeeShare/GroupSettings_Sync.png b/docs/KeeShare/GroupSettings_Sync.png deleted file mode 100644 index 7385229e8..000000000 Binary files a/docs/KeeShare/GroupSettings_Sync.png and /dev/null differ diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md deleted file mode 100644 index f1668ace8..000000000 --- a/docs/QUICKSTART.md +++ /dev/null @@ -1,137 +0,0 @@ -# Quick Start for KeePassXC - -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). - -**TL;DR** KeePassXC saves your passwords securely. -When you double-click a URL in KeePassXC, it launches your default browser to that URL. -With browser integration configured, KeePassXC automatically enters username/password credentials into web page fields. - -## Installing and Starting KeePassXC - -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. -1. Open the KeePassXC application. -1. 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. -1. Create a few entries - enter the username, password, URL, and optionally notes about the entry. -1. KeePassXC securely stores those entries in the database. - -## Setting up Browser Integration with KeePassXC - -1. *Within KeePassXC*, go to **Tools → Settings** (on macOS, go to **KeePassXC → Preferences**). -1. In **Browser Integration**, check **Enable KeePassXC browser integration**. -1. Right below that, click the checkbox for the browser(s) you use. -Leave the other options at their defaults. -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). -1. Click the KeePassXC icon in the upper-right corner. You'll see the dialog below. -1. Click the blue Connect button to make the browser extension connect to the KeePassXC application. - - KeePassXC Connect Dialog - -7. *Switch back to KeePassXC.* You'll see a dialog (below) indicating that a request to connect has arrived. -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. - -KeePassXC Accept Connection Dialog - -## Using Browser Integration - -1. *Within KeePassXC,* double-click the URL of an entry, or select it and type Ctrl+U (Cmd+U on macOS). -1. Your browser opens to that URL. -1. 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. -1. Check *Remember this decision* to allow this each time you visit the page. - -KeePassCX Confirm Access Dialog - -## Using Sharing - -Sharing allows you to share a subset of your credentials with others and vice versa. - -### Enable Sharing - -To use sharing, you need to enable it for the application. - -1. Go to Tools → Settings. -1. Select the category KeeShare. -1. Check _Allow import_ if you want to import shared credentials. -1. Check _Allow export_ if you want to share credentials. - -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. - -KeeShare Application Settings - -### 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 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. Select the sharing section. -1. Choose _Export to path_ as the sharing method. -1. Choose a path to store the shared credentials to. -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. - -KeeShare Group Sharing Settings - -### Using Shared Credentials - -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. Open the edit sheet on that group. -1. Select the sharing section. -1. Choose _Import from path_ as the sharing method. -1. Choose a share container that is shared with you. -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. - -Please note, that the import currently is not restricted to the configured group. Every entry which was imported and moved outside the import group will be updated regardless of it's location! - -KeeShare Group Import Settings - -### Using Synchronized Credentials - -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. Select the sharing section. -1. Choose _Synchronize with path_ as the sharing method. -1. Choose a database that you want to use a synchronization file. -1. Enter the password for the database. - -KeeShare Group Synchronization Settings - -### Disable Sharing for Credentials - -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 -* 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 - -There is a simple overview of shared groups to keep track of your data. - -1. Open the Database Settings. -1. Select the KeeShare category. - -KeeShare Group Sharing Ovewview - -## Technical Details and Limitations of Sharing - -Sharing relies on the combination of file exports and imports as well as the synchronization mechanism provided by KeePassXC. Since the merge algorithm uses the history of entries to prevent data loss, this history must be enabled and have a sufficient size. Furthermore, the merge algorithm is location independent, therefore it does not matter if entries are moved outside of an import group. These entries will be updated none the less. Moving entries outside of export groups will prevent a further export of the entry, but it will not ensure that the already shared data will be removed from any client. - -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 functionality, 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. diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc new file mode 100644 index 000000000..f879ce99b --- /dev/null +++ b/docs/UserGuide.adoc @@ -0,0 +1,37 @@ += KeePassXC: User Guide +KeePassXC Team +v2.6.0 +:data-uri: +:homepage: https://keepassxc.org +:icons: font +:imagesdir: images +:stylesheet: styles/dark.css +:toc: left +ifdef::backend-pdf[] +:title-page: +:title-logo-image: {imagesdir}/kpxc_logo.png +:pdf-theme: styles/pdf_theme.yml +:compress: +endif::[] + +include::topics/Disclaimers.adoc[] + +<<< + +// Include feature topics and advanced sections + +include::topics/UserInterface.adoc[tags=*] + +include::topics/DatabaseOperations.adoc[tags=*] + +include::topics/ImportExport.adoc[tags=*] + +include::topics/PasswordGenerator.adoc[tags=*] + +include::topics/BrowserPlugin.adoc[tags=*] + +include::topics/AutoType.adoc[tags=*] + +include::topics/KeeShare.adoc[tags=*] + +include::topics/SSHAgent.adoc[tags=*] diff --git a/docs/images/autotype_entry_sequences.png b/docs/images/autotype_entry_sequences.png new file mode 100644 index 000000000..d5899bc2a Binary files /dev/null and b/docs/images/autotype_entry_sequences.png differ diff --git a/docs/images/autotype_entrylevel.png b/docs/images/autotype_entrylevel.png new file mode 100644 index 000000000..5a92df4e9 Binary files /dev/null and b/docs/images/autotype_entrylevel.png differ diff --git a/docs/images/autotype_selection_dialog.png b/docs/images/autotype_selection_dialog.png new file mode 100644 index 000000000..6f15a6ea6 Binary files /dev/null and b/docs/images/autotype_selection_dialog.png differ diff --git a/docs/images/autotype_settings.png b/docs/images/autotype_settings.png new file mode 100644 index 000000000..7d1d63e8d Binary files /dev/null and b/docs/images/autotype_settings.png differ diff --git a/docs/images/browser_advanced_settings.png b/docs/images/browser_advanced_settings.png new file mode 100644 index 000000000..9f4a8bd2f Binary files /dev/null and b/docs/images/browser_advanced_settings.png differ diff --git a/docs/images/browser_confirm_access_dialog.png b/docs/images/browser_confirm_access_dialog.png new file mode 100644 index 000000000..0e268e4ff Binary files /dev/null and b/docs/images/browser_confirm_access_dialog.png differ diff --git a/docs/images/browser_database_settings.png b/docs/images/browser_database_settings.png new file mode 100644 index 000000000..2b559e839 Binary files /dev/null and b/docs/images/browser_database_settings.png differ diff --git a/docs/images/browser_entry_settings.png b/docs/images/browser_entry_settings.png new file mode 100644 index 000000000..0a2b4dd71 Binary files /dev/null and b/docs/images/browser_entry_settings.png differ diff --git a/docs/images/browser_extension_association.png b/docs/images/browser_extension_association.png new file mode 100644 index 000000000..1a2368eb0 Binary files /dev/null and b/docs/images/browser_extension_association.png differ diff --git a/docs/images/browser_extension_connect.png b/docs/images/browser_extension_connect.png new file mode 100644 index 000000000..74674745f Binary files /dev/null and b/docs/images/browser_extension_connect.png differ diff --git a/docs/images/browser_extension_icons.png b/docs/images/browser_extension_icons.png new file mode 100644 index 000000000..bd2ba77ef Binary files /dev/null and b/docs/images/browser_extension_icons.png differ diff --git a/docs/images/browser_extension_reload.png b/docs/images/browser_extension_reload.png new file mode 100644 index 000000000..e3272582f Binary files /dev/null and b/docs/images/browser_extension_reload.png differ diff --git a/docs/images/browser_fill_credentials.png b/docs/images/browser_fill_credentials.png new file mode 100644 index 000000000..5766f4a84 Binary files /dev/null and b/docs/images/browser_fill_credentials.png differ diff --git a/docs/images/browser_settings.png b/docs/images/browser_settings.png new file mode 100644 index 000000000..0466b34d3 Binary files /dev/null and b/docs/images/browser_settings.png differ diff --git a/docs/images/clone_entry.png b/docs/images/clone_entry.png new file mode 100644 index 000000000..bd3145fb9 Binary files /dev/null and b/docs/images/clone_entry.png differ diff --git a/docs/images/clone_entry_dialog.png b/docs/images/clone_entry_dialog.png new file mode 100644 index 000000000..8fd9d49c5 Binary files /dev/null and b/docs/images/clone_entry_dialog.png differ diff --git a/docs/images/clone_entry_references.png b/docs/images/clone_entry_references.png new file mode 100644 index 000000000..99e16d6a4 Binary files /dev/null and b/docs/images/clone_entry_references.png differ diff --git a/docs/images/compact_mode_comparison.png b/docs/images/compact_mode_comparison.png new file mode 100644 index 000000000..364597532 Binary files /dev/null and b/docs/images/compact_mode_comparison.png differ diff --git a/docs/images/csv_import.png b/docs/images/csv_import.png new file mode 100644 index 000000000..666aeb0b6 Binary files /dev/null and b/docs/images/csv_import.png differ diff --git a/docs/images/database_security.png b/docs/images/database_security.png new file mode 100644 index 000000000..f2d8b0586 Binary files /dev/null and b/docs/images/database_security.png differ diff --git a/docs/images/database_security_credentials.png b/docs/images/database_security_credentials.png new file mode 100644 index 000000000..bc947fbc6 Binary files /dev/null and b/docs/images/database_security_credentials.png differ diff --git a/docs/images/database_security_encryption.png b/docs/images/database_security_encryption.png new file mode 100644 index 000000000..86f0f9996 Binary files /dev/null and b/docs/images/database_security_encryption.png differ diff --git a/docs/images/database_security_encryption_advanced.png b/docs/images/database_security_encryption_advanced.png new file mode 100644 index 000000000..cb68078e2 Binary files /dev/null and b/docs/images/database_security_encryption_advanced.png differ diff --git a/docs/images/database_settings.png b/docs/images/database_settings.png new file mode 100644 index 000000000..a9f34003d Binary files /dev/null and b/docs/images/database_settings.png differ diff --git a/docs/images/database_view.png b/docs/images/database_view.png new file mode 100644 index 000000000..a4a1f31b8 Binary files /dev/null and b/docs/images/database_view.png differ diff --git a/docs/images/edit_entry.png b/docs/images/edit_entry.png new file mode 100644 index 000000000..80bdd1e56 Binary files /dev/null and b/docs/images/edit_entry.png differ diff --git a/docs/images/edit_entry_attachments.png b/docs/images/edit_entry_attachments.png new file mode 100644 index 000000000..42bef27da Binary files /dev/null and b/docs/images/edit_entry_attachments.png differ diff --git a/docs/images/edit_entry_attributes.png b/docs/images/edit_entry_attributes.png new file mode 100644 index 000000000..047c4fd68 Binary files /dev/null and b/docs/images/edit_entry_attributes.png differ diff --git a/docs/images/edit_entry_colors.png b/docs/images/edit_entry_colors.png new file mode 100644 index 000000000..0c9482a82 Binary files /dev/null and b/docs/images/edit_entry_colors.png differ diff --git a/docs/images/edit_entry_history.png b/docs/images/edit_entry_history.png new file mode 100644 index 000000000..e16e3ec01 Binary files /dev/null and b/docs/images/edit_entry_history.png differ diff --git a/docs/images/edit_entry_icons.png b/docs/images/edit_entry_icons.png new file mode 100644 index 000000000..f86fca036 Binary files /dev/null and b/docs/images/edit_entry_icons.png differ diff --git a/docs/images/edit_entry_properties.png b/docs/images/edit_entry_properties.png new file mode 100644 index 000000000..c781192ae Binary files /dev/null and b/docs/images/edit_entry_properties.png differ diff --git a/docs/images/export_database.png b/docs/images/export_database.png new file mode 100644 index 000000000..92a417ac0 Binary files /dev/null and b/docs/images/export_database.png differ diff --git a/docs/images/install_wizard_1.png b/docs/images/install_wizard_1.png new file mode 100644 index 000000000..a466f834b Binary files /dev/null and b/docs/images/install_wizard_1.png differ diff --git a/docs/images/install_wizard_2.png b/docs/images/install_wizard_2.png new file mode 100644 index 000000000..b7c9c0712 Binary files /dev/null and b/docs/images/install_wizard_2.png differ diff --git a/docs/images/keeshare_application_settings.png b/docs/images/keeshare_application_settings.png new file mode 100644 index 000000000..a50302ef1 Binary files /dev/null and b/docs/images/keeshare_application_settings.png differ diff --git a/docs/images/keeshare_group_settings.png b/docs/images/keeshare_group_settings.png new file mode 100644 index 000000000..51febf41f Binary files /dev/null and b/docs/images/keeshare_group_settings.png differ diff --git a/docs/images/keeshare_shared_group.png b/docs/images/keeshare_shared_group.png new file mode 100644 index 000000000..4d23aca89 Binary files /dev/null and b/docs/images/keeshare_shared_group.png differ diff --git a/docs/images/kpxc_logo.png b/docs/images/kpxc_logo.png new file mode 100644 index 000000000..9af29eb30 Binary files /dev/null and b/docs/images/kpxc_logo.png differ diff --git a/docs/images/linux_store.png b/docs/images/linux_store.png new file mode 100644 index 000000000..7c63ca7be Binary files /dev/null and b/docs/images/linux_store.png differ diff --git a/docs/images/macos_install.png b/docs/images/macos_install.png new file mode 100644 index 000000000..f72222786 Binary files /dev/null and b/docs/images/macos_install.png differ diff --git a/docs/images/main_interface.png b/docs/images/main_interface.png new file mode 100644 index 000000000..80a564698 Binary files /dev/null and b/docs/images/main_interface.png differ diff --git a/docs/images/new_db_wizard_1.png b/docs/images/new_db_wizard_1.png new file mode 100644 index 000000000..360033543 Binary files /dev/null and b/docs/images/new_db_wizard_1.png differ diff --git a/docs/images/new_db_wizard_2.png b/docs/images/new_db_wizard_2.png new file mode 100644 index 000000000..3c384e1d5 Binary files /dev/null and b/docs/images/new_db_wizard_2.png differ diff --git a/docs/images/new_db_wizard_3.png b/docs/images/new_db_wizard_3.png new file mode 100644 index 000000000..e6ac46769 Binary files /dev/null and b/docs/images/new_db_wizard_3.png differ diff --git a/docs/images/open_database.png b/docs/images/open_database.png new file mode 100644 index 000000000..755f08caa Binary files /dev/null and b/docs/images/open_database.png differ diff --git a/docs/images/passphrase_generator.png b/docs/images/passphrase_generator.png new file mode 100644 index 000000000..b032e227d Binary files /dev/null and b/docs/images/passphrase_generator.png differ diff --git a/docs/images/password_generator.png b/docs/images/password_generator.png new file mode 100644 index 000000000..19d770135 Binary files /dev/null and b/docs/images/password_generator.png differ diff --git a/docs/images/password_generator_advanced.png b/docs/images/password_generator_advanced.png new file mode 100644 index 000000000..2536ad78e Binary files /dev/null and b/docs/images/password_generator_advanced.png differ diff --git a/docs/images/save_database_backup.png b/docs/images/save_database_backup.png new file mode 100644 index 000000000..ad543b4c3 Binary files /dev/null and b/docs/images/save_database_backup.png differ diff --git a/docs/images/sshagent_application_settings.png b/docs/images/sshagent_application_settings.png new file mode 100644 index 000000000..1c9325a74 Binary files /dev/null and b/docs/images/sshagent_application_settings.png differ diff --git a/docs/images/sshagent_context_menu.png b/docs/images/sshagent_context_menu.png new file mode 100644 index 000000000..8bd280fde Binary files /dev/null and b/docs/images/sshagent_context_menu.png differ diff --git a/docs/images/sshagent_entry_settings.png b/docs/images/sshagent_entry_settings.png new file mode 100644 index 000000000..263f55822 Binary files /dev/null and b/docs/images/sshagent_entry_settings.png differ diff --git a/docs/images/sshagent_puttygen.png b/docs/images/sshagent_puttygen.png new file mode 100644 index 000000000..0888f04a7 Binary files /dev/null and b/docs/images/sshagent_puttygen.png differ diff --git a/docs/images/theme_comparison.png b/docs/images/theme_comparison.png new file mode 100644 index 000000000..408bb892c Binary files /dev/null and b/docs/images/theme_comparison.png differ diff --git a/docs/images/theme_selection.png b/docs/images/theme_selection.png new file mode 100644 index 000000000..162c51a9e Binary files /dev/null and b/docs/images/theme_selection.png differ diff --git a/docs/images/toolbar.png b/docs/images/toolbar.png new file mode 100644 index 000000000..9fd94673e Binary files /dev/null and b/docs/images/toolbar.png differ diff --git a/docs/images/uac_dialog.png b/docs/images/uac_dialog.png new file mode 100644 index 000000000..1477626c2 Binary files /dev/null and b/docs/images/uac_dialog.png differ diff --git a/docs/images/unlock_database.png b/docs/images/unlock_database.png new file mode 100644 index 000000000..5cd3c37d8 Binary files /dev/null and b/docs/images/unlock_database.png differ diff --git a/docs/images/welcome_screen.png b/docs/images/welcome_screen.png new file mode 100644 index 000000000..d035172b6 Binary files /dev/null and b/docs/images/welcome_screen.png differ diff --git a/docs/man/keepassxc-cli.1.adoc b/docs/man/keepassxc-cli.1.adoc new file mode 100644 index 000000000..13d3ec011 --- /dev/null +++ b/docs/man/keepassxc-cli.1.adoc @@ -0,0 +1,282 @@ += keepassxc-cli(1) +:docdate: 2020-07-05 +:doctype: manpage +:manmanual: General Commands Manual + +== NAME +keepassxc-cli - command line interface for the KeePassXC password manager. + +== SYNOPSIS +*keepassxc-cli* _command_ [_options_] + +== DESCRIPTION +*keepassxc-cli* is the command line interface for the *KeePassXC* password manager. +It provides the ability to query and modify the entries of a KeePass database, directly from the command line. + +== COMMANDS +*add* [_options_] <__database__> <__entry__>:: + Adds a new entry to a database. + A password can be generated (_-g_ option), or a prompt can be displayed to input the password (_-p_ option). + The same password generation options as documented for the generate command can be used when the _-g_ option is set. + +*analyze* [_options_] <__database__>:: + Analyzes passwords in a database for weaknesses. + +*clip* [_options_] <__database__> <__entry__> [_timeout_]:: + Copies an attribute or the current TOTP (if the _-t_ option is specified) of a database entry to the clipboard. + If no attribute name is specified using the _-a_ option, the password is copied. + If multiple entries with the same name exist in different groups, only the attribute for the first one is copied. + For copying the attribute 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. + +*close*:: + In interactive mode, closes the currently opened database (see _open_). + +*db-create* [_options_] <__database__>:: + Creates a new database with a password and/or a key file. + 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. + +*db-info* [_options_] <__database__>:: + Show a database's information. + +*diceware* [_options_]:: + Generates a random diceware passphrase. + +*edit* [_options_] <__database__> <__entry__>:: + Edits a database entry. + A password can be generated (_-g_ option), or a prompt can be displayed to input the password (_-p_ option). + The same password generation options as documented for the generate command can be used when the _-g_ option is set. + +*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. + +*exit*:: + Exits interactive mode. + Synonymous with _quit_. + +*export* [_options_] <__database__>:: + Exports the content of a database to standard output in the specified format (defaults to XML). + +*generate* [_options_]:: + Generates a random password. + +*help* [_command_]:: + Displays a list of available commands, or detailed information about the specified command. + +*import* [_options_] <__xml__> <__database__>:: + Imports the contents of an XML database to the target database. + +*locate* [_options_] <__database__> <__term__>:: + Locates all the entries that match a specific search term in a database. + +*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. + +*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 _--same-credentials_ or _-s_ option can be used. + +*mkdir* [_options_] <__database__> <__group__>:: + Adds a new group to a database. + +*mv* [_options_] <__database__> <__entry__> <__group__>:: + Moves an entry to a new group. + +*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. _ls_ followed by _show_). + +*quit*:: + Exits interactive mode. + Synonymous with _exit_. + +*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. + +*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. + +*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 _clip_ command section also applies here. + +== OPTIONS +=== General options +*--debug-info*:: + Displays debugging information. + +*-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. + +*--no-password*:: + Deactivates the password key for the database. + +*-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. + +*-q*, *--quiet* <__path__>:: + Silences password prompt and other secondary outputs. + +*-h*, *--help*:: + Displays help information. + +*-v*, *--version*:: + Displays the program version. + +=== Merge options +*-d*, *--dry-run* <__path__>:: + Prints the changes detected by the merge operation without making any changes to the database. + +*--key-file-from* <__path__>:: + Sets the path of the key file for the second database. + +*--no-password-from*:: + Deactivates password key for the database to merge from. + +*--yubikey-from* <__slot__>:: + YubiKey slot for the second database. + +*-s*, *--same-credentials*:: + Uses the same credentials for unlocking both databases. + +=== 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. + +*-u*, *--username* <__username__>:: + Specifies the username of the entry. + +*--url* <__url__>:: + Specifies the URL of the entry. + +*-p*, *--password-prompt*:: + Uses a password prompt for the entry's password. + +*-g*, *--generate*:: + Generates a new password for the entry. + +=== Edit options +*-t*, *--title* <__title__>:: + Specifies the title of the entry. + +=== Estimate options +*-a*, *--advanced*:: + Performs advanced analysis on the password. + +=== Analyze options +*-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). + +=== Clip options +*-a*, *--attribute*:: + Copies the specified attribute to the clipboard. + If no attribute is specified, the password attribute is the default. + For example, "_-a_ username" would copy the username to the clipboard. + [Default: password] + +*-t*, *--totp*:: + Copies the current TOTP instead of the specified attribute to the clipboard. + Will report an error if no TOTP is configured for the entry. + +=== Create options +*-k*, *--set-key-file* <__path__>:: + Set the key file for the database. + +*-p*, *--set-password*:: + Set a password for the database. + +*-t*, *--decryption-time* <__time__>:: + Target decryption time in MS for the database. + +=== Show options +*-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 _-t_ is not specified, a summary of the default attributes is given. + Protected attributes will be displayed in clear text if specified explicitly by this option. + +*-s*, *--show-protected*:: + Shows the protected attributes in clear text. + +*-t*, *--totp*:: + Also shows the current TOTP, reporting an error if no TOTP is configured for the entry. + +=== Diceware options +*-W*, *--words* <__count__>:: + Sets the desired number of words for the generated passphrase. + [Default: 7] + +*-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. + +=== Export options +*-f*, *--format*:: + Format to use when exporting. + Available choices are xml or csv. + Defaults to xml. + +=== List options +*-R*, *--recursive*:: + Recursively lists the elements of the group. + +*-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. + +=== Generate options +*-L*, *--length* <__length__>:: + Sets the desired length for the generated password. + [Default: 16] + +*-l*, *--lower*:: + Uses lowercase characters for the generated password. + [Default: Enabled] + +*-U*, *--upper*:: + Uses uppercase characters for the generated password. + [Default: Enabled] + +*-n*, *--numeric*:: + Uses numbers characters for the generated password. + [Default: Enabled] + +*-s*, *--special*:: + Uses special characters for the generated password. + [Default: Disabled] + +*-e*, *--extended*:: + Uses extended ASCII characters for the generated password. + [Default: Disabled] + +*-x*, *--exclude* <__chars__>:: + Comma-separated list of characters to exclude from the generated password. + None is excluded by default. + +*--exclude-similar*:: + Exclude similar looking characters. + [Default: Disabled] + +*--every-group*:: + Include characters from every selected group. + [Default: Disabled] + +== REPORTING BUGS +Bugs and feature requests can be reported on GitHub at https://github.com/keepassxreboot/keepassxc/issues. + +== AUTHOR +This manual page was originally written by Manolis Agkopian , +and is maintained by the KeePassXC Team . diff --git a/docs/man/keepassxc.1.adoc b/docs/man/keepassxc.1.adoc new file mode 100644 index 000000000..965f7ac46 --- /dev/null +++ b/docs/man/keepassxc.1.adoc @@ -0,0 +1,41 @@ += keepassxc(1) +:docdate: 2020-07-05 +:doctype: manpage +:manmanual: General Commands Manual + +== NAME +keepassxc - password manager + +== SYNOPSIS +*keepassxc* [_options_] [_filename(s)_] + +== DESCRIPTION +*KeePassXC* 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. + +== OPTIONS +*-h*, *--help*:: + Displays this help. + +*-v*, *--version*:: + Displays version information. + +*--config* <__config__>:: + Path to a custom config file + +*--keyfile* <__keyfile__>:: + Key file of the database + +*--pw-stdin*:: + Read password of the database from stdin + +*--pw*, *--parent-window* <__handle__>:: + Parent window handle + +*--debug-info*:: + Displays debugging information. + +== AUTHOR +This manual page is maintained by the KeePassXC Team . diff --git a/docs/styles/dark.css b/docs/styles/dark.css new file mode 100644 index 000000000..90e632b3a --- /dev/null +++ b/docs/styles/dark.css @@ -0,0 +1,541 @@ +@import url(https://fonts.googleapis.com/css?family=Noto+Sans); + +/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */ +/* Uncomment @import statement below to use as custom stylesheet */ +/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/ +article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} +audio,canvas,video{display:inline-block} +audio:not([controls]){display:none;height:0} +script{display:none!important} +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} +a{background:transparent} +a:focus{outline:thin dotted} +a:active,a:hover{outline:0} +h1{font-size:2em;margin:.67em 0} +abbr[title]{border-bottom:1px dotted} +b,strong{font-weight:bold} +dfn{font-style:italic} +hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} +mark{background:#ff0;color:#000} +code,kbd,pre,samp{font-family:monospace;font-size:1em} +pre{white-space:pre-wrap} +q{quotes:"\201C" "\201D" "\2018" "\2019"} +small{font-size:80%} +sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} +sup{top:-.5em} +sub{bottom:-.25em} +img{border:0} +svg:not(:root){overflow:hidden} +figure{margin:0} +fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em} +legend{border:0;padding:0} +button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} +button,input{line-height:normal} +button,select{text-transform:none} +button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} +button[disabled],html input[disabled]{cursor:default} +input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} +button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} +textarea{overflow:auto;vertical-align:top} +table{border-collapse:collapse;border-spacing:0} +*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} +html,body{font-size:100%} +body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} +a:hover{cursor:pointer} +img,object,embed{max-width:100%;height:auto} +object,embed{height:100%} +img{-ms-interpolation-mode:bicubic} +.left{float:left!important} +.right{float:right!important} +.text-left{text-align:left!important} +.text-right{text-align:right!important} +.text-center{text-align:center!important} +.text-justify{text-align:justify!important} +.hide{display:none} +img,object,svg{display:inline-block;vertical-align:middle} +textarea{height:auto;min-height:50px} +select{width:100%} +.center{margin-left:auto;margin-right:auto} +.stretch{width:100%} +.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} +div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} +a{color:#2156a5;text-decoration:underline;line-height:inherit} +a:hover,a:focus{color:#1d4b8f} +a img{border:none} +p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} +p aside{font-size:.875em;line-height:1.35;font-style:italic} +h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} +h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} +h1{font-size:2.125em} +h2{font-size:1.6875em} +h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} +h4,h5{font-size:1.125em} +h6{font-size:1em} +hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} +em,i{font-style:italic;line-height:inherit} +strong,b{font-weight:bold;line-height:inherit} +small{font-size:60%;line-height:inherit} +code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} +ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} +ul,ol{margin-left:1.5em} +ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} +ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} +ul.square{list-style-type:square} +ul.circle{list-style-type:circle} +ul.disc{list-style-type:disc} +ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} +dl dt{margin-bottom:.3125em;font-weight:bold} +dl dd{margin-bottom:1.25em} +abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} +abbr{text-transform:none} +blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} +blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} +blockquote cite::before{content:"\2014 \0020"} +blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} +blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} +@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} +h1{font-size:2.75em} +h2{font-size:2.3125em} +h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} +h4{font-size:1.4375em}} +table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} +table thead,table tfoot{background:#f7f8f7} +table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} +table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} +table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} +table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} +h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} +h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} +.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table} +.clearfix::after,.float-group::after{clear:both} +*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word} +*:not(pre)>code.nobreak{word-wrap:normal} +*:not(pre)>code.nowrap{white-space:nowrap} +pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} +em em{font-style:normal} +strong strong{font-weight:400} +.keyseq{color:rgba(51,51,51,.8)} +kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} +.keyseq kbd:first-child{margin-left:0} +.keyseq kbd:last-child{margin-right:0} +.menuseq,.menuref{color:#000} +.menuseq b:not(.caret),.menuref{font-weight:inherit} +.menuseq{word-spacing:-.02em} +.menuseq b.caret{font-size:1.25em;line-height:.8} +.menuseq i.caret{font-weight:bold;text-align:center;width:.45em} +b.button::before,b.button::after{position:relative;top:-1px;font-weight:400} +b.button::before{content:"[";padding:0 3px 0 2px} +b.button::after{content:"]";padding:0 2px 0 3px} +p a>code:hover{color:rgba(0,0,0,.9)} +#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} +#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table} +#header::after,#content::after,#footnotes::after,#footer::after{clear:both} +#content{margin-top:1.25em} +#content::before{content:none} +#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} +#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8} +#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px} +#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} +#header .details span:first-child{margin-left:-.125em} +#header .details span.email a{color:rgba(0,0,0,.85)} +#header .details br{display:none} +#header .details br+span::before{content:"\00a0\2013\00a0"} +#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} +#header .details br+span#revremark::before{content:"\00a0|\00a0"} +#header #revnumber{text-transform:capitalize} +#header #revnumber::after{content:"\00a0"} +#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} +#toc{border-bottom:1px solid #efefed;padding-bottom:.5em} +#toc>ul{margin-left:.125em} +#toc ul.sectlevel0>li>a{font-style:italic} +#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} +#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} +#toc li{line-height:1.3334;margin-top:.3334em} +#toc a{text-decoration:none} +#toc a:active{text-decoration:underline} +#toctitle{color:#7a2518;font-size:1.2em} +@media screen and (min-width:768px){#toctitle{font-size:1.375em} +body.toc2{padding-left:15em;padding-right:0} +#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} +#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} +#toc.toc2>ul{font-size:.9em;margin-bottom:0} +#toc.toc2 ul ul{margin-left:0;padding-left:1em} +#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} +body.toc2.toc-right{padding-left:0;padding-right:15em} +body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}} +@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0} +#toc.toc2{width:20em} +#toc.toc2 #toctitle{font-size:1.375em} +#toc.toc2>ul{font-size:.95em} +#toc.toc2 ul ul{padding-left:1.25em} +body.toc2.toc-right{padding-left:0;padding-right:20em}} +#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} +#content #toc>:first-child{margin-top:0} +#content #toc>:last-child{margin-bottom:0} +#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} +#footer-text{color:rgba(255,255,255,.8);line-height:1.44} +#content{margin-bottom:.625em} +.sect1{padding-bottom:.625em} +@media screen and (min-width:768px){#content{margin-bottom:1.25em} +.sect1{padding-bottom:1.25em}} +.sect1:last-child{padding-bottom:0} +.sect1+.sect1{border-top:1px solid #efefed} +#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} +#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} +#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} +#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} +#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} +.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} +.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic} +table.tableblock.fit-content>caption.title{white-space:nowrap;width:0} +.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)} +table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit} +.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} +.admonitionblock>table td.icon{text-align:center;width:80px} +.admonitionblock>table td.icon img{max-width:none} +.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} +.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)} +.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} +.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} +.exampleblock>.content>:first-child{margin-top:0} +.exampleblock>.content>:last-child{margin-bottom:0} +.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} +.sidebarblock>:first-child{margin-top:0} +.sidebarblock>:last-child{margin-bottom:0} +.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} +.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} +.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} +.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} +.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em} +.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal} +@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}} +@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}} +.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} +.listingblock pre.highlightjs{padding:0} +.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} +.listingblock pre.prettyprint{border-width:0} +.listingblock>.content{position:relative} +.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} +.listingblock:hover code[data-lang]::before{display:block} +.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999} +.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"} +table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} +table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45} +table.pyhltable td.code{padding-left:.75em;padding-right:0} +pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8} +pre.pygments .lineno{display:inline-block;margin-right:.25em} +table.pyhltable .linenodiv{background:none!important;padding-right:0!important} +.quoteblock{margin:0 1em 1.25em 1.5em;display:table} +.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} +.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} +.quoteblock blockquote{margin:0;padding:0;border:0} +.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} +.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} +.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right} +.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)} +.quoteblock .quoteblock blockquote{padding:0 0 0 .75em} +.quoteblock .quoteblock blockquote::before{display:none} +.verseblock{margin:0 1em 1.25em} +.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} +.verseblock pre strong{font-weight:400} +.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} +.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} +.quoteblock .attribution br,.verseblock .attribution br{display:none} +.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} +.quoteblock.abstract{margin:0 1em 1.25em;display:block} +.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center} +.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{word-spacing:0;line-height:1.6} +.quoteblock.abstract blockquote::before,.quoteblock.abstract p::before{display:none} +table.tableblock{max-width:100%;border-collapse:separate} +p.tableblock:last-child{margin-bottom:0} +td.tableblock>.content{margin-bottom:-1.25em} +table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} +table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0} +table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0} +table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0} +table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px} +table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0} +table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0} +table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0} +table.frame-all{border-width:1px} +table.frame-sides{border-width:0 1px} +table.frame-topbot,table.frame-ends{border-width:1px 0} +table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7} +table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none} +th.halign-left,td.halign-left{text-align:left} +th.halign-right,td.halign-right{text-align:right} +th.halign-center,td.halign-center{text-align:center} +th.valign-top,td.valign-top{vertical-align:top} +th.valign-bottom,td.valign-bottom{vertical-align:bottom} +th.valign-middle,td.valign-middle{vertical-align:middle} +table thead th,table tfoot th{font-weight:bold} +tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} +tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} +p.tableblock>code:only-child{background:none;padding:0} +p.tableblock{font-size:1em} +td>div.verse{white-space:pre} +ol{margin-left:1.75em} +ul li ol{margin-left:1.5em} +dl dd{margin-left:1.125em} +dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} +ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} +ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none} +ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em} +ul.unstyled,ol.unstyled{margin-left:0} +ul.checklist{margin-left:.625em} +ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em} +ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em} +ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em} +ul.inline>li{margin-left:1.25em} +.unstyled dl dt{font-weight:400;font-style:normal} +ol.arabic{list-style-type:decimal} +ol.decimal{list-style-type:decimal-leading-zero} +ol.loweralpha{list-style-type:lower-alpha} +ol.upperalpha{list-style-type:upper-alpha} +ol.lowerroman{list-style-type:lower-roman} +ol.upperroman{list-style-type:upper-roman} +ol.lowergreek{list-style-type:lower-greek} +.hdlist>table,.colist>table{border:0;background:none} +.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} +td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} +td.hdlist1{font-weight:bold;padding-bottom:1.25em} +.literalblock+.colist,.listingblock+.colist{margin-top:-.5em} +.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top} +.colist td:not([class]):first-child img{max-width:none} +.colist td:not([class]):last-child{padding:.25em 0} +.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} +.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0} +.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em} +.imageblock>.title{margin-bottom:0} +.imageblock.thumb,.imageblock.th{border-width:6px} +.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} +.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} +.image.left{margin-right:.625em} +.image.right{margin-left:.625em} +a.image{text-decoration:none;display:inline-block} +a.image object{pointer-events:none} +sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} +sup.footnote a,sup.footnoteref a{text-decoration:none} +sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} +#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} +#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0} +#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em} +#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em} +#footnotes .footnote:last-of-type{margin-bottom:0} +#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} +.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} +.gist .file-data>table td.line-data{width:99%} +div.unbreakable{page-break-inside:avoid} +.big{font-size:larger} +.small{font-size:smaller} +.underline{text-decoration:underline} +.overline{text-decoration:overline} +.line-through{text-decoration:line-through} +.aqua{color:#00bfbf} +.aqua-background{background-color:#00fafa} +.black{color:#000} +.black-background{background-color:#000} +.blue{color:#0000bf} +.blue-background{background-color:#0000fa} +.fuchsia{color:#bf00bf} +.fuchsia-background{background-color:#fa00fa} +.gray{color:#606060} +.gray-background{background-color:#7d7d7d} +.green{color:#006000} +.green-background{background-color:#007d00} +.lime{color:#00bf00} +.lime-background{background-color:#00fa00} +.maroon{color:#600000} +.maroon-background{background-color:#7d0000} +.navy{color:#000060} +.navy-background{background-color:#00007d} +.olive{color:#606000} +.olive-background{background-color:#7d7d00} +.purple{color:#600060} +.purple-background{background-color:#7d007d} +.red{color:#bf0000} +.red-background{background-color:#fa0000} +.silver{color:#909090} +.silver-background{background-color:#bcbcbc} +.teal{color:#006060} +.teal-background{background-color:#007d7d} +.white{color:#bfbfbf} +.white-background{background-color:#fafafa} +.yellow{color:#bfbf00} +.yellow-background{background-color:#fafa00} +span.icon>.fa{cursor:default} +a span.icon>.fa{cursor:inherit} +.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} +.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c} +.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} +.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900} +.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400} +.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000} +.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} +.conum[data-value] *{color:#fff!important} +.conum[data-value]+b{display:none} +.conum[data-value]::after{content:attr(data-value)} +pre .conum[data-value]{position:relative;top:-.125em} +b.conum *{color:inherit!important} +.conum:not([data-value]):empty{display:none} +dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} +h1,h2,p,td.content,span.alt{letter-spacing:-.01em} +p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} +p,blockquote,dt,td.content,span.alt{font-size:1.0625rem} +p{margin-bottom:1.25rem} +.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} +.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} +.print-only{display:none!important} +@page{margin:1.25cm .75cm} +@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important} +html{font-size:80%} +a{color:inherit!important;text-decoration:underline!important} +a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important} +a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em} +abbr[title]::after{content:" (" attr(title) ")"} +pre,blockquote,tr,img,object,svg{page-break-inside:avoid} +thead{display:table-header-group} +svg{max-width:100%} +p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3} +h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid} +#toc,.sidebarblock,.exampleblock>.content{background:none!important} +#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important} +body.book #header{text-align:center} +body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em} +body.book #header .details{border:0!important;display:block;padding:0!important} +body.book #header .details span:first-child{margin-left:0!important} +body.book #header .details br{display:block} +body.book #header .details br+span::before{content:none!important} +body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important} +body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always} +.listingblock code[data-lang]::before{display:block} +#footer{padding:0 .9375em} +.hide-on-print{display:none!important} +.print-only{display:block!important} +.hide-for-print{display:none!important} +.show-for-print{display:inherit!important}} +@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem} +.sect1{padding:0!important} +.sect1+.sect1{border:0} +#footer{background:none} +#footer-text{color:rgba(0,0,0,.6);font-size:.9em}} +@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}} + + + +/* CUSTOMISATIONS */ +/* Change the values in root for quick customisation. If you want even more fine grain... venture further. */ +:root { +--textcolor: #CACBCE; +--textcoloralt: #e7b649; +--background: #3B3B3D; +--sidebarbackground: #2C2C30; +--header1color: #4adb22; +--header2color: #6de597; +--quotecolor: #20b82b; +--toccolor: #f3bf4a; +--toccolorhover: #eece83; +--linkcolor: #6de597; +--linkhovercolor: #8fdaa9; +--tipcolor: #f0f0f0; +--notecolor: #f3bf4a; +--warningcolor: #FF7D7D; +} + +/* Text styles */ + +body{font-family: "Noto Sans",sans-serif;background-color: var(--background);color:var(--textcolor);} + +h1{color:var(--header1color) !important;font-family:"Noto Sans",sans-serif;} +h2,h3,h4,h5,h6{color:var(--header2color) !important;font-family:"Noto Sans",sans-serif;} +.title{color:var(--textcolor) !important;font-family:"Noto Sans",sans-serif;font-style: normal; font-weight: normal;} +p{font-family: "Noto Sans",sans-serif !important} +#toc.toc2 a:link{color:var(--toccolor)} +#toc.toc2 a:hover{color:var(--toccolorhover)} +blockquote{color:var(--quotecolor) !important} +.quoteblock{color:var(--textcolor)} +code{color:var(--textcoloralt);background-color: var(--sidebarbackground) !important} + + +/* Table styles */ +th{background-color: var(--background);color: var(--textcolor) !important;} +td{background-color: var(--background);color: var(--textcoloralt) !important;} + + +#toc.toc2{background-color:var(--sidebarbackground);} +#toctitle{color:var(--textcolor);} + +/* Responsiveness fixes */ +video { + max-width: 100%; +} + +@media all and (max-width: 600px) { + table { + width: 55vw!important; + font-size: 3vw; + } +} + +.exampleblock > .content { + background-color: var(--background); +} + +a {color: var(--linkcolor);} +a:hover {color: var(--linkhovercolor);} + +.admonitionblock.tip td.content, .admonitionblock td.icon .icon-tip::before { + text-shadow: none; + color: var(--tipcolor) !important; +} + +.admonitionblock.note td.content, .admonitionblock td.icon .icon-note::before { + color: var(--notecolor) !important; +} + +.admonitionblock.important td.content, .admonitionblock td.icon .icon-important::before { + color: var(--warningcolor) !important; +} + +.admonitionblock.warning td.content, .admonitionblock td.icon .icon-warning::before { + color: var(--warningcolor) !important; +} + +#preamble > .sectionbody > .paragraph:first-of-type p { + color: var(--textcolor); +} + +.quoteblock blockquote::before { + color: var(--header1color); +} +.quoteblock .attribution cite, .verseblock .attribution cite { + color: var(--textcolor); +} +.verseblock pre { + color: var(--textcolor); +} +.quoteblock blockquote, .quoteblock blockquote p { + color: var(--textcolor); +} + +.sidebarblock { + background: var(--sidebarbackground); +} +.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { + background: var(--sidebarbackground); + color: var(--textcolor); +} + +#header .details { + color: var(--textcolor); +} +#header .details span.email a { + color: var(--toccolor); +} + +.title { + font-size: 3em; +} +.subtitle { + font-size: 1.5em; +} \ No newline at end of file diff --git a/docs/styles/pdf_theme.yml b/docs/styles/pdf_theme.yml new file mode 100644 index 000000000..2313279da --- /dev/null +++ b/docs/styles/pdf_theme.yml @@ -0,0 +1,30 @@ +page: + layout: portrait + margin: [0.75in, 1in, 0.75in, 1in] + size: Letter +base: + font-color: #333333 + font-family: Times-Roman + font-size: 12 + line-height-length: 17 + line-height: $base-line-height-length / $base-font-size +vertical-spacing: $base-line-height-length +heading: + font-color: #262626 + font-size: 17 + font-style: bold + line-height: 1.2 + margin-bottom: $vertical-spacing +link: + font-color: #002FA7 +outline-list: + indent: $base-font-size * 1.5 +footer: + height: $base-line-height-length * 2.5 + line-height: 1 + recto: + right: + content: '{page-number}' + verso: + left: + content: $footer-recto-right-content \ No newline at end of file diff --git a/docs/topics/.sharedheader b/docs/topics/.sharedheader new file mode 100644 index 000000000..715ec3c0f --- /dev/null +++ b/docs/topics/.sharedheader @@ -0,0 +1,7 @@ +KeePassXC Team +v2.6.0 +:data-uri: +:homepage: https://keepassxc.org +:stylesheet: ../styles/dark.css +:icons: font +:toc: left diff --git a/docs/topics/AutoType.adoc b/docs/topics/AutoType.adoc new file mode 100644 index 000000000..abe1afeef --- /dev/null +++ b/docs/topics/AutoType.adoc @@ -0,0 +1,84 @@ += KeePassXC - Auto-Type +:imagesdir: ../images + +// tag::content[] +== Auto-Type +The Auto-Type feature acts like a virtual keyboard to populate data from your entries directly into the corresponding websites or applications that you use. You can use the Auto-Type feature on a global level or entry level. Each entry can be configured to be associated with a particular window title and multiple Auto-Type sequences can be pre-defined and selected upon use. + +NOTE: Auto-Type is a completely separate feature from Browser Integration. You do not need to have the KeePassXC browser extension installed in your browser to use Auto-Type. + +=== Configure Global Auto-Type +You can define a global Auto-Type hotkey that starts the Auto-Type process. To configure the hotkey, perform the following steps: + +1. Navigate to _Tools_ -> _Settings_ -> Auto-Type tab *(1)*. Click into the _Global Auto-Type shortcut_ box and press the desired key combination that will trigger the Auto-Type process *(2)*. ++ +.Auto-Type settings +image::autotype_settings.png[] ++ +You can configure additional Auto-Type settings in this window such as start delay, inter-key typing delay, and matching options. If Auto-Type is not working well for you, try adjusting the default delays. + +=== Configure Auto-Type Sequences +Each entry in your database can have multiple Auto-Type sequences associated with various window titles. Simulated key presses can be sent to any other currently open window of your choice (web browser windows, login dialogs boxes, and so on). When the Global Auto-Type hotkey is pressed, KeePassXC will search your database for entries matching the current selected window title. + +NOTE: The default Auto-Type sequence is `{USERNAME}{TAB}{PASSWORD}{ENTER}`. This means that it first types the username of the selected entry, then presses the `Tab` key, then types the password of the entry and finally presses the `Enter` key. + +To configure Auto-Type sequences for your entries, perform the following steps: + +1. Navigate to the entries list and open the desired entry for editing. Click the _Auto-Type_ item from the left-hand menu bar *(1)*. Press the `+` button *(2)* to add a new sequence entry. Select the desired window using the drop-down menu, or simply type a window title in the box *(3)*. You can use wildcard `*` to match any value (e.g., when a window title contains a filename or website name). ++ +.Auto-Type entry sequences +image::autotype_entry_sequences.png[] + +2. _(Optional)_ Define a custom auto-type sequence for each window title match by selecting the _Use specific sequence for this association_ checkbox. Sequence action codes and field placeholders are detailed in the following table. A complete list of supported actions and placeholders can be found at https://keepass.info/help/base/autotype.html#autoseq[KeePass Auto-Type Action Codes] and https://keepass.info/help/base/placeholders.html[KeePass Placeholders]. Action codes and placeholders are not case sensitive. ++ +[grid=rows, frame=none, width=70%] +|=== +|Action Code |Description + +|{TAB}, {ENTER}, {SPACE}, {INSERT}, {DELETE}, {HOME}, {END}, {PGUP}, {PGDN}, {BACKSPACE}, {CAPSLOCK}, {ESC} +|Press the corresponding keyboard key + +|{UP}, {DOWN}, {LEFT}, {RIGHT} |Press the corresponding arrow key +|{F1}, {F2}, ..., {F16} |Press F1, F2, etc. +|{LEFTBRACE}, {RIGHTBRACE} |Press `{` or `}`, respectively +|{DELAY=X} |Set key press delay to X milliseconds +|{DELAY X} |Delay typing start by X milliseconds +|{CLEARFIELD} |Clear the input field before typing +|{TOTP} |Insert calculated TOTP value (if configured) +|{ X} |Repeat X times (e.g., {SPACE 5} inserts five spaces) +|=== ++ +[grid=rows, frame=none, width=70%] +|=== +|Placeholder |Description + +|{TITLE} |Entry Title +|{USERNAME} |Username +|{PASSWORD} |Password +|{URL} |URL +|{NOTES} |Notes +|{TOTP} |Current TOTP value (if configured) +|{DT_SIMPLE} |Current date-time +|{DB_DIR} |Absolute directory path for database file +|{S:} |Value for the given attribute name +|{REF:@:} |Search for a field in another entry using the reference syntax. +|=== + +=== Performing Global Auto-Type +The global Auto-Type keyboard shortcut is used when you have focus on the window you want to type into. To make use of this feature, you must have previously configured an Auto-Type hotkey. + +Pressing the global Auto-Type hotkey cause KeePassXC to search the database for entries that match the window title. Multiple matches may be returned and will cause the sequence selection dialog to appear. Click on a sequence line will immediately execute the Auto-Type action. A search box is also available in case numerous matches are returned. + +.Auto-Type sequence selection +image::autotype_selection_dialog.png[,70%] + +TIP: The _Sequence_ column will only appear when there are different sequences defined by one or more entries displayed in the selection dialog. + +=== Performing Entry-Level Auto-Type +You can quickly activate the default Auto-Type sequence for a particular entry using Entry-Level Auto-Type. For this operation, the KeePassXC window will be minimized and the Auto-Type sequence occurs in the previously selected window. You can perform Entry-Level Auto-Type from the toolbar icon *(A)*, entry context menu *(B)*, or by pressing `Ctrl+Shift+V`. + +WARNING: Be careful when using Entry-Level Auto-Type as you can inadvertently type into the wrong window. For example, a chat window or email. + +.Entry-Level Auto-Type +image::autotype_entrylevel.png[] +// end::content[] \ No newline at end of file diff --git a/docs/topics/BrowserPlugin.adoc b/docs/topics/BrowserPlugin.adoc new file mode 100644 index 000000000..0331eda7f --- /dev/null +++ b/docs/topics/BrowserPlugin.adoc @@ -0,0 +1,108 @@ += KeePassXC - Browser Plugin +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +== Setup Browser Integration +The KeePassXC-Browser extension is installed within your web browser so that you can automatically pull usernames and passwords from KeePassXC and populate them directly into website fields. It is a very useful and secure extension that enhances your productivity while using KeePassXC. With this extension, you do not need to manually copy the data from your KeePassXC database and paste it into the website fields. + +The KeePassXC-Browser extension is available on the following web browsers: + +* Google Chrome, Vivaldi, and Brave +* Mozilla Firefox and Tor-Browser +* Microsoft Edge +* Chromium + +=== Install the Browser Extension +You can download the KeePassXC-Browser extension from your web browser. To download the KeePassXC-Browser extension, perform the following steps: + +1. Click the link corresponding to your browser: + * https://chrome.google.com/webstore/detail/keepassxc-browser/oboonakemofpalcgghocfoadofidjkkk[Chrome, Chromium, Vivaldi, and Brave] + * https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser[Mozilla Firefox and Tor-Browser] + * https://microsoftedge.microsoft.com/addons/detail/keepassxcbrowser/pdffhmdngciaglkoonimfcmckehcpafo[Microsoft Edge] + +2. Click the button to install/add the extension to the browser. Accept any confirmation dialogs. + +=== Configure KeePassXC-Browser +To start using KeePassXC-Browser, you must configure it so that it can communicate with the KeePassXC application on your desktop. + +To configure KeePassXC-Browser, perform the following steps: + +1. Open the KeePassXC application on your desktop and navigate to Tools > Settings. + +2. Click the Browser Integration option on the left-hand side *(1)*. The following screen appears: ++ +.Browser Settings +image::browser_settings.png[] + +3. Click the _Enable browser integration_ checkbox *(2)*. Then select the browsers for which you have downloaded the KeePassXC-Browser extension *(3)* and click *OK*. + +4. Ensure your database is unlocked, then open (or restart) your browser. + +5. Click the KeePassXC-Browser extension icon *(A)* in your browser (see figure below). A pop-up window appears. ++ +.Connect Extension to KeePassXC +image::browser_extension_connect.png[,80%] + +6. Click the _Connect_ button *(B)* in the pop-up window to complete integrating the KeePassXC-Browser extension with your KeePassXC desktop application. + +7. You are now prompted to enter a unique name to identify the connection between this browser and your database. Enter a unique name in the field (e.g., firefox-laptop) and click the _Save and allow access_ button. ++ +.Extension Association Dialog +image::browser_extension_association.png[,80%] + +WARNING: If you reuse a connection name in a database, the previous browser connection will be overwritten and prevent access. + +=== Using the Browser Extension +The KeePassXC-Browser extension lets you automatically populate the entries from your KeePassXC database into the fields on websites you visit. To do so, perform the following steps: + +1. Open your KeePassXC desktop application and unlock your database. + +2. Open your web browser. The KeePassXC-Browser extension icon in your browser window will change based on its connection state. The figure below shows the different states. ++ +*(A)* KeePassXC is not running or is disconnected + +*(B)* Connected to KeePassXC, but database is locked + +*\(C)* Connected to KeePassXC and ready to use ++ +.Extension Icon States +image::browser_extension_icons.png[,70%] + +3. If the KeePassXC desktop application is not connected with the KeePassXC-Browser extension, click the extension icon in your web browser and click _Reload_ from the pop-up window as shown in the following screen. ++ +.Reload Extension Connection +image::browser_extension_reload.png[,80%] + +4. Open the URL for which you want to use with your database. If you have previously created an entry in your database then the KeePassXC-Browser Confirm Access dialog may appear: ++ +.Confirm Access Dialog +image::browser_confirm_access_dialog.png[,80%] + +5. Ensure the credentials you want use are checked, then click *(A)* Remember _(optional)_, then click _Allow Selected_ *(B)*. + +6. In your website, the KeePassXC icon will appear in the username field of the login form *(A)*. Click the icon to populate the field with your stored credentials. If you have more than one credential for this website, a dropdown will appear to choose the one to use. ++ +.Fill Credentials +image::browser_fill_credentials.png[,80%] + +// tag::advanced[] +=== Advanced Usage +You can configure unique browser integration behavior for each entry. This allows you to add multiple URLs to an entry, hide an entry from the browser integration, and more. To access these settings, open an entry for editing then click on _Browser Integration_ option in the left-hand menu *(1)*. + +After opening the settings you can add any number of additional URLs by clicking the _Add_ button *(2)* and typing the URL in the list to the left *(3)*. + +.Entry browser settings +image::browser_entry_settings.png[] + +Database-wide operations are available in the database settings. To access these use the _Database_ -> _Database settings..._ menu option. Click on _Browser Integration_ on the left-hand menu. From here you can disconnect all browsers, convert legacy KeePass-HTTP settings, reset all entry-level settings, and refresh the database root group ID (useful when making copies of your database file). + +.Database browser settings +image::browser_database_settings.png[] + +Finally, advanced application-wide settings are available in the Browser Integration tab of the application settings. + +WARNING: We do not recommend changing any of these settings as they may break the browser integration plugin. + +.Advanced browser settings +image::browser_advanced_settings.png[] +// end::advanced[] +// end::content[] diff --git a/docs/topics/DatabaseOperations.adoc b/docs/topics/DatabaseOperations.adoc new file mode 100644 index 000000000..eafe861b6 --- /dev/null +++ b/docs/topics/DatabaseOperations.adoc @@ -0,0 +1,296 @@ += KeePassXC - Database Operations +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +== Database Operations +=== Creating Your First Database +To start using KeePassXC, you need to first create a database that will store the password and other details. + +To create a database, perform the following steps: + +1. Open your KeePassXC application. Click the create new database button *(A)*: ++ +.Create database - Welcome screen +image::welcome_screen.png[] + +2. The database creation wizard appears. Enter the desired database name and a short description (optional): ++ +.Create database - General information +image::new_db_wizard_1.png[,80%] + +3. Click Continue. The Encryption Settings screen appears, we don't recommend making any changes besides increasing or decreasing the decryption time using the slider. Setting the Decryption Time slider at a higher values means that the database will have higher level of protection but the time taken by the database to open will increase. ++ +.Create database - Encryption settings +image::new_db_wizard_2.png[,80%] + +4. Click the Continue button. The Database Credentials screen appears, enter your desired database password. We recommend using a long, randomized password. ++ +.Create database - Database credentials +image::new_db_wizard_3.png[,80%] ++ +*(A)* Open the password generator + +*(B)* Toggle password visibility ++ +NOTE: Keep this password for your database safe. Either memorize it or note it down somewhere. Losing the database password might result in permanent locking of your database and you will not be able to retrieve information stored in the database. + +5. Click Done. You will be prompted to select a location to save your database file. The database file is saved on to your computer with the default `.kdbx` extension. You can store your database wherever you wish, it is fully encrypted at all times preventing unauthorized access. + +=== Opening an Existing Database +To open an existing database, perform the following steps: + +1. Open your KeePassXC application. Click the Open existing database button *(A)* or select a recent database from the Recent Databases list *(B)*. ++ +.Open an existing database +image::open_database.png[] + +2. Navigate to the location of the your database on your computer and open the database file. The database unlock screen will appear: ++ +.Database unlock screen +image::unlock_database.png[] + +3. Enter the password for your database. + +4. _(Optional)_ Browse for the Key File if you have chosen it as an additional authentication factor while creating the database. Refer to the KeePassXC User Guide for more information on setting a Key File as an additional authentication factor. + +5. Click *OK*. The database opens and the following screen is displayed: ++ +.Unlocked database +image::database_view.png[] + +=== Adding an Entry +All the details such as usernames, passwords, URLs, attachments, notes, and so on are stored in database entries. You can create as many entries as you want in the database. + +To add an entry, perform the following step: + +1. Navigate to Entries > New Entry (Or, press Ctrl+N). The following screen appears: ++ +.Adding a new entry +image::edit_entry.png[] + +2. Enter a desired title for the entry, username, password, URL, and notes on this screen. + +3. _(Optional)_ Select the Expires check-box to set the expiry date for the password. You can manually enter the date and time or click the Presets button to select a expiry date and time for your password. + +4. Click *OK* to add the entry to your database. + +=== Editing an Entry +To edit the details in an entry, perform the following steps: + +1. Select the entry you want to edit. + +2. Press `Enter`, click the edit toolbar icon, or right-click and select Edit Entry from the menu. + +3. Make the desired changes. + +4. Click *OK*. + +=== Deleting an Entry +To delete an entry, perform the following steps: + +1. Select the entry you want to delete and press the `Delete` button on your keyboard. + +2. You will be prompted to move the entry to the Recycle Bin (if enabled). ++ +NOTE: You can disable the recycle bin within the Database Settings. If the recycle bin is disabled then deleted entries will be permanently removed from the database. + +3. To permanently delete the entry, navigate to the Recycle Bin, select the entry you want to delete and press the `Delete` button on your keyboard. + +// tag::advanced[] +=== Clone an Entry +Creating a clone of an entry provides you a ready-to-use template for creating new entries with similar details of a master entry. + +To create a clone of an existing entry, perform the following steps: + +1. Right-click on the entry for which you want to create a clone and select _Clone Entry_. Alternatively, select the desired entry and press `Ctrl+K`. ++ +.Clone entry from context menu +image::clone_entry.png[] + +2. The clone dialog will appear. ++ +.Clone entry dialog +image::clone_entry_dialog.png[,70%] + * Select the Append ‘ - Clone’ to title check-box to create a new entry with the word Clone as the suffix to the name of the new entry. + * Select the Replace username and password with references check-box to create the new entry where the username and the password fields contain the references to the username and password to the master entry. + * Select the Copy history checkbox to copy the history of the master entry to the clone. + +3. If you chose to replace username and password entries with references, then the new entry will point these fields to the original entry's values. Changing the original entry will automatically change the resolved value of the cloned entry. This is useful if you have multiple accounts for the same service that use a similar username or password combination. ++ +.References in a cloned entry +image::clone_entry_references.png[] + +4. You can create your own references using the following syntax: ++ +`{REF:@I:}` ++ +Where `` is the Unique Identifier of the entry to pull data from and `` is from the following: ++ + * T - Title + * U - Username + * P - Password + * A - URL + * N - Notes + * I - UUID + +== Searching the Database +KeePassXC provides an enhanced and granular search features the enables you to search for specific entries in the databases using the different modifiers, wild card characters, and logical operators. + +=== Modifiers and Fields +[grid=rows, frame=none, width=70%] +|=== +|Modifier |Description + +|- |Exclude this term from results +|+ |Match this term exactly +|* |Term is handled as a regular expression +|=== + +The following fields can be searched along with their abbreviated name in parenthesis: + +* Title (t) +* Username (u) +* Password (p, pw) +* URL +* Notes (n) +* Attribute (attr) +* Attachment (attach) +* Group (g) + +=== Wild Card Characters and Logical Operators +[grid=rows, frame=none, width=70%] +|=== +|Wild Card Character |Description + +|* |Match anything +|? |Match one character +|\| |Logical OR +|=== + +=== Sample Search Queries +The following tables lists a few samples search queries for your reference: + +|=== +|Query |Description + +|`user:johnsmith url:www.google.com` +|Searches the Username field for johnsmith and the URL field for www.google.com. + +|`user:john\|smith` +|Searches the Username field for john OR smith. + +|`+user:johnsmith -url:www.google.com *notes:"secret note \d"` +|Search the username field for exactly johnsmith, the URL must not contain www.google.com, and notes contains secret note [digit]. +|=== + +== Advanced Entry Options +=== Additional Attributes +A lot of applications and web sites now require to provide additional information when you create accounts. The additional information is used to block hackers if any suspicious activity is detected. In addition, the additional information you provide can be used to reset passwords if you forget them. You can also store arbitrary information here that can be copied to the clipboard or Auto-Typed using the `{S: _Database settings_. The following screen appears: ++ +.Database settings +image::database_settings.png[] + +2. Click the General button in the left-hand menu bar to access the following settings: + * *Database name:* This is the default identifier for your database and is shown in the tab bar and title bar (when active). You can change this name as desired. + * *Database description:* Provide some meaningful description for your database. + * *Default username:* Provide a default username for all new entries that you create in this database. + * *Max history items:* This is the maximum number of history items that are stored for each entry. When you set this to 0, no history will be saved. Set this value to a low value to prevent the database from getting too large (we recommend no more than 10). + * *Max. history size:* When the history of an entry gets above this size, it is truncated. For example, this happens when entries have large attachments. Set this value small to prevent the database from getting too large (we recommend 6 MiB). + * *Use recycle bin:* Select this check-box if you want deleted entries to move to the recycle bin instead of being permanently removed. The recycle bin will be created if it does not already exist after your first deletion. To delete entries permanently, you must empty the recycle bin manually. + * *Enable compression:* KeePassXC databases can be compressed before being encrypted. Compression reduces the size of the database and does not have any appreciable affect on speed. It is recommended to always save databases with compression. + +3. Click the Security button in the left-hand menu bar to change your database credentials and change encryption settings. ++ +.Database security +image::database_security.png[] + +4. Here you can change your database password or add/remove additional credentials to protect your database. KeePassXC supports adding a randomly generated, static key file and hardware keys such as YubiKey and OnlyKey. To add a key file, click _Add Key File_ and either browse for an existing file or generate a new one *(A)*. To add a hardware key, click _Add YubiKey Challenge-Response_, plug in your hardware key, then click refresh *(B)*. ++ +.Database credentials +image::database_security_credentials.png[] + +5. Encryption settings allows you to change the average time it takes to encrypt and decrypt the database. The longer time that is chosen, the harder it will be to brute force attack your database. *We recommend a setting of one second.* ++ +.Database encryption +image::database_security_encryption.png[] ++ +WARNING: Encryption time is dependent on your computer's hardware. If sharing a database with a mobile device, be mindful that it will likely take two to four times longer to access and save your database than on your home computer. + +6. Advanced encryption settings can be accessed by clicking the _Advanced Settings_ checkbox in the lower left-hand corner. These settings are only meant for people who know what they mean. *We do not recommend touching these settings.* ++ +.Database encryption advanced settings +image::database_security_encryption_advanced.png[] ++ +The following key derivation functions are supported: + + * AES-KDF (KDBX 4 and KDBX 3.1): This key derivation function is based on iterating AES. Users can change the number of iterations. The more iterations, the harder are dictionary and guessing attacks, but also database loading/saving takes more time (linearly). KDBX 3.1 only supports AES-KDF; any other key derivation function, like for instance Argon2, requires KDBX 4. + + * Argon2 (KDBX 4 - recommended): KDBX 4, the Argon2 key derivation function can be used for transforming the composite master key (as protection against dictionary attacks). The main advantage of Argon2 over AES-KDF is that it provides a better resistance against GPU/ASIC attacks (due to being a memory-hard function). The number of iterations scales linearly with the required time. By increasing the memory parameter, GPU/ASIC attacks become harder (and the required time increases). The parallelism parameter can be used to specify how many threads should be used. +// end::advanced[] + +== Storing a Database File +The database file that you create might contain highly sensitive data and must be stored in a very secure way. You must make sure that the database is always protected with a strong and long password. The database file that is protected with a strong and long password is secure and encrypted while stored on your computer or cloud storage service. + +Make sure that the database file is stored in a folder that is secure. Make sure that you or someone else does not accidentally delete the database file. Deletion of the database file will result in the total loss of your information and a lot of inconvenience to manually retrieve your logins for various web applications. You must not share your database file with anyone unless absolutely necessary. + +== Backing up a Database File +It is a good practice to create copies of your database file and store the copies of your database on a different computer, smart phone, or cloud storage space such a Google Drive or Microsoft OneDrive. Backups can be created automatically by selecting the _Backup database file before saving_ option in the application settings. Additionally, you can create a backup on-demand using the _Database_ -> _Save Database Backup..._ menu feature. + +.Saving a database backup +image::save_database_backup.png[,40%] + +Creating backups for your database give you a peace of mind should you lose one copy of your database. You can quickly retrieve the copy of your database and start using it. +// end::content[] diff --git a/docs/topics/Disclaimers.adoc b/docs/topics/Disclaimers.adoc new file mode 100644 index 000000000..a8e9be57c --- /dev/null +++ b/docs/topics/Disclaimers.adoc @@ -0,0 +1,32 @@ +== License and Disclaimers + +KeePassXC is licensed with the +https://github.com/keepassxreboot/keepassxc/blob/master/LICENSE.GPL-3[GNU General Public License Version 3]. +All copyrights and additional licenses are recorded in +https://github.com/keepassxreboot/keepassxc/blob/master/COPYING[COPYING]. + +=== Disclaimer of Warranty + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +Except when otherwise stated in writing the copyright holders and/or other parties provide the program "as is" without +Warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of +Merchantability and fitness for a particular purpose. The entire risk as to the quality and performance of the program +Is with you. Should the program prove defective, you assume the cost of all necessary servicing, repair or correction. + +=== Limitation of Liability + +In no event unless required by applicable law or agreed to in writing will any copyright holder, or any other party +Who modifies and/or conveys the program as permitted above, be liable to you for damages, including any general, +Special, incidental or consequential damages arising out of the use or inability to use the program (including but not +Limited to loss of data or data being rendered inaccurate or losses sustained by you or third parties or a failure of +The program to operate with any other programs), even if such holder or other party has been advised of the possibility +Of such damages. + +== Contact Us + +We are committed to continually improve KeePassXC through customer experience and your feedback is important to us. +Please send us your feedback or comments to team@keepassxc.org. +To report issues, visit: https://github.com/keepassxreboot/keepassxc. + +Thank You, + +Team KeePassXC diff --git a/docs/topics/DownloadInstall.adoc b/docs/topics/DownloadInstall.adoc new file mode 100644 index 000000000..4e17c66bc --- /dev/null +++ b/docs/topics/DownloadInstall.adoc @@ -0,0 +1,60 @@ += KeePassXC - Download and Install +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +== Downloading KeePassXC +KeePassXC is available for download for the following operating systems and platforms: + +* Microsoft Windows +** Portable and MSI Installer (64-bit and 32-bit) +* Linux - Official Cross-Distribution Packages +** AppImage and Snap Package +* Linux - Distribution-Specific Packages +** Ubuntu, Debian, Arch Linux, Gentoo, Fedora, CentOS, and OpenSUSE +* macOS +** DMG Installer, Homebrew Cask + +To download the KeePassXC installer for your desired platform, visit https://keepassxc.org/download or directly from our https://github.com/keepassxreboot/keepassxc/releases[GitHub Releases]. + +NOTE: KeePassXC is open-source software and may be available on other websites that are unaffiliated with Team KeePassXC. *We strongly discourage downloading KeePassXC from third-party websites.* + +Before installing KeePassXC, it is recommended that you verify that your downloaded installer matches the signature, which is published alongside the release package. By verifying the signatures of KeePassXC releases, you can verify the authenticity and integrity of the downloaded installation file. This guarantees that the file you downloaded was originally created by the KeePassXC Team and its contents have not been tampered with. + +To know more about the steps to verify the authenticity and integrity of your downloaded package, visit https://keepassxc.org/verifying-signatures. + +=== Microsoft Windows +The Windows MSI installer is signed by a secure certificate owned by DroidMonkey Apps, LLC. If you do not see this dialog when installing the application, click *NO* and download the installer from https://keepassxc.org. + +.Windows UAC Dialog +image::uac_dialog.png[50%] + +Installing KeePassXC is a simple process. In the following example, installation steps for KeePassXC on Microsoft Windows are described. Installing KeePassXC on other operating systems is also a simple process, which you can accomplish by using the native installers. To know more about the installation instructions on the other operating systems, refer to the KeePassXC User Manual. + +To install KeePassXC on Microsoft Windows, perform the following steps: + +1. Double click on the KeePassXC-Y.Y.Y-WinZZ.msi file. Here, Y.Y.Y represents the version of the software and ZZ represents the 32-bit/64-bit version of the Microsoft Windows operating system. ++ +.Install wizard +image::install_wizard_1.png[,80%] + +2. Click Next and follow the simple instructions on the KeepPassXC Setup Wizard to complete the installation. You will have the option to choose your install location, add a desktop shortcut, and launch on startup. ++ +.Install wizard (cont) +image::install_wizard_2.png[,80%] + +=== Linux +You can easily download the KeePassXC installer for Linux. When you search for KeePassXC, multiple options are displayed as shown in the following screen: + +.Ubuntu Store +image::linux_store.png[] + +The Snap and Flatpak options are sandboxed applications (more secure). The Native option is installed with the operating system files. Read more about the limitations of these options here: https://keepassxc.org/docs/#faq-appsnap-yubikey[KeePassXC Snap FAQ] + +=== macOS +To install the KeePassXC app on macOS, double click on the downloaded DMG file and use the click and drag option as shown: + +.macOS DMG Install +image::macos_install.png[,80%] + +// end::content[] diff --git a/docs/topics/ImportExport.adoc b/docs/topics/ImportExport.adoc new file mode 100644 index 000000000..f051846de --- /dev/null +++ b/docs/topics/ImportExport.adoc @@ -0,0 +1,64 @@ += KeePassXC - Import/Export Operations +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +== Importing External Databases +KeePassXC allows your to import external databases from the following options: + +* Comma-Separated Values (CSV) file +* 1Password OPVault +* KeePass 1 Database + +=== Importing CSV File +If you have been saving your URLs, usernames, passwords, and so on in a CSV file, you can migrate all that information from the CSV file to KeePassXC and start using KeePassXC to maintain your data. + +To open the CSV file, perform the following steps: + +1. Open KeePassXC. + +2. Click Import from CSV button on the welcome screen or use the menu Database > Import > CSV File. + +3. Navigate to the location of the your CSV file on your computer and open the file. The new database wizard will appear. Follow the steps of creating a new database in Chapter 1. + +4. After saving your new database file, the CSV import wizard will appear: ++ +.CSV Import Wizard +image::csv_import.png[,80%] + +Your CSV file gets imported to KeePassXC and the data is converted to the KeePassXC format for further usage and maintenance. The new database file is saved on to your computer with the default `.kdbx` extension. + +=== Importing 1Password OPVault +Save your 1Password Vault locally to create an OPVault directory. Please see 1Password instructions on how to do this. Once an OPVault is created, perform the following steps: + +1. Open KeePassXC. + +2. Use the menu Database > Import > 1Password Vault. Select the OPVault to import. + +3. Enter the password for your OPVault to unlock and import. + +=== Importing KeePass 1 Database +KeePass 1 database is an older format of the database created using legacy version of KeePass. KeePassXC lets your import this older format of the database and you can seamlessly start using this database in your new KeePassXC application. + +To import a KeePass 1 database file in KeePassXC, perform the following steps: + +1. Open KeePassXC. + +2. Click Import from KeePass 1 button on the welcome screen or use the menu Database > Import > KeePass 1 Database. + +3. Navigate to the location of the your legacy KeePass 1 database file (`.kdb`) on your computer and open the file. You are prompted for the password and the Key file for your `.kdb` file. + +4. Enter the password for your old `.kdb` file and click *OK*. You are prompted for provide a name for the new database format that KeePassXC recognizes. + +5. Provide a name for the new database format, select a folder on your computer to save the file, and click Save. + +6. The data from the `.kdb` file gets imported and converted to the new format, which is compatible with KeePassXC. You can now start using the new database file (`.kdbx`) in KeePassXC. + +== Exporting Databases +KeePassXC supports multiple ways to export your database for transfer to another program or to print out and archive. To export your database into the KDB XML format, you must use the KeePassXC Command Line Interface program: `keepassxc-cli export `. + +WARNING: Exporting your database will result in all of your passwords and sensitive information being stored unencrypted. We do not recommend saving your exported database for long periods of time as that can cause compromise. + +.Database export menu +image::export_database.png[,80%] +// end::content[] diff --git a/docs/topics/KeeShare.adoc b/docs/topics/KeeShare.adoc new file mode 100644 index 000000000..9451d2bfc --- /dev/null +++ b/docs/topics/KeeShare.adoc @@ -0,0 +1,51 @@ += KeePassXC - KeeShare +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +== Database Sharing with KeeShare +KeeShare allows you to share a subset of your credentials with others and vice versa. + +=== Enable Sharing +To use sharing, you need to enable it for the application. + +1. Go to _Tools_ -> _Settings_. Select the KeeShare category on the left sidebar *(1)*. +2. Check _Allow import_ if you want to import shared credentials. Check _Allow export_ if you want to share credentials. *(2)* +3. (Optional) Click _Generate_ *(3)* to create your own certificate or _Import_ to select an existing one. The certificate allows you to sign shared databases. This ensures the integrity of the share and prevent import of untrusted information. + +.KeeShare Application Settings +image::keeshare_application_settings.png[] + +=== Sharing Credentials +If you checked _Allow export_ in the Sharing settings you can now share a group of passwords. Sharing is always is defined on a particular group. If you enable sharing on a group, every entry under this group, and its children, are shared. If you enable sharing on the root node, **every password** inside your database gets shared! + +NOTE: KeeShare does not synchronize group structure after the initial share is created. At this time, KeeShare operates at the entry level; shared entries moved outside of a shared group are still synchronized. + +1. Open the edit sheet on a group you want to share. +2. Select the KeeShare category on the left toolbar. +3. Choose a sharing type: + a. *Inactive* - Disable sharing this group + b. *Import* - Read-only import of entries, merge changes + c. *Export* - Write-only export of entries, no merge + d. *Synchronize* - Read/Write entries from the share, merge changes +4. Choose a path to store the shared credentials to. +5. The password to use for this share container. + +The export file will not be generated automatically. Instead, each time the database is saved, the file gets written. The file should be written to a location that is accessible by others. An easy setup is a network share or storing the file in cloud storage. + +.KeeShare Group Settings +image::keeshare_group_settings.png[] + +=== Using Shared Credentials +KeeShare watches the container for changes and merges them into your database when necessary (Import and Synchronize modes). Entries merge in time order; older data is moved to the history of the entry. + +A shared group shows a cloud icon badge over the group icon *(A)* and a banner is displayed showing the sharing mode and file location *(B)*. If the share is disabled or unavailable, the cloud icon will show as red with a white X. + +.KeeShare shared group +image::keeshare_shared_group.png[] + +=== Technical Details and Limitations of Sharing +Sharing relies on the combination of file exports and imports as well as the synchronization mechanism provided by KeePassXC. Since the merge algorithm uses the history of entries to prevent data loss, this history must be enabled and have a sufficient size. Furthermore, the merge algorithm is location independent, therefore it does not matter if entries are moved outside of an import group. These entries will be updated none the less. Moving entries outside of export groups will prevent a further export of the entry, but it will not ensure that the already shared data will be removed from any client. + +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. +// end::content[] diff --git a/docs/topics/KeyboardShortcuts.adoc b/docs/topics/KeyboardShortcuts.adoc new file mode 100644 index 000000000..489c81598 --- /dev/null +++ b/docs/topics/KeyboardShortcuts.adoc @@ -0,0 +1,40 @@ += KeePassXC - Keyboard Shortcuts +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +[grid=rows, frame=none, width=75%] +|=== +|Action | Keyboard Shortcut + +|Open Database | Ctrl + O +|Save Database | Ctrl + S +|Save Database As | Ctrl + Shift + S +|New Database | Ctrl + Shift + N +|Close Database | Ctrl + W ; Ctrl + F4 +|Lock All Databases | Ctrl + L +|Quit | Ctrl + Q +|New Entry | Ctrl + N +|Edit Entry | Enter ; Ctrl + E +|Delete Entry | Delete +|Clone Entry | Ctrl + K +|Copy Username | Ctrl + B +|Copy Password | Ctrl + C +|Copy URL | Ctrl + U +|Open URL | Ctrl + Shift + U +|Copy TOTP | Ctrl + T +|Show TOTP | Ctrl + Shift + T +|Trigger AutoType | Ctrl + Shift + V +|Add key to SSH Agent | Ctrl + H +|Remove key from SSH Agent | Ctrl + Shift + H +|Minimize Window | Ctrl + M +|Hide Window | Ctrl + Shift + M +|Select Next Database Tab | Ctrl + Tab ; Ctrl + PageDn +|Select Previous Database Tab | Ctrl + Shift + Tab ; Ctrl + PageUp +|Toggle Passwords Hidden | Ctrl + Shift + C +|Toggle Usernames Hidden | Ctrl + Shift + B +|Focus Search | Ctrl + F +|Clear Search | Escape +|Show Keyboard Shortcuts | Ctrl + / +|=== +// end::content[] diff --git a/docs/topics/PasswordGenerator.adoc b/docs/topics/PasswordGenerator.adoc new file mode 100644 index 000000000..ea05000ef --- /dev/null +++ b/docs/topics/PasswordGenerator.adoc @@ -0,0 +1,44 @@ += KeePassXC - Password Generator +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +== Password Generator +This password generator helps you to generate random strong passwords and passphrases that you can use for your applications and websites you visit. + +=== Generating Passwords +To generate random passwords, specify the characters to be used in your choice of password (for example, upper-case letters, digits, special characters, and so on) and KeePassXC will randomly pick characters out of the set. + +To generate the random password using Password Generator, perform the following steps: + +1. Open KeePassXC. +2. Navigate to Tools > Password Generator. The following screen appears: ++ +.Password Generator +image::password_generator.png[] + +3. Select the length of the desired password by dragging the Length slider. +4. Select the character-sets that you want to include in your password. +5. Use the regenerate button (Ctrl + R) to make a new password using the chosen options. +6. Use the clipboard button (Ctrl + C) to copy the generated password to the clipboard. +// tag::advanced[] +7. Click the Advanced button to specify additional conditions for your desired password. ++ +.Advanced Password Generator Options +image::password_generator_advanced.png[] + +=== Generating Passphrases +A passphrase is a sequence of words or other text used to control access to your applications and data. A passphrase is similar to a password in usage, but is generally longer for added security. To generate the random passphrase using Password Generator, perform the following steps: + +1. From the password generator, click the Passphrase tab. The following screen appears: ++ +.Passphrase Generator +image::passphrase_generator.png[] + +2. Select the number of words you want to be included in your passphrase by dragging the +Word Count slider. +3. In the Word Separator field, enter a character, word, number, or space that you want to use a separator between the words in your passphrase. +4. Click the Regenerate button (Ctrl + R) to generate a new random passphrase. +5. Click the Clipboard button (Ctrl + C) to copy the passphrase to the clipboard. +// end::advanced[] +// end::content[] diff --git a/docs/topics/SSHAgent.adoc b/docs/topics/SSHAgent.adoc new file mode 100644 index 000000000..7ade8f256 --- /dev/null +++ b/docs/topics/SSHAgent.adoc @@ -0,0 +1,125 @@ += KeePassXC - SSH Agent +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +== SSH Agent +SSH (Secure Shell) is a widely used remote secure shell protocol and is considered an industry standard for secure remote access to UNIX-like systems including Linux, BSDs, MacOS and more recently even Windows received native support. SSH supports multiple types of authentication and the most widely used ones are either interactive keyboard input with a password or a public-key cryptography pair of keys. + +KeePassXC SSH Agent integration is built to manage SSH keys in a secure manner by either storing them completely within your KeePassXC database or by having only the decryption key of a key file that is stored elsewhere. SSH Agent integration _does not_ provide an agent itself but works as a client for any agent implementation that is OpenSSH compatible. + +=== OpenSSH agent on Linux +If you are using a modern desktop Linux distribution it is very likely the OpenSSH agent is already configured and running when you have logged in to a graphical desktop session. +This should be true for distributions like Debian, Ubuntu (including Kubuntu, Xubuntu and Lubuntu), Linux Mint, Fedora, ElementaryOS and Manjaro. + +First, open a terminal and check the output of `ssh-add -l`: + + $ ssh-add -l + The agent has no identities. + +If you either got a list of fingerprints or the message above the agent is already running and no further setup is required. +If instead you got a message saying _"Could not open a connection to your authentication agent."_ that means the agent is either misconfigured or not running at all. + +Since every distribution and desktop environment is configured differently there is no general guide how to properly set it up yourself. +The general rule of thumb, however, is that `ssh-agent` needs to be started as part of the startup programs for a session in a way its environment variables are exposed to all processes started by the desktop environment. +One of the easiest ways to achieve this is to enable _GNOME Keyring_ which should in turn start the agent as part of its services. + +There are many guides on the internet how to hack your login shell to start an agent but it is very prone to errors and is not a supported configuration. If you prefer the login shell startup hack you need to set it up with a static socket path and use the _SSH_AUTH_SOCK override_ option in SSH Agent settings to match that. + +WARNING: _GNU Privacy Guard (gpg)_ with its SSH agent implementation is *not* compatible with KeePassXC as it does not support _removing_ keys that have been added to it making it impossible to use any external tool to manage key lifetime. + +WARNING: _GNOME Keyring_ prior to release 3.27.92 had its own custom implementation of an agent which does not support modern key types and was known to be buggy. +It does not support any constraints you may want to configure for an added key. +If you are running a modern distribution the custom agent has been removed and replaced with the stock OpenSSH agent which is feature complete. + +=== OpenSSH agent on MacOS +Apple has made OpenSSH an integrated part of MacOS with automatic agent startup when it is first used. No further configuration is needed. + +=== Pageant agent on Windows +The SSH Agent integration on Windows supports both _PuTTY Pageant_ and _OpenSSH for Windows 10_. +Since Pageant is currently still the most widely used implementation and is easily installable on any version of Windows we focus on that. +It is also the default on KeePassXC. + +Download Pageant from the official PuTTY home page at https://www.chiark.greenend.org.uk/~sgtatham/putty/ + +To use Pageant with KeePassXC, simply start it and it will minimize into the system tray and is ready to use. PuTTY and compatible tools will use Pageant automatically. + +=== Setting up SSH Agent integration +By default the SSH Agent integration plugin is disabled. +To enable integration, follow the steps below to access the settings: + + 1. Select _Tools > Settings_ from the menu + 2. Select _SSH Agent_ category on the left sidebar + +.SSH Agent Application Settings Page +image::sshagent_application_settings.png[] + +On the settings page you can enable the integration by checking _Enable SSH Agent integration_. +When the integration is enabled coming back to the settings page also shows if connection to the agent is working. + +On Windows you have the option to select between _Pageant_ and _OpenSSH for Windows_ and on other platforms the settings page shows the current value of _SSH_AUTH_SOCK_ environment variable which is used to connect to the running agent and an option to manually override the automatically detected path. + +If the value of _SSH_AUTH_SOCK_ is empty it means the agent is not properly configured and KeePassXC will be unable to connect to it unless you provide a static override path to the socket. + +=== Generating a key to use with KeePassXC +KeePassXC only supports keys in the _OpenSSH_ format. On Windows, _PuTTYgen_ saves keys in its own format by default and you will need to convert them to OpenSSH format before being used. In this guide we are going to generate a standard RSA key in the default size. + +==== Generating a key on Linux or MacOS with _ssh-keygen_ + +Open a terminal window and type the following command to generate a key: + + $ ssh-keygen -o -f keepassxc -C johndoe@example + Generating public/private rsa key pair. + Enter passphrase (empty for no passphrase): + Enter same passphrase again: + Your identification has been saved in keepassxc + Your public key has been saved in keepassxc.pub + The key fingerprint is: + SHA256:pN+o5AqUmijYBDUrFV/caMus9oIR61+MiWLa8fcsVYI johndoe@example + The key's randomart image is: + +---[RSA 3072]----+ + | =. ..o | + | o + .+ . | + |o . .+ o. | + | o.. Eo. . | + | +o .. So | + |o*o.o+ ..o | + |Bo=+o.+.o . | + |+oo+.++o | + |. ..++ooo | + +----[SHA256]-----+ + + +Now we can see two files were generated: + + $ ls -l keepassxc* + -rw------- 1 user group 2.6K Apr 5 07:36 keepassxc + -rw-r--r-- 1 user group 569 Apr 5 07:36 keepassxc.pub + +With KeePassXC you only need the first file listed. + +==== Generating a key on Windows with PuTTYgen +Please read the manual on how to use PuTTYgen for details on generate a key: https://the.earth.li/~sgtatham/putty/0.74/htmldoc/Chapter8.html#pubkey-puttygen. Once generated, you must save the key in OpenSSH format, follow the image below. + +.Generating a key with PuTTYgen +image::sshagent_puttygen.png[,70%] + +=== Configuring an entry to use SSH Agent +The last step is to setup an entry to contain the SSH Agent settings and key file you generated. + +1. Create a new entry, or open an existing entry in edit mode. +2. Set the password you used for the key file in the password field. +3. Go to the advanced category and attach the key file you generated previously. +4. Go to the SSH Agent category *(1)* and select the attachment from the list *(2)*. +5. Alternatively, you can load an external file dynamically using the file selection. +6. Choose the options for this key. +7. Press *OK* to accept the entry. Depending on the options you chose, KeePassXC will load the key and present it for use. + +.SSH Agent Entry Settings Page +image::sshagent_entry_settings.png[] + +If you chose to not auto-load the key on database unlock, you can manually make the key available by using the context menu from the entry list. + +.SSH Agent Load Key from Context Menu +image::sshagent_context_menu.png[] +// end::content[] diff --git a/docs/topics/UserInterface.adoc b/docs/topics/UserInterface.adoc new file mode 100644 index 000000000..1fee94608 --- /dev/null +++ b/docs/topics/UserInterface.adoc @@ -0,0 +1,51 @@ += KeePassXC - Database Operations +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +== Interface Overview +=== Application Layout +The KeePassXC interface is designed for simplicity and easy access to your information. The main database view is split into three main partitions detailed below. You can open multiple databases at the same time, they will appear in tabs. + +.Main database interface +image::main_interface.png[] + +*(A) Groups* - Organize your entries into discrete groups to bring order to all of your sensitive information. Groups can be nested under each other to create a hierarchy. Settings from parent groups get applied to their children. + +*(B) Entries* - Entries contain all the information for each website or application you are storing in KeePassXC. This view shows all the entries in the selected group. Each column can be resized, reordered, and shown or hidden based on your preference. Right click the header row to see all available options. + +*\(C) Preview* - Shows a preview of the selected group or entry. You can temporarily hide this preview using the close button on the right hand side or completely disabled in the application settings. + +TIP: Double clicking on the text in the entries list copies that field to the clipboard. Double clicking the entry title will open the entry for editing. + +=== Toolbar +The toolbar provides a quick way to perform common tasks with your database. Some entries in the toolbar are dynamically disabled based on the information contained in the selected entry. Every common action in KeePassXC can be controlled with a keyboard shortcut as well. + +.Toolbar overview +image::toolbar.png[] + +*(A) Database* - Open Database, Save Database + +*(B) Entries* - Create Entry, Edit Selected Entry, Delete Selected Entry + +*\(C) Entry Data* - Copy Username, Copy Password, Copy URL, Perform Auto-Type + +*(D) Lock All Databases* + +*(E) Tools* - Password Generator, Application Settings + +*(F) Search* + +=== Application Settings +Users can configure KeePassXC to their personal tastes with a wide variety of general and security settings that apply to the whole application. These settings are accessible from _Tools_ -> _Settings_ or the cog wheel icon from the toolbar. Settings include: startup options, file management, entry management, user interface, language, security timeouts, and convenience. + +==== Setting the Theme +KeePassXC ships with light and dark themes specifically designed to meet accessibility standards. In most cases, the appropriate theme for your system will be determined automatically, but you can always set a specific theme by using the _View_ menu. When a new theme is selected you will be prompted to restart KeePassXC to apply the theme immediately. + +.Setting the theme +image::theme_selection.png[] + +==== Compact Mode +For users with smaller screens or those who desire seeing more entries at once, KeePassXC offers a compact view mode. This mode shows smaller toolbar, group, and entry icons. The effect of compact mode (left side) can be seen below. + +.Compact mode comparison +image::compact_mode_comparison.png[] + +=== Keyboard Shortcuts +include::KeyboardShortcuts.adoc[tag=content, leveloffset=+1] +// end::content[] diff --git a/docs/topics/Welcome.adoc b/docs/topics/Welcome.adoc new file mode 100644 index 000000000..576b3d818 --- /dev/null +++ b/docs/topics/Welcome.adoc @@ -0,0 +1,49 @@ += KeePassXC - Welcome +include::.sharedheader[] +:imagesdir: ../images + +// tag::content[] +== Welcome +KeePassXC is a modern open-source password manager. It is used to store and manage information such as URLs, usernames, passwords, and so on for various accounts on your web applications. KeePassXC stores all data in an encrypted format while still providing secure access to your information. + +KeePassXC is helpful for people with extremely high demands of secure personal data management. It saves many different information, such as user names, passwords, URLs, attachments, and comments in one single database. For a better management, user-defined titles and icons can be specified for different entries in KeePassXC. In addition, the entries are sorted in customizable groups. The integrated search function allows to search in a single group or the complete database. + +KeePassXC also provides a secure, customizable, fast, and easy-to-use password generator utility. This utility is very helpful to those who generate passwords frequently. + +=== Overview +You can store an unlimited number of passwords and information in a KeePassXC database. Every piece of information you store in your database is encrypted at all times within the `kdbx` file. When you are accessing your database from within KeePassXC, your information in decrypted and stored in your computer's memory. KeePassXC places controls over the access to this data so other applications cannot read it (unless they have administrative rights). The interface is designed to let you quickly access your passwords, search for the right entry, perform Auto-Type or copy/paste +operations, make and save changes, and then get out of your way. + +KeePassXC ships with light and dark themes specifically designed to meet accessibility standards. In most cases, the appropriate theme for your system will be determined automatically, but you can always set a specific theme in the application settings. + +.Light and Dark Themes +image::theme_comparison.png[] + +=== Features +KeePassXC has numerous features for novice and power users alike. This guide will go over the basic features to get you up and running quickly. The User Guide contains more in-depth discussions on the major features in the application. + +* Basic Features + ** Create, open, and save databases in the KDBX format (KeePass Compatible) + ** Store sensitive information in entries that are organized by groups + ** Search for entries + ** Password generator + ** Auto-Type passwords into applications + ** Browser integration with Google Chrome, Mozilla Firefox, Microsoft Edge, Chromium, Vivaldi, Brave, and Tor-Browser + ** Entry icon download + ** Import databases from CSV, 1Password, and KeePass1 formats + +* Advanced Features + ** Database reports (password health, HIBP, and statistics) + ** Database export to CSV and HTML formats + ** TOTP storage and generation + ** Field references between entries + ** File attachments and custom attributes + ** Entry history and data restoration + ** YubiKey/OnlyKey challenge-response support + ** Command line interface (keepassxc-cli) + ** Auto-Open databases + ** KeeShare shared databases (import, export, and synchronize) + ** SSH Agent + ** FreeDesktop.org Secret Service (replace Gnome keyring, etc.) + ** Additional encryption choices: Twofish and ChaCha20 +// end::content[] diff --git a/release-tool b/release-tool index 0d176835a..b95b0ddb8 100755 --- a/release-tool +++ b/release-tool @@ -736,12 +736,9 @@ EOF local appimage_name="KeePassXC-x86_64.AppImage" if [ "" != "$RELEASE_NAME" ]; then appimage_name="KeePassXC-${RELEASE_NAME}-x86_64.AppImage" + echo "X-AppImage-Version=${RELEASE_NAME}" >> "$desktop_file" 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 # --no-appstream is required, since it may crash on newer systems # see: https://github.com/AppImage/AppImageKit/issues/856 diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index 47fcc3f7b..6d689df9e 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -40,9 +40,6 @@ endif() install(FILES icons/application/256x256/apps/keepassxc.png DESTINATION ${DATA_INSTALL_DIR}/icons/application/256x256/apps) -install(DIRECTORY docs/ DESTINATION ${DATA_INSTALL_DIR}/docs FILES_MATCHING PATTERN "*.pdf") - - add_custom_target(icons) add_custom_command(TARGET icons COMMAND bash ./icons/minify.sh diff --git a/share/docs/KeePassXC_GettingStarted.pdf b/share/docs/KeePassXC_GettingStarted.pdf deleted file mode 100644 index 2ae781ae9..000000000 Binary files a/share/docs/KeePassXC_GettingStarted.pdf and /dev/null differ diff --git a/share/docs/KeePassXC_UserGuide.pdf b/share/docs/KeePassXC_UserGuide.pdf deleted file mode 100644 index 9f9379e81..000000000 Binary files a/share/docs/KeePassXC_UserGuide.pdf and /dev/null differ diff --git a/share/docs/man/keepassxc-cli.1 b/share/docs/man/keepassxc-cli.1 deleted file mode 100644 index bac9a8d37..000000000 --- a/share/docs/man/keepassxc-cli.1 +++ /dev/null @@ -1,274 +0,0 @@ -.TH KEEPASSXC-CLI 1 "Jan 04, 2020" - -.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 "\fBadd\fP [options] " -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 "\fBanalyze\fP [options] " -Analyzes passwords in a database for weaknesses. - -.IP "\fBclip\fP [options] [timeout]" -Copies an attribute or the current TOTP (if the \fI-t\fP option is specified) of a database entry to the clipboard. If no attribute name is specified using the \fI-a\fP option, the password is copied. If multiple entries with the same name exist in different groups, only the attribute for the first one is copied. For copying the attribute 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 "\fBclose\fP" -In interactive mode, closes the currently opened database (see \fIopen\fP). - -.IP "\fBdb-create\fP [options] " -Creates a new database with a password and/or a key file. 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 "\fBdb-info\fP [options] " -Show a database's information. - -.IP "\fBdiceware\fP [options]" -Generates a random diceware passphrase. - -.IP "\fBedit\fP [options] " -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 "\fBestimate\fP [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 "\fBexit\fP" -Exits interactive mode. Synonymous with \fIquit\fP. - -.IP "\fBexport\fP [options] " -Exports the content of a database to standard output in the specified format (defaults to XML). - -.IP "\fBgenerate\fP [options]" -Generates a random password. - -.IP "\fBhelp\fP [command]" -Displays a list of available commands, or detailed information about the specified command. - -.IP "\fBimport\fP [options] " -Imports the contents of an XML database to the target database. - -.IP "\fBlocate\fP [options] " -Locates all the entries that match a specific search term in a database. - -.IP "\fBls\fP [options] [group]" -Lists the contents of a group in a database. If no group is specified, it will default to the root group. - -.IP "\fBmerge\fP [options] " -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 "\fBmkdir\fP [options] " -Adds a new group to a database. - -.IP "\fBmv\fP [options] " -Moves an entry to a new group. - -.IP "\fBopen\fP [options] " -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 "\fBquit\fP" -Exits interactive mode. Synonymous with \fIexit\fP. - -.IP "\fBrm\fP [options] " -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 "\fBrmdir\fP [options] " -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 "\fBshow\fP [options] " -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 "\fB--debug-info\fP" -Displays debugging information. - -.IP "\fB-k\fP, \fB--key-file\fP " -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 "\fB--no-password\fP" -Deactivates the password key for the database. - -.IP "\fB-y\fP, \fB--yubikey\fP " -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 "\fB-q\fP, \fB--quiet\fP " -Silences password prompt and other secondary outputs. - -.IP "\fB-h\fP, \fB--help\fP" -Displays help information. - -.IP "\fB-v\fP, \fB--version\fP" -Displays the program version. - - -.SS "Merge options" - -.IP "\fB-d\fP, \fB--dry-run\fP " -Prints the changes detected by the merge operation without making any changes to the database. - -.IP "\fB--key-file-from\fP " -Sets the path of the key file for the second database. - -.IP "\fB--no-password-from\fP" -Deactivates password key for the database to merge from. - -.IP "\fB--yubikey-from\fP " -Yubikey slot for the second database. - -.IP "\fB-s\fP, \fB--same-credentials\fP" -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 "\fB-u\fP, \fB--username\fP " -Specifies the username of the entry. - -.IP "\fB--url\fP " -Specifies the URL of the entry. - -.IP "\fB-p\fP, \fB--password-prompt\fP" -Uses a password prompt for the entry's password. - -.IP "\fB-g\fP, \fB--generate\fP" -Generates a new password for the entry. - - -.SS "Edit options" - -.IP "\fB-t\fP, \fB--title\fP " -Specifies the title of the entry. - - -.SS "Estimate options" - -.IP "\fB-a\fP, \fB--advanced\fP" -Performs advanced analysis on the password. - - -.SS "Analyze options" - -.IP "\fB-H\fP, \fB--hibp\fP <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 "\fB-a\fP, \fB--attribute\fP" -Copies the specified attribute to the clipboard. If no attribute is specified, -the password attribute is the default. For example, "\fI-a\fP username" would -copy the username to the clipboard. [Default: password] - -.IP "\fB-t\fP, \fB--totp\fP" -Copies the current TOTP instead of the specified attribute to the clipboard. -Will report an error if no TOTP is configured for the entry. - -.SS "Create options" - -.IP "\fB-k\fP, \fB--set-key-file\fP <path>" -Set the key file for the database. - -.IP "\fB-p\fP, \fB--set-password\fP" -Set a password for the database. - -.IP "\fB-t\fP, \fB--decryption-time\fP <time>" -Target decryption time in MS for the database. - - -.SS "Show options" - -.IP "\fB-a\fP, \fB--attributes\fP <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. -Protected attributes will be displayed in clear text if specified explicitly by this option. - -.IP "\fB-s\fP, \fB--show-protected\fP" -Shows the protected attributes in clear text. - -.IP "\fB-t\fP, \fB--totp\fP" -Also shows the current TOTP, reporting an error if no TOTP is configured for -the entry. - - -.SS "Diceware options" - -.IP "\fB-W\fP, \fB--words\fP <count>" -Sets the desired number of words for the generated passphrase. [Default: 7] - -.IP "\fB-w\fP, \fB--word-list\fP <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 "\fB-f\fP, \fB--format\fP" -Format to use when exporting. Available choices are xml or csv. Defaults to xml. - - -.SS "List options" - -.IP "\fB-R\fP, \fB--recursive\fP" -Recursively lists the elements of the group. - -.IP "\fB-f\fP, \fB--flatten\fP" -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 "\fB-L\fP, \fB--length\fP <length>" -Sets the desired length for the generated password. [Default: 16] - -.IP "\fB-l\fP, \fB--lower\fP" -Uses lowercase characters for the generated password. [Default: Enabled] - -.IP "\fB-U\fP, \fB--upper\fP" -Uses uppercase characters for the generated password. [Default: Enabled] - -.IP "\fB-n\fP, \fB--numeric\fP" -Uses numbers characters for the generated password. [Default: Enabled] - -.IP "\fB-s\fP, \fB--special\fP" -Uses special characters for the generated password. [Default: Disabled] - -.IP "\fB-e\fP, \fB--extended\fP" -Uses extended ASCII characters for the generated password. [Default: Disabled] - -.IP "\fB-x\fP, \fB--exclude\fP <chars>" -Comma-separated list of characters to exclude from the generated password. None is excluded by default. - -.IP "\fB--exclude-similar\fP" -Exclude similar looking characters. [Default: Disabled] - -.IP "\fB--every-group\fP" -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>. diff --git a/share/docs/man/keepassxc.1 b/share/docs/man/keepassxc.1 deleted file mode 100644 index fd2bbced4..000000000 --- a/share/docs/man/keepassxc.1 +++ /dev/null @@ -1,39 +0,0 @@ -.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 "\fB-h\fP, \fB--help\fP" -Displays this help. - -.IP "\fB-v\fP, \fB--version\fP" -Displays version information. - -.IP "\fB--config\fP <config>" -Path to a custom config file - -.IP "\fB--keyfile\fP <keyfile>" -Key file of the database - -.IP "\fB--pw-stdin\fP" -Read password of the database from stdin - -.IP "\fB--pw\fP, \fB--parent-window\fP <handle>" -Parent window handle - -.IP "\fB--debug-info\fP" -Displays debugging information. - -.SH AUTHOR -This manual page is maintained by the KeePassXC Team <team@keepassxc.org>. diff --git a/share/translations/keepassx_en_US.ts b/share/translations/keepassx_en_US.ts index f5477c488..3c2e56599 100644 --- a/share/translations/keepassx_en_US.ts +++ b/share/translations/keepassx_en_US.ts @@ -6587,7 +6587,7 @@ Kernel: %3 %4</translation> </message> <message> <source>Own certificate</source> - <translation>Own certificate</translation> + <translation>Personal certificate</translation> </message> <message> <source>Fingerprint:</source> @@ -6724,7 +6724,7 @@ Kernel: %3 %4</translation> </message> <message> <source>Export own certificate</source> - <translation>Export own certificate</translation> + <translation>Export personal certificate</translation> </message> <message> <source>Known shares</source> diff --git a/share/translations/keepassx_fr.ts b/share/translations/keepassx_fr.ts index 89d148f0a..376fa39fd 100644 --- a/share/translations/keepassx_fr.ts +++ b/share/translations/keepassx_fr.ts @@ -619,7 +619,7 @@ Veuillez sélectionner la base de donnée souhaitée pour enregistrer les identi </message> <message> <source>Re&quest to unlock the database if it is locked</source> - <translation>Demander de déverrouiller la base de données lorsque celle-ci est verrouillée</translation> + <translation>Demander de &déverrouiller la base de données si elle est verrouillée</translation> </message> <message> <source>Only entries with the same scheme (http://, https://, ...) are returned.</source> @@ -735,7 +735,7 @@ Veuillez sélectionner la base de donnée souhaitée pour enregistrer les identi </message> <message> <source>Please see special instructions for browser extension use below</source> - <translation>Veuillez regarder les instructions spéciales pour l'extension pour navigateur web utilisé ci-dessous</translation> + <translation>Veuillez consulter ci-dessous les instructions spéciales de l’extension pour navigateurs</translation> </message> <message> <source>KeePassXC-Browser is needed for the browser integration to work. <br />Download it for %1 and %2. %3</source> @@ -2194,7 +2194,7 @@ Désactiver les enregistrements sécurisés et ressayer ?</translation> </message> <message> <source>n/a</source> - <translation>n/a</translation> + <translation>s.o.</translation> </message> <message> <source>(encrypted)</source> @@ -2270,7 +2270,7 @@ Désactiver les enregistrements sécurisés et ressayer ?</translation> </message> <message> <source>[PROTECTED] Press reveal to view or edit</source> - <translation>[PROTÉGÉ] Appuyez pour voir ou modifier</translation> + <translation>[PROTÉGÉ] Appuyer sur Révéler pour visualiser ou modifier</translation> </message> <message numerus="yes"> <source>%n year(s)</source> @@ -2321,7 +2321,7 @@ Désactiver les enregistrements sécurisés et ressayer ?</translation> </message> <message> <source>Attachments</source> - <translation>Pièces jointes</translation> + <translation>Fichiers joints</translation> </message> <message> <source>Foreground Color:</source> @@ -2644,11 +2644,11 @@ Désactiver les enregistrements sécurisés et ressayer ?</translation> </message> <message> <source>Decrypt</source> - <translation>Déchiffré</translation> + <translation>Déchiffrer</translation> </message> <message> <source>n/a</source> - <translation>n/a</translation> + <translation>s.o.</translation> </message> <message> <source>Copy to clipboard</source> @@ -2669,7 +2669,7 @@ Désactiver les enregistrements sécurisés et ressayer ?</translation> </message> <message> <source>Attachment</source> - <translation>Pièce jointe</translation> + <translation>Fichier joint</translation> </message> <message> <source>Add to agent</source> @@ -3124,7 +3124,7 @@ This may cause the affected plugins to malfunction.</source> </message> <message> <source>Save</source> - <translation>Enregistrer le fichier</translation> + <translation>Enregistrer</translation> </message> <message> <source>Select files</source> @@ -3183,7 +3183,7 @@ This may cause the affected plugins to malfunction.</source> </message> <message> <source>Attachments</source> - <translation>Pièces jointes</translation> + <translation>Fichiers joints</translation> </message> <message> <source>Add new attachment</source> @@ -3281,7 +3281,7 @@ This may cause the affected plugins to malfunction.</source> </message> <message> <source>Attachments</source> - <translation>Pièces jointes</translation> + <translation>Fichiers joints</translation> </message> <message> <source>Yes</source> @@ -3324,7 +3324,7 @@ This may cause the affected plugins to malfunction.</source> </message> <message> <source>Attachments</source> - <translation>Pièces jointes</translation> + <translation>Fichiers joints</translation> </message> <message> <source>Notes</source> @@ -3548,7 +3548,7 @@ Vous pouvez activer le service d'icônes de sites Web de DuckDuckGo dans la </message> <message> <source>Invalid header id size</source> - <translation>Taille de l’identifiant d’en-tête invalide</translation> + <translation>La taille de l’ID d’en-tête est invalide</translation> </message> <message> <source>Invalid header field length</source> @@ -3556,7 +3556,7 @@ Vous pouvez activer le service d'icônes de sites Web de DuckDuckGo dans la </message> <message> <source>Invalid header data length</source> - <translation>Longueur des données d’en-tête invalide</translation> + <translation>La longueur des données d’en-tête est invalide</translation> </message> <message> <source>Invalid credentials were provided, please try again. @@ -3569,7 +3569,7 @@ Si le problème persiste, le fichier de la base de données peut être corrompu. <name>Kdbx3Writer</name> <message> <source>Unable to issue challenge-response.</source> - <translation>Impossible de lancer une question-réponse.</translation> + <translation>Impossible de générer une question-réponse.</translation> </message> <message> <source>Unable to calculate master key</source> @@ -3580,7 +3580,7 @@ Si le problème persiste, le fichier de la base de données peut être corrompu. <name>Kdbx4Reader</name> <message> <source>missing database headers</source> - <translation>en-têtes de la base de données manquantes</translation> + <translation>il manque des en-têtes de base de données</translation> </message> <message> <source>Unable to calculate master key</source> @@ -3588,11 +3588,11 @@ Si le problème persiste, le fichier de la base de données peut être corrompu. </message> <message> <source>Invalid header checksum size</source> - <translation>Taille de la somme de contrôle de d’en-tête invalide</translation> + <translation>La taille de la somme de contrôle de l’en-tête est invalide</translation> </message> <message> <source>Header SHA256 mismatch</source> - <translation>En-tête SHA256 incohérent</translation> + <translation>Le SHA256 de l’en-tête ne correspond pas</translation> </message> <message> <source>Unknown cipher</source> @@ -3600,7 +3600,7 @@ Si le problème persiste, le fichier de la base de données peut être corrompu. </message> <message> <source>Invalid header id size</source> - <translation>Taille de l’identifiant d’en-tête invalide</translation> + <translation>La taille de l’ID d’en-tête est invalide</translation> </message> <message> <source>Invalid header field length</source> @@ -3608,11 +3608,11 @@ Si le problème persiste, le fichier de la base de données peut être corrompu. </message> <message> <source>Invalid header data length</source> - <translation>Longueur des données d’en-tête invalide</translation> + <translation>La longueur des données d’en-tête est invalide</translation> </message> <message> <source>Failed to open buffer for KDF parameters in header</source> - <translation>Échec lors de l’ouverture d’une mémoire tampon pour les paramètres KDF dans l’en-tête</translation> + <translation>Échec d’ouverture d’un tampon pour les paramètres KDF dans l’en-tête</translation> </message> <message> <source>Unsupported key derivation function (KDF) or invalid parameters</source> @@ -3624,7 +3624,7 @@ Si le problème persiste, le fichier de la base de données peut être corrompu. </message> <message> <source>Invalid inner header id size</source> - <translation>Taille de identifiant d’en-tête interne invalide</translation> + <translation>La taille de l’ID d’en-tête interne est invalide</translation> </message> <message> <source>Invalid inner header field length</source> @@ -3746,7 +3746,7 @@ Si le problème persiste, le fichier de la base de données peut être corrompu. </message> <message> <source>Invalid transform seed size</source> - <translation>Taille du salage transformé invalide</translation> + <translation>La taille de la semence de transformation est invalide</translation> </message> <message> <source>Invalid transform rounds size</source> @@ -3780,7 +3780,7 @@ Il s’agit d’une migration à sens unique. Vous ne pourrez pas ouvrir la base </message> <message> <source>Unsupported KeePass 2 database version.</source> - <translation>Version de la base de données KeePass 2 non prise en charge.</translation> + <translation>Version de base de données KeePass 2 non pris en charge.</translation> </message> <message> <source>Invalid cipher uuid length: %1 (length=%2)</source> @@ -3950,7 +3950,7 @@ Ligne %2, colonne %3</translation> </message> <message> <source>Unsupported KeePass database version.</source> - <translation>Version de base de données KeePass non prise en charge.</translation> + <translation>Version de base de données KeePass non prise en charge.</translation> </message> <message> <source>Unable to read encryption IV</source> @@ -3971,7 +3971,7 @@ Ligne %2, colonne %3</translation> </message> <message> <source>Invalid transform seed size</source> - <translation>Taille du salage transformé invalide</translation> + <translation>La taille de la semence de transformation est invalide</translation> </message> <message> <source>Invalid number of transform rounds</source> @@ -5582,7 +5582,7 @@ Commandes disponibles : </message> <message> <source>Word count for the diceware passphrase.</source> - <translation>Nombre de mots de la phrase secrète générés avec la méthode du lancer de dés.</translation> + <translation>Nombre de mots de la phrase de passe générée avec la méthode du lancer de dés.</translation> </message> <message> <source>Wordlist for the diceware generator. @@ -6137,7 +6137,7 @@ Noyau : %3 %4</translation> </message> <message> <source>Invalid word count %1</source> - <translation>Nombre de mots %1 invalide</translation> + <translation>Le nombre de mots %1 est invalide</translation> </message> <message> <source>The word list is too small (< 1000 items)</source> @@ -6321,7 +6321,7 @@ Noyau : %3 %4</translation> </message> <message> <source>Show the protected attributes in clear text.</source> - <translation>Afficher les attributs protégés en clair.</translation> + <translation>Afficher en clair les attributs protégés.</translation> </message> </context> <context> @@ -6976,7 +6976,7 @@ Noyau : %3 %4</translation> </message> <message> <source>Algorithm:</source> - <translation>Algorithme :</translation> + <translation>Algorithme :</translation> </message> <message> <source>Time step field</source> diff --git a/share/translations/keepassx_id.ts b/share/translations/keepassx_id.ts index cbe0cc940..2c4fca7da 100644 --- a/share/translations/keepassx_id.ts +++ b/share/translations/keepassx_id.ts @@ -97,11 +97,11 @@ </message> <message> <source>Reset Settings?</source> - <translation type="unfinished"/> + <translation>Atur Ulang Pengaturan?</translation> </message> <message> <source>Are you sure you want to reset all general and security settings to default?</source> - <translation type="unfinished"/> + <translation>Apakah anda yakin ingin mengatur ulang pengaturan umum dan keamanan ke nilai bawaan?</translation> </message> </context> <context> @@ -225,63 +225,63 @@ </message> <message> <source>Remember previously used databases</source> - <translation type="unfinished"/> + <translation>Ingat basis data yang sebelumnya digunakan</translation> </message> <message> <source>Load previously open databases on startup</source> - <translation type="unfinished"/> + <translation>Muat basis data yang sebelumnya terbuka saat memulai</translation> </message> <message> <source>Remember database key files and security dongles</source> - <translation type="unfinished"/> + <translation>Ingat berkas kunci dan dongle kemanan</translation> </message> <message> <source>Check for updates at application startup once per week</source> - <translation type="unfinished"/> + <translation>Periksa pembaruan saat memulai aplikasi sekali seminggu</translation> </message> <message> <source>Include beta releases when checking for updates</source> - <translation type="unfinished"/> + <translation>Termasuk rilis beta saat memeriksa pembaruan</translation> </message> <message> <source>Button style:</source> - <translation type="unfinished"/> + <translation>Gaya tombol:</translation> </message> <message> <source>Language:</source> - <translation type="unfinished"/> + <translation>Bahasa:</translation> </message> <message> <source>(restart program to activate)</source> - <translation type="unfinished"/> + <translation>(mulai ulang program untuk mengaktifkan)</translation> </message> <message> <source>Minimize window after unlocking database</source> - <translation type="unfinished"/> + <translation>Minimalkan jendela setelah membuka basis data</translation> </message> <message> <source>Minimize when opening a URL</source> - <translation type="unfinished"/> + <translation>Minimalkan saat membuka URL</translation> </message> <message> <source>Hide window when copying to clipboard</source> - <translation type="unfinished"/> + <translation>Sembunyikan jendela saat menyalin ke papan klip</translation> </message> <message> <source>Minimize</source> - <translation type="unfinished"/> + <translation>Minimalkan</translation> </message> <message> <source>Drop to background</source> - <translation type="unfinished"/> + <translation>Beralih ke latar belakang</translation> </message> <message> <source>Favicon download timeout:</source> - <translation type="unfinished"/> + <translation>Waktu habis mengunduh favicon:</translation> </message> <message> <source>Website icon download timeout in seconds</source> - <translation type="unfinished"/> + <translation>Waktu habis mengunduh ikon situs web dalam detik</translation> </message> <message> <source> sec</source> @@ -290,15 +290,15 @@ </message> <message> <source>Toolbar button style</source> - <translation type="unfinished"/> + <translation>Gaya tombol bilah perkakas</translation> </message> <message> <source>Use monospaced font for Notes</source> - <translation type="unfinished"/> + <translation>Gunakan fon monospace untuk Catatan</translation> </message> <message> <source>Language selection</source> - <translation type="unfinished"/> + <translation>Pemilihan bahasa</translation> </message> <message> <source>Reset Settings to Default</source> @@ -306,15 +306,15 @@ </message> <message> <source>Global auto-type shortcut</source> - <translation type="unfinished"/> + <translation>Pintasan ketik-otomatis global</translation> </message> <message> <source>Auto-type character typing delay milliseconds</source> - <translation type="unfinished"/> + <translation>Tundaan pengetikan karakter ketik-otomatis dalam milidetik</translation> </message> <message> <source>Auto-type start delay milliseconds</source> - <translation type="unfinished"/> + <translation>Tundaan mulai ketik-otomatis dalam milidetik</translation> </message> </context> <context> @@ -390,15 +390,15 @@ </message> <message> <source>Use DuckDuckGo service to download website icons</source> - <translation type="unfinished"/> + <translation>Gunakan layanan DuckDuckGo untuk mengunduh ikon situs web</translation> </message> <message> <source>Clipboard clear seconds</source> - <translation type="unfinished"/> + <translation>Waktu menghapus papan klip (detik)</translation> </message> <message> <source>Touch ID inactivity reset</source> - <translation type="unfinished"/> + <translation>Atur ulang Touch ID setelah tidak aktif</translation> </message> <message> <source>Database lock timeout seconds</source> @@ -411,7 +411,7 @@ </message> <message> <source>Clear search query after</source> - <translation type="unfinished"/> + <translation>Hapus kueri pencarian setelah</translation> </message> </context> <context> @@ -446,11 +446,11 @@ </message> <message> <source>Permission Required</source> - <translation type="unfinished"/> + <translation>Membutuhkan Izin</translation> </message> <message> <source>KeePassXC requires the Accessibility permission in order to perform entry level Auto-Type. If you already granted permission, you may have to restart KeePassXC.</source> - <translation type="unfinished"/> + <translation>KeePassXC membutuhkan izin Aksesibilitas untuk menjalankan Ketik-Otomatis entri. Jika anda sudah memberikan izin, anda perlu memulai ulang KeePassXC.</translation> </message> </context> <context> @@ -502,11 +502,11 @@ <name>AutoTypePlatformMac</name> <message> <source>Permission Required</source> - <translation type="unfinished"/> + <translation>Membutuhkan Izin</translation> </message> <message> <source>KeePassXC requires the Accessibility and Screen Recorder permission in order to perform global Auto-Type. Screen Recording is necessary to use the window title to find entries. If you already granted permission, you may have to restart KeePassXC.</source> - <translation type="unfinished"/> + <translation>KeePassXC membutuhkan izin Aksesibilitas dan Perekaman Layar untuk menjalankan Ketik-Otomatis secara global. Perekaman Layar dibutuhkan untuk mengakses judul jendela dari entri terkait. Jika anda sudah memberikan izin, anda perlu memulai ulang KeePassXC.</translation> </message> </context> <context> @@ -755,11 +755,11 @@ Silakan pilih basis data yang digunakan untuk menyimpan kredensial.</translation </message> <message> <source>Enable browser integration</source> - <translation type="unfinished"/> + <translation>Aktifkan integrasi peramban</translation> </message> <message> <source>Browsers installed as snaps are currently not supported.</source> - <translation type="unfinished"/> + <translation>Peramban yang dipasang sebagai snap saat ini tidak didukung.</translation> </message> <message> <source>All databases connected to the extension will return matching credentials.</source> @@ -767,7 +767,7 @@ Silakan pilih basis data yang digunakan untuk menyimpan kredensial.</translation </message> <message> <source>Don't display the popup suggesting migration of legacy KeePassHTTP settings.</source> - <translation type="unfinished"/> + <translation>Jangan pernah tampilkan popup yang menyarankan migrasi pengaturan KeePassHTTP versi lama.</translation> </message> <message> <source>&Do not prompt for KeePassHTTP settings migration.</source> @@ -775,11 +775,11 @@ Silakan pilih basis data yang digunakan untuk menyimpan kredensial.</translation </message> <message> <source>Custom proxy location field</source> - <translation type="unfinished"/> + <translation>Ruas lokasi proksi khusus</translation> </message> <message> <source>Browser for custom proxy file</source> - <translation type="unfinished"/> + <translation>Peramban untuk berkas proksi khusus</translation> </message> <message> <source><b>Warning</b>, the keepassxc-proxy application was not found!<br />Please check the KeePassXC installation directory or confirm the custom path in advanced options.<br />Browser integration WILL NOT WORK without the proxy application.<br />Expected Path: %1</source> @@ -985,23 +985,24 @@ chrome-laptop.</source> <message> <source>CSV import: writer has errors: %1</source> - <translation type="unfinished"/> + <translation>Impor CSV: galat penulis: +%1</translation> </message> <message> <source>Text qualification</source> - <translation type="unfinished"/> + <translation>Kualifikasi teks</translation> </message> <message> <source>Field separation</source> - <translation type="unfinished"/> + <translation>Pemisahan ruas</translation> </message> <message> <source>Number of header lines to discard</source> - <translation type="unfinished"/> + <translation>Jumlah baris tajuk untuk dibuang</translation> </message> <message> <source>CSV import preview</source> - <translation type="unfinished"/> + <translation>Pratinjau impor CSV</translation> </message> </context> <context> @@ -1054,19 +1055,20 @@ chrome-laptop.</source> <message> <source>%1 Backup database located at %2</source> - <translation type="unfinished"/> + <translation>%1 +Lokasi cadangan basis data ada di %2</translation> </message> <message> <source>Could not save, database does not point to a valid file.</source> - <translation type="unfinished"/> + <translation>Tidak bisa menyimpan, basis data tidak merujuk ke berkas yang valid.</translation> </message> <message> <source>Could not save, database file is read-only.</source> - <translation type="unfinished"/> + <translation>Tidak bisa menyimpan, basis data memiliki atribut baca-saja.</translation> </message> <message> <source>Database file has unmerged changes.</source> - <translation type="unfinished"/> + <translation>Berkas basis data memiliki perubahan yang belum digabung.</translation> </message> <message> <source>Recycle Bin</source> @@ -1122,7 +1124,7 @@ Harap pertimbangkan membuat berkas kunci baru.</translation> </message> <message> <source>Failed to open key file: %1</source> - <translation type="unfinished"/> + <translation>Gagal untuk membuka berkas kunci: %1</translation> </message> <message> <source>Select slot...</source> @@ -1130,15 +1132,15 @@ Harap pertimbangkan membuat berkas kunci baru.</translation> </message> <message> <source>Unlock KeePassXC Database</source> - <translation type="unfinished"/> + <translation>Buka Kunci Basis Data KeePassXC</translation> </message> <message> <source>Enter Password:</source> - <translation type="unfinished"/> + <translation>Masukkan Sandi:</translation> </message> <message> <source>Password field</source> - <translation type="unfinished"/> + <translation>Ruas sandi</translation> </message> <message> <source>Toggle password visibility</source> @@ -1146,15 +1148,15 @@ Harap pertimbangkan membuat berkas kunci baru.</translation> </message> <message> <source>Key file selection</source> - <translation type="unfinished"/> + <translation>Pemilihan berkas kunci</translation> </message> <message> <source>Hardware key slot selection</source> - <translation type="unfinished"/> + <translation>Pemilihan slot kunci perangkat keras</translation> </message> <message> <source>Browse for key file</source> - <translation type="unfinished"/> + <translation>Temukan berkas kunci</translation> </message> <message> <source>Browse...</source> @@ -1162,19 +1164,19 @@ Harap pertimbangkan membuat berkas kunci baru.</translation> </message> <message> <source>Refresh hardware tokens</source> - <translation type="unfinished"/> + <translation>Segarkan token perangkat keras</translation> </message> <message> <source>Hardware Key:</source> - <translation type="unfinished"/> + <translation>Kunci Perangkat Keras:</translation> </message> <message> <source>Hardware key help</source> - <translation type="unfinished"/> + <translation>Bantuan kunci perangkat keras</translation> </message> <message> <source>TouchID for Quick Unlock</source> - <translation type="unfinished"/> + <translation>TouchID untuk Buka Cepat</translation> </message> <message> <source>Clear</source> @@ -1182,11 +1184,11 @@ Harap pertimbangkan membuat berkas kunci baru.</translation> </message> <message> <source>Clear Key File</source> - <translation type="unfinished"/> + <translation>Kosongkan Berkas Kunci</translation> </message> <message> <source>Unlock failed and no password given</source> - <translation type="unfinished"/> + <translation>Gagal membuka dan sandi tidak tersedia</translation> </message> <message> <source>Unlocking the database failed and you did not enter a password. @@ -1197,11 +1199,11 @@ To prevent this error from appearing, you must go to "Database Settings / S </message> <message> <source>Retry with empty password</source> - <translation type="unfinished"/> + <translation>Ulangi dengan sandi kosong</translation> </message> <message> <source>Enter Additional Credentials (if any):</source> - <translation type="unfinished"/> + <translation>Masukkan Kredensial Tambahan (jika ada):</translation> </message> <message> <source><p>You can use a hardware security key such as a <strong>YubiKey</strong> or <strong>OnlyKey</strong> with slots configured for HMAC-SHA1.</p> @@ -1214,24 +1216,25 @@ To prevent this error from appearing, you must go to "Database Settings / S </message> <message> <source>Key file help</source> - <translation type="unfinished"/> + <translation>Bantuan berkas kunci</translation> </message> <message> <source>?</source> - <translation type="unfinished"/> + <translation>?</translation> </message> <message> <source>Select key file...</source> - <translation type="unfinished"/> + <translation>Pilih berkas kunci...</translation> </message> <message> <source>Cannot use database file as key file</source> - <translation type="unfinished"/> + <translation>Tidak bisa menggunakan berkas basis data sebagai berkas kunci</translation> </message> <message> <source>You cannot use your database file as a key file. If you do not have a key file, please leave the field empty.</source> - <translation type="unfinished"/> + <translation>Anda tidak bisa menggunakan berkas basis data anda sebagai berkas kunci, +Jika anda tidak memiliki berkas kunci, biarkan ruas tetap kosong.</translation> </message> </context> <context> @@ -1388,11 +1391,11 @@ Hal ini diperlukan untuk mempertahankan kompatibilitas dengan plugin peramban.</ </message> <message> <source>Stored browser keys</source> - <translation type="unfinished"/> + <translation>Simpan kunci peramban</translation> </message> <message> <source>Remove selected key</source> - <translation type="unfinished"/> + <translation>Buang kunci yang dipilih</translation> </message> </context> <context> @@ -1538,23 +1541,23 @@ Jika anda tetap mempertahankan jumlah serendah ini, basis data anda mungkin akan </message> <message> <source>Change existing decryption time</source> - <translation type="unfinished"/> + <translation>Ubah waktu dekripsi yang ada</translation> </message> <message> <source>Decryption time in seconds</source> - <translation type="unfinished"/> + <translation>Waktu dekripsi dalam detik</translation> </message> <message> <source>Database format</source> - <translation type="unfinished"/> + <translation>Format basis data</translation> </message> <message> <source>Encryption algorithm</source> - <translation type="unfinished"/> + <translation>Algoritma enkripsi</translation> </message> <message> <source>Key derivation function</source> - <translation type="unfinished"/> + <translation>Fungi derivasi kunci</translation> </message> <message> <source>Transform rounds</source> @@ -1562,18 +1565,18 @@ Jika anda tetap mempertahankan jumlah serendah ini, basis data anda mungkin akan </message> <message> <source>Memory usage</source> - <translation type="unfinished"/> + <translation>Penggunaan memori</translation> </message> <message> <source>Parallelism</source> - <translation type="unfinished"/> + <translation>Paralelisme</translation> </message> </context> <context> <name>DatabaseSettingsWidgetFdoSecrets</name> <message> <source>Exposed Entries</source> - <translation type="unfinished"/> + <translation>Entri Yang Diekspos</translation> </message> <message> <source>Don't e&xpose this database</source> @@ -1636,36 +1639,37 @@ Jika anda tetap mempertahankan jumlah serendah ini, basis data anda mungkin akan </message> <message> <source>Database name field</source> - <translation type="unfinished"/> + <translation>Ruas nama basis data</translation> </message> <message> <source>Database description field</source> - <translation type="unfinished"/> + <translation>Ruas deskripsi basis data</translation> </message> <message> <source>Default username field</source> - <translation type="unfinished"/> + <translation>Ruas nama pengguna baku</translation> </message> <message> <source>Maximum number of history items per entry</source> - <translation type="unfinished"/> + <translation>Jumlah maksimum item riwayat per entri</translation> </message> <message> <source>Maximum size of history per entry</source> - <translation type="unfinished"/> + <translation>Ukuran maksimum riwayat per entri</translation> </message> <message> <source>Delete Recycle Bin</source> - <translation type="unfinished"/> + <translation>Hapus Keranjang Sampah</translation> </message> <message> <source>Do you want to delete the current recycle bin and all its contents? This action is not reversible.</source> - <translation type="unfinished"/> + <translation>Apakah anda yakin ingin menghapus keranjang sampah dan semua isinya? +Tidakan ini tidak bisa diurungkan.</translation> </message> <message> <source> (old)</source> - <translation type="unfinished"/> + <translation>(lama)</translation> </message> </context> <context> @@ -1688,7 +1692,7 @@ This action is not reversible.</source> </message> <message> <source>Last Signer</source> - <translation type="unfinished"/> + <translation>Penanda Tangan Terakhir</translation> </message> <message> <source>Certificates</source> @@ -1736,7 +1740,7 @@ Apakah anda tetap ingin melanjutkan tanpa mengatur sandi?</translation> </message> <message> <source>Continue without password</source> - <translation type="unfinished"/> + <translation>Lanjutkan tanpa sandi</translation> </message> </context> <context> @@ -1751,18 +1755,18 @@ Apakah anda tetap ingin melanjutkan tanpa mengatur sandi?</translation> </message> <message> <source>Database name field</source> - <translation type="unfinished"/> + <translation>Ruas nama basis data</translation> </message> <message> <source>Database description field</source> - <translation type="unfinished"/> + <translation>Ruas deskripsi basis data</translation> </message> </context> <context> <name>DatabaseSettingsWidgetStatistics</name> <message> <source>Statistics</source> - <translation type="unfinished"/> + <translation>Statistik</translation> </message> <message> <source>Hover over lines with error icons for further information.</source> @@ -1950,27 +1954,27 @@ Masalah ini jelas sebuah bug, silakan laporkan ke pengembang.</translation> </message> <message> <source>Failed to open %1. It either does not exist or is not accessible.</source> - <translation type="unfinished"/> + <translation>Gagal untuk membuka %1. Mungkin tidak ada atau tidak bisa diakses.</translation> </message> <message> <source>Export database to HTML file</source> - <translation type="unfinished"/> + <translation>Ekspor basis data ke berkas HTML</translation> </message> <message> <source>HTML file</source> - <translation type="unfinished"/> + <translation>Berkas HTML</translation> </message> <message> <source>Writing the HTML file failed.</source> - <translation type="unfinished"/> + <translation>Gagal menyimpan ke berkas HTML.</translation> </message> <message> <source>Export Confirmation</source> - <translation type="unfinished"/> + <translation>Konfirmasi Ekspor</translation> </message> <message> <source>You are about to export your database to an unencrypted file. This will leave your passwords and sensitive information vulnerable! Are you sure you want to continue?</source> - <translation type="unfinished"/> + <translation>Anda akan mengekspor basis data anda ke berkas tanpa enkripsi. Ini akan membuat sandi dan informasi sensitif lainnya menjadi sangat rentan. Apakah anda yakin ingin melanjutkan?</translation> </message> </context> <context> @@ -2151,7 +2155,7 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>This database is opened in read-only mode. Autosave is disabled.</source> - <translation type="unfinished"/> + <translation>Basis data ini dibuka dalam mode baca-saja. Simpan otomatis dinonaktifkan.</translation> </message> </context> <context> @@ -2278,11 +2282,11 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source><empty URL></source> - <translation type="unfinished"/> + <translation><empty URL></translation> </message> <message> <source>Are you sure you want to remove this URL?</source> - <translation type="unfinished"/> + <translation>Apakah anda yakin ingin membuang URL ini?</translation> </message> </context> <context> @@ -2325,39 +2329,39 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Attribute selection</source> - <translation type="unfinished"/> + <translation>Pemilihan atribut</translation> </message> <message> <source>Attribute value</source> - <translation type="unfinished"/> + <translation>Nilai atribut</translation> </message> <message> <source>Add a new attribute</source> - <translation type="unfinished"/> + <translation>Tambah atribut baru</translation> </message> <message> <source>Remove selected attribute</source> - <translation type="unfinished"/> + <translation>Buang atribut yang dipilih</translation> </message> <message> <source>Edit attribute name</source> - <translation type="unfinished"/> + <translation>Sunting nama atribut</translation> </message> <message> <source>Toggle attribute protection</source> - <translation type="unfinished"/> + <translation>Aktif/Nonaktifkan proteksi atribut</translation> </message> <message> <source>Show a protected attribute</source> - <translation type="unfinished"/> + <translation>Tampilkan atribut yang dilindungi</translation> </message> <message> <source>Foreground color selection</source> - <translation type="unfinished"/> + <translation>Pemilihan warna latar depan</translation> </message> <message> <source>Background color selection</source> - <translation type="unfinished"/> + <translation>Pemilihan warna latar belakang</translation> </message> </context> <context> @@ -2396,46 +2400,46 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Custom Auto-Type sequence</source> - <translation type="unfinished"/> + <translation>Urutan Ketik-Otomatis khusus</translation> </message> <message> <source>Open Auto-Type help webpage</source> - <translation type="unfinished"/> + <translation>Buka laman bantuan Ketik-Otomatis</translation> </message> <message> <source>Existing window associations</source> - <translation type="unfinished"/> + <translation>Asosiasi jendela yang ada</translation> </message> <message> <source>Add new window association</source> - <translation type="unfinished"/> + <translation>Tambah asosiasi jendela baru</translation> </message> <message> <source>Remove selected window association</source> - <translation type="unfinished"/> + <translation>Buang asosiasi jendela yang dipilih</translation> </message> <message> <source>You can use an asterisk (*) to match everything</source> - <translation type="unfinished"/> + <translation>Anda bisa menggunakan asterik (*) untuk mencocokkan semuanya</translation> </message> <message> <source>Set the window association title</source> - <translation type="unfinished"/> + <translation>Atur judul asosiasi jendela</translation> </message> <message> <source>You can use an asterisk to match everything</source> - <translation type="unfinished"/> + <translation>Anda bisa menggunakan asterik untuk mencocokkan semuanya</translation> </message> <message> <source>Custom Auto-Type sequence for this window</source> - <translation type="unfinished"/> + <translation>Urutan Ketik-Otomatis khusus untuk jendela ini</translation> </message> </context> <context> <name>EditEntryWidgetBrowser</name> <message> <source>These settings affect to the entry's behaviour with the browser extension.</source> - <translation type="unfinished"/> + <translation>Pengaturan ini mempengaruhi perilaku entri dengan ekstensi peramban.</translation> </message> <message> <source>General</source> @@ -2443,15 +2447,15 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Skip Auto-Submit for this entry</source> - <translation type="unfinished"/> + <translation>Lewati Kirim-Otomatis untuk entri ini</translation> </message> <message> <source>Hide this entry from the browser extension</source> - <translation type="unfinished"/> + <translation>Sembunyikan entri ini dari ekstensi peramban</translation> </message> <message> <source>Additional URL's</source> - <translation type="unfinished"/> + <translation>URL tambahan</translation> </message> <message> <source>Add</source> @@ -2486,7 +2490,7 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Entry history selection</source> - <translation type="unfinished"/> + <translation>Pemilihan riwayat entri</translation> </message> <message> <source>Show entry at selected history state</source> @@ -2502,7 +2506,7 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Delete all history</source> - <translation type="unfinished"/> + <translation>Hapus semua riwayat</translation> </message> </context> <context> @@ -2545,15 +2549,15 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Url field</source> - <translation type="unfinished"/> + <translation>Ruas url</translation> </message> <message> <source>Download favicon for URL</source> - <translation type="unfinished"/> + <translation>Untuk favicon untuk URL</translation> </message> <message> <source>Repeat password field</source> - <translation type="unfinished"/> + <translation>Ruas pengulangan sandi</translation> </message> <message> <source>Toggle password generator</source> @@ -2561,7 +2565,7 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Password field</source> - <translation type="unfinished"/> + <translation>Ruas sandi</translation> </message> <message> <source>Toggle password visibility</source> @@ -2569,11 +2573,11 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Toggle notes visible</source> - <translation type="unfinished"/> + <translation>Aktif/Nonaktifkan visibilitas cacatan</translation> </message> <message> <source>Expiration field</source> - <translation type="unfinished"/> + <translation>Ruas kedaluwarsa</translation> </message> <message> <source>Expiration Presets</source> @@ -2585,26 +2589,26 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Notes field</source> - <translation type="unfinished"/> + <translation>Ruas catatan</translation> </message> <message> <source>Title field</source> - <translation type="unfinished"/> + <translation>Ruas judul</translation> </message> <message> <source>Username field</source> - <translation type="unfinished"/> + <translation>Ruas nama pengguna</translation> </message> <message> <source>Toggle expiration</source> - <translation type="unfinished"/> + <translation>Aktif/Nonaktifkan kedaluwarsa</translation> </message> </context> <context> <name>EditEntryWidgetSSHAgent</name> <message> <source>Form</source> - <translation type="unfinished"/> + <translation>Formulir</translation> </message> <message> <source>Remove key from agent after</source> @@ -2681,15 +2685,15 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Browser for key file</source> - <translation type="unfinished"/> + <translation>Peramban untuk berkas kunci</translation> </message> <message> <source>External key file</source> - <translation type="unfinished"/> + <translation>Berkas kunci eksternal</translation> </message> <message> <source>Select attachment file</source> - <translation type="unfinished"/> + <translation>Pilih berkas lampiran</translation> </message> </context> <context> @@ -2735,7 +2739,7 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> <name>EditGroupWidgetKeeShare</name> <message> <source>Form</source> - <translation type="unfinished"/> + <translation>Formulir</translation> </message> <message> <source>Type:</source> @@ -2759,11 +2763,11 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>KeeShare unsigned container</source> - <translation type="unfinished"/> + <translation>Kontainer KeeShare tak bertanda tangan</translation> </message> <message> <source>KeeShare signed container</source> - <translation type="unfinished"/> + <translation>Kontainer KeeShare bertanda tangan</translation> </message> <message> <source>Select import source</source> @@ -2791,20 +2795,21 @@ Nonaktifkan penyimpanan aman dan coba lagi?</translation> </message> <message> <source>Synchronize</source> - <translation type="unfinished"/> + <translation>Sinkronkan</translation> </message> <message> <source>Your KeePassXC version does not support sharing this container type. Supported extensions are: %1.</source> - <translation type="unfinished"/> + <translation>Versi KeePassXC anda tidak mendukung fitur berbagi untuk tipe kontainer ini. +Ekstensi yang didukung adalah: %1.</translation> </message> <message> <source>%1 is already being exported by this database.</source> - <translation type="unfinished"/> + <translation>%1 sudah diekspor oleh basis data ini.</translation> </message> <message> <source>%1 is already being imported by this database.</source> - <translation type="unfinished"/> + <translation>%1 telah diimpor oleh basis data ini.</translation> </message> <message> <source>%1 is being imported and exported by different groups in this database.</source> @@ -2817,19 +2822,19 @@ Supported extensions are: %1.</source> </message> <message> <source>Database export is currently disabled by application settings.</source> - <translation type="unfinished"/> + <translation>Ekspor basis data saat ini dinonaktifkan oleh pengaturan aplikasi.</translation> </message> <message> <source>Database import is currently disabled by application settings.</source> - <translation type="unfinished"/> + <translation>Impor basis data saat ini dinonaktifkan oleh pengaturan aplikasi.</translation> </message> <message> <source>Sharing mode field</source> - <translation type="unfinished"/> + <translation>Ruas mode berbagi</translation> </message> <message> <source>Path to share file field</source> - <translation type="unfinished"/> + <translation>Ruas jalur ke berkas yang dibagikan</translation> </message> <message> <source>Browser for share file</source> @@ -2837,7 +2842,7 @@ Supported extensions are: %1.</source> </message> <message> <source>Password field</source> - <translation type="unfinished"/> + <translation>Ruas sandi</translation> </message> <message> <source>Toggle password visibility</source> @@ -2849,7 +2854,7 @@ Supported extensions are: %1.</source> </message> <message> <source>Clear fields</source> - <translation type="unfinished"/> + <translation>Kosongkan ruas</translation> </message> </context> <context> @@ -2884,31 +2889,31 @@ Supported extensions are: %1.</source> </message> <message> <source>Name field</source> - <translation type="unfinished"/> + <translation>Ruas nama</translation> </message> <message> <source>Notes field</source> - <translation type="unfinished"/> + <translation>Ruas catatan</translation> </message> <message> <source>Toggle expiration</source> - <translation type="unfinished"/> + <translation>Aktif/Nonaktifkan kedaluwarsa</translation> </message> <message> <source>Auto-Type toggle for this and sub groups</source> - <translation type="unfinished"/> + <translation>Aktif/Nonaktifkan Ketik-Otomatis untuk ini dan sub grup</translation> </message> <message> <source>Expiration field</source> - <translation type="unfinished"/> + <translation>Ruas kedaluwarsa</translation> </message> <message> <source>Search toggle for this and sub groups</source> - <translation type="unfinished"/> + <translation>Aktif/Nonaktifkan pencarian untuk ini dan sub grup</translation> </message> <message> <source>Default auto-type sequence field</source> - <translation type="unfinished"/> + <translation>Ruas urutan ketik-otomatis baku</translation> </message> </context> <context> @@ -2975,15 +2980,15 @@ Supported extensions are: %1.</source> </message> <message> <source>You can enable the DuckDuckGo website icon service under Tools -> Settings -> Security</source> - <translation type="unfinished"/> + <translation>Anda bisa mengaktifkan layanan ikon situs web oleh DuckDuckGo di Perkakas > Pengaturan > Keamanan</translation> </message> <message> <source>Download favicon for URL</source> - <translation type="unfinished"/> + <translation>Untuk favicon untuk URL</translation> </message> <message> <source>Apply selected icon to subgroups and entries</source> - <translation type="unfinished"/> + <translation>Terapkan ikon yang dipilih ke subgrup dan entri</translation> </message> <message> <source>Apply icon &to ...</source> @@ -3068,15 +3073,15 @@ Ini mungkin akan menyebabkan plugin terkait tidak berfungsi.</translation> </message> <message> <source>Unique ID</source> - <translation type="unfinished"/> + <translation>ID Unik</translation> </message> <message> <source>Plugin data</source> - <translation type="unfinished"/> + <translation>Data pengaya</translation> </message> <message> <source>Remove selected plugin data</source> - <translation type="unfinished"/> + <translation>Buang data pengaya yang dipilih</translation> </message> </context> <context> @@ -3101,7 +3106,7 @@ Ini mungkin akan menyebabkan plugin terkait tidak berfungsi.</translation> <name>EntryAttachmentsWidget</name> <message> <source>Form</source> - <translation type="unfinished"/> + <translation>Formulir</translation> </message> <message> <source>Add</source> @@ -3178,19 +3183,19 @@ Ini mungkin akan menyebabkan plugin terkait tidak berfungsi.</translation> </message> <message> <source>Add new attachment</source> - <translation type="unfinished"/> + <translation>Tambah lampiran baru</translation> </message> <message> <source>Remove selected attachment</source> - <translation type="unfinished"/> + <translation>Buang lampiran yang dipilih</translation> </message> <message> <source>Open selected attachment</source> - <translation type="unfinished"/> + <translation>Buka lampiran yang dipilih</translation> </message> <message> <source>Save selected attachment to disk</source> - <translation type="unfinished"/> + <translation>Simpan lampiran yang dipilih ke diska</translation> </message> </context> <context> @@ -3372,7 +3377,7 @@ Ini mungkin akan menyebabkan plugin terkait tidak berfungsi.</translation> </message> <message> <source>Display current TOTP value</source> - <translation type="unfinished"/> + <translation>Tampilkan nilai TOTP saat ini</translation> </message> <message> <source>Advanced</source> @@ -3414,7 +3419,7 @@ Ini mungkin akan menyebabkan plugin terkait tidak berfungsi.</translation> <name>FdoSecrets::Item</name> <message> <source>Entry "%1" from database "%2" was used by %3</source> - <translation type="unfinished"/> + <translation>Entri "%1" dari basis data "%2" telah digunakan oleh %3</translation> </message> </context> <context> @@ -3459,7 +3464,7 @@ Ini mungkin akan menyebabkan plugin terkait tidak berfungsi.</translation> <name>IconDownloaderDialog</name> <message> <source>Download Favicons</source> - <translation type="unfinished"/> + <translation>Unduh Favicon</translation> </message> <message> <source>Cancel</source> @@ -3484,11 +3489,11 @@ You can enable the DuckDuckGo website icon service in the security section of th </message> <message> <source>Please wait, processing entry list...</source> - <translation type="unfinished"/> + <translation>Silakan tunggu, sedang memproses daftar entri...</translation> </message> <message> <source>Downloading...</source> - <translation type="unfinished"/> + <translation>Mengunduh...</translation> </message> <message> <source>Ok</source> @@ -3496,15 +3501,15 @@ You can enable the DuckDuckGo website icon service in the security section of th </message> <message> <source>Already Exists</source> - <translation type="unfinished"/> + <translation>Sudah Ada</translation> </message> <message> <source>Download Failed</source> - <translation type="unfinished"/> + <translation>Gagal Mengunduh</translation> </message> <message> <source>Downloading favicons (%1/%2)...</source> - <translation type="unfinished"/> + <translation>Mengunduh favicon (%1/%2)...</translation> </message> </context> <context> @@ -3534,7 +3539,7 @@ You can enable the DuckDuckGo website icon service in the security section of th </message> <message> <source>Header doesn't match hash</source> - <translation type="unfinished"/> + <translation>Header tidak cocok dengan hash</translation> </message> <message> <source>Invalid header id size</source> @@ -3551,7 +3556,8 @@ You can enable the DuckDuckGo website icon service in the security section of th <message> <source>Invalid credentials were provided, please try again. If this reoccurs, then your database file may be corrupt.</source> - <translation type="unfinished"/> + <translation>Kredensial yang diberikan tidak valid, silakan coba lagi. +Jika terus berulang, maka basis data anda mungkin rusak.</translation> </message> </context> <context> @@ -3686,7 +3692,8 @@ If this reoccurs, then your database file may be corrupt.</source> <message> <source>Invalid credentials were provided, please try again. If this reoccurs, then your database file may be corrupt.</source> - <translation type="unfinished"/> + <translation>Kredensial yang diberikan tidak valid, silakan coba lagi. +Jika terus berulang, maka basis data anda mungkin rusak.</translation> </message> <message> <source>(HMAC mismatch)</source> @@ -3919,7 +3926,7 @@ Baris %2, kolom %3</translation> </message> <message> <source>Import KeePass1 Database</source> - <translation type="unfinished"/> + <translation>Impor Basis Data KeePass1</translation> </message> </context> <context> @@ -4076,7 +4083,8 @@ Baris %2, kolom %3</translation> <message> <source>Invalid credentials were provided, please try again. If this reoccurs, then your database file may be corrupt.</source> - <translation type="unfinished"/> + <translation>Kredensial yang diberikan tidak valid, silakan coba lagi. +Jika terus berulang, maka basis data anda mungkin rusak.</translation> </message> </context> <context> @@ -4095,19 +4103,19 @@ If this reoccurs, then your database file may be corrupt.</source> </message> <message> <source>Exported to %1</source> - <translation type="unfinished"/> + <translation>Diekspor ke %1</translation> </message> <message> <source>Synchronized with %1</source> - <translation type="unfinished"/> + <translation>Disinkronkan dengan %1</translation> </message> <message> <source>Import is disabled in settings</source> - <translation type="unfinished"/> + <translation>Impor dinonaktifkan di dalam pengaturan</translation> </message> <message> <source>Export is disabled in settings</source> - <translation type="unfinished"/> + <translation>Ekspor dinonaktifkan di dalam pengaturan</translation> </message> <message> <source>Inactive share</source> @@ -4115,15 +4123,15 @@ If this reoccurs, then your database file may be corrupt.</source> </message> <message> <source>Imported from</source> - <translation type="unfinished"/> + <translation>Diimpor ke</translation> </message> <message> <source>Exported to</source> - <translation type="unfinished"/> + <translation>Diekspor dari</translation> </message> <message> <source>Synchronized with</source> - <translation type="unfinished"/> + <translation>Disinkronkan dengan</translation> </message> </context> <context> @@ -4225,11 +4233,11 @@ Pesan: %2</translation> </message> <message> <source>Key file selection</source> - <translation type="unfinished"/> + <translation>Pemilihan berkas kunci</translation> </message> <message> <source>Browse for key file</source> - <translation type="unfinished"/> + <translation>Temukan berkas kunci</translation> </message> <message> <source>Browse...</source> @@ -4237,7 +4245,7 @@ Pesan: %2</translation> </message> <message> <source>Generate a new key file</source> - <translation type="unfinished"/> + <translation>Buat berkas kunci baru</translation> </message> <message> <source>Note: Do not use a file that may change as that will prevent you from unlocking your database!</source> @@ -4245,7 +4253,7 @@ Pesan: %2</translation> </message> <message> <source>Invalid Key File</source> - <translation type="unfinished"/> + <translation>Berkas Kunci Tidak Valid</translation> </message> <message> <source>You cannot use the current database as its own keyfile. Please choose a different file or generate a new key file.</source> @@ -4253,7 +4261,7 @@ Pesan: %2</translation> </message> <message> <source>Suspicious Key File</source> - <translation type="unfinished"/> + <translation>Berkas Kunci Mencurigakan</translation> </message> <message> <source>The chosen key file looks like a password database file. A key file must be a static file that never changes or you will lose access to your database forever. @@ -4553,7 +4561,7 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>&Export</source> - <translation type="unfinished"/> + <translation>&Ekspor</translation> </message> <message> <source>&Check for Updates...</source> @@ -4565,15 +4573,15 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>Sort &A-Z</source> - <translation type="unfinished"/> + <translation>Urutkan &A-Z</translation> </message> <message> <source>Sort &Z-A</source> - <translation type="unfinished"/> + <translation>Urutkan &Z-A</translation> </message> <message> <source>&Password Generator</source> - <translation type="unfinished"/> + <translation>&Pembuat Sandi</translation> </message> <message> <source>Download favicon</source> @@ -4589,15 +4597,15 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>Import a 1Password Vault</source> - <translation type="unfinished"/> + <translation>Impor Brankas 1Password</translation> </message> <message> <source>&Getting Started</source> - <translation type="unfinished"/> + <translation>&Memulai</translation> </message> <message> <source>Open Getting Started Guide PDF</source> - <translation type="unfinished"/> + <translation>Buka PDF Panduan Memulai</translation> </message> <message> <source>&Online Help...</source> @@ -4605,19 +4613,19 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>Go to online documentation (opens browser)</source> - <translation type="unfinished"/> + <translation>Kunjungi dokumentasi daring (membuka peramban)</translation> </message> <message> <source>&User Guide</source> - <translation type="unfinished"/> + <translation>Pand&uan Pengguna</translation> </message> <message> <source>Open User Guide PDF</source> - <translation type="unfinished"/> + <translation>Buka PDF Panduan Pengguna</translation> </message> <message> <source>&Keyboard Shortcuts</source> - <translation type="unfinished"/> + <translation>Pintasan &Kibor</translation> </message> </context> <context> @@ -4924,7 +4932,7 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa <name>PasswordEdit</name> <message> <source>Passwords do not match</source> - <translation type="unfinished"/> + <translation>Sandi tidak sama</translation> </message> <message> <source>Passwords match so far</source> @@ -4959,7 +4967,7 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>Password field</source> - <translation type="unfinished"/> + <translation>Ruas sandi</translation> </message> <message> <source>Toggle password visibility</source> @@ -4967,7 +4975,7 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>Repeat password field</source> - <translation type="unfinished"/> + <translation>Ruas pengulangan sandi</translation> </message> <message> <source>Toggle password generator</source> @@ -5175,39 +5183,39 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>Generated password</source> - <translation type="unfinished"/> + <translation>Sandi yang dibuat</translation> </message> <message> <source>Upper-case letters</source> - <translation type="unfinished"/> + <translation>Huruf besar</translation> </message> <message> <source>Lower-case letters</source> - <translation type="unfinished"/> + <translation>Huruf kecil</translation> </message> <message> <source>Special characters</source> - <translation type="unfinished"/> + <translation>Karakter spesial</translation> </message> <message> <source>Math Symbols</source> - <translation type="unfinished"/> + <translation>Simbol Matematika</translation> </message> <message> <source>Dashes and Slashes</source> - <translation type="unfinished"/> + <translation>Garis Tengah dan Miring</translation> </message> <message> <source>Excluded characters</source> - <translation type="unfinished"/> + <translation>Karakter yang dikecualikan</translation> </message> <message> <source>Hex Passwords</source> - <translation type="unfinished"/> + <translation>Sandi Hex</translation> </message> <message> <source>Password length</source> - <translation type="unfinished"/> + <translation>Panjang sandi</translation> </message> <message> <source>Word Case:</source> @@ -5215,7 +5223,7 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>Regenerate password</source> - <translation type="unfinished"/> + <translation>Buat ulang sandi</translation> </message> <message> <source>Copy password</source> @@ -5227,11 +5235,11 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>lower case</source> - <translation type="unfinished"/> + <translation>huruf kecil</translation> </message> <message> <source>UPPER CASE</source> - <translation type="unfinished"/> + <translation>HURUF BESAR</translation> </message> <message> <source>Title Case</source> @@ -5250,14 +5258,14 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>Statistics</source> - <translation type="unfinished"/> + <translation>Statistik</translation> </message> </context> <context> <name>QMessageBox</name> <message> <source>Overwrite</source> - <translation type="unfinished"/> + <translation>Timpa</translation> </message> <message> <source>Delete</source> @@ -5289,7 +5297,7 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>Continue</source> - <translation type="unfinished"/> + <translation>Lanjutkan</translation> </message> </context> <context> @@ -5304,7 +5312,7 @@ Jangan kaget jika ada masalah dan bug, versi ini tidak ditujukan untuk penggunaa </message> <message> <source>Client public key not received</source> - <translation type="unfinished"/> + <translation>Kunci publik klien tidak diterima</translation> </message> <message> <source>Cannot decrypt message</source> @@ -5668,7 +5676,7 @@ Perintah yang tersedia: </message> <message> <source>Log10 %1</source> - <translation type="unfinished"/> + <translation>Log10 %1</translation> </message> <message> <source>Multi-word extra bits %1</source> @@ -5988,7 +5996,7 @@ Perintah yang tersedia: </message> <message> <source>Displays debugging information.</source> - <translation type="unfinished"/> + <translation>Tampilkan informasi pengawakutuan.</translation> </message> <message> <source>Deactivate password key for the database to merge from.</source> @@ -6495,7 +6503,7 @@ Kernel: %3 %4</translation> </message> <message> <source>File Name</source> - <translation type="unfinished"/> + <translation>Nama Berkas</translation> </message> <message> <source>Group</source> @@ -6503,7 +6511,7 @@ Kernel: %3 %4</translation> </message> <message> <source>Manage</source> - <translation type="unfinished"/> + <translation>Kelola</translation> </message> <message> <source>Authorization</source> @@ -6515,11 +6523,11 @@ Kernel: %3 %4</translation> </message> <message> <source>Application</source> - <translation type="unfinished"/> + <translation>Aplikasi</translation> </message> <message> <source>Disconnect</source> - <translation type="unfinished"/> + <translation>Putuskan koneksi</translation> </message> <message> <source>Database settings</source> @@ -6527,7 +6535,7 @@ Kernel: %3 %4</translation> </message> <message> <source>Edit database settings</source> - <translation type="unfinished"/> + <translation>Sunting pengaturan basisdata</translation> </message> <message> <source>Unlock database</source> @@ -6535,7 +6543,7 @@ Kernel: %3 %4</translation> </message> <message> <source>Unlock database to show more information</source> - <translation type="unfinished"/> + <translation>Buka kunci basisdata untuk menampilkan lebih banyak informasi</translation> </message> <message> <source>Lock database</source> @@ -6543,7 +6551,7 @@ Kernel: %3 %4</translation> </message> <message> <source>Unlock to show</source> - <translation type="unfinished"/> + <translation>Buka kunci untuk menampilkan</translation> </message> <message> <source>None</source> @@ -7105,11 +7113,11 @@ Example: JBSWY3DPEHPK3PXP</source> </message> <message> <source>Refresh hardware tokens</source> - <translation type="unfinished"/> + <translation>Segarkan token perangkat keras</translation> </message> <message> <source>Hardware key slot selection</source> - <translation type="unfinished"/> + <translation>Pemilihan slot kunci perangkat keras</translation> </message> </context> </TS> \ No newline at end of file diff --git a/share/translations/keepassx_lt.ts b/share/translations/keepassx_lt.ts index 6f22bd656..12359797d 100644 --- a/share/translations/keepassx_lt.ts +++ b/share/translations/keepassx_lt.ts @@ -97,7 +97,7 @@ </message> <message> <source>Reset Settings?</source> - <translation type="unfinished"/> + <translation>Atstatyti nustatymus?</translation> </message> <message> <source>Are you sure you want to reset all general and security settings to default?</source> @@ -249,7 +249,7 @@ </message> <message> <source>Language:</source> - <translation type="unfinished"/> + <translation>Kalba:</translation> </message> <message> <source>(restart program to activate)</source> diff --git a/share/translations/keepassx_nl_NL.ts b/share/translations/keepassx_nl_NL.ts index d7d03446a..c16c4a62b 100644 --- a/share/translations/keepassx_nl_NL.ts +++ b/share/translations/keepassx_nl_NL.ts @@ -865,7 +865,7 @@ Wil je deze groep aanmaken? This is necessary to maintain your current browser connections. Would you like to migrate your existing settings now?</source> <translation>De KeePassXC-Browser instellingen moeten worden verplaatst naar de instellingen-database. -Dit is nodig om de huidige browser verbindingen te behouden. +Dit is nodig om de huidige browserverbindingen te behouden. Wil je de bestaande instellingen nu migreren?</translation> </message> <message> @@ -6570,7 +6570,7 @@ Kernelversie: %3 %4</translation> <name>SettingsWidgetKeeShare</name> <message> <source>Active</source> - <translation>Actieve</translation> + <translation>Activering</translation> </message> <message> <source>Allow export</source> diff --git a/share/translations/keepassx_pt.ts b/share/translations/keepassx_pt.ts index d5b4b6b5d..d3af8ba09 100644 --- a/share/translations/keepassx_pt.ts +++ b/share/translations/keepassx_pt.ts @@ -225,7 +225,7 @@ </message> <message> <source>Remember previously used databases</source> - <translation type="unfinished"/> + <translation>Lembrar bases de dados usadas anteriormente</translation> </message> <message> <source>Load previously open databases on startup</source> @@ -249,7 +249,7 @@ </message> <message> <source>Language:</source> - <translation type="unfinished"/> + <translation>Idioma:</translation> </message> <message> <source>(restart program to activate)</source> @@ -269,7 +269,7 @@ </message> <message> <source>Minimize</source> - <translation type="unfinished"/> + <translation>Minimizar</translation> </message> <message> <source>Drop to background</source> @@ -298,7 +298,7 @@ </message> <message> <source>Language selection</source> - <translation type="unfinished"/> + <translation>Seleção de idioma</translation> </message> <message> <source>Reset Settings to Default</source> @@ -550,11 +550,11 @@ Selecione se deseja permitir o acesso.</translation> </message> <message> <source>Allow access</source> - <translation type="unfinished"/> + <translation>Permitir acesso</translation> </message> <message> <source>Deny access</source> - <translation type="unfinished"/> + <translation>Negar acesso</translation> </message> </context> <context> diff --git a/share/translations/keepassx_th.ts b/share/translations/keepassx_th.ts index 915852139..fc50c5d01 100644 --- a/share/translations/keepassx_th.ts +++ b/share/translations/keepassx_th.ts @@ -98,7 +98,7 @@ </message> <message> <source>Reset Settings?</source> - <translation type="unfinished"/> + <translation>ล้างการตั้งค่าหรือไม่?</translation> </message> <message> <source>Are you sure you want to reset all general and security settings to default?</source> @@ -230,7 +230,7 @@ </message> <message> <source>Load previously open databases on startup</source> - <translation type="unfinished"/> + <translation>เรียกใช้ฐานข้อมูลที่เปิดใช้ก่อนหน้าในตอนเริ่มโปรแกรม</translation> </message> <message> <source>Remember database key files and security dongles</source> @@ -246,7 +246,7 @@ </message> <message> <source>Button style:</source> - <translation type="unfinished"/> + <translation>สไตล์ปุ่ม:</translation> </message> <message> <source>Language:</source> @@ -266,7 +266,7 @@ </message> <message> <source>Hide window when copying to clipboard</source> - <translation type="unfinished"/> + <translation>ซ่อนหน้าต่างขณะที่คัดลอกไปยังคลิปบอร์ด</translation> </message> <message> <source>Minimize</source> @@ -278,7 +278,7 @@ </message> <message> <source>Favicon download timeout:</source> - <translation type="unfinished"/> + <translation>ระยะหมดเวลาดาวน์โหลด favicon:</translation> </message> <message> <source>Website icon download timeout in seconds</source> @@ -291,31 +291,31 @@ </message> <message> <source>Toolbar button style</source> - <translation type="unfinished"/> + <translation>รูปแบบปุ่มบนแถบเครื่องมือ</translation> </message> <message> <source>Use monospaced font for Notes</source> - <translation type="unfinished"/> + <translation>ใช้ฟอนต์ความกว้างเดียวสำหรับบันทึก</translation> </message> <message> <source>Language selection</source> - <translation type="unfinished"/> + <translation>เลือกภาษา</translation> </message> <message> <source>Reset Settings to Default</source> - <translation type="unfinished"/> + <translation>ล้างการตั้งค่ากลับไปเป็นค่าเริ่มต้น</translation> </message> <message> <source>Global auto-type shortcut</source> - <translation type="unfinished"/> + <translation>ปุ่มลัดพิมพ์อัตโนมัติในทุกโปรแกรม</translation> </message> <message> <source>Auto-type character typing delay milliseconds</source> - <translation type="unfinished"/> + <translation>หน่วงเวลาพิมพ์อัตโนมัติแต่ละตัวอักษร หน่วยเป็นมิลลิวินาที</translation> </message> <message> <source>Auto-type start delay milliseconds</source> - <translation type="unfinished"/> + <translation>หน่วงเวลาเริ่มพิมพ์อัตโนมัติ หน่วยเป็นมิลลิวินาที</translation> </message> </context> <context> @@ -391,11 +391,11 @@ </message> <message> <source>Use DuckDuckGo service to download website icons</source> - <translation type="unfinished"/> + <translation>ใช้บริการของ DuckDuckGo เพื่อดาวน์โหลดไอคอนของเว็บไซต์</translation> </message> <message> <source>Clipboard clear seconds</source> - <translation type="unfinished"/> + <translation>ล้างคลิปบอร์ดภายใน หน่วยเป็นวินาที</translation> </message> <message> <source>Touch ID inactivity reset</source> @@ -412,7 +412,7 @@ </message> <message> <source>Clear search query after</source> - <translation type="unfinished"/> + <translation>ล้างคำค้นหลังจาก</translation> </message> </context> <context> @@ -551,11 +551,11 @@ Please select whether you want to allow access.</source> </message> <message> <source>Allow access</source> - <translation type="unfinished"/> + <translation>อนุญาตการเข้าถึง</translation> </message> <message> <source>Deny access</source> - <translation type="unfinished"/> + <translation>ปฏิเสธการเข้าถึง</translation> </message> </context> <context> @@ -1123,7 +1123,7 @@ Please consider generating a new key file.</source> </message> <message> <source>Select slot...</source> - <translation type="unfinished"/> + <translation>เลือกช่อง...</translation> </message> <message> <source>Unlock KeePassXC Database</source> @@ -1179,7 +1179,7 @@ Please consider generating a new key file.</source> </message> <message> <source>Clear Key File</source> - <translation type="unfinished"/> + <translation>ล้างแฟ้มกุญแจ</translation> </message> <message> <source>Unlock failed and no password given</source> @@ -1211,15 +1211,15 @@ To prevent this error from appearing, you must go to "Database Settings / S </message> <message> <source>Key file help</source> - <translation type="unfinished"/> + <translation>ช่วยเหลือเรื่องแฟ้มกุญแจ</translation> </message> <message> <source>?</source> - <translation type="unfinished"/> + <translation>?</translation> </message> <message> <source>Select key file...</source> - <translation type="unfinished"/> + <translation>เลือกแฟ้มกุญแจ...</translation> </message> <message> <source>Cannot use database file as key file</source> @@ -1388,7 +1388,7 @@ This is necessary to maintain compatibility with the browser plugin.</source> </message> <message> <source>Remove selected key</source> - <translation type="unfinished"/> + <translation>ลบกุญแจที่เลือก</translation> </message> </context> <context> @@ -1538,15 +1538,15 @@ If you keep this number, your database may be too easy to crack!</source> </message> <message> <source>Decryption time in seconds</source> - <translation type="unfinished"/> + <translation>เวลาถอดรหัสลับ หน่วยเป็นวินาที</translation> </message> <message> <source>Database format</source> - <translation type="unfinished"/> + <translation>รูปแบบฐานข้อมูล</translation> </message> <message> <source>Encryption algorithm</source> - <translation type="unfinished"/> + <translation>อัลกอริทึมการเข้ารหัสลับ</translation> </message> <message> <source>Key derivation function</source> @@ -1558,7 +1558,7 @@ If you keep this number, your database may be too easy to crack!</source> </message> <message> <source>Memory usage</source> - <translation type="unfinished"/> + <translation>หน่วยความจำที่ใช้</translation> </message> <message> <source>Parallelism</source> @@ -1632,15 +1632,15 @@ If you keep this number, your database may be too easy to crack!</source> </message> <message> <source>Database name field</source> - <translation type="unfinished"/> + <translation>ช่องข้อมูลชื่อฐานข้อมูล</translation> </message> <message> <source>Database description field</source> - <translation type="unfinished"/> + <translation>ช่องข้อมูลคำอธิบายฐานข้อมูล</translation> </message> <message> <source>Default username field</source> - <translation type="unfinished"/> + <translation>ช่องข้อมูลชื่อผู้ใช้ฐานข้อมูล</translation> </message> <message> <source>Maximum number of history items per entry</source> @@ -1652,7 +1652,7 @@ If you keep this number, your database may be too easy to crack!</source> </message> <message> <source>Delete Recycle Bin</source> - <translation type="unfinished"/> + <translation>ลบถังขยะ</translation> </message> <message> <source>Do you want to delete the current recycle bin and all its contents? @@ -1661,7 +1661,7 @@ This action is not reversible.</source> </message> <message> <source> (old)</source> - <translation type="unfinished"/> + <translation> (เก่า)</translation> </message> </context> <context> @@ -1747,18 +1747,18 @@ Are you sure you want to continue without a password?</source> </message> <message> <source>Database name field</source> - <translation type="unfinished"/> + <translation>ช่องข้อมูลชื่อฐานข้อมูล</translation> </message> <message> <source>Database description field</source> - <translation type="unfinished"/> + <translation>ช่องข้อมูลคำอธิบายฐานข้อมูล</translation> </message> </context> <context> <name>DatabaseSettingsWidgetStatistics</name> <message> <source>Statistics</source> - <translation type="unfinished"/> + <translation>สถิติ</translation> </message> <message> <source>Hover over lines with error icons for further information.</source> @@ -1774,31 +1774,31 @@ Are you sure you want to continue without a password?</source> </message> <message> <source>Database name</source> - <translation type="unfinished"/> + <translation>ชื่อฐานข้อมูล</translation> </message> <message> <source>Description</source> - <translation type="unfinished"/> + <translation>คำอธิบาย</translation> </message> <message> <source>Location</source> - <translation type="unfinished"/> + <translation>ที่ตั้ง</translation> </message> <message> <source>Last saved</source> - <translation type="unfinished"/> + <translation>บันทึกครั้งสุดท้าย</translation> </message> <message> <source>Unsaved changes</source> - <translation type="unfinished"/> + <translation>ความเปลี่ยนแปลงที่ยังไม่ได้บันทึก</translation> </message> <message> <source>yes</source> - <translation type="unfinished"/> + <translation>ใช่</translation> </message> <message> <source>no</source> - <translation type="unfinished"/> + <translation>ไม่</translation> </message> <message> <source>The database was modified, but the changes have not yet been saved to disk.</source> @@ -1806,31 +1806,31 @@ Are you sure you want to continue without a password?</source> </message> <message> <source>Number of groups</source> - <translation type="unfinished"/> + <translation>จำนวนกลุ่ม</translation> </message> <message> <source>Number of entries</source> - <translation type="unfinished"/> + <translation>จำนวนรายการ</translation> </message> <message> <source>Number of expired entries</source> - <translation type="unfinished"/> + <translation>จำนวนรายการที่หมดอายุ</translation> </message> <message> <source>The database contains entries that have expired.</source> - <translation type="unfinished"/> + <translation>ฐานข้อมูลมีรายการที่หมดอายุแล้ว</translation> </message> <message> <source>Unique passwords</source> - <translation type="unfinished"/> + <translation>รหัสผ่านที่ไม่ซ้ำ</translation> </message> <message> <source>Non-unique passwords</source> - <translation type="unfinished"/> + <translation>รหัสผ่านที่ซ้ำ</translation> </message> <message> <source>More than 10% of passwords are reused. Use unique passwords when possible.</source> - <translation type="unfinished"/> + <translation>มากกว่า 10% ของรหัสผ่านถูกใช้ซ้ำ ควรใช้รหัสผ่านที่ไม่ซ้ำถ้าทำได้</translation> </message> <message> <source>Maximum password reuse</source> @@ -1862,7 +1862,7 @@ Are you sure you want to continue without a password?</source> </message> <message> <source>%1 characters</source> - <translation type="unfinished"/> + <translation>%1 ตัวอักษร</translation> </message> <message> <source>Average password length is less than ten characters. Longer passwords provide more security.</source> @@ -1954,7 +1954,7 @@ This is definitely a bug, please report it to the developers.</source> </message> <message> <source>HTML file</source> - <translation type="unfinished"/> + <translation>แฟ้ม HTML</translation> </message> <message> <source>Writing the HTML file failed.</source> @@ -2051,7 +2051,7 @@ Do you want to merge your changes?</source> </message> <message numerus="yes"> <source>Delete entry(s)?</source> - <translation type="unfinished"><numerusform></numerusform></translation> + <translation><numerusform>ลบรายการหรือไม่?</numerusform></translation> </message> <message numerus="yes"> <source>Move entry(s) to recycle bin?</source> @@ -5252,7 +5252,7 @@ Expect some bugs and minor issues, this version is not meant for production use. </message> <message> <source>Statistics</source> - <translation type="unfinished"/> + <translation>สถิติ</translation> </message> </context> <context> @@ -6053,7 +6053,7 @@ Kernel: %3 %4</source> </message> <message> <source>None</source> - <translation type="unfinished"/> + <translation>ไม่มี</translation> </message> <message> <source>Enabled extensions:</source> @@ -6468,7 +6468,7 @@ Kernel: %3 %4</source> <name>SettingsWidgetFdoSecrets</name> <message> <source>Options</source> - <translation type="unfinished"/> + <translation>ตัวเลือก</translation> </message> <message> <source>Enable KeepassXC Freedesktop.org Secret Service integration</source> @@ -6496,7 +6496,7 @@ Kernel: %3 %4</source> </message> <message> <source>File Name</source> - <translation type="unfinished"/> + <translation>ชื่อแฟ้ม</translation> </message> <message> <source>Group</source> @@ -6504,11 +6504,11 @@ Kernel: %3 %4</source> </message> <message> <source>Manage</source> - <translation type="unfinished"/> + <translation>จัดการ</translation> </message> <message> <source>Authorization</source> - <translation type="unfinished"/> + <translation>ตรวจยืนยันสิทธิ์</translation> </message> <message> <source>These applications are currently connected:</source> @@ -6516,11 +6516,11 @@ Kernel: %3 %4</source> </message> <message> <source>Application</source> - <translation type="unfinished"/> + <translation>แอปพลิเคชัน</translation> </message> <message> <source>Disconnect</source> - <translation type="unfinished"/> + <translation>หยุดเชื่อมต่อ</translation> </message> <message> <source>Database settings</source> @@ -6528,7 +6528,7 @@ Kernel: %3 %4</source> </message> <message> <source>Edit database settings</source> - <translation type="unfinished"/> + <translation>แก้ไขการตั้งค่าฐานข้อมูล</translation> </message> <message> <source>Unlock database</source> @@ -6548,7 +6548,7 @@ Kernel: %3 %4</source> </message> <message> <source>None</source> - <translation type="unfinished"/> + <translation>ไม่มี</translation> </message> </context> <context> @@ -6676,11 +6676,11 @@ Kernel: %3 %4</source> </message> <message> <source>Allow KeeShare imports</source> - <translation type="unfinished"/> + <translation>อนุญาตการนำเข้า KeeShare</translation> </message> <message> <source>Allow KeeShare exports</source> - <translation type="unfinished"/> + <translation>อนุญาตการส่งออก KeeShare</translation> </message> <message> <source>Only show warnings and errors</source> @@ -6952,7 +6952,7 @@ Kernel: %3 %4</source> </message> <message> <source>Secret Key:</source> - <translation type="unfinished"/> + <translation>กุญแจลับ:</translation> </message> <message> <source>Secret key must be in Base32 format</source> @@ -6972,7 +6972,7 @@ Kernel: %3 %4</source> </message> <message> <source> digits</source> - <translation type="unfinished"/> + <translation>หลัก</translation> </message> <message> <source>Invalid TOTP Secret</source> @@ -7075,11 +7075,11 @@ Example: JBSWY3DPEHPK3PXP</source> </message> <message> <source>Import from 1Password</source> - <translation type="unfinished"/> + <translation>นำเข้าจาก 1Password</translation> </message> <message> <source>Open a recent database</source> - <translation type="unfinished"/> + <translation>เปิดฐานข้อมูลล่าสุด</translation> </message> </context> <context> diff --git a/share/translations/keepassx_tr.ts b/share/translations/keepassx_tr.ts index 78c8592e8..d28dc1af0 100644 --- a/share/translations/keepassx_tr.ts +++ b/share/translations/keepassx_tr.ts @@ -50,7 +50,7 @@ <name>AgentSettingsWidget</name> <message> <source>Enable SSH Agent (requires restart)</source> - <translation>SSH İstemcisini etkinleştir (yeniden başlatma gerekli)</translation> + <translation>SSH İstemcisini etkinleştir (yeniden başlatılmalı)</translation> </message> <message> <source>Use OpenSSH for Windows instead of Pageant</source> @@ -948,7 +948,7 @@ linux-laptop.</translation> </message> <message> <source>Preview</source> - <translation>Ön izleme</translation> + <translation>Ön izle</translation> </message> <message> <source>Column layout</source> @@ -1131,7 +1131,7 @@ Lütfen yeni bir anahtar dosyası oluşturmayı düşünün.</translation> </message> <message> <source>Select slot...</source> - <translation>Alan seç...</translation> + <translation>Yuva seç...</translation> </message> <message> <source>Unlock KeePassXC Database</source> @@ -1341,7 +1341,7 @@ Bu işlem, tarayıcı eklentisi bağlantısını engelleyebilir.</translation> </message> <message> <source>KeePassXC: Removed keys from database</source> - <translation>KeePassXC: Anahtarlar veritabanından kaldırıldı</translation> + <translation>KeePassXC: Anahtarlar veritabanı üstünden kaldırıldı</translation> </message> <message numerus="yes"> <source>Successfully removed %n encryption key(s) from KeePassXC settings.</source> @@ -1641,15 +1641,15 @@ Eğer bu sayı ile devam ederseniz, veritabanınız çok kolay çözülerek kır </message> <message> <source>Database name field</source> - <translation type="unfinished"/> + <translation>Veritabanı isim alanı</translation> </message> <message> <source>Database description field</source> - <translation type="unfinished"/> + <translation>Veritabanı açıklama alanı</translation> </message> <message> <source>Default username field</source> - <translation type="unfinished"/> + <translation>Varsayılan kullanıcı adı alanı</translation> </message> <message> <source>Maximum number of history items per entry</source> @@ -1666,11 +1666,12 @@ Eğer bu sayı ile devam ederseniz, veritabanınız çok kolay çözülerek kır <message> <source>Do you want to delete the current recycle bin and all its contents? This action is not reversible.</source> - <translation type="unfinished"/> + <translation>Mevcut geri dönüşüm kutusunu ve tüm içeriğini silmek istiyor musunuz? +Bu eylem geri alınamaz.</translation> </message> <message> <source> (old)</source> - <translation type="unfinished"/> + <translation> (eski)</translation> </message> </context> <context> @@ -1741,7 +1742,7 @@ Parola olmadan devam etmek istediğinize emin misiniz?</translation> </message> <message> <source>Continue without password</source> - <translation type="unfinished"/> + <translation>Parola olmadan devam et</translation> </message> </context> <context> @@ -1756,11 +1757,11 @@ Parola olmadan devam etmek istediğinize emin misiniz?</translation> </message> <message> <source>Database name field</source> - <translation type="unfinished"/> + <translation>Veritabanı isim alanı</translation> </message> <message> <source>Database description field</source> - <translation type="unfinished"/> + <translation>Veritabanı açıklama alanı</translation> </message> </context> <context> @@ -1811,7 +1812,7 @@ Parola olmadan devam etmek istediğinize emin misiniz?</translation> </message> <message> <source>The database was modified, but the changes have not yet been saved to disk.</source> - <translation type="unfinished"/> + <translation>Veritabanı değiştirildi, ancak değişiklikler henüz diske kaydedilmedi.</translation> </message> <message> <source>Number of groups</source> @@ -1827,7 +1828,7 @@ Parola olmadan devam etmek istediğinize emin misiniz?</translation> </message> <message> <source>The database contains entries that have expired.</source> - <translation type="unfinished"/> + <translation>Veritabanı süresi dolmuş girdiler içeriyor.</translation> </message> <message> <source>Unique passwords</source> @@ -1863,7 +1864,7 @@ Parola olmadan devam etmek istediğinize emin misiniz?</translation> </message> <message> <source>Recommend using long, randomized passwords with a rating of 'good' or 'excellent'.</source> - <translation type="unfinished"/> + <translation>'İyi' veya 'mükemmel' derecesine sahip uzun, rastgele parolalar kullanmanızı öneririz.</translation> </message> <message> <source>Average password length</source> @@ -1875,11 +1876,11 @@ Parola olmadan devam etmek istediğinize emin misiniz?</translation> </message> <message> <source>Average password length is less than ten characters. Longer passwords provide more security.</source> - <translation type="unfinished"/> + <translation>Ortalama parola uzunluğu on karakterden az. Daha uzun parolalar daha fazla güvenlik sağlar.</translation> </message> <message> <source>Please wait, database statistics are being calculated...</source> - <translation type="unfinished"/> + <translation>Lütfen bekleyin, veritabanı istatistikleri hesaplanıyor...</translation> </message> </context> <context> @@ -1955,7 +1956,7 @@ Bu kesinlikle bir hatadır, lütfen geliştiricilere bildirin.</translation> </message> <message> <source>Failed to open %1. It either does not exist or is not accessible.</source> - <translation type="unfinished"/> + <translation>%1 açılamadı. Ya mevcut değil ya da erişilebilir değil.</translation> </message> <message> <source>Export database to HTML file</source> @@ -1967,7 +1968,7 @@ Bu kesinlikle bir hatadır, lütfen geliştiricilere bildirin.</translation> </message> <message> <source>Writing the HTML file failed.</source> - <translation type="unfinished"/> + <translation>HTML dosyası yazılamadı.</translation> </message> <message> <source>Export Confirmation</source> @@ -2287,7 +2288,7 @@ Güvenli kaydetme devre dışı bırakılsın ve tekrar denensin mi?</translatio </message> <message> <source>Are you sure you want to remove this URL?</source> - <translation type="unfinished"/> + <translation>Bu URL'yi kaldırmak istediğinizden emin misiniz?</translation> </message> </context> <context> @@ -2346,7 +2347,7 @@ Güvenli kaydetme devre dışı bırakılsın ve tekrar denensin mi?</translatio </message> <message> <source>Edit attribute name</source> - <translation type="unfinished"/> + <translation>Öznitelik adını düzenle</translation> </message> <message> <source>Toggle attribute protection</source> @@ -2425,11 +2426,11 @@ Güvenli kaydetme devre dışı bırakılsın ve tekrar denensin mi?</translatio </message> <message> <source>Set the window association title</source> - <translation type="unfinished"/> + <translation>Pencere ilişkilendirme başlığını ayarla</translation> </message> <message> <source>You can use an asterisk to match everything</source> - <translation type="unfinished"/> + <translation>Her şeyi eşleştirmek için yıldız işareti kullanabilirsiniz</translation> </message> <message> <source>Custom Auto-Type sequence for this window</source> @@ -2448,15 +2449,15 @@ Güvenli kaydetme devre dışı bırakılsın ve tekrar denensin mi?</translatio </message> <message> <source>Skip Auto-Submit for this entry</source> - <translation type="unfinished"/> + <translation>Bu girdi için Otomatik Gönder'i atla</translation> </message> <message> <source>Hide this entry from the browser extension</source> - <translation type="unfinished"/> + <translation>Bu girdiyi tarayıcı eklentisi üstünde gizle</translation> </message> <message> <source>Additional URL's</source> - <translation type="unfinished"/> + <translation>Ek URL'ler</translation> </message> <message> <source>Add</source> @@ -2594,11 +2595,11 @@ Güvenli kaydetme devre dışı bırakılsın ve tekrar denensin mi?</translatio </message> <message> <source>Title field</source> - <translation type="unfinished"/> + <translation>Başlık alanı</translation> </message> <message> <source>Username field</source> - <translation type="unfinished"/> + <translation>Kullanıcı adı alanı</translation> </message> <message> <source>Toggle expiration</source> @@ -2835,7 +2836,7 @@ Desteklenen eklentiler: %1.</translation> </message> <message> <source>Path to share file field</source> - <translation type="unfinished"/> + <translation>Dosya paylaşım yolu</translation> </message> <message> <source>Browser for share file</source> @@ -3062,15 +3063,15 @@ Bu etkilenen eklentilerin bozulmasına neden olabilir.</translation> </message> <message> <source>Datetime created</source> - <translation type="unfinished"/> + <translation>Oluşturulma tarih saati</translation> </message> <message> <source>Datetime modified</source> - <translation type="unfinished"/> + <translation>Düzenlenme tarih saati</translation> </message> <message> <source>Datetime accessed</source> - <translation type="unfinished"/> + <translation>Erişim tarih saati</translation> </message> <message> <source>Unique ID</source> @@ -3560,7 +3561,8 @@ DuckDuckGo web sitesi simge servisini uygulama ayarlarının güvenlik bölümü <message> <source>Invalid credentials were provided, please try again. If this reoccurs, then your database file may be corrupt.</source> - <translation type="unfinished"/> + <translation>Geçersiz kimlik bilgileri sağlandı, lütfen tekrar deneyin. +Bu yeniden oluşursa, veritabanı dosyanız bozuk olabilir.</translation> </message> </context> <context> @@ -3695,7 +3697,8 @@ If this reoccurs, then your database file may be corrupt.</source> <message> <source>Invalid credentials were provided, please try again. If this reoccurs, then your database file may be corrupt.</source> - <translation type="unfinished"/> + <translation>Geçersiz kimlik bilgileri sağlandı, lütfen tekrar deneyin. +Bu yeniden oluşursa, veritabanı dosyanız bozuk olabilir.</translation> </message> <message> <source>(HMAC mismatch)</source> @@ -4085,14 +4088,15 @@ Satır %2, sütun %3</translation> <message> <source>Invalid credentials were provided, please try again. If this reoccurs, then your database file may be corrupt.</source> - <translation type="unfinished"/> + <translation>Geçersiz kimlik bilgileri sağlandı, lütfen tekrar deneyin. +Bu yeniden oluşursa, veritabanı dosyanız bozuk olabilir.</translation> </message> </context> <context> <name>KeeShare</name> <message> <source>Invalid sharing reference</source> - <translation type="unfinished"/> + <translation>Geçersiz paylaşım referansı</translation> </message> <message> <source>Inactive share %1</source> @@ -4104,19 +4108,19 @@ If this reoccurs, then your database file may be corrupt.</source> </message> <message> <source>Exported to %1</source> - <translation type="unfinished"/> + <translation>%1 klasörüne aktarıldı</translation> </message> <message> <source>Synchronized with %1</source> - <translation type="unfinished"/> + <translation>%1 ile eşitlendi</translation> </message> <message> <source>Import is disabled in settings</source> - <translation type="unfinished"/> + <translation>Ayarlarda içe aktarma devre dışı</translation> </message> <message> <source>Export is disabled in settings</source> - <translation type="unfinished"/> + <translation>Ayarlarda dışa aktarma devre dışı</translation> </message> <message> <source>Inactive share</source> @@ -4124,7 +4128,7 @@ If this reoccurs, then your database file may be corrupt.</source> </message> <message> <source>Imported from</source> - <translation type="unfinished"/> + <translation>İçe aktarıldı</translation> </message> <message> <source>Exported to</source> @@ -4250,7 +4254,7 @@ Message: %2</source> </message> <message> <source>Note: Do not use a file that may change as that will prevent you from unlocking your database!</source> - <translation type="unfinished"/> + <translation>Not: Veritabanınızın kilidini açmanızı engelleyeceği için değişebilecek bir dosya kullanmayın!</translation> </message> <message> <source>Invalid Key File</source> @@ -4258,16 +4262,17 @@ Message: %2</source> </message> <message> <source>You cannot use the current database as its own keyfile. Please choose a different file or generate a new key file.</source> - <translation type="unfinished"/> + <translation>Mevcut veritabanını kendi anahtar dosyası olarak kullanamazsınız. Lütfen farklı bir dosya seçin veya yeni bir anahtar dosyası oluşturun.</translation> </message> <message> <source>Suspicious Key File</source> - <translation type="unfinished"/> + <translation>Şüpheli Anahtar Dosyası</translation> </message> <message> <source>The chosen key file looks like a password database file. A key file must be a static file that never changes or you will lose access to your database forever. Are you sure you want to continue with this file?</source> - <translation type="unfinished"/> + <translation>Seçilen anahtar dosyası bir parola veritabanı dosyasına benziyor. Anahtar dosya, değişmeyen statik bir dosya olmalıdır, aksi takdirde veritabanınıza sonsuza kadar erişiminizi kaybedersiniz. +Bu dosyaya devam etmek istediğinizden emin misiniz?</translation> </message> </context> <context> @@ -4689,11 +4694,11 @@ Bazı hatalar ve küçük sorunlar olabilir, bu sürüm şu an dağıtımda değ </message> <message> <source>Removed custom data %1 [%2]</source> - <translation type="unfinished"/> + <translation>Özel veriler kaldırıldı %1 [%2]</translation> </message> <message> <source>Adding custom data %1 [%2]</source> - <translation type="unfinished"/> + <translation>Özel veriler eklendi %1 [%2]</translation> </message> </context> <context> @@ -5997,11 +6002,11 @@ Kullanılabilir komutlar: </message> <message> <source>Displays debugging information.</source> - <translation type="unfinished"/> + <translation>Hata ayıklama bilgilerini görüntüler.</translation> </message> <message> <source>Deactivate password key for the database to merge from.</source> - <translation type="unfinished"/> + <translation>Veritabanının birleştirileceği parola anahtarını devre dışı bırak.</translation> </message> <message> <source>Version %1</source> @@ -6025,7 +6030,7 @@ Kullanılabilir komutlar: </message> <message> <source>Debugging mode is enabled.</source> - <translation type="unfinished"/> + <translation>Hata ayıklama kipi etkin.</translation> </message> <message> <source>Operating system: %1 @@ -6069,7 +6074,7 @@ MİB mimarisi: %2 </message> <message> <source>Cryptographic libraries:</source> - <translation type="unfinished"/> + <translation>Şifreleme kütüphaneleri:</translation> </message> <message> <source>Cannot generate a password and prompt at the same time!</source> @@ -6081,7 +6086,7 @@ MİB mimarisi: %2 </message> <message> <source>Path of the group to add.</source> - <translation type="unfinished"/> + <translation>Eklenecek kümenin yolu.</translation> </message> <message> <source>Group %1 already exists!</source> @@ -6161,7 +6166,7 @@ MİB mimarisi: %2 </message> <message> <source>Use numbers</source> - <translation type="unfinished"/> + <translation>Sayıları kullan</translation> </message> <message> <source>Invalid password length %1</source> diff --git a/share/windows/wix-template.xml b/share/windows/wix-template.xml index 228bf2a48..eb49f872b 100644 --- a/share/windows/wix-template.xml +++ b/share/windows/wix-template.xml @@ -51,7 +51,7 @@ <RegistryValue Id="Autostart.rst" Root="HKCU" Action="write" Key="Software\Microsoft\Windows\CurrentVersion\Run" Name="$(var.CPACK_PACKAGE_NAME)" - Value="[#CM_FP_KeePassXC.exe]" + Value=""[#CM_FP_KeePassXC.exe]"" Type="string" /> <Condition>AUTOSTARTPROGRAM</Condition> </Component> diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index b488e041e..5f49d0092 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -71,6 +71,7 @@ parts: - libargon2-0-dev - libqrencode-dev - libquazip5-dev + - asciidoctor stage-packages: - dbus - qttranslations5-l10n # common translations diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8af339f1c..2f8c3b156 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -153,16 +153,16 @@ set(keepassx_SOURCES gui/group/EditGroupWidget.cpp gui/group/GroupModel.cpp gui/group/GroupView.cpp - gui/masterkey/KeyComponentWidget.cpp - gui/masterkey/PasswordEditWidget.cpp - gui/masterkey/YubiKeyEditWidget.cpp - gui/masterkey/KeyFileEditWidget.cpp + gui/databasekey/KeyComponentWidget.cpp + gui/databasekey/PasswordEditWidget.cpp + gui/databasekey/YubiKeyEditWidget.cpp + gui/databasekey/KeyFileEditWidget.cpp gui/dbsettings/DatabaseSettingsWidget.cpp gui/dbsettings/DatabaseSettingsDialog.cpp gui/dbsettings/DatabaseSettingsWidgetGeneral.cpp gui/dbsettings/DatabaseSettingsWidgetMetaDataSimple.cpp gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp - gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp + gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp gui/reports/ReportsWidget.cpp gui/reports/ReportsDialog.cpp gui/reports/ReportsWidgetHealthcheck.cpp @@ -179,7 +179,7 @@ set(keepassx_SOURCES gui/wizard/NewDatabaseWizardPage.cpp gui/wizard/NewDatabaseWizardPageMetaData.cpp gui/wizard/NewDatabaseWizardPageEncryption.cpp - gui/wizard/NewDatabaseWizardPageMasterKey.cpp + gui/wizard/NewDatabaseWizardPageDatabaseKey.cpp keys/CompositeKey.cpp keys/FileKey.cpp keys/PasswordKey.cpp @@ -419,10 +419,6 @@ install(TARGETS ${PROGNAME} BUNDLE DESTINATION . 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(${CMAKE_SIZEOF_VOID_P} EQUAL "8") set(OUTPUT_FILE_POSTFIX "Win64") diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 117df903b..01ef9d762 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -35,6 +35,7 @@ #include "core/ListDeleter.h" #include "core/Resources.h" #include "core/Tools.h" +#include "gui/MainWindow.h" #include "gui/MessageBox.h" #ifdef Q_OS_MAC @@ -51,6 +52,7 @@ AutoType::AutoType(QObject* parent, bool test) , m_pluginLoader(new QPluginLoader(this)) , m_plugin(nullptr) , m_executor(nullptr) + , m_windowState(WindowState::Normal) , m_windowForGlobal(0) { // prevent crash when the plugin has unresolved symbols @@ -227,6 +229,7 @@ void AutoType::executeAutoTypeActions(const Entry* entry, QWidget* hideWindow, c "KeePassXC.")); return; } + macUtils()->raiseLastActiveWindow(); m_plugin->hideOwnWindow(); #else @@ -286,6 +289,18 @@ void AutoType::startGlobalAutoType() { m_windowForGlobal = m_plugin->activeWindow(); m_windowTitleForGlobal = m_plugin->activeWindowTitle(); +#ifdef Q_OS_MACOS + m_windowState = WindowState::Normal; + if (getMainWindow()) { + if (getMainWindow()->isMinimized()) { + m_windowState = WindowState::Minimized; + } + if (getMainWindow()->isHidden()) { + m_windowState = WindowState::Hidden; + } + } +#endif + emit globalAutoTypeTriggered(); } @@ -332,9 +347,12 @@ void AutoType::performGlobalAutoType(const QList<QSharedPointer<Database>>& dbLi .append(m_windowTitleForGlobal)); msgBox->setIcon(QMessageBox::Information); msgBox->setStandardButtons(QMessageBox::Ok); - msgBox->show(); - msgBox->raise(); - msgBox->activateWindow(); +#ifdef Q_OS_MACOS + m_plugin->raiseOwnWindow(); + Tools::wait(200); +#endif + msgBox->exec(); + restoreWindowState(); } m_inGlobalAutoTypeDialog.unlock(); @@ -361,8 +379,23 @@ void AutoType::performGlobalAutoType(const QList<QSharedPointer<Database>>& dbLi } } +void AutoType::restoreWindowState() +{ +#ifdef Q_OS_MAC + if (getMainWindow()) { + if (m_windowState == WindowState::Minimized) { + getMainWindow()->showMinimized(); + } else if (m_windowState == WindowState::Hidden) { + getMainWindow()->hideWindow(); + } + } +#endif +} + void AutoType::performAutoTypeFromGlobal(AutoTypeMatch match) { + restoreWindowState(); + m_plugin->raiseWindow(m_windowForGlobal); executeAutoTypeActions(match.entry, nullptr, match.sequence, m_windowForGlobal); @@ -380,6 +413,7 @@ void AutoType::autoTypeRejectedFromGlobal() m_windowForGlobal = 0; m_windowTitleForGlobal.clear(); + restoreWindowState(); emit autotypeRejected(); } diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h index ad8607529..7f9e3ab22 100644 --- a/src/autotype/AutoType.h +++ b/src/autotype/AutoType.h @@ -73,6 +73,13 @@ private slots: void unloadPlugin(); private: + enum WindowState + { + Normal, + Minimized, + Hidden + }; + explicit AutoType(QObject* parent = nullptr, bool test = false); ~AutoType() override; void loadPlugin(const QString& pluginPath); @@ -86,6 +93,7 @@ private: bool windowMatchesTitle(const QString& windowTitle, const QString& resolvedTitle); bool windowMatchesUrl(const QString& windowTitle, const QString& resolvedUrl); bool windowMatches(const QString& windowTitle, const QString& windowPattern); + void restoreWindowState(); QMutex m_inAutoType; QMutex m_inGlobalAutoTypeDialog; @@ -98,6 +106,7 @@ private: static AutoType* m_instance; QString m_windowTitleForGlobal; + WindowState m_windowState; WId m_windowForGlobal; Q_DISABLE_COPY(AutoType) diff --git a/src/browser/BrowserHost.cpp b/src/browser/BrowserHost.cpp index 62c3e9cd8..ac4e996c3 100644 --- a/src/browser/BrowserHost.cpp +++ b/src/browser/BrowserHost.cpp @@ -28,6 +28,16 @@ #include "sodium.h" #include <iostream> +#ifdef Q_OS_WIN +#include <fcntl.h> +#include <winsock2.h> + +#include <windows.h> +#else +#include <sys/socket.h> +#include <sys/types.h> +#endif + BrowserHost::BrowserHost(QObject* parent) : QObject(parent) { @@ -77,6 +87,11 @@ void BrowserHost::readProxyMessage() } socket->setReadBufferSize(BrowserShared::NATIVEMSG_MAX_LENGTH); + int socketDesc = socket->socketDescriptor(); + if (socketDesc) { + int max = BrowserShared::NATIVEMSG_MAX_LENGTH; + setsockopt(socketDesc, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>(&max), sizeof(max)); + } QJsonParseError error; auto json = QJsonDocument::fromJson(socket->readAll(), &error); diff --git a/src/browser/BrowserService.cpp b/src/browser/BrowserService.cpp index c78744e0b..1f54e33ca 100644 --- a/src/browser/BrowserService.cpp +++ b/src/browser/BrowserService.cpp @@ -64,6 +64,7 @@ BrowserService::BrowserService() : QObject() , m_browserHost(new BrowserHost) , m_dialogActive(false) + , m_bringToFrontRequested(false) , m_prevWindowState(WindowState::Normal) , m_keepassBrowserUUID(Tools::hexToUuid("de887cc3036343b8974b5911b8816224")) { @@ -109,6 +110,8 @@ bool BrowserService::openDatabase(bool triggerUnlock) } if (triggerUnlock) { + m_bringToFrontRequested = true; + updateWindowState(); emit requestUnlock(); } @@ -751,11 +754,10 @@ QList<Entry*> BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm, } m_dialogActive = true; - bool wasAppActive = qApp->activeWindow() == getMainWindow()->window(); + updateWindowState(); BrowserAccessControlDialog accessControlDialog; connect(m_currentDatabaseWidget, SIGNAL(databaseLocked()), &accessControlDialog, SLOT(reject())); - connect(this, SIGNAL(activeDatabaseChanged()), &accessControlDialog, SLOT(reject())); connect(&accessControlDialog, &BrowserAccessControlDialog::disableAccess, [&](QTableWidgetItem* item) { auto entry = pwEntriesToConfirm[item->row()]; @@ -797,11 +799,7 @@ QList<Entry*> BrowserService::confirmEntries(QList<Entry*>& pwEntriesToConfirm, #ifdef Q_OS_MAC // Re-hide the application if it wasn't visible before // only affects macOS because dialogs force the main window to show - if (!wasAppActive) { - hideWindow(); - } -#else - Q_UNUSED(wasAppActive); + hideWindow(); #endif m_dialogActive = false; @@ -848,13 +846,14 @@ QJsonObject BrowserService::prepareEntry(const Entry* entry) BrowserService::Access BrowserService::checkAccess(const Entry* entry, const QString& host, const QString& submitHost, const QString& realm) { + if (entry->isExpired()) { + return browserSettings()->allowExpiredCredentials() ? Allowed : Denied; + } + BrowserEntryConfig config; if (!config.load(entry)) { return Unknown; } - if (entry->isExpired()) { - return browserSettings()->allowExpiredCredentials() ? Allowed : Denied; - } if ((config.isAllowed(host)) && (submitHost.isEmpty() || config.isAllowed(submitHost))) { return Allowed; } @@ -1247,6 +1246,13 @@ void BrowserService::databaseLocked(DatabaseWidget* dbWidget) void BrowserService::databaseUnlocked(DatabaseWidget* dbWidget) { if (dbWidget) { +#ifdef Q_OS_MAC + if (m_bringToFrontRequested) { + m_bringToFrontRequested = false; + hideWindow(); + } +#endif + QJsonObject msg; msg["action"] = QString("database-unlocked"); m_browserHost->sendClientMessage(msg); diff --git a/src/browser/BrowserService.h b/src/browser/BrowserService.h index 1a9af8082..6567a44d0 100644 --- a/src/browser/BrowserService.h +++ b/src/browser/BrowserService.h @@ -154,6 +154,7 @@ private: QHash<QString, QSharedPointer<BrowserAction>> m_browserClients; bool m_dialogActive; + bool m_bringToFrontRequested; WindowState m_prevWindowState; QUuid m_keepassBrowserUUID; diff --git a/src/cli/CMakeLists.txt b/src/cli/CMakeLists.txt index 2bce90f88..f49ef9e9c 100644 --- a/src/cli/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -118,7 +118,3 @@ if(APPLE AND WITH_APP_BUNDLE) COMMAND ${CMAKE_COMMAND} -E copy keepassxc-cli ${CLI_APP_DIR}/keepassxc-cli COMMENT "Copying keepassxc-cli inside the application") endif() - -if(APPLE OR UNIX) - install(FILES ../../share/docs/man/keepassxc-cli.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1/) -endif() diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 77684cee3..6d55df8c7 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -101,6 +101,7 @@ static const QHash<Config::ConfigKey, ConfigDirective> configStrings = { {Config::GUI_AdvancedSettings, {QS("GUI/AdvancedSettings"), Roaming, false}}, {Config::GUI_MonospaceNotes, {QS("GUI/MonospaceNotes"), Roaming, false}}, {Config::GUI_ApplicationTheme, {QS("GUI/ApplicationTheme"), Roaming, QS("auto")}}, + {Config::GUI_CompactMode, {QS("GUI/CompactMode"), Roaming, false}}, {Config::GUI_CheckForUpdates, {QS("GUI/CheckForUpdates"), Roaming, true}}, {Config::GUI_CheckForUpdatesNextCheck, {QS("GUI/CheckForUpdatesNextCheck"), Local, 0}}, {Config::GUI_CheckForUpdatesIncludeBetas, {QS("GUI/CheckForUpdatesIncludeBetas"), Roaming, false}}, @@ -441,11 +442,12 @@ Config::Config(QObject* parent) configPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); localConfigPath = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); #elif defined(Q_OS_MACOS) - configPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + configPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); localConfigPath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); #else - configPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)); - localConfigPath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); + // On case-sensitive Operating Systems, force use of lowercase app directories + configPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/keepassxc"; + localConfigPath = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) + "/keepassxc"; #endif configPath += "/keepassxc"; diff --git a/src/core/Config.h b/src/core/Config.h index b3dc0fb85..9363873c9 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -84,6 +84,7 @@ public: GUI_AdvancedSettings, GUI_MonospaceNotes, GUI_ApplicationTheme, + GUI_CompactMode, GUI_CheckForUpdates, GUI_CheckForUpdatesIncludeBetas, diff --git a/src/core/Database.cpp b/src/core/Database.cpp index f3615be77..a315adf96 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -253,10 +253,14 @@ bool Database::saveAs(const QString& filePath, QString* error, bool atomic, bool QFileInfo fileInfo(filePath); auto realFilePath = fileInfo.exists() ? fileInfo.canonicalFilePath() : fileInfo.absoluteFilePath(); + bool isNewFile = !QFile::exists(realFilePath); bool ok = AsyncTask::runAndWaitForFuture([&] { return performSave(realFilePath, error, atomic, backup); }); if (ok) { markAsClean(); setFilePath(filePath); + if (isNewFile) { + QFile::setPermissions(realFilePath, QFile::ReadUser | QFile::WriteUser); + } m_fileWatcher->start(realFilePath, 30, 1); } else { // Saving failed, don't rewatch file since it does not represent our database @@ -304,6 +308,7 @@ bool Database::performSave(const QString& filePath, QString* error, bool atomic, } // Delete the original db and move the temp file in place + auto perms = QFile::permissions(filePath); QFile::remove(filePath); // Note: call into the QFile rename instead of QTemporaryFile @@ -312,6 +317,7 @@ bool Database::performSave(const QString& filePath, QString* error, bool atomic, if (tempFile.QFile::rename(filePath)) { // successfully saved the database tempFile.setAutoRemove(false); + QFile::setPermissions(filePath, perms); return true; } else if (!backup || !restoreDatabase(filePath)) { // Failed to copy new database in place, and @@ -345,7 +351,7 @@ bool Database::writeDatabase(QIODevice* device, QString* error) PasswordKey oldTransformedKey; if (m_data.key->isEmpty()) { - oldTransformedKey.setHash(m_data.transformedMasterKey->rawKey()); + oldTransformedKey.setHash(m_data.transformedDatabaseKey->rawKey()); } KeePass2Writer writer; @@ -360,7 +366,7 @@ bool Database::writeDatabase(QIODevice* device, QString* error) return false; } - QByteArray newKey = m_data.transformedMasterKey->rawKey(); + QByteArray newKey = m_data.transformedDatabaseKey->rawKey(); Q_ASSERT(!newKey.isEmpty()); Q_ASSERT(newKey != oldTransformedKey.rawKey()); if (newKey.isEmpty() || newKey == oldTransformedKey.rawKey()) { @@ -454,9 +460,12 @@ bool Database::backupDatabase(const QString& filePath) auto match = re.match(filePath); auto backupFilePath = filePath; + auto perms = QFile::permissions(filePath); backupFilePath = backupFilePath.replace(re, "") + ".old" + match.captured(1); QFile::remove(backupFilePath); - return QFile::copy(filePath, backupFilePath); + bool res = QFile::copy(filePath, backupFilePath); + QFile::setPermissions(backupFilePath, perms); + return res; } /** @@ -472,11 +481,13 @@ bool Database::restoreDatabase(const QString& filePath) static auto re = QRegularExpression("^(.*?)(\\.[^.]+)?$"); auto match = re.match(filePath); + auto perms = QFile::permissions(filePath); auto backupFilePath = match.captured(1) + ".old" + match.captured(2); // Only try to restore if the backup file actually exists if (QFile::exists(backupFilePath)) { QFile::remove(filePath); return QFile::copy(backupFilePath, filePath); + QFile::setPermissions(filePath, perms); } return false; } @@ -651,9 +662,9 @@ Database::CompressionAlgorithm Database::compressionAlgorithm() const return m_data.compressionAlgorithm; } -QByteArray Database::transformedMasterKey() const +QByteArray Database::transformedDatabaseKey() const { - return m_data.transformedMasterKey->rawKey(); + return m_data.transformedDatabaseKey->rawKey(); } QByteArray Database::challengeResponseKey() const @@ -712,7 +723,7 @@ bool Database::setKey(const QSharedPointer<const CompositeKey>& key, if (!key) { m_data.key.reset(); - m_data.transformedMasterKey.reset(new PasswordKey()); + m_data.transformedDatabaseKey.reset(new PasswordKey()); return true; } @@ -721,28 +732,28 @@ bool Database::setKey(const QSharedPointer<const CompositeKey>& key, Q_ASSERT(!m_data.kdf->seed().isEmpty()); } - PasswordKey oldTransformedMasterKey; + PasswordKey oldTransformedDatabaseKey; if (m_data.key && !m_data.key->isEmpty()) { - oldTransformedMasterKey.setHash(m_data.transformedMasterKey->rawKey()); + oldTransformedDatabaseKey.setHash(m_data.transformedDatabaseKey->rawKey()); } - QByteArray transformedMasterKey; + QByteArray transformedDatabaseKey; if (!transformKey) { - transformedMasterKey = QByteArray(oldTransformedMasterKey.rawKey()); - } else if (!key->transform(*m_data.kdf, transformedMasterKey, &m_keyError)) { + transformedDatabaseKey = QByteArray(oldTransformedDatabaseKey.rawKey()); + } else if (!key->transform(*m_data.kdf, transformedDatabaseKey, &m_keyError)) { return false; } m_data.key = key; - if (!transformedMasterKey.isEmpty()) { - m_data.transformedMasterKey->setHash(transformedMasterKey); + if (!transformedDatabaseKey.isEmpty()) { + m_data.transformedDatabaseKey->setHash(transformedDatabaseKey); } if (updateChangedTime) { - m_metadata->setMasterKeyChanged(Clock::currentDateTimeUtc()); + m_metadata->setDatabaseKeyChanged(Clock::currentDateTimeUtc()); } - if (oldTransformedMasterKey.rawKey() != m_data.transformedMasterKey->rawKey()) { + if (oldTransformedDatabaseKey.rawKey() != m_data.transformedDatabaseKey->rawKey()) { markAsModified(); } @@ -897,16 +908,16 @@ bool Database::changeKdf(const QSharedPointer<Kdf>& kdf) Q_ASSERT(!m_data.isReadOnly); kdf->randomizeSeed(); - QByteArray transformedMasterKey; + QByteArray transformedDatabaseKey; if (!m_data.key) { m_data.key = QSharedPointer<CompositeKey>::create(); } - if (!m_data.key->transform(*kdf, transformedMasterKey)) { + if (!m_data.key->transform(*kdf, transformedDatabaseKey)) { return false; } setKdf(kdf); - m_data.transformedMasterKey->setHash(transformedMasterKey); + m_data.transformedDatabaseKey->setHash(transformedDatabaseKey); markAsModified(); return true; diff --git a/src/core/Database.h b/src/core/Database.h index c5b7e965d..86d7e0898 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -130,7 +130,7 @@ public: QSharedPointer<Kdf> kdf() const; void setKdf(QSharedPointer<Kdf> kdf); bool changeKdf(const QSharedPointer<Kdf>& kdf); - QByteArray transformedMasterKey() const; + QByteArray transformedDatabaseKey() const; static Database* databaseByUuid(const QUuid& uuid); @@ -164,7 +164,7 @@ private: CompressionAlgorithm compressionAlgorithm = CompressionGZip; QScopedPointer<PasswordKey> masterSeed; - QScopedPointer<PasswordKey> transformedMasterKey; + QScopedPointer<PasswordKey> transformedDatabaseKey; QScopedPointer<PasswordKey> challengeResponseKey; QSharedPointer<const CompositeKey> key; @@ -174,7 +174,7 @@ private: DatabaseData() : masterSeed(new PasswordKey()) - , transformedMasterKey(new PasswordKey()) + , transformedDatabaseKey(new PasswordKey()) , challengeResponseKey(new PasswordKey()) { kdf->randomizeSeed(); @@ -185,7 +185,7 @@ private: filePath.clear(); masterSeed.reset(); - transformedMasterKey.reset(); + transformedDatabaseKey.reset(); challengeResponseKey.reset(); key.reset(); diff --git a/src/core/DatabaseIcons.cpp b/src/core/DatabaseIcons.cpp index 2935d98ff..7b4499026 100644 --- a/src/core/DatabaseIcons.cpp +++ b/src/core/DatabaseIcons.cpp @@ -17,6 +17,7 @@ #include "DatabaseIcons.h" +#include "core/Config.h" #include "core/Global.h" #include "core/Resources.h" #include "gui/MainWindow.h" @@ -44,6 +45,9 @@ DatabaseIcons::DatabaseIcons() iconList = QDir(iconDir).entryList(QDir::NoFilter, QDir::Name); badgeList = QDir(badgeDir).entryList(QDir::NoFilter, QDir::Name); + + // Set this early and once to ensure consistent icon size until app restart + m_compactMode = config()->get(Config::GUI_CompactMode).toBool(); } DatabaseIcons* DatabaseIcons::instance() @@ -66,13 +70,13 @@ QPixmap DatabaseIcons::icon(int index, IconSize size) auto icon = m_iconCache.value(cacheKey); if (icon.isNull()) { icon.addFile(iconDir + iconList[index]); - icon.addPixmap(icon.pixmap(IconSize::Default)); - icon.addPixmap(icon.pixmap(IconSize::Medium)); - icon.addPixmap(icon.pixmap(IconSize::Large)); + icon.addPixmap(icon.pixmap(iconSize(IconSize::Default))); + icon.addPixmap(icon.pixmap(iconSize(IconSize::Medium))); + icon.addPixmap(icon.pixmap(iconSize(IconSize::Large))); m_iconCache.insert(cacheKey, icon); } - return icon.pixmap(size); + return icon.pixmap(iconSize(size)); } QPixmap DatabaseIcons::applyBadge(const QPixmap& basePixmap, Badges badgeIndex) @@ -83,7 +87,8 @@ QPixmap DatabaseIcons::applyBadge(const QPixmap& basePixmap, Badges badgeIndex) qWarning("DatabaseIcons: Out-of-range badge index given to applyBadge: %d", badgeIndex); } else if (!QPixmapCache::find(cacheKey, &pixmap)) { int baseSize = basePixmap.width(); - int badgeSize = baseSize <= IconSize::Default * basePixmap.devicePixelRatio() ? baseSize * 0.6 : baseSize * 0.5; + int badgeSize = + baseSize <= iconSize(IconSize::Default) * basePixmap.devicePixelRatio() ? baseSize * 0.6 : baseSize * 0.5; QPoint badgePos(baseSize - badgeSize, baseSize - badgeSize); badgePos /= basePixmap.devicePixelRatio(); @@ -106,3 +111,15 @@ int DatabaseIcons::count() { return iconList.size(); } + +int DatabaseIcons::iconSize(IconSize size) +{ + switch (size) { + case Medium: + return m_compactMode ? 26 : 30; + case Large: + return m_compactMode ? 30 : 36; + default: + return m_compactMode ? 16 : 22; + } +} diff --git a/src/core/DatabaseIcons.h b/src/core/DatabaseIcons.h index 9f33644ee..2abb8a485 100644 --- a/src/core/DatabaseIcons.h +++ b/src/core/DatabaseIcons.h @@ -39,11 +39,14 @@ public: QPixmap applyBadge(const QPixmap& basePixmap, Badges badgeIndex); int count(); + int iconSize(IconSize size); + private: DatabaseIcons(); static DatabaseIcons* m_instance; QHash<QString, QIcon> m_iconCache; + bool m_compactMode; Q_DISABLE_COPY(DatabaseIcons) }; diff --git a/src/core/Global.h b/src/core/Global.h index ad6cc1f08..aebdb4559 100644 --- a/src/core/Global.h +++ b/src/core/Global.h @@ -48,9 +48,9 @@ static const auto FALSE_STR = QStringLiteral("false"); enum IconSize { - Default = 22, - Medium = 30, - Large = 36 + Default, + Medium, + Large }; template <typename T> struct AddConst diff --git a/src/core/Metadata.cpp b/src/core/Metadata.cpp index 67a58b068..4cad498f6 100644 --- a/src/core/Metadata.cpp +++ b/src/core/Metadata.cpp @@ -20,6 +20,7 @@ #include <QtCore/QCryptographicHash> #include "core/Clock.h" +#include "core/DatabaseIcons.h" #include "core/Entry.h" #include "core/Group.h" #include "core/Tools.h" @@ -186,7 +187,7 @@ QPixmap Metadata::customIconPixmap(const QUuid& uuid, IconSize size) const if (!hasCustomIcon(uuid)) { return {}; } - return m_customIcons.value(uuid).pixmap(size); + return m_customIcons.value(uuid).pixmap(databaseIcons()->iconSize(size)); } QHash<QUuid, QPixmap> Metadata::customIconsPixmaps(IconSize size) const @@ -250,17 +251,17 @@ const Group* Metadata::lastTopVisibleGroup() const return m_lastTopVisibleGroup; } -QDateTime Metadata::masterKeyChanged() const +QDateTime Metadata::databaseKeyChanged() const { return m_masterKeyChanged; } -int Metadata::masterKeyChangeRec() const +int Metadata::databaseKeyChangeRec() const { return m_data.masterKeyChangeRec; } -int Metadata::masterKeyChangeForce() const +int Metadata::databaseKeyChangeForce() const { return m_data.masterKeyChangeForce; } @@ -380,9 +381,9 @@ void Metadata::addCustomIcon(const QUuid& uuid, const QImage& image) // Generate QIcon with pre-baked resolutions auto basePixmap = QPixmap::fromImage(image).scaled(128, 128, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); QIcon icon(basePixmap); - icon.addPixmap(icon.pixmap(IconSize::Default)); - icon.addPixmap(icon.pixmap(IconSize::Medium)); - icon.addPixmap(icon.pixmap(IconSize::Large)); + icon.addPixmap(icon.pixmap(databaseIcons()->iconSize(IconSize::Default))); + icon.addPixmap(icon.pixmap(databaseIcons()->iconSize(IconSize::Medium))); + icon.addPixmap(icon.pixmap(databaseIcons()->iconSize(IconSize::Large))); m_customIcons.insert(uuid, icon); } else { m_customIcons.insert(uuid, QIcon()); @@ -473,7 +474,7 @@ void Metadata::setLastTopVisibleGroup(Group* group) set(m_lastTopVisibleGroup, group); } -void Metadata::setMasterKeyChanged(const QDateTime& value) +void Metadata::setDatabaseKeyChanged(const QDateTime& value) { Q_ASSERT(value.timeSpec() == Qt::UTC); m_masterKeyChanged = value; diff --git a/src/core/Metadata.h b/src/core/Metadata.h index c61bfacb2..dc09b3cca 100644 --- a/src/core/Metadata.h +++ b/src/core/Metadata.h @@ -96,9 +96,9 @@ public: QDateTime entryTemplatesGroupChanged() const; const Group* lastSelectedGroup() const; const Group* lastTopVisibleGroup() const; - QDateTime masterKeyChanged() const; - int masterKeyChangeRec() const; - int masterKeyChangeForce() const; + QDateTime databaseKeyChanged() const; + int databaseKeyChangeRec() const; + int databaseKeyChangeForce() const; int historyMaxItems() const; int historyMaxSize() const; CustomData* customData(); @@ -133,7 +133,7 @@ public: void setEntryTemplatesGroupChanged(const QDateTime& value); void setLastSelectedGroup(Group* group); void setLastTopVisibleGroup(Group* group); - void setMasterKeyChanged(const QDateTime& value); + void setDatabaseKeyChanged(const QDateTime& value); void setMasterKeyChangeRec(int value); void setMasterKeyChangeForce(int value); void setHistoryMaxItems(int value); @@ -142,7 +142,7 @@ public: /* * Copy all attributes from other except: * - Group pointers/uuids - * - Master key changed date + * - Database key changed date * - Custom icons * - Custom fields * - Settings changed date diff --git a/src/fdosecrets/FdoSecretsPlugin.cpp b/src/fdosecrets/FdoSecretsPlugin.cpp index 9db35338d..96d76e345 100644 --- a/src/fdosecrets/FdoSecretsPlugin.cpp +++ b/src/fdosecrets/FdoSecretsPlugin.cpp @@ -30,13 +30,21 @@ using FdoSecrets::Service; +// TODO: Only used for testing. Need to split service functions away from settings page. +QPointer<FdoSecretsPlugin> g_fdoSecretsPlugin; + FdoSecretsPlugin::FdoSecretsPlugin(DatabaseTabWidget* tabWidget) - : QObject(tabWidget) - , m_dbTabs(tabWidget) + : m_dbTabs(tabWidget) { + g_fdoSecretsPlugin = this; FdoSecrets::registerDBusTypes(); } +FdoSecretsPlugin* FdoSecretsPlugin::getPlugin() +{ + return g_fdoSecretsPlugin; +} + QWidget* FdoSecretsPlugin::createWidget() { return new SettingsWidgetFdoSecrets(this); diff --git a/src/fdosecrets/FdoSecretsPlugin.h b/src/fdosecrets/FdoSecretsPlugin.h index 674c3c3b8..d0008b80a 100644 --- a/src/fdosecrets/FdoSecretsPlugin.h +++ b/src/fdosecrets/FdoSecretsPlugin.h @@ -70,6 +70,9 @@ public: */ QString reportExistingService() const; + // TODO: Only used for testing. Need to split service functions away from settings page. + static FdoSecretsPlugin* getPlugin(); + public slots: void emitRequestSwitchToDatabases(); void emitRequestShowNotification(const QString& msg, const QString& title = {}); diff --git a/src/fdosecrets/objects/Service.cpp b/src/fdosecrets/objects/Service.cpp index 59f086107..892ba68a4 100644 --- a/src/fdosecrets/objects/Service.cpp +++ b/src/fdosecrets/objects/Service.cpp @@ -471,14 +471,14 @@ namespace FdoSecrets return collection; } - void Service::doSwitchToChangeDatabaseSettings(DatabaseWidget* dbWidget) + void Service::doSwitchToDatabaseSettings(DatabaseWidget* dbWidget) { if (dbWidget->isLocked()) { return; } // switch selected to current m_databases->setCurrentWidget(dbWidget); - m_databases->changeDatabaseSettings(); + m_databases->showDatabaseSettings(); // open settings (switch from app settings to m_dbTabs) m_plugin->emitRequestSwitchToDatabases(); diff --git a/src/fdosecrets/objects/Service.h b/src/fdosecrets/objects/Service.h index 5de48da1c..4e0eeb0ff 100644 --- a/src/fdosecrets/objects/Service.h +++ b/src/fdosecrets/objects/Service.h @@ -110,7 +110,7 @@ namespace FdoSecrets public slots: bool doCloseDatabase(DatabaseWidget* dbWidget); Collection* doNewDatabase(); - void doSwitchToChangeDatabaseSettings(DatabaseWidget* dbWidget); + void doSwitchToDatabaseSettings(DatabaseWidget* dbWidget); /** * Async, connect to signal doneUnlockDatabaseInDialog for finish notification diff --git a/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.cpp b/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.cpp index 7fb971c0e..9938def17 100644 --- a/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.cpp +++ b/src/fdosecrets/widgets/SettingsWidgetFdoSecrets.cpp @@ -71,7 +71,7 @@ namespace return; } auto db = m_dbWidget; - m_plugin->serviceInstance()->doSwitchToChangeDatabaseSettings(m_dbWidget); + m_plugin->serviceInstance()->doSwitchToDatabaseSettings(m_dbWidget); }); addAction(m_dbSettingsAct); diff --git a/src/format/Kdbx3Reader.cpp b/src/format/Kdbx3Reader.cpp index 002aa8af0..35244f618 100644 --- a/src/format/Kdbx3Reader.cpp +++ b/src/format/Kdbx3Reader.cpp @@ -50,7 +50,7 @@ bool Kdbx3Reader::readDatabaseImpl(QIODevice* device, bool ok = AsyncTask::runAndWaitForFuture([&] { return db->setKey(key, false); }); if (!ok) { - raiseError(tr("Unable to calculate master key")); + raiseError(tr("Unable to calculate database key")); return false; } @@ -62,7 +62,7 @@ bool Kdbx3Reader::readDatabaseImpl(QIODevice* device, CryptoHash hash(CryptoHash::Sha256); hash.addData(m_masterSeed); hash.addData(db->challengeResponseKey()); - hash.addData(db->transformedMasterKey()); + hash.addData(db->transformedDatabaseKey()); QByteArray finalKey = hash.result(); SymmetricCipher::Algorithm cipher = SymmetricCipher::cipherToAlgorithm(db->cipher()); diff --git a/src/format/Kdbx3Writer.cpp b/src/format/Kdbx3Writer.cpp index 7d492e4e7..b1c1b820a 100644 --- a/src/format/Kdbx3Writer.cpp +++ b/src/format/Kdbx3Writer.cpp @@ -47,16 +47,16 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db) } if (!db->setKey(db->key(), false, true)) { - raiseError(tr("Unable to calculate master key")); + raiseError(tr("Unable to calculate database key")); return false; } - // generate transformed master key + // generate transformed database key CryptoHash hash(CryptoHash::Sha256); hash.addData(masterSeed); hash.addData(db->challengeResponseKey()); - Q_ASSERT(!db->transformedMasterKey().isEmpty()); - hash.addData(db->transformedMasterKey()); + Q_ASSERT(!db->transformedDatabaseKey().isEmpty()); + hash.addData(db->transformedDatabaseKey()); QByteArray finalKey = hash.result(); // write header diff --git a/src/format/Kdbx4Reader.cpp b/src/format/Kdbx4Reader.cpp index f5e7382fe..baeab903c 100644 --- a/src/format/Kdbx4Reader.cpp +++ b/src/format/Kdbx4Reader.cpp @@ -50,13 +50,13 @@ bool Kdbx4Reader::readDatabaseImpl(QIODevice* device, bool ok = AsyncTask::runAndWaitForFuture([&] { return db->setKey(key, false, false); }); if (!ok) { - raiseError(tr("Unable to calculate master key: %1").arg(db->keyError())); + raiseError(tr("Unable to calculate database key: %1").arg(db->keyError())); return false; } CryptoHash hash(CryptoHash::Sha256); hash.addData(m_masterSeed); - hash.addData(db->transformedMasterKey()); + hash.addData(db->transformedDatabaseKey()); QByteArray finalKey = hash.result(); QByteArray headerSha256 = device->read(32); @@ -71,7 +71,7 @@ bool Kdbx4Reader::readDatabaseImpl(QIODevice* device, } // clang-format off - QByteArray hmacKey = KeePass2::hmacKey(m_masterSeed, db->transformedMasterKey()); + QByteArray hmacKey = KeePass2::hmacKey(m_masterSeed, db->transformedDatabaseKey()); if (headerHmac != CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256)) { raiseError(tr("Invalid credentials were provided, please try again.\n" "If this reoccurs, then your database file may be corrupt.") + " " + tr("(HMAC mismatch)")); diff --git a/src/format/Kdbx4Writer.cpp b/src/format/Kdbx4Writer.cpp index 57211248e..1810d9aa7 100644 --- a/src/format/Kdbx4Writer.cpp +++ b/src/format/Kdbx4Writer.cpp @@ -53,15 +53,15 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db) QByteArray endOfHeader = "\r\n\r\n"; if (!db->setKey(db->key(), false, true)) { - raiseError(tr("Unable to calculate master key: %1").arg(db->keyError())); + raiseError(tr("Unable to calculate database key: %1").arg(db->keyError())); return false; } - // generate transformed master key + // generate transformed database key CryptoHash hash(CryptoHash::Sha256); hash.addData(masterSeed); - Q_ASSERT(!db->transformedMasterKey().isEmpty()); - hash.addData(db->transformedMasterKey()); + Q_ASSERT(!db->transformedDatabaseKey().isEmpty()); + hash.addData(db->transformedDatabaseKey()); QByteArray finalKey = hash.result(); // write header @@ -109,7 +109,7 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db) QByteArray headerHash = CryptoHash::hash(headerData, CryptoHash::Sha256); // write HMAC-authenticated cipher stream - QByteArray hmacKey = KeePass2::hmacKey(masterSeed, db->transformedMasterKey()); + QByteArray hmacKey = KeePass2::hmacKey(masterSeed, db->transformedDatabaseKey()); QByteArray headerHmac = CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256); CHECK_RETURN_FALSE(writeData(device, headerHash)); diff --git a/src/format/KdbxXmlReader.cpp b/src/format/KdbxXmlReader.cpp index ecc4111bf..8466dde7f 100644 --- a/src/format/KdbxXmlReader.cpp +++ b/src/format/KdbxXmlReader.cpp @@ -262,7 +262,7 @@ void KdbxXmlReader::parseMeta() } else if (m_xml.name() == "Color") { m_meta->setColor(readColor()); } else if (m_xml.name() == "MasterKeyChanged") { - m_meta->setMasterKeyChanged(readDateTime()); + m_meta->setDatabaseKeyChanged(readDateTime()); } else if (m_xml.name() == "MasterKeyChangeRec") { m_meta->setMasterKeyChangeRec(readNumber()); } else if (m_xml.name() == "MasterKeyChangeForce") { diff --git a/src/format/KdbxXmlWriter.cpp b/src/format/KdbxXmlWriter.cpp index 14d920439..701c246bd 100644 --- a/src/format/KdbxXmlWriter.cpp +++ b/src/format/KdbxXmlWriter.cpp @@ -112,9 +112,9 @@ void KdbxXmlWriter::writeMetadata() writeDateTime("DefaultUserNameChanged", m_meta->defaultUserNameChanged()); writeNumber("MaintenanceHistoryDays", m_meta->maintenanceHistoryDays()); writeString("Color", m_meta->color()); - writeDateTime("MasterKeyChanged", m_meta->masterKeyChanged()); - writeNumber("MasterKeyChangeRec", m_meta->masterKeyChangeRec()); - writeNumber("MasterKeyChangeForce", m_meta->masterKeyChangeForce()); + writeDateTime("MasterKeyChanged", m_meta->databaseKeyChanged()); + writeNumber("MasterKeyChangeRec", m_meta->databaseKeyChangeRec()); + writeNumber("MasterKeyChangeForce", m_meta->databaseKeyChangeForce()); writeMemoryProtection(); writeCustomIcons(); writeBool("RecycleBinEnabled", m_meta->recycleBinEnabled()); diff --git a/src/format/KeePass1Reader.cpp b/src/format/KeePass1Reader.cpp index 0319b1b2d..80e84d8cd 100644 --- a/src/format/KeePass1Reader.cpp +++ b/src/format/KeePass1Reader.cpp @@ -242,7 +242,7 @@ KeePass1Reader::readDatabase(QIODevice* device, const QString& password, QIODevi } if (!db->setKey(key)) { - raiseError(tr("Unable to calculate master key")); + raiseError(tr("Unable to calculate database key")); return {}; } diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index d256fde8a..b97d62590 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -30,11 +30,10 @@ static const QString aboutMaintainers = R"( <p><ul> <li>Jonathan White (<a href="https://github.com/droidmonkey">droidmonkey</a>)</li> <li>Janek Bevendorff (<a href="https://github.com/phoerious">phoerious</a>)</li> - <li><a href="https://github.com/TheZ3ro">TheZ3ro</a></li> - <li>Louis-Bertrand (<a href="https://github.com/louib">louib</a>)</li> - <li>Weslly Honorato (<a href="https://github.com/weslly">weslly</a>)</li> - <li>Toni Spets (<a href="https://github.com/hifi">hifi</a>)</li> <li>Sami Vänttinen (<a href="https://github.com/varjolintu">varjolintu</a>)</li> + <li>Toni Spets (<a href="https://github.com/hifi">hifi</a>)</li> + <li>Louis-Bertrand (<a href="https://github.com/louib">louib</a>)</li> + <li><a href="https://github.com/TheZ3ro">TheZ3ro</a> (retired)</li> </ul></p> )"; @@ -57,19 +56,21 @@ static const QString aboutContributors = R"( <li>Riley Moses</li> <li>Korbinian Schildmann</li> <li>Andreas (nitrohorse)</li> + <li>Kernellinux</li> + <li>Micha Ober</li> + <li>PublicByte</li> </ul> <h3>Notable Code Contributions:</h3> <ul> <li>droidmonkey</li> <li>phoerious</li> - <li>TheZ3ro</li> - <li>louib</li> - <li>weslly</li> - <li>varjolintu (KeePassXC-Browser)</li> + <li>louib (CLI)</li> + <li>varjolintu (Browser Integration)</li> <li>hifi (SSH Agent)</li> <li>ckieschnick (KeeShare)</li> <li>seatedscribe (CSV Import)</li> - <li>Aetf (Secret Storage Server)</li> + <li>Aetf (FdoSecrets Storage Server)</li> + <li>weslly (macOS improvements)</li> <li>brainplot (many improvements)</li> <li>kneitinger (many improvements)</li> <li>frostasm (many improvements)</li> @@ -78,43 +79,45 @@ static const QString aboutContributors = R"( <li>c4rlo (Offline HIBP Checker)</li> <li>wolframroesler (HTML Export, Statistics, Password Health, HIBP integration)</li> <li>mdaniel (OpVault Importer)</li> - <li>keithbennett (KeePassHTTP)</li> - <li>Typz (KeePassHTTP)</li> - <li>denk-mal (KeePassHTTP)</li> <li>angelsl (KDBX 4)</li> + <li>TheZ3ro (retired lead)</li> <li>debfx (KeePassX)</li> <li>BlueIce (KeePassX)</li> </ul> <h3>Patreon Supporters:</h3> <ul> + <li>Igor Zinovik</li> <li>Alexanderjb</li> - <li>Andreas Kollmann</li> <li>Richard Ames</li> - <li>Christian Rasmussen</li> - <li>Gregory Werbin</li> - <li>Nuutti Toivola</li> <li>SLmanDR</li> - <li>Ashura</li> + <li>Christian Rasmussen</li> <li>Tyler Gass</li> - <li>Lionel Laské</li> - <li>Dmitrii Galinskii</li> - <li>Sergei Maximov</li> - <li>John-Ivar</li> - <li>Clayton Casciato</li> - <li>John</li> + <li>Nuutti Toivola</li> + <li>Gregory Werbin</li> + <li>Lionel Laské</li> + <li>Ivar</li> <li>Darren</li> <li>Brad</li> <li>Mathieu Peltier</li> + <li>gonczor</li> <li>Oleksii Aleksieiev</li> - <li>Daniel Epp</li> <li>Gernot Premper</li> <li>Julian Stier</li> - <li>gonczor</li> + <li>Daniel Epp</li> <li>Ruben Schade</li> <li>Esteban Martinez</li> + <li>Niels Ganser</li> <li>turin231</li> <li>judd</li> - <li>Niels Ganser</li> + <li>Tarek Sherif</li> + <li>Bernhard</li> + <li>William Komanetsky</li> + <li>Clark Henry</li> + <li>Justin Carroll</li> + <li>Shintaro Matsushima</li> + <li>Larry Siden</li> + <li>Thammachart Chinvarapon</li> + <li>Patrick Evans</li> </ul> <h3>Translations:</h3> <ul> diff --git a/src/gui/Application.cpp b/src/gui/Application.cpp index 273ab8763..625540c1d 100644 --- a/src/gui/Application.cpp +++ b/src/gui/Application.cpp @@ -315,3 +315,16 @@ bool Application::isDarkTheme() const { return m_darkTheme; } + +void Application::restart() +{ + // Disable single instance + m_lockServer.close(); + if (m_lockFile) { + m_lockFile->unlock(); + delete m_lockFile; + m_lockFile = nullptr; + } + + exit(RESTART_EXITCODE); +} diff --git a/src/gui/Application.h b/src/gui/Application.h index 21dff6aff..9f694f8c3 100644 --- a/src/gui/Application.h +++ b/src/gui/Application.h @@ -31,6 +31,8 @@ class OSEventFilter; class QLockFile; class QSocketNotifier; +constexpr int RESTART_EXITCODE = -1; + class Application : public QApplication { Q_OBJECT @@ -47,6 +49,8 @@ public: bool sendFileNamesToRunningInstance(const QStringList& fileNames); + void restart(); + signals: void openFile(const QString& filename); void anotherInstanceStarted(); diff --git a/src/gui/ApplicationSettingsWidget.cpp b/src/gui/ApplicationSettingsWidget.cpp index d3fa1ea4f..691115368 100644 --- a/src/gui/ApplicationSettingsWidget.cpp +++ b/src/gui/ApplicationSettingsWidget.cpp @@ -106,7 +106,6 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent) connect(m_generalUi->autoSaveAfterEveryChangeCheckBox, SIGNAL(toggled(bool)), SLOT(autoSaveToggled(bool))); connect(m_generalUi->hideWindowOnCopyCheckBox, SIGNAL(toggled(bool)), SLOT(hideWindowOnCopyCheckBoxToggled(bool))); connect(m_generalUi->systrayShowCheckBox, SIGNAL(toggled(bool)), SLOT(systrayToggled(bool))); - connect(m_generalUi->toolbarHideCheckBox, SIGNAL(toggled(bool)), SLOT(toolbarSettingsToggled(bool))); connect(m_generalUi->rememberLastDatabasesCheckBox, SIGNAL(toggled(bool)), SLOT(rememberDatabasesToggled(bool))); connect(m_generalUi->resetSettingsButton, SIGNAL(clicked()), SLOT(resetSettings())); @@ -126,7 +125,6 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent) m_generalUi->faviconTimeoutSpinBox->installEventFilter(mouseWheelFilter); m_generalUi->toolButtonStyleComboBox->installEventFilter(mouseWheelFilter); m_generalUi->languageComboBox->installEventFilter(mouseWheelFilter); - m_generalUi->appThemeSelection->installEventFilter(mouseWheelFilter); #ifdef WITH_XC_UPDATECHECK connect(m_generalUi->checkForUpdatesOnStartupCheckBox, SIGNAL(toggled(bool)), SLOT(checkUpdatesToggled(bool))); @@ -210,20 +208,9 @@ void ApplicationSettingsWidget::loadSettings() m_generalUi->languageComboBox->setCurrentIndex(defaultIndex); } - m_generalUi->previewHideCheckBox->setChecked(config()->get(Config::GUI_HidePreviewPanel).toBool()); - m_generalUi->toolbarHideCheckBox->setChecked(config()->get(Config::GUI_HideToolbar).toBool()); - toolbarSettingsToggled(m_generalUi->toolbarHideCheckBox->isChecked()); m_generalUi->toolbarMovableCheckBox->setChecked(config()->get(Config::GUI_MovableToolbar).toBool()); m_generalUi->monospaceNotesCheckBox->setChecked(config()->get(Config::GUI_MonospaceNotes).toBool()); - m_generalUi->appThemeSelection->clear(); - m_generalUi->appThemeSelection->addItem(tr("Automatic"), "auto"); - m_generalUi->appThemeSelection->addItem(tr("Light"), "light"); - m_generalUi->appThemeSelection->addItem(tr("Dark"), "dark"); - m_generalUi->appThemeSelection->addItem(tr("Classic (Platform-native)"), "classic"); - m_generalUi->appThemeSelection->setCurrentIndex( - m_generalUi->appThemeSelection->findData(config()->get(Config::GUI_ApplicationTheme).toString())); - m_generalUi->toolButtonStyleComboBox->clear(); m_generalUi->toolButtonStyleComboBox->addItem(tr("Icon only"), Qt::ToolButtonIconOnly); m_generalUi->toolButtonStyleComboBox->addItem(tr("Text only"), Qt::ToolButtonTextOnly); @@ -338,14 +325,9 @@ void ApplicationSettingsWidget::saveSettings() config()->set(Config::FaviconDownloadTimeout, m_generalUi->faviconTimeoutSpinBox->value()); config()->set(Config::GUI_Language, m_generalUi->languageComboBox->currentData().toString()); - config()->set(Config::GUI_HidePreviewPanel, m_generalUi->previewHideCheckBox->isChecked()); - config()->set(Config::GUI_HideToolbar, m_generalUi->toolbarHideCheckBox->isChecked()); config()->set(Config::GUI_MovableToolbar, m_generalUi->toolbarMovableCheckBox->isChecked()); config()->set(Config::GUI_MonospaceNotes, m_generalUi->monospaceNotesCheckBox->isChecked()); - QString theme = m_generalUi->appThemeSelection->currentData().toString(); - config()->set(Config::GUI_ApplicationTheme, theme); - config()->set(Config::GUI_ToolButtonStyle, m_generalUi->toolButtonStyleComboBox->currentData().toString()); config()->set(Config::GUI_ShowTrayIcon, m_generalUi->systrayShowCheckBox->isChecked()); @@ -481,13 +463,6 @@ void ApplicationSettingsWidget::systrayToggled(bool checked) m_generalUi->systrayMinimizeToTrayCheckBox->setEnabled(checked); } -void ApplicationSettingsWidget::toolbarSettingsToggled(bool checked) -{ - m_generalUi->toolbarMovableCheckBox->setEnabled(!checked); - m_generalUi->toolButtonStyleComboBox->setEnabled(!checked); - m_generalUi->toolButtonStyleLabel->setEnabled(!checked); -} - void ApplicationSettingsWidget::rememberDatabasesToggled(bool checked) { if (!checked) { diff --git a/src/gui/ApplicationSettingsWidget.h b/src/gui/ApplicationSettingsWidget.h index 63487e1b5..f36e5ef12 100644 --- a/src/gui/ApplicationSettingsWidget.h +++ b/src/gui/ApplicationSettingsWidget.h @@ -60,7 +60,6 @@ private slots: void autoSaveToggled(bool checked); void hideWindowOnCopyCheckBoxToggled(bool checked); void systrayToggled(bool checked); - void toolbarSettingsToggled(bool checked); void rememberDatabasesToggled(bool checked); void checkUpdatesToggled(bool checked); diff --git a/src/gui/ApplicationSettingsWidgetGeneral.ui b/src/gui/ApplicationSettingsWidgetGeneral.ui index fea7481aa..7324c5ab7 100644 --- a/src/gui/ApplicationSettingsWidgetGeneral.ui +++ b/src/gui/ApplicationSettingsWidgetGeneral.ui @@ -307,13 +307,6 @@ </property> </widget> </item> - <item> - <widget class="QCheckBox" name="previewHideCheckBox"> - <property name="text"> - <string>Hide the entry preview panel</string> - </property> - </widget> - </item> <item> <widget class="QCheckBox" name="minimizeOnOpenUrlCheckBox"> <property name="text"> @@ -460,8 +453,8 @@ <property name="horizontalSpacing"> <number>10</number> </property> - <item row="0" column="1"> - <widget class="QComboBox" name="appThemeSelection"> + <item row="1" column="1"> + <widget class="QComboBox" name="toolButtonStyleComboBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> <horstretch>0</horstretch> @@ -472,51 +465,30 @@ <enum>Qt::StrongFocus</enum> </property> <property name="accessibleName"> - <string>Application Theme Selection</string> + <string>Toolbar button style</string> </property> - </widget> - </item> - <item row="0" column="3"> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>(restart program to activate)</string> + <property name="sizeAdjustPolicy"> + <enum>QComboBox::AdjustToContents</enum> </property> </widget> </item> <item row="1" column="2"> - <widget class="QLabel" name="languageLabel_3"> + <widget class="QCheckBox" name="toolbarMovableCheckBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> <property name="text"> - <string>(restart program to activate)</string> + <string>Movable toolbar</string> </property> </widget> </item> - <item row="0" column="0"> - <widget class="QLabel" name="appThemeLabel"> - <property name="text"> - <string>Application theme:</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="buddy"> - <cstring>appThemeSelection</cstring> - </property> - </widget> - </item> - <item row="1" column="1"> + <item row="0" column="1"> <widget class="QComboBox" name="languageComboBox"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> @@ -532,7 +504,7 @@ </property> </widget> </item> - <item row="1" column="0"> + <item row="0" column="0"> <widget class="QLabel" name="languageLabel_2"> <property name="sizePolicy"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> @@ -551,7 +523,27 @@ </property> </widget> </item> - <item row="2" column="0"> + <item row="0" column="2"> + <widget class="QLabel" name="languageLabel_3"> + <property name="text"> + <string>(restart program to activate)</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> <widget class="QLabel" name="toolButtonStyleLabel"> <property name="enabled"> <bool>true</bool> @@ -576,66 +568,8 @@ </property> </widget> </item> - <item row="2" column="1"> - <widget class="QComboBox" name="toolButtonStyleComboBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="focusPolicy"> - <enum>Qt::StrongFocus</enum> - </property> - <property name="accessibleName"> - <string>Toolbar button style</string> - </property> - <property name="sizeAdjustPolicy"> - <enum>QComboBox::AdjustToContents</enum> - </property> - </widget> - </item> </layout> </item> - <item> - <spacer name="verticalSpacer_5"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>10</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QCheckBox" name="toolbarHideCheckBox"> - <property name="text"> - <string>Hide toolbar</string> - </property> - </widget> - </item> - <item> - <widget class="QCheckBox" name="toolbarMovableCheckBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Movable toolbar</string> - </property> - </widget> - </item> <item> <widget class="QCheckBox" name="monospaceNotesCheckBox"> <property name="text"> @@ -1102,20 +1036,18 @@ <tabstop>autoReloadOnChangeCheckBox</tabstop> <tabstop>useAtomicSavesCheckBox</tabstop> <tabstop>useGroupIconOnEntryCreationCheckBox</tabstop> - <tabstop>previewHideCheckBox</tabstop> <tabstop>minimizeOnOpenUrlCheckBox</tabstop> <tabstop>hideWindowOnCopyCheckBox</tabstop> <tabstop>minimizeOnCopyRadioButton</tabstop> <tabstop>dropToBackgroundOnCopyRadioButton</tabstop> <tabstop>faviconTimeoutSpinBox</tabstop> - <tabstop>appThemeSelection</tabstop> <tabstop>languageComboBox</tabstop> <tabstop>toolButtonStyleComboBox</tabstop> - <tabstop>toolbarHideCheckBox</tabstop> - <tabstop>toolbarMovableCheckBox</tabstop> <tabstop>monospaceNotesCheckBox</tabstop> + <tabstop>toolbarMovableCheckBox</tabstop> <tabstop>minimizeOnCloseCheckBox</tabstop> <tabstop>systrayShowCheckBox</tabstop> + <tabstop>trayIconAppearance</tabstop> <tabstop>systrayMinimizeToTrayCheckBox</tabstop> <tabstop>resetSettingsButton</tabstop> <tabstop>autoTypeEntryTitleMatchCheckBox</tabstop> diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index c3a780112..4dbe9dc9d 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -199,8 +199,8 @@ void DatabaseOpenWidget::openDatabase() { m_ui->messageWidget->hide(); - QSharedPointer<CompositeKey> masterKey = databaseKey(); - if (!masterKey) { + QSharedPointer<CompositeKey> databaseKey = buildDatabaseKey(); + if (!databaseKey) { return; } @@ -213,7 +213,7 @@ void DatabaseOpenWidget::openDatabase() QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); m_ui->passwordFormFrame->setEnabled(false); QCoreApplication::processEvents(); - bool ok = m_db->open(m_filename, masterKey, &error, false); + bool ok = m_db->open(m_filename, databaseKey, &error, false); QApplication::restoreOverrideCursor(); m_ui->passwordFormFrame->setEnabled(true); @@ -271,12 +271,12 @@ void DatabaseOpenWidget::openDatabase() } } -QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() +QSharedPointer<CompositeKey> DatabaseOpenWidget::buildDatabaseKey() { - auto masterKey = QSharedPointer<CompositeKey>::create(); + auto databaseKey = QSharedPointer<CompositeKey>::create(); if (!m_ui->editPassword->text().isEmpty() || m_retryUnlockWithEmptyPassword) { - masterKey->addKey(QSharedPointer<PasswordKey>::create(m_ui->editPassword->text())); + databaseKey->addKey(QSharedPointer<PasswordKey>::create(m_ui->editPassword->text())); } #ifdef WITH_XC_TOUCHID @@ -284,7 +284,7 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() if (m_ui->checkTouchID->isChecked() && TouchID::getInstance().isAvailable() && m_ui->editPassword->text().isEmpty()) { // clear empty password from composite key - masterKey->clear(); + databaseKey->clear(); // try to get, decrypt and use PasswordKey QSharedPointer<QByteArray> passwordKey = TouchID::getInstance().getKey(m_filename); @@ -293,7 +293,7 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() if (passwordKey.isNull()) return QSharedPointer<CompositeKey>(); - masterKey->addKey(PasswordKey::fromRawKey(*passwordKey)); + databaseKey->addKey(PasswordKey::fromRawKey(*passwordKey)); } } #endif @@ -326,7 +326,7 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() legacyWarning.exec(); } - masterKey->addKey(key); + databaseKey->addKey(key); lastKeyFiles.insert(m_filename, keyFilename); } @@ -342,7 +342,7 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() if (selectionIndex > 0) { auto slot = m_ui->challengeResponseCombo->itemData(selectionIndex).value<YubiKeySlot>(); auto crKey = QSharedPointer<YkChallengeResponseKey>(new YkChallengeResponseKey(slot)); - masterKey->addChallengeResponseKey(crKey); + databaseKey->addChallengeResponseKey(crKey); // Qt doesn't read custom types in settings so stuff into a QString lastChallengeResponse.insert(m_filename, QStringLiteral("%1:%2").arg(slot.first).arg(slot.second)); @@ -353,7 +353,7 @@ QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() } #endif - return masterKey; + return databaseKey; } void DatabaseOpenWidget::reject() diff --git a/src/gui/DatabaseOpenWidget.h b/src/gui/DatabaseOpenWidget.h index a7505d190..6d2b688ca 100644 --- a/src/gui/DatabaseOpenWidget.h +++ b/src/gui/DatabaseOpenWidget.h @@ -52,7 +52,7 @@ signals: protected: void showEvent(QShowEvent* event) override; void hideEvent(QHideEvent* event) override; - QSharedPointer<CompositeKey> databaseKey(); + QSharedPointer<CompositeKey> buildDatabaseKey(); const QScopedPointer<Ui::DatabaseOpenWidget> m_ui; QSharedPointer<Database> m_db; diff --git a/src/gui/DatabaseOpenWidget.ui b/src/gui/DatabaseOpenWidget.ui index cd2d0b438..a7510baba 100644 --- a/src/gui/DatabaseOpenWidget.ui +++ b/src/gui/DatabaseOpenWidget.ui @@ -250,7 +250,7 @@ <enum>Qt::ClickFocus</enum> </property> <property name="toolTip"> - <string><p>In addition to your master password, you can use a secret file to enhance the security of your database. Such a file can be generated in your database's security settings.</p><p>This is <strong>not</strong> your *.kdbx database file!<br>If you do not have a key file, leave the field empty.</p><p>Click for more information...</p></string> + <string><p>In addition to a password, you can use a secret file to enhance the security of your database. This file can be generated in your database's security settings.</p><p>This is <strong>not</strong> your *.kdbx database file!<br>If you do not have a key file, leave this field empty.</p><p>Click for more information...</p></string> </property> <property name="accessibleName"> <string>Key file help</string> diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 7408c4900..34fe4db72 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -476,17 +476,17 @@ bool DatabaseTabWidget::warnOnExport() return ans == MessageBox::Yes; } -void DatabaseTabWidget::changeMasterKey() +void DatabaseTabWidget::showDatabaseSecurity() { - currentDatabaseWidget()->switchToMasterKeyChange(); + currentDatabaseWidget()->switchToDatabaseSecurity(); } -void DatabaseTabWidget::changeReports() +void DatabaseTabWidget::showDatabaseReports() { - currentDatabaseWidget()->switchToReports(); + currentDatabaseWidget()->switchToDatabaseReports(); } -void DatabaseTabWidget::changeDatabaseSettings() +void DatabaseTabWidget::showDatabaseSettings() { currentDatabaseWidget()->switchToDatabaseSettings(); } diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index 89086e5ec..e59681ea7 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -78,9 +78,9 @@ public slots: void unlockDatabaseInDialog(DatabaseWidget* dbWidget, DatabaseOpenDialog::Intent intent, const QString& filePath); void relockPendingDatabase(); - void changeMasterKey(); - void changeReports(); - void changeDatabaseSettings(); + void showDatabaseSecurity(); + void showDatabaseReports(); + void showDatabaseSettings(); void performGlobalAutoType(); void performBrowserUnlock(); diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index f0fa8049b..61f2b2163 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -1219,7 +1219,7 @@ void DatabaseWidget::entryActivationSignalReceived(Entry* entry, EntryModel::Mod } } -void DatabaseWidget::switchToReports() +void DatabaseWidget::switchToDatabaseReports() { m_reportsDialog->load(m_db); setCurrentWidget(m_reportsDialog); @@ -1307,10 +1307,10 @@ void DatabaseWidget::sortGroupsDesc() m_groupView->sortGroups(true); } -void DatabaseWidget::switchToMasterKeyChange() +void DatabaseWidget::switchToDatabaseSecurity() { switchToDatabaseSettings(); - m_databaseSettingDialog->showMasterKeySettings(); + m_databaseSettingDialog->showDatabaseKeySettings(); } void DatabaseWidget::performUnlockDatabase(const QString& password, const QString& keyfile) diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 9243669b0..a31dfd37b 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -197,8 +197,8 @@ public slots: void switchToGroupEdit(); void sortGroupsAsc(); void sortGroupsDesc(); - void switchToMasterKeyChange(); - void switchToReports(); + void switchToDatabaseSecurity(); + void switchToDatabaseReports(); void switchToDatabaseSettings(); void switchToOpenDatabase(); void switchToOpenDatabase(const QString& filePath); diff --git a/src/gui/EntryPreviewWidget.cpp b/src/gui/EntryPreviewWidget.cpp index eee1dd00d..b873800a8 100644 --- a/src/gui/EntryPreviewWidget.cpp +++ b/src/gui/EntryPreviewWidget.cpp @@ -77,6 +77,12 @@ EntryPreviewWidget::EntryPreviewWidget(QWidget* parent) connect(m_ui->entryTabWidget, SIGNAL(tabBarClicked(int)), SLOT(updateTabIndexes()), Qt::QueuedConnection); connect(&m_totpTimer, SIGNAL(timeout()), SLOT(updateTotpLabel())); + connect(config(), &Config::changed, this, [this](Config::ConfigKey key) { + if (key == Config::GUI_HidePreviewPanel) { + setVisible(!config()->get(Config::GUI_HidePreviewPanel).toBool()); + } + }); + // Group m_ui->groupCloseButton->setIcon(resources()->icon("dialog-close")); connect(m_ui->groupCloseButton, SIGNAL(clicked()), SLOT(hide())); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 3f85390f8..9751a3e77 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -37,6 +37,7 @@ #include "core/Tools.h" #include "gui/AboutDialog.h" #include "gui/DatabaseWidget.h" +#include "gui/MessageBox.h" #include "gui/SearchWidget.h" #include "keys/CompositeKey.h" #include "keys/FileKey.h" @@ -50,7 +51,6 @@ #endif #ifdef WITH_XC_UPDATECHECK -#include "gui/MessageBox.h" #include "gui/UpdateCheckDialog.h" #include "updatecheck/UpdateChecker.h" #endif @@ -107,6 +107,10 @@ MainWindow::MainWindow() setAcceptDrops(true); + if (config()->get(Config::GUI_CompactMode).toBool()) { + m_ui->toolBar->setIconSize({20, 20}); + } + // Setup the search widget in the toolbar m_searchWidget = new SearchWidget(); m_searchWidget->connectSignals(m_actionMultiplexer); @@ -167,6 +171,8 @@ MainWindow::MainWindow() m_ui->actionEntryAddToAgent->setVisible(false); m_ui->actionEntryRemoveFromAgent->setVisible(false); + initViewMenu(); + #if defined(WITH_XC_KEESHARE) KeeShare::init(this); m_ui->settingsWidget->addSettingsPage(new SettingsPageKeeShare(m_ui->tabWidget)); @@ -334,7 +340,7 @@ MainWindow::MainWindow() m_ui->actionDatabaseClose->setIcon(resources()->icon("document-close")); m_ui->actionReports->setIcon(resources()->icon("reports")); m_ui->actionDatabaseSettings->setIcon(resources()->icon("document-edit")); - m_ui->actionChangeMasterKey->setIcon(resources()->icon("database-change-key")); + m_ui->actionDatabaseSecurity->setIcon(resources()->icon("database-change-key")); m_ui->actionLockDatabases->setIcon(resources()->icon("database-lock")); m_ui->actionQuit->setIcon(resources()->icon("application-exit")); m_ui->actionDatabaseMerge->setIcon(resources()->icon("database-merge")); @@ -411,9 +417,9 @@ MainWindow::MainWindow() connect(m_ui->actionDatabaseSaveBackup, SIGNAL(triggered()), m_ui->tabWidget, SLOT(saveDatabaseBackup())); connect(m_ui->actionDatabaseClose, SIGNAL(triggered()), m_ui->tabWidget, SLOT(closeCurrentDatabaseTab())); connect(m_ui->actionDatabaseMerge, SIGNAL(triggered()), m_ui->tabWidget, SLOT(mergeDatabase())); - connect(m_ui->actionChangeMasterKey, SIGNAL(triggered()), m_ui->tabWidget, SLOT(changeMasterKey())); - connect(m_ui->actionReports, SIGNAL(triggered()), m_ui->tabWidget, SLOT(changeReports())); - connect(m_ui->actionDatabaseSettings, SIGNAL(triggered()), m_ui->tabWidget, SLOT(changeDatabaseSettings())); + connect(m_ui->actionDatabaseSecurity, SIGNAL(triggered()), m_ui->tabWidget, SLOT(showDatabaseSecurity())); + connect(m_ui->actionReports, SIGNAL(triggered()), m_ui->tabWidget, SLOT(showDatabaseReports())); + connect(m_ui->actionDatabaseSettings, SIGNAL(triggered()), m_ui->tabWidget, SLOT(showDatabaseSettings())); connect(m_ui->actionImportCsv, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importCsv())); connect(m_ui->actionImportKeePass1, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importKeePass1Database())); connect(m_ui->actionImportOpVault, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importOpVaultDatabase())); @@ -521,8 +527,6 @@ MainWindow::MainWindow() m_trayIconTriggerTimer.setSingleShot(true); connect(&m_trayIconTriggerTimer, SIGNAL(timeout()), SLOT(processTrayIconTrigger())); - updateTrayIcon(); - if (config()->hasAccessError()) { m_ui->globalMessageWidget->showMessage(tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error); @@ -724,7 +728,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionGroupDownloadFavicons->setVisible(!recycleBinSelected); m_ui->actionGroupDownloadFavicons->setEnabled(groupSelected && currentGroupHasEntries && !recycleBinSelected); - m_ui->actionChangeMasterKey->setEnabled(true); + m_ui->actionDatabaseSecurity->setEnabled(true); m_ui->actionReports->setEnabled(true); m_ui->actionDatabaseSettings->setEnabled(true); m_ui->actionDatabaseSave->setEnabled(m_ui->tabWidget->canSave()); @@ -780,7 +784,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) action->setEnabled(false); } - m_ui->actionChangeMasterKey->setEnabled(false); + m_ui->actionDatabaseSecurity->setEnabled(false); m_ui->actionReports->setEnabled(false); m_ui->actionDatabaseSettings->setEnabled(false); m_ui->actionDatabaseSave->setEnabled(false); @@ -809,7 +813,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) action->setEnabled(false); } - m_ui->actionChangeMasterKey->setEnabled(false); + m_ui->actionDatabaseSecurity->setEnabled(false); m_ui->actionReports->setEnabled(false); m_ui->actionDatabaseSettings->setEnabled(false); m_ui->actionDatabaseSave->setEnabled(false); @@ -960,12 +964,12 @@ void MainWindow::openBugReportUrl() void MainWindow::openGettingStartedGuide() { - customOpenUrl(QString("file:///%1").arg(resources()->dataPath("docs/KeePassXC_GettingStarted.pdf"))); + customOpenUrl(QString("file:///%1").arg(resources()->dataPath("docs/KeePassXC_GettingStarted.html"))); } void MainWindow::openUserGuide() { - customOpenUrl(QString("file:///%1").arg(resources()->dataPath("docs/KeePassXC_UserGuide.pdf"))); + customOpenUrl(QString("file:///%1").arg(resources()->dataPath("docs/KeePassXC_UserGuide.html"))); } void MainWindow::openOnlineHelp() @@ -975,7 +979,7 @@ void MainWindow::openOnlineHelp() void MainWindow::openKeyboardShortcuts() { - customOpenUrl("https://github.com/keepassxreboot/keepassxc/blob/develop/docs/KEYBINDS.md"); + customOpenUrl(QString("file:///%1").arg(resources()->dataPath("docs/KeePassXC_KeyboardShortcuts.html"))); } void MainWindow::switchToDatabases() @@ -1132,11 +1136,12 @@ void MainWindow::closeEvent(QCloseEvent* event) if (m_appExiting) { saveWindowInformation(); event->accept(); - QApplication::quit(); + m_restartRequested ? kpxcApp->restart() : QApplication::quit(); return; } m_appExitCalled = false; + m_restartRequested = false; event->ignore(); } @@ -1328,14 +1333,14 @@ void MainWindow::applySettingsChanges() } #ifdef WITH_XC_TOUCHID - // forget TouchID (in minutes) - timeout = config()->get(Config::Security_ResetTouchIdTimeout).toInt() * 60 * 1000; - if (timeout <= 0) { - timeout = 30 * 60 * 1000; - } + if (config()->get(Config::Security_ResetTouchId).toBool()) { + // Calculate TouchID timeout in milliseconds + timeout = config()->get(Config::Security_ResetTouchIdTimeout).toInt() * 60 * 1000; + if (timeout <= 0) { + timeout = 30 * 60 * 1000; + } - m_touchIDinactivityTimer->setInactivityTimeout(timeout); - if (config()->get(Config::Security_ResetTouchIdTimeout).toBool()) { + m_touchIDinactivityTimer->setInactivityTimeout(timeout); m_touchIDinactivityTimer->activate(); } else { m_touchIDinactivityTimer->deactivate(); @@ -1639,3 +1644,62 @@ void MainWindow::displayDesktopNotification(const QString& msg, QString title, i m_trayIcon->showMessage(title, msg, QSystemTrayIcon::Information, msTimeoutHint); #endif } + +void MainWindow::restartApp(const QString& message) +{ + auto ans = MessageBox::question( + this, tr("Restart Application?"), message, MessageBox::Yes | MessageBox::No, MessageBox::Yes); + if (ans == MessageBox::Yes) { + m_appExitCalled = true; + m_restartRequested = true; + close(); + } else { + m_restartRequested = false; + } +} + +void MainWindow::initViewMenu() +{ + m_ui->actionThemeAuto->setData("auto"); + m_ui->actionThemeLight->setData("light"); + m_ui->actionThemeDark->setData("dark"); + m_ui->actionThemeClassic->setData("classic"); + + auto themeActions = new QActionGroup(this); + themeActions->addAction(m_ui->actionThemeAuto); + themeActions->addAction(m_ui->actionThemeLight); + themeActions->addAction(m_ui->actionThemeDark); + themeActions->addAction(m_ui->actionThemeClassic); + + auto theme = config()->get(Config::GUI_ApplicationTheme).toString(); + for (auto action : themeActions->actions()) { + if (action->data() == theme) { + action->setChecked(true); + break; + } + } + + connect(themeActions, &QActionGroup::triggered, this, [this](QAction* action) { + if (action->data() != config()->get(Config::GUI_ApplicationTheme)) { + config()->set(Config::GUI_ApplicationTheme, action->data()); + restartApp(tr("You must restart the application to apply this setting. Would you like to restart now?")); + } + }); + + m_ui->actionCompactMode->setChecked(config()->get(Config::GUI_CompactMode).toBool()); + connect(m_ui->actionCompactMode, &QAction::toggled, this, [this](bool checked) { + config()->set(Config::GUI_CompactMode, checked); + restartApp(tr("You must restart the application to apply this setting. Would you like to restart now?")); + }); + + m_ui->actionShowToolbar->setChecked(!config()->get(Config::GUI_HideToolbar).toBool()); + connect(m_ui->actionShowToolbar, &QAction::toggled, this, [this](bool checked) { + config()->set(Config::GUI_HideToolbar, !checked); + applySettingsChanges(); + }); + + m_ui->actionShowPreviewPanel->setChecked(!config()->get(Config::GUI_HidePreviewPanel).toBool()); + connect(m_ui->actionShowPreviewPanel, &QAction::toggled, this, [](bool checked) { + config()->set(Config::GUI_HidePreviewPanel, !checked); + }); +} diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 230e6256e..95e8e5a8b 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -81,6 +81,7 @@ public slots: void closeAllDatabases(); void lockAllDatabases(); void displayDesktopNotification(const QString& msg, QString title = "", int msTimeoutHint = 10000); + void restartApp(const QString& message); protected: void closeEvent(QCloseEvent* event) override; @@ -152,6 +153,8 @@ private: void dragEnterEvent(QDragEnterEvent* event) override; void dropEvent(QDropEvent* event) override; + void initViewMenu(); + const QScopedPointer<Ui::MainWindow> m_ui; SignalMultiplexer m_actionMultiplexer; QPointer<QAction> m_clearHistoryAction; @@ -171,6 +174,7 @@ private: bool m_appExitCalled = false; bool m_appExiting = false; + bool m_restartRequested = false; bool m_contextMenuFocusLock = false; bool m_showToolbarSeparator = false; qint64 m_lastFocusOutTime = 0; diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index 64883b142..10951f3c0 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -256,7 +256,7 @@ <addaction name="separator"/> <addaction name="actionReports"/> <addaction name="actionDatabaseSettings"/> - <addaction name="actionChangeMasterKey"/> + <addaction name="actionDatabaseSecurity"/> <addaction name="separator"/> <addaction name="actionDatabaseMerge"/> <addaction name="menuImport"/> @@ -327,6 +327,9 @@ <addaction name="separator"/> <addaction name="actionEntryOpenUrl"/> <addaction name="actionEntryDownloadIcon"/> + <addaction name="separator"/> + <addaction name="actionEntryAddToAgent"/> + <addaction name="actionEntryRemoveFromAgent"/> </widget> <widget class="QMenu" name="menuGroups"> <property name="title"> @@ -350,10 +353,29 @@ <addaction name="actionPasswordGenerator"/> <addaction name="actionSettings"/> </widget> + <widget class="QMenu" name="menuView"> + <property name="title"> + <string>View</string> + </property> + <widget class="QMenu" name="menuTheme"> + <property name="title"> + <string>Theme</string> + </property> + <addaction name="actionThemeAuto"/> + <addaction name="actionThemeLight"/> + <addaction name="actionThemeDark"/> + <addaction name="actionThemeClassic"/> + </widget> + <addaction name="menuTheme"/> + <addaction name="actionCompactMode"/> + <addaction name="actionShowPreviewPanel"/> + <addaction name="actionShowToolbar"/> + </widget> <addaction name="menuFile"/> <addaction name="menuEntries"/> <addaction name="menuGroups"/> <addaction name="menuTools"/> + <addaction name="menuView"/> <addaction name="menuHelp"/> </widget> <widget class="QToolBar" name="toolBar"> @@ -543,12 +565,12 @@ <string>Sa&ve Database As…</string> </property> </action> - <action name="actionChangeMasterKey"> + <action name="actionDatabaseSecurity"> <property name="enabled"> <bool>false</bool> </property> <property name="text"> - <string>Change Master &Key…</string> + <string>Database &Security…</string> </property> </action> <action name="actionReports"> @@ -556,7 +578,7 @@ <bool>false</bool> </property> <property name="text"> - <string>&Database Reports...</string> + <string>Database &Reports...</string> </property> <property name="toolTip"> <string>Statistics, health check, etc.</string> @@ -795,7 +817,7 @@ <string>&Getting Started</string> </property> <property name="toolTip"> - <string>Open Getting Started Guide PDF</string> + <string>Open Getting Started Guide</string> </property> </action> <action name="actionOnlineHelp"> @@ -803,7 +825,7 @@ <string>&Online Help</string> </property> <property name="toolTip"> - <string>Go to online documentation (opens browser)</string> + <string>Go to online documentation</string> </property> </action> <action name="actionUserGuide"> @@ -811,7 +833,7 @@ <string>&User Guide</string> </property> <property name="toolTip"> - <string>Open User Guide PDF</string> + <string>Open User Guide</string> </property> </action> <action name="actionKeyboardShortcuts"> @@ -840,6 +862,71 @@ <string>Remove key from SSH Agent</string> </property> </action> + <action name="actionCompactMode"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Compact Mode</string> + </property> + </action> + <action name="actionThemeAuto"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="text"> + <string>Automatic</string> + </property> + </action> + <action name="actionThemeLight"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Light</string> + </property> + </action> + <action name="actionThemeDark"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Dark</string> + </property> + </action> + <action name="actionThemeClassic"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="text"> + <string>Classic (Platform-native)</string> + </property> + </action> + <action name="actionShowToolbar"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="text"> + <string>Show Toolbar</string> + </property> + </action> + <action name="actionShowPreviewPanel"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="text"> + <string>Show Preview Panel</string> + </property> + </action> </widget> <customwidgets> <customwidget> diff --git a/src/gui/SearchWidget.ui b/src/gui/SearchWidget.ui index b98f4aea7..74cc468cf 100644 --- a/src/gui/SearchWidget.ui +++ b/src/gui/SearchWidget.ui @@ -6,17 +6,11 @@ <rect> <x>0</x> <y>0</y> - <width>630</width> + <width>465</width> <height>34</height> </rect> </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <layout class="QHBoxLayout" name="horizontalLayout" stretch="4"> + <layout class="QHBoxLayout" name="horizontalLayout"> <property name="leftMargin"> <number>3</number> </property> @@ -32,20 +26,17 @@ <item> <widget class="QLineEdit" name="searchEdit"> <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> <horstretch>0</horstretch> <verstretch>0</verstretch> </sizepolicy> </property> <property name="minimumSize"> <size> - <width>0</width> + <width>150</width> <height>0</height> </size> </property> - <property name="styleSheet"> - <string notr="true">padding:3px</string> - </property> <property name="placeholderText"> <string/> </property> diff --git a/src/gui/csvImport/CsvImportWidget.cpp b/src/gui/csvImport/CsvImportWidget.cpp index 85c9e591c..01fd5fc89 100644 --- a/src/gui/csvImport/CsvImportWidget.cpp +++ b/src/gui/csvImport/CsvImportWidget.cpp @@ -39,69 +39,26 @@ CsvImportWidget::CsvImportWidget(QWidget* parent) , m_comboModel(new QStringListModel(this)) , m_columnHeader(QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") << QObject::tr("Password") << QObject::tr("URL") << QObject::tr("Notes") - << QObject::tr("Last Modified") << QObject::tr("Created") - /* << QObject::tr("Future field1") */) -{ - m_ui->setupUi(this); - - m_ui->comboBoxCodec->addItems(QStringList() << "UTF-8" - << "Windows-1252" - << "UTF-16" - << "UTF-16LE"); - m_ui->comboBoxFieldSeparator->addItems(QStringList() << "," - << ";" - << "-" - << ":" - << "." - << "TAB (\\t)"); - m_fieldSeparatorList = QStringList() << "," + << QObject::tr("Last Modified") << QObject::tr("Created")) + , m_fieldSeparatorList(QStringList() << "," << ";" << "-" << ":" << "." - << "\t"; - m_ui->comboBoxTextQualifier->addItems(QStringList() << "\"" - << "'" - << ":" - << "." - << "|"); - m_ui->comboBoxComment->addItems(QStringList() << "#" - << ";" - << ":" - << "@"); + << "\t") +{ + m_ui->setupUi(this); + m_ui->tableViewFields->setSelectionMode(QAbstractItemView::NoSelection); m_ui->tableViewFields->setFocusPolicy(Qt::NoFocus); m_ui->messageWidget->setHidden(true); - for (int i = 0; i < m_columnHeader.count(); ++i) { - QLabel* label = new QLabel(m_columnHeader.at(i), this); - label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); - QFont font = label->font(); - font.setBold(false); - label->setFont(font); + m_combos << m_ui->groupCombo << m_ui->titleCombo << m_ui->usernameCombo << m_ui->passwordCombo << m_ui->urlCombo + << m_ui->notesCombo << m_ui->lastModifiedCombo << m_ui->createdCombo; - QComboBox* combo = new QComboBox(this); - font = combo->font(); - font.setBold(false); - combo->setFont(font); - m_combos.append(combo); + for (auto combo : m_combos) { combo->setModel(m_comboModel); -#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) - connect(combo, QOverload<int>::of(&QComboBox::currentIndexChanged), [=] { comboChanged(combo, i); }); -#else - connect(combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=] { - comboChanged(combo, i); - }); -#endif - - // layout labels and combo fields in column-first order - int combo_rows = 1 + (m_columnHeader.count() - 1) / 2; - int x = i % combo_rows; - int y = 2 * (i / combo_rows); - m_ui->gridLayout_combos->addWidget(label, x, y); - m_ui->gridLayout_combos->addWidget(combo, x, y + 1); - QSpacerItem* item = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed); - m_ui->gridLayout_combos->addItem(item, x, y + 2); + connect(combo, SIGNAL(currentIndexChanged(int)), SLOT(comboChanged(int))); } m_parserModel->setHeaderLabels(m_columnHeader); @@ -119,12 +76,10 @@ CsvImportWidget::CsvImportWidget(QWidget* parent) connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); } -void CsvImportWidget::comboChanged(QComboBox* currentSender, int comboId) +void CsvImportWidget::comboChanged(int index) { - if (currentSender->currentIndex() != -1) { - // this line is the one that actually updates GUI table - m_parserModel->mapColumns(currentSender->currentIndex(), comboId); - } + // this line is the one that actually updates GUI table + m_parserModel->mapColumns(index, m_combos.indexOf(qobject_cast<QComboBox*>(sender()))); updateTableview(); } @@ -167,19 +122,17 @@ void CsvImportWidget::updatePreview() m_ui->spinBoxSkip->setRange(minSkip, qMax(minSkip, m_parserModel->rowCount() - 1)); m_ui->spinBoxSkip->setValue(minSkip); - int emptyId = 0; - QString columnName; - QStringList list(tr("Not present in CSV file")); - + QStringList list(tr("Not Present")); for (int i = 1; i < m_parserModel->getCsvCols(); ++i) { if (m_ui->checkBoxFieldNames->isChecked()) { - columnName = m_parserModel->getCsvTable().at(0).at(i); + auto columnName = m_parserModel->getCsvTable().at(0).at(i); if (columnName.isEmpty()) { - columnName = "<" + tr("Empty fieldname %1").arg(++emptyId) + ">"; + list << QString(tr("Column %1").arg(i)); + } else { + list << columnName; } - list << columnName; } else { - list << QString(tr("column %1").arg(i)); + list << QString(tr("Column %1").arg(i)); } } m_comboModel->setStringList(list); @@ -221,7 +174,6 @@ void CsvImportWidget::parse() } else { m_ui->messageWidget->setHidden(true); } - QWidget::adjustSize(); } QString CsvImportWidget::formatStatusText() const diff --git a/src/gui/csvImport/CsvImportWidget.h b/src/gui/csvImport/CsvImportWidget.h index a5807eefd..a81550aa1 100644 --- a/src/gui/csvImport/CsvImportWidget.h +++ b/src/gui/csvImport/CsvImportWidget.h @@ -49,7 +49,7 @@ signals: private slots: void parse(); - void comboChanged(QComboBox* currentSender, int comboId); + void comboChanged(int index); void skippedChanged(int rows); void writeDatabase(); void updatePreview(); diff --git a/src/gui/csvImport/CsvImportWidget.ui b/src/gui/csvImport/CsvImportWidget.ui index 845fe16b4..1c268fd9d 100644 --- a/src/gui/csvImport/CsvImportWidget.ui +++ b/src/gui/csvImport/CsvImportWidget.ui @@ -6,444 +6,657 @@ <rect> <x>0</x> <y>0</y> - <width>892</width> - <height>525</height> + <width>788</width> + <height>530</height> </rect> </property> <property name="windowTitle"> <string/> </property> - <layout class="QGridLayout" name="gridLayout_4"> - <item row="0" column="0" rowspan="2" colspan="2"> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="MessageWidget" name="messageWidget" native="true"/> - </item> - <item> - <widget class="QLabel" name="labelHeadline"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <pointsize>11</pointsize> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>Import CSV fields</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="labelFilename"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>filename</string> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="labelSizeRowsCols"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>size, rows, columns</string> - </property> - </widget> - </item> - </layout> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="MessageWidget" name="messageWidget" native="true"/> </item> - <item row="1" column="1"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> + <property name="widgetResizable"> + <bool>true</bool> </property> - <property name="sizeHint" stdset="0"> - <size> - <width>758</width> - <height>24</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="0" colspan="2"> - <widget class="QGroupBox" name="Encoding"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="font"> - <font> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="title"> - <string>Encoding</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <widget class="QLabel" name="labelCodec"> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="text"> - <string>Codec</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="0" column="1" colspan="2"> - <widget class="QComboBox" name="comboBoxCodec"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="accessibleName"> - <string>Codec</string> - </property> - <property name="editable"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="0" column="3"> - <widget class="QLabel" name="labelTextQualifier"> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="text"> - <string>Text is qualified by</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="0" column="4"> - <widget class="QComboBox" name="comboBoxTextQualifier"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="accessibleName"> - <string>Text qualification</string> - </property> - <property name="editable"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="labelFieldSeparator"> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="text"> - <string>Fields are separated by</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="1" column="1" colspan="2"> - <widget class="QComboBox" name="comboBoxFieldSeparator"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="accessibleName"> - <string>Field separation</string> - </property> - <property name="editable"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="1" column="3"> - <widget class="QLabel" name="labelComments"> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="text"> - <string>Comments start with</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item row="1" column="4"> - <widget class="QComboBox" name="comboBoxComment"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>0</height> - </size> - </property> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="accessibleName"> - <string>Comments start with</string> - </property> - <property name="editable"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="2" column="0" colspan="2"> - <widget class="QCheckBox" name="checkBoxFieldNames"> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="text"> - <string>First record has field names</string> - </property> - </widget> - </item> - <item row="2" column="2"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="labelSkipRows"> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="text"> - <string>Number of header lines to discard</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="spinBoxSkip"> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="accessibleName"> - <string>Number of header lines to discard</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="2" column="3"> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>122</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="4"> - <widget class="QCheckBox" name="checkBoxBackslash"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="text"> - <string>Consider '\' an escape character</string> - </property> - </widget> - </item> - <item row="2" column="5"> - <widget class="QLabel" name="labelWarnings"> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - <kerning>true</kerning> - </font> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>753</width> + <height>615</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QLabel" name="labelHeadline"> + <property name="font"> + <font> + <pointsize>11</pointsize> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Import CSV fields</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="labelFilename"> + <property name="text"> + <string>filename</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="labelSizeRowsCols"> + <property name="text"> + <string>size, rows, columns</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QGroupBox" name="groupBoxColumnAssociations"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="title"> + <string>Column Association</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_4"> + <item> + <layout class="QGridLayout" name="gridLayout_combos"> + <item row="2" column="2"> + <widget class="QLabel" name="lastModifiedLabel"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Last Modified</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="passwordLabel"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Password</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="passwordCombo"/> + </item> + <item row="3" column="2"> + <widget class="QLabel" name="createdLabel"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Created</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="notesLabel"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Notes</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="titleLabel"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Title</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="groupCombo"/> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="groupLabel"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Group</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="urlLabel"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>URL</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="usernameLabel"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Username</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="usernameCombo"/> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="titleCombo"/> + </item> + <item row="0" column="3"> + <widget class="QComboBox" name="urlCombo"/> + </item> + <item row="1" column="3"> + <widget class="QComboBox" name="notesCombo"/> + </item> + <item row="2" column="3"> + <widget class="QComboBox" name="lastModifiedCombo"/> + </item> + <item row="3" column="3"> + <widget class="QComboBox" name="createdCombo"/> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="Encoding"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="title"> + <string>Encoding</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="labelCodec"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Codec</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="comboBoxCodec"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="accessibleName"> + <string>Codec</string> + </property> + <property name="editable"> + <bool>false</bool> + </property> + <property name="currentText"> + <string notr="true">UTF-8</string> + </property> + <item> + <property name="text"> + <string notr="true">UTF-8</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">Windows-1252</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">UTF-16</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">UTF-16LE</string> + </property> + </item> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="labelTextQualifier"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Text is qualified by</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="comboBoxTextQualifier"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="accessibleName"> + <string>Text qualification</string> + </property> + <property name="editable"> + <bool>false</bool> + </property> + <property name="currentText"> + <string notr="true">"</string> + </property> + <item> + <property name="text"> + <string notr="true">"</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">'</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">:</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">.</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">|</string> + </property> + </item> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="labelFieldSeparator"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Fields are separated by</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="comboBoxFieldSeparator"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="accessibleName"> + <string>Field separation</string> + </property> + <property name="editable"> + <bool>false</bool> + </property> + <property name="currentText"> + <string notr="true">,</string> + </property> + <item> + <property name="text"> + <string notr="true">,</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">;</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">-</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">:</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">.</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">TAB (\t)</string> + </property> + </item> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="labelComments"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Comments start with</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="comboBoxComment"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="accessibleName"> + <string>Comments start with</string> + </property> + <property name="editable"> + <bool>false</bool> + </property> + <property name="currentText"> + <string notr="true">#</string> + </property> + <item> + <property name="text"> + <string notr="true">#</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">;</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">:</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">@</string> + </property> + </item> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="labelSkipRows"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Header lines skipped</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="4" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QSpinBox" name="spinBoxSkip"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="accessibleName"> + <string>Number of header lines to discard</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>122</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="5" column="1"> + <widget class="QCheckBox" name="checkBoxFieldNames"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>First line has field names</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QCheckBox" name="checkBoxBackslash"> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Consider '\' an escape character</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBoxPreview"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="title"> + <string>Preview</string> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTableView" name="tableViewFields"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>300</height> + </size> + </property> + <property name="font"> + <font> + <weight>50</weight> + <bold>false</bold> + </font> + </property> + <property name="accessibleName"> + <string>CSV import preview</string> + </property> + <property name="cornerButtonEnabled"> + <bool>false</bool> + </property> + <attribute name="horizontalHeaderVisible"> + <bool>true</bool> + </attribute> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> </widget> </item> - <item row="4" column="0" colspan="2"> - <widget class="QGroupBox" name="groupBoxPreview"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>200</height> - </size> - </property> - <property name="font"> - <font> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="title"> - <string>Preview</string> - </property> - <property name="checkable"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QTableView" name="tableViewFields"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <weight>50</weight> - <bold>false</bold> - </font> - </property> - <property name="accessibleName"> - <string>CSV import preview</string> - </property> - <attribute name="horizontalHeaderVisible"> - <bool>true</bool> - </attribute> - </widget> - </item> - </layout> - </widget> - </item> - <item row="5" column="0" colspan="2"> + <item> <widget class="QDialogButtonBox" name="buttonBox"> <property name="standardButtons"> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> @@ -453,40 +666,6 @@ </property> </widget> </item> - <item row="3" column="0" colspan="2"> - <widget class="QGroupBox" name="groupBoxColumnAssociations"> - <property name="sizePolicy"> - <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="font"> - <font> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="title"> - <string>Column layout</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <layout class="QGridLayout" name="gridLayout_combos"> - <property name="leftMargin"> - <number>6</number> - </property> - <property name="rightMargin"> - <number>6</number> - </property> - <property name="bottomMargin"> - <number>0</number> - </property> - </layout> - </item> - </layout> - </widget> - </item> </layout> </widget> <customwidgets> @@ -498,12 +677,21 @@ </customwidget> </customwidgets> <tabstops> + <tabstop>scrollArea</tabstop> + <tabstop>groupCombo</tabstop> + <tabstop>titleCombo</tabstop> + <tabstop>usernameCombo</tabstop> + <tabstop>passwordCombo</tabstop> + <tabstop>urlCombo</tabstop> + <tabstop>notesCombo</tabstop> + <tabstop>lastModifiedCombo</tabstop> + <tabstop>createdCombo</tabstop> <tabstop>comboBoxCodec</tabstop> <tabstop>comboBoxTextQualifier</tabstop> <tabstop>comboBoxFieldSeparator</tabstop> <tabstop>comboBoxComment</tabstop> - <tabstop>checkBoxFieldNames</tabstop> <tabstop>spinBoxSkip</tabstop> + <tabstop>checkBoxFieldNames</tabstop> <tabstop>checkBoxBackslash</tabstop> <tabstop>tableViewFields</tabstop> </tabstops> diff --git a/src/gui/masterkey/KeyComponentWidget.cpp b/src/gui/databasekey/KeyComponentWidget.cpp similarity index 100% rename from src/gui/masterkey/KeyComponentWidget.cpp rename to src/gui/databasekey/KeyComponentWidget.cpp diff --git a/src/gui/masterkey/KeyComponentWidget.h b/src/gui/databasekey/KeyComponentWidget.h similarity index 100% rename from src/gui/masterkey/KeyComponentWidget.h rename to src/gui/databasekey/KeyComponentWidget.h diff --git a/src/gui/masterkey/KeyComponentWidget.ui b/src/gui/databasekey/KeyComponentWidget.ui similarity index 100% rename from src/gui/masterkey/KeyComponentWidget.ui rename to src/gui/databasekey/KeyComponentWidget.ui diff --git a/src/gui/masterkey/KeyFileEditWidget.cpp b/src/gui/databasekey/KeyFileEditWidget.cpp similarity index 98% rename from src/gui/masterkey/KeyFileEditWidget.cpp rename to src/gui/databasekey/KeyFileEditWidget.cpp index e6b5bef49..e0486ae07 100644 --- a/src/gui/masterkey/KeyFileEditWidget.cpp +++ b/src/gui/databasekey/KeyFileEditWidget.cpp @@ -52,7 +52,7 @@ bool KeyFileEditWidget::addToCompositeKey(QSharedPointer<CompositeKey> key) tr("Legacy key file format"), tr("You are using a legacy key file format which may become\n" "unsupported in the future.\n\n" - "Please go to the master key settings and generate a new key file."), + "Generate a new key file in the database security settings."), QMessageBox::Ok); } diff --git a/src/gui/masterkey/KeyFileEditWidget.h b/src/gui/databasekey/KeyFileEditWidget.h similarity index 100% rename from src/gui/masterkey/KeyFileEditWidget.h rename to src/gui/databasekey/KeyFileEditWidget.h diff --git a/src/gui/masterkey/KeyFileEditWidget.ui b/src/gui/databasekey/KeyFileEditWidget.ui similarity index 100% rename from src/gui/masterkey/KeyFileEditWidget.ui rename to src/gui/databasekey/KeyFileEditWidget.ui diff --git a/src/gui/masterkey/PasswordEditWidget.cpp b/src/gui/databasekey/PasswordEditWidget.cpp similarity index 100% rename from src/gui/masterkey/PasswordEditWidget.cpp rename to src/gui/databasekey/PasswordEditWidget.cpp diff --git a/src/gui/masterkey/PasswordEditWidget.h b/src/gui/databasekey/PasswordEditWidget.h similarity index 100% rename from src/gui/masterkey/PasswordEditWidget.h rename to src/gui/databasekey/PasswordEditWidget.h diff --git a/src/gui/masterkey/PasswordEditWidget.ui b/src/gui/databasekey/PasswordEditWidget.ui similarity index 100% rename from src/gui/masterkey/PasswordEditWidget.ui rename to src/gui/databasekey/PasswordEditWidget.ui diff --git a/src/gui/masterkey/YubiKeyEditWidget.cpp b/src/gui/databasekey/YubiKeyEditWidget.cpp similarity index 100% rename from src/gui/masterkey/YubiKeyEditWidget.cpp rename to src/gui/databasekey/YubiKeyEditWidget.cpp diff --git a/src/gui/masterkey/YubiKeyEditWidget.h b/src/gui/databasekey/YubiKeyEditWidget.h similarity index 100% rename from src/gui/masterkey/YubiKeyEditWidget.h rename to src/gui/databasekey/YubiKeyEditWidget.h diff --git a/src/gui/masterkey/YubiKeyEditWidget.ui b/src/gui/databasekey/YubiKeyEditWidget.ui similarity index 100% rename from src/gui/masterkey/YubiKeyEditWidget.ui rename to src/gui/databasekey/YubiKeyEditWidget.ui diff --git a/src/gui/dbsettings/DatabaseSettingsDialog.cpp b/src/gui/dbsettings/DatabaseSettingsDialog.cpp index bfb7031b4..32a9b74c2 100644 --- a/src/gui/dbsettings/DatabaseSettingsDialog.cpp +++ b/src/gui/dbsettings/DatabaseSettingsDialog.cpp @@ -19,9 +19,9 @@ #include "DatabaseSettingsDialog.h" #include "ui_DatabaseSettingsDialog.h" +#include "DatabaseSettingsWidgetDatabaseKey.h" #include "DatabaseSettingsWidgetEncryption.h" #include "DatabaseSettingsWidgetGeneral.h" -#include "DatabaseSettingsWidgetMasterKey.h" #ifdef WITH_XC_BROWSER #include "DatabaseSettingsWidgetBrowser.h" #endif @@ -65,7 +65,7 @@ DatabaseSettingsDialog::DatabaseSettingsDialog(QWidget* parent) , m_ui(new Ui::DatabaseSettingsDialog()) , m_generalWidget(new DatabaseSettingsWidgetGeneral(this)) , m_securityTabWidget(new QTabWidget(this)) - , m_masterKeyWidget(new DatabaseSettingsWidgetMasterKey(this)) + , m_databaseKeyWidget(new DatabaseSettingsWidgetDatabaseKey(this)) , m_encryptionWidget(new DatabaseSettingsWidgetEncryption(this)) #ifdef WITH_XC_BROWSER , m_browserWidget(new DatabaseSettingsWidgetBrowser(this)) @@ -81,7 +81,7 @@ DatabaseSettingsDialog::DatabaseSettingsDialog(QWidget* parent) m_ui->stackedWidget->addWidget(m_generalWidget); m_ui->stackedWidget->addWidget(m_securityTabWidget); - m_securityTabWidget->addTab(m_masterKeyWidget, tr("Master Key")); + m_securityTabWidget->addTab(m_databaseKeyWidget, tr("Database Credentials")); m_securityTabWidget->addTab(m_encryptionWidget, tr("Encryption Settings")); #if defined(WITH_XC_KEESHARE) @@ -115,7 +115,7 @@ void DatabaseSettingsDialog::load(const QSharedPointer<Database>& db) { m_ui->categoryList->setCurrentCategory(0); m_generalWidget->load(db); - m_masterKeyWidget->load(db); + m_databaseKeyWidget->load(db); m_encryptionWidget->load(db); #ifdef WITH_XC_BROWSER m_browserWidget->load(db); @@ -139,9 +139,9 @@ void DatabaseSettingsDialog::addSettingsPage(IDatabaseSettingsPage* page) } /** - * Show page and tab with database master key settings. + * Show page and tab with database database key settings. */ -void DatabaseSettingsDialog::showMasterKeySettings() +void DatabaseSettingsDialog::showDatabaseKeySettings() { m_ui->categoryList->setCurrentCategory(1); m_securityTabWidget->setCurrentIndex(0); @@ -153,7 +153,7 @@ void DatabaseSettingsDialog::save() return; } - if (!m_masterKeyWidget->save()) { + if (!m_databaseKeyWidget->save()) { return; } @@ -185,7 +185,7 @@ void DatabaseSettingsDialog::pageChanged() if (Page::Security == pageIndex) { int tabIndex = m_securityTabWidget->currentIndex(); - enabled = (tabIndex == 0 && m_masterKeyWidget->hasAdvancedMode()); + enabled = (tabIndex == 0 && m_databaseKeyWidget->hasAdvancedMode()); enabled |= (tabIndex == 1 && m_encryptionWidget->hasAdvancedMode()); } @@ -198,8 +198,8 @@ void DatabaseSettingsDialog::toggleAdvancedMode(bool advanced) m_generalWidget->setAdvancedMode(advanced); } - if (m_masterKeyWidget->hasAdvancedMode()) { - m_masterKeyWidget->setAdvancedMode(advanced); + if (m_databaseKeyWidget->hasAdvancedMode()) { + m_databaseKeyWidget->setAdvancedMode(advanced); } if (m_encryptionWidget->hasAdvancedMode()) { diff --git a/src/gui/dbsettings/DatabaseSettingsDialog.h b/src/gui/dbsettings/DatabaseSettingsDialog.h index 855978f29..ba708c65b 100644 --- a/src/gui/dbsettings/DatabaseSettingsDialog.h +++ b/src/gui/dbsettings/DatabaseSettingsDialog.h @@ -28,7 +28,7 @@ class Database; class DatabaseSettingsWidgetGeneral; class DatabaseSettingsWidgetEncryption; -class DatabaseSettingsWidgetMasterKey; +class DatabaseSettingsWidgetDatabaseKey; #ifdef WITH_XC_BROWSER class DatabaseSettingsWidgetBrowser; #endif @@ -63,7 +63,7 @@ public: void load(const QSharedPointer<Database>& db); void addSettingsPage(IDatabaseSettingsPage* page); - void showMasterKeySettings(); + void showDatabaseKeySettings(); signals: void editFinished(bool accepted); @@ -85,7 +85,7 @@ private: const QScopedPointer<Ui::DatabaseSettingsDialog> m_ui; QPointer<DatabaseSettingsWidgetGeneral> m_generalWidget; QPointer<QTabWidget> m_securityTabWidget; - QPointer<DatabaseSettingsWidgetMasterKey> m_masterKeyWidget; + QPointer<DatabaseSettingsWidgetDatabaseKey> m_databaseKeyWidget; QPointer<DatabaseSettingsWidgetEncryption> m_encryptionWidget; #ifdef WITH_XC_BROWSER QPointer<DatabaseSettingsWidgetBrowser> m_browserWidget; diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp b/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp similarity index 82% rename from src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp rename to src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp index a58ee701f..2d733d06d 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.cpp +++ b/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.cpp @@ -15,13 +15,13 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "DatabaseSettingsWidgetMasterKey.h" +#include "DatabaseSettingsWidgetDatabaseKey.h" #include "core/Database.h" #include "gui/MessageBox.h" -#include "gui/masterkey/KeyFileEditWidget.h" -#include "gui/masterkey/PasswordEditWidget.h" -#include "gui/masterkey/YubiKeyEditWidget.h" +#include "gui/databasekey/KeyFileEditWidget.h" +#include "gui/databasekey/PasswordEditWidget.h" +#include "gui/databasekey/YubiKeyEditWidget.h" #include "keys/FileKey.h" #include "keys/PasswordKey.h" #include "keys/YkChallengeResponseKey.h" @@ -30,7 +30,7 @@ #include <QSpacerItem> #include <QVBoxLayout> -DatabaseSettingsWidgetMasterKey::DatabaseSettingsWidgetMasterKey(QWidget* parent) +DatabaseSettingsWidgetDatabaseKey::DatabaseSettingsWidgetDatabaseKey(QWidget* parent) : DatabaseSettingsWidget(parent) , m_additionalKeyOptionsToggle(new QPushButton(tr("Add additional protection..."), this)) , m_additionalKeyOptions(new QWidget(this)) @@ -65,11 +65,11 @@ DatabaseSettingsWidgetMasterKey::DatabaseSettingsWidgetMasterKey(QWidget* parent setLayout(vbox); } -DatabaseSettingsWidgetMasterKey::~DatabaseSettingsWidgetMasterKey() +DatabaseSettingsWidgetDatabaseKey::~DatabaseSettingsWidgetDatabaseKey() { } -void DatabaseSettingsWidgetMasterKey::load(QSharedPointer<Database> db) +void DatabaseSettingsWidgetDatabaseKey::load(QSharedPointer<Database> db) { DatabaseSettingsWidget::load(db); @@ -107,7 +107,7 @@ void DatabaseSettingsWidgetMasterKey::load(QSharedPointer<Database> db) #endif } -void DatabaseSettingsWidgetMasterKey::initialize() +void DatabaseSettingsWidgetDatabaseKey::initialize() { bool blocked = blockSignals(true); m_passwordEditWidget->setComponentAdded(false); @@ -118,11 +118,11 @@ void DatabaseSettingsWidgetMasterKey::initialize() blockSignals(blocked); } -void DatabaseSettingsWidgetMasterKey::uninitialize() +void DatabaseSettingsWidgetDatabaseKey::uninitialize() { } -bool DatabaseSettingsWidgetMasterKey::save() +bool DatabaseSettingsWidgetDatabaseKey::save() { m_isDirty |= (m_passwordEditWidget->visiblePage() == KeyComponentWidget::Page::Edit); m_isDirty |= (m_keyFileEditWidget->visiblePage() == KeyComponentWidget::Page::Edit); @@ -202,17 +202,17 @@ bool DatabaseSettingsWidgetMasterKey::save() return true; } -void DatabaseSettingsWidgetMasterKey::discard() +void DatabaseSettingsWidgetDatabaseKey::discard() { emit editFinished(false); } -void DatabaseSettingsWidgetMasterKey::showAdditionalKeyOptions() +void DatabaseSettingsWidgetDatabaseKey::showAdditionalKeyOptions() { setAdditionalKeyOptionsVisible(true); } -void DatabaseSettingsWidgetMasterKey::setAdditionalKeyOptionsVisible(bool show) +void DatabaseSettingsWidgetDatabaseKey::setAdditionalKeyOptionsVisible(bool show) { m_additionalKeyOptionsToggle->setVisible(!show); m_additionalKeyOptions->setVisible(show); @@ -220,14 +220,14 @@ void DatabaseSettingsWidgetMasterKey::setAdditionalKeyOptionsVisible(bool show) emit sizeChanged(); } -bool DatabaseSettingsWidgetMasterKey::addToCompositeKey(KeyComponentWidget* widget, - QSharedPointer<CompositeKey>& newKey, - QSharedPointer<Key>& oldKey) +bool DatabaseSettingsWidgetDatabaseKey::addToCompositeKey(KeyComponentWidget* widget, + QSharedPointer<CompositeKey>& newKey, + QSharedPointer<Key>& oldKey) { if (widget->visiblePage() == KeyComponentWidget::Edit) { QString error = tr("Unknown error"); if (!widget->validate(error) || !widget->addToCompositeKey(newKey)) { - MessageBox::critical(this, tr("Failed to change master key"), error, MessageBox::Ok); + MessageBox::critical(this, tr("Failed to change database credentials"), error, MessageBox::Ok); return false; } } else if (widget->visiblePage() == KeyComponentWidget::LeaveOrRemove) { @@ -237,14 +237,14 @@ bool DatabaseSettingsWidgetMasterKey::addToCompositeKey(KeyComponentWidget* widg return true; } -bool DatabaseSettingsWidgetMasterKey::addToCompositeKey(KeyComponentWidget* widget, - QSharedPointer<CompositeKey>& newKey, - QSharedPointer<ChallengeResponseKey>& oldKey) +bool DatabaseSettingsWidgetDatabaseKey::addToCompositeKey(KeyComponentWidget* widget, + QSharedPointer<CompositeKey>& newKey, + QSharedPointer<ChallengeResponseKey>& oldKey) { if (widget->visiblePage() == KeyComponentWidget::Edit) { QString error = tr("Unknown error"); if (!widget->validate(error) || !widget->addToCompositeKey(newKey)) { - MessageBox::critical(this, tr("Failed to change master key"), error, MessageBox::Ok); + MessageBox::critical(this, tr("Failed to change database credentials"), error, MessageBox::Ok); return false; } } else if (widget->visiblePage() == KeyComponentWidget::LeaveOrRemove) { @@ -254,7 +254,7 @@ bool DatabaseSettingsWidgetMasterKey::addToCompositeKey(KeyComponentWidget* widg return true; } -void DatabaseSettingsWidgetMasterKey::markDirty() +void DatabaseSettingsWidgetDatabaseKey::markDirty() { m_isDirty = true; } diff --git a/src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.h b/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.h similarity index 84% rename from src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.h rename to src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.h index 1a3d6ed3f..a7d90e43e 100644 --- a/src/gui/dbsettings/DatabaseSettingsWidgetMasterKey.h +++ b/src/gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.h @@ -15,8 +15,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef KEEPASSXC_DATABASESETTINGSPAGECHANGEMASTERKEY_H -#define KEEPASSXC_DATABASESETTINGSPAGECHANGEMASTERKEY_H +#ifndef KEEPASSXC_DATABASESETTINGSPAGECHANGEDBKEY_H +#define KEEPASSXC_DATABASESETTINGSPAGECHANGEDBKEY_H #include "DatabaseSettingsWidget.h" #include "config-keepassx.h" @@ -33,14 +33,14 @@ class KeyFileEditWidget; class YubiKeyEditWidget; class QPushButton; -class DatabaseSettingsWidgetMasterKey : public DatabaseSettingsWidget +class DatabaseSettingsWidgetDatabaseKey : public DatabaseSettingsWidget { Q_OBJECT public: - explicit DatabaseSettingsWidgetMasterKey(QWidget* parent = nullptr); - Q_DISABLE_COPY(DatabaseSettingsWidgetMasterKey); - ~DatabaseSettingsWidgetMasterKey() override; + explicit DatabaseSettingsWidgetDatabaseKey(QWidget* parent = nullptr); + Q_DISABLE_COPY(DatabaseSettingsWidgetDatabaseKey); + ~DatabaseSettingsWidgetDatabaseKey() override; void load(QSharedPointer<Database> db) override; @@ -82,4 +82,4 @@ private: #endif }; -#endif // KEEPASSXC_DATABASESETTINGSPAGECHANGEMASTERKEY_H +#endif // KEEPASSXC_DATABASESETTINGSPAGECHANGEDBKEY_H diff --git a/src/gui/osutils/winutils/WinUtils.cpp b/src/gui/osutils/winutils/WinUtils.cpp index 44f77043e..385a9389a 100644 --- a/src/gui/osutils/winutils/WinUtils.cpp +++ b/src/gui/osutils/winutils/WinUtils.cpp @@ -18,6 +18,7 @@ #include "WinUtils.h" #include <QAbstractNativeEventFilter> #include <QApplication> +#include <QDir> #include <QSettings> #include <windows.h> @@ -88,14 +89,13 @@ bool WinUtils::isLaunchAtStartupEnabled() const { return QSettings(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run)", QSettings::NativeFormat) .contains(qAppName()); - ; } void WinUtils::setLaunchAtStartup(bool enable) { QSettings reg(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run)", QSettings::NativeFormat); if (enable) { - reg.setValue(qAppName(), QApplication::applicationFilePath()); + reg.setValue(qAppName(), QString("\"%1\"").arg(QDir::toNativeSeparators(QApplication::applicationFilePath()))); } else { reg.remove(qAppName()); } diff --git a/src/gui/reports/ReportsWidgetHealthcheck.cpp b/src/gui/reports/ReportsWidgetHealthcheck.cpp index 9e1cf1812..5f502b16b 100644 --- a/src/gui/reports/ReportsWidgetHealthcheck.cpp +++ b/src/gui/reports/ReportsWidgetHealthcheck.cpp @@ -28,6 +28,7 @@ #include <QMenu> #include <QSharedPointer> +#include <QSortFilterProxyModel> #include <QStandardItemModel> namespace @@ -119,11 +120,13 @@ ReportsWidgetHealthcheck::ReportsWidgetHealthcheck(QWidget* parent) : QWidget(parent) , m_ui(new Ui::ReportsWidgetHealthcheck()) , m_errorIcon(Resources::instance()->icon("dialog-error")) + , m_referencesModel(new QStandardItemModel(this)) + , m_modelProxy(new QSortFilterProxyModel(this)) { m_ui->setupUi(this); - m_referencesModel.reset(new QStandardItemModel()); - m_ui->healthcheckTableView->setModel(m_referencesModel.data()); + m_modelProxy->setSourceModel(m_referencesModel.data()); + m_ui->healthcheckTableView->setModel(m_modelProxy.data()); m_ui->healthcheckTableView->setSelectionMode(QAbstractItemView::NoSelection); m_ui->healthcheckTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); m_ui->healthcheckTableView->setSortingEnabled(true); @@ -272,7 +275,8 @@ void ReportsWidgetHealthcheck::emitEntryActivated(const QModelIndex& index) return; } - const auto row = m_rowToEntry[index.row()]; + auto mappedIndex = m_modelProxy->mapToSource(index); + const auto row = m_rowToEntry[mappedIndex.row()]; const auto group = row.first; const auto entry = row.second; if (group && entry) { @@ -288,7 +292,8 @@ void ReportsWidgetHealthcheck::customMenuRequested(QPoint pos) if (!index.isValid()) { return; } - m_contextmenuEntry = const_cast<Entry*>(m_rowToEntry[index.row()].second); + auto mappedIndex = m_modelProxy->mapToSource(index); + m_contextmenuEntry = const_cast<Entry*>(m_rowToEntry[mappedIndex.row()].second); if (!m_contextmenuEntry) { return; } diff --git a/src/gui/reports/ReportsWidgetHealthcheck.h b/src/gui/reports/ReportsWidgetHealthcheck.h index ca848e686..58ac0a03b 100644 --- a/src/gui/reports/ReportsWidgetHealthcheck.h +++ b/src/gui/reports/ReportsWidgetHealthcheck.h @@ -28,6 +28,7 @@ class Database; class Entry; class Group; class PasswordHealth; +class QSortFilterProxyModel; class QStandardItemModel; namespace Ui @@ -66,6 +67,7 @@ private: bool m_healthCalculated = false; QIcon m_errorIcon; QScopedPointer<QStandardItemModel> m_referencesModel; + QScopedPointer<QSortFilterProxyModel> m_modelProxy; QSharedPointer<Database> m_db; QList<QPair<const Group*, const Entry*>> m_rowToEntry; Entry* m_contextmenuEntry = nullptr; diff --git a/src/gui/reports/ReportsWidgetHibp.cpp b/src/gui/reports/ReportsWidgetHibp.cpp index 48e3946a4..48e36518d 100644 --- a/src/gui/reports/ReportsWidgetHibp.cpp +++ b/src/gui/reports/ReportsWidgetHibp.cpp @@ -27,6 +27,7 @@ #include "gui/MessageBox.h" #include <QMenu> +#include <QSortFilterProxyModel> #include <QStandardItemModel> namespace @@ -49,11 +50,13 @@ namespace ReportsWidgetHibp::ReportsWidgetHibp(QWidget* parent) : QWidget(parent) , m_ui(new Ui::ReportsWidgetHibp()) + , m_referencesModel(new QStandardItemModel(this)) + , m_modelProxy(new QSortFilterProxyModel(this)) { m_ui->setupUi(this); - m_referencesModel.reset(new QStandardItemModel()); - m_ui->hibpTableView->setModel(m_referencesModel.data()); + m_modelProxy->setSourceModel(m_referencesModel.data()); + m_ui->hibpTableView->setModel(m_modelProxy.data()); m_ui->hibpTableView->setSelectionMode(QAbstractItemView::NoSelection); m_ui->hibpTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); m_ui->hibpTableView->setSortingEnabled(true); @@ -299,7 +302,8 @@ void ReportsWidgetHibp::emitEntryActivated(const QModelIndex& index) } // Find which database entry was double-clicked - const auto entry = m_rowToEntry[index.row()]; + auto mappedIndex = m_modelProxy->mapToSource(index); + const auto entry = m_rowToEntry[mappedIndex.row()]; if (entry) { // Found it, invoke entry editor m_editedEntry = entry; @@ -350,7 +354,8 @@ void ReportsWidgetHibp::customMenuRequested(QPoint pos) if (!index.isValid()) { return; } - m_contextmenuEntry = const_cast<Entry*>(m_rowToEntry[index.row()]); + auto mappedIndex = m_modelProxy->mapToSource(index); + m_contextmenuEntry = const_cast<Entry*>(m_rowToEntry[mappedIndex.row()]); if (!m_contextmenuEntry) { return; } diff --git a/src/gui/reports/ReportsWidgetHibp.h b/src/gui/reports/ReportsWidgetHibp.h index f7d1a754b..0d76c07fe 100644 --- a/src/gui/reports/ReportsWidgetHibp.h +++ b/src/gui/reports/ReportsWidgetHibp.h @@ -33,6 +33,7 @@ class Database; class Entry; class Group; +class QSortFilterProxyModel; class QStandardItemModel; namespace Ui @@ -69,6 +70,7 @@ private: QScopedPointer<Ui::ReportsWidgetHibp> m_ui; QScopedPointer<QStandardItemModel> m_referencesModel; + QScopedPointer<QSortFilterProxyModel> m_modelProxy; QSharedPointer<Database> m_db; QMap<QString, int> m_pwndPasswords; // Passwords we found to have been pwned (value is pwn count) diff --git a/src/gui/wizard/NewDatabaseWizard.cpp b/src/gui/wizard/NewDatabaseWizard.cpp index c810f42ce..45ac8e46d 100644 --- a/src/gui/wizard/NewDatabaseWizard.cpp +++ b/src/gui/wizard/NewDatabaseWizard.cpp @@ -16,8 +16,8 @@ */ #include "NewDatabaseWizard.h" +#include "NewDatabaseWizardPageDatabaseKey.h" #include "NewDatabaseWizardPageEncryption.h" -#include "NewDatabaseWizardPageMasterKey.h" #include "NewDatabaseWizardPageMetaData.h" #include "core/Database.h" @@ -41,7 +41,7 @@ NewDatabaseWizard::NewDatabaseWizard(QWidget* parent) // clang-format off m_pages << new NewDatabaseWizardPageMetaData() << new NewDatabaseWizardPageEncryption() - << new NewDatabaseWizardPageMasterKey(); + << new NewDatabaseWizardPageDatabaseKey(); // clang-format on for (const auto& page : asConst(m_pages)) { diff --git a/src/gui/wizard/NewDatabaseWizardPageMasterKey.cpp b/src/gui/wizard/NewDatabaseWizardPageDatabaseKey.cpp similarity index 65% rename from src/gui/wizard/NewDatabaseWizardPageMasterKey.cpp rename to src/gui/wizard/NewDatabaseWizardPageDatabaseKey.cpp index 71bd5e60f..3180400c0 100644 --- a/src/gui/wizard/NewDatabaseWizardPageMasterKey.cpp +++ b/src/gui/wizard/NewDatabaseWizardPageDatabaseKey.cpp @@ -15,26 +15,26 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "NewDatabaseWizardPageMasterKey.h" -#include "gui/dbsettings/DatabaseSettingsWidgetMasterKey.h" +#include "NewDatabaseWizardPageDatabaseKey.h" +#include "gui/dbsettings/DatabaseSettingsWidgetDatabaseKey.h" #include <QApplication> -NewDatabaseWizardPageMasterKey::NewDatabaseWizardPageMasterKey(QWidget* parent) +NewDatabaseWizardPageDatabaseKey::NewDatabaseWizardPageDatabaseKey(QWidget* parent) : NewDatabaseWizardPage(parent) { - setPageWidget(new DatabaseSettingsWidgetMasterKey()); + setPageWidget(new DatabaseSettingsWidgetDatabaseKey()); - setTitle(tr("Database Master Key")); - setSubTitle(tr("A master key known only to you protects your database.")); + setTitle(tr("Database Credentials")); + setSubTitle(tr("A set of credentials known only to you that protects your database.")); connect(pageWidget(), SIGNAL(sizeChanged()), SLOT(updateWindowSize())); } -NewDatabaseWizardPageMasterKey::~NewDatabaseWizardPageMasterKey() +NewDatabaseWizardPageDatabaseKey::~NewDatabaseWizardPageDatabaseKey() { } -void NewDatabaseWizardPageMasterKey::updateWindowSize() +void NewDatabaseWizardPageDatabaseKey::updateWindowSize() { // ugly workaround for QWizard not managing to react to size changes automatically window()->adjustSize(); diff --git a/src/gui/wizard/NewDatabaseWizardPageMasterKey.h b/src/gui/wizard/NewDatabaseWizardPageDatabaseKey.h similarity index 66% rename from src/gui/wizard/NewDatabaseWizardPageMasterKey.h rename to src/gui/wizard/NewDatabaseWizardPageDatabaseKey.h index 3b5072846..e0fb5349e 100644 --- a/src/gui/wizard/NewDatabaseWizardPageMasterKey.h +++ b/src/gui/wizard/NewDatabaseWizardPageDatabaseKey.h @@ -15,22 +15,22 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef KEEPASSXC_NEWDATABASEWIZARDPAGEMASTERKEY_H -#define KEEPASSXC_NEWDATABASEWIZARDPAGEMASTERKEY_H +#ifndef KEEPASSXC_NEWDATABASEWIZARDPAGEDATABASEKEY_H +#define KEEPASSXC_NEWDATABASEWIZARDPAGEDATABASEKEY_H #include "NewDatabaseWizardPage.h" -class NewDatabaseWizardPageMasterKey : public NewDatabaseWizardPage +class NewDatabaseWizardPageDatabaseKey : public NewDatabaseWizardPage { Q_OBJECT public: - explicit NewDatabaseWizardPageMasterKey(QWidget* parent = nullptr); - Q_DISABLE_COPY(NewDatabaseWizardPageMasterKey); - ~NewDatabaseWizardPageMasterKey() override; + explicit NewDatabaseWizardPageDatabaseKey(QWidget* parent = nullptr); + Q_DISABLE_COPY(NewDatabaseWizardPageDatabaseKey); + ~NewDatabaseWizardPageDatabaseKey() override; private slots: void updateWindowSize(); }; -#endif // KEEPASSXC_NEWDATABASEWIZARDPAGEMASTERKEY_H +#endif // KEEPASSXC_NEWDATABASEWIZARDPAGEDATABASEKEY_H diff --git a/src/keys/FileKey.cpp b/src/keys/FileKey.cpp index 9c3d41c1d..6142d58d7 100644 --- a/src/keys/FileKey.cpp +++ b/src/keys/FileKey.cpp @@ -200,6 +200,7 @@ bool FileKey::create(const QString& fileName, QString* errorMsg, int size) } create(&file, size); file.close(); + file.setPermissions(QFile::ReadUser); if (file.error()) { if (errorMsg) { diff --git a/src/keys/drivers/YubiKey.cpp b/src/keys/drivers/YubiKey.cpp index 82773bd56..d64452f3e 100644 --- a/src/keys/drivers/YubiKey.cpp +++ b/src/keys/drivers/YubiKey.cpp @@ -203,6 +203,8 @@ void YubiKey::findValidKeys() ykds_free(st); closeKey(yk_key); + + Tools::wait(100); } else { // No more keys are connected break; diff --git a/src/main.cpp b/src/main.cpp index 9a0ba4172..36e05cdae 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,6 +52,9 @@ int main(int argc, char** argv) QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); +#endif Application app(argc, argv); Application::setApplicationName("KeePassXC"); @@ -145,6 +148,7 @@ int main(int argc, char** argv) // buffer for native messaging, even if the specified file does not exist QTextStream out(stdout, QIODevice::WriteOnly); out << QObject::tr("Database password: ") << flush; + Utils::setDefaultTextStreams(); password = Utils::getPassword(); } @@ -155,6 +159,12 @@ int main(int argc, char** argv) int exitCode = Application::exec(); + // Check if restart was requested + if (exitCode == RESTART_EXITCODE) { + QProcess* proc = new QProcess(); + proc->start(QCoreApplication::applicationFilePath()); + } + #if defined(WITH_ASAN) && defined(WITH_LSAN) // do leak check here to prevent massive tail of end-of-process leak errors from third-party libraries __lsan_do_leak_check(); diff --git a/src/proxy/CMakeLists.txt b/src/proxy/CMakeLists.txt index b7bec6deb..bb00f057b 100755 --- a/src/proxy/CMakeLists.txt +++ b/src/proxy/CMakeLists.txt @@ -53,4 +53,8 @@ if(WITH_XC_BROWSER) COMMAND ${CMAKE_COMMAND} -E copy keepassxc-proxy ${PROXY_APP_DIR}/keepassxc-proxy COMMENT "Copying keepassxc-proxy inside the application") endif() + + if(MINGW) + target_link_libraries(keepassxc-proxy Wtsapi32.lib Ws2_32.lib) + endif() endif() diff --git a/src/proxy/NativeMessagingProxy.cpp b/src/proxy/NativeMessagingProxy.cpp index a7bd1c0f3..f5839e92b 100644 --- a/src/proxy/NativeMessagingProxy.cpp +++ b/src/proxy/NativeMessagingProxy.cpp @@ -25,7 +25,12 @@ #ifdef Q_OS_WIN #include <fcntl.h> +#include <winsock2.h> + #include <windows.h> +#else +#include <sys/socket.h> +#include <sys/types.h> #endif NativeMessagingProxy::NativeMessagingProxy() @@ -85,6 +90,11 @@ void NativeMessagingProxy::setupLocalSocket() m_localSocket.reset(new QLocalSocket()); m_localSocket->connectToServer(BrowserShared::localServerPath()); m_localSocket->setReadBufferSize(BrowserShared::NATIVEMSG_MAX_LENGTH); + int socketDesc = m_localSocket->socketDescriptor(); + if (socketDesc) { + int max = BrowserShared::NATIVEMSG_MAX_LENGTH; + setsockopt(socketDesc, SOL_SOCKET, SO_SNDBUF, reinterpret_cast<char*>(&max), sizeof(max)); + } connect(m_localSocket.data(), SIGNAL(readyRead()), this, SLOT(transferSocketMessage())); connect(m_localSocket.data(), SIGNAL(disconnected()), this, SLOT(socketDisconnected())); diff --git a/tests/TestKeePass2Format.cpp b/tests/TestKeePass2Format.cpp index f58d0a885..b0217c942 100644 --- a/tests/TestKeePass2Format.cpp +++ b/tests/TestKeePass2Format.cpp @@ -87,9 +87,9 @@ void TestKeePass2Format::testXmlMetadata() QCOMPARE(m_xmlDb->metadata()->defaultUserNameChanged(), MockClock::datetimeUtc(2010, 8, 8, 17, 27, 45)); QCOMPARE(m_xmlDb->metadata()->maintenanceHistoryDays(), 127); QCOMPARE(m_xmlDb->metadata()->color(), QString("#FFEF00")); - QCOMPARE(m_xmlDb->metadata()->masterKeyChanged(), MockClock::datetimeUtc(2012, 4, 5, 17, 9, 34)); - QCOMPARE(m_xmlDb->metadata()->masterKeyChangeRec(), 101); - QCOMPARE(m_xmlDb->metadata()->masterKeyChangeForce(), -1); + QCOMPARE(m_xmlDb->metadata()->databaseKeyChanged(), MockClock::datetimeUtc(2012, 4, 5, 17, 9, 34)); + QCOMPARE(m_xmlDb->metadata()->databaseKeyChangeRec(), 101); + QCOMPARE(m_xmlDb->metadata()->databaseKeyChangeForce(), -1); QCOMPARE(m_xmlDb->metadata()->protectTitle(), false); QCOMPARE(m_xmlDb->metadata()->protectUsername(), true); QCOMPARE(m_xmlDb->metadata()->protectPassword(), false); diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index e59540a02..70417dbd5 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -63,15 +63,15 @@ #include "gui/SearchWidget.h" #include "gui/TotpDialog.h" #include "gui/TotpSetupDialog.h" +#include "gui/databasekey/KeyComponentWidget.h" +#include "gui/databasekey/KeyFileEditWidget.h" +#include "gui/databasekey/PasswordEditWidget.h" #include "gui/dbsettings/DatabaseSettingsDialog.h" #include "gui/entry/EditEntryWidget.h" #include "gui/entry/EntryView.h" #include "gui/group/EditGroupWidget.h" #include "gui/group/GroupModel.h" #include "gui/group/GroupView.h" -#include "gui/masterkey/KeyComponentWidget.h" -#include "gui/masterkey/KeyFileEditWidget.h" -#include "gui/masterkey/PasswordEditWidget.h" #include "gui/wizard/NewDatabaseWizard.h" #include "keys/FileKey.h" #include "keys/PasswordKey.h" diff --git a/tests/gui/TestGuiFdoSecrets.cpp b/tests/gui/TestGuiFdoSecrets.cpp index c869aac4f..9dffa6ba5 100644 --- a/tests/gui/TestGuiFdoSecrets.cpp +++ b/tests/gui/TestGuiFdoSecrets.cpp @@ -200,7 +200,7 @@ void TestGuiFdoSecrets::initTestCase() m_mainWindow.reset(new MainWindow()); m_tabWidget = m_mainWindow->findChild<DatabaseTabWidget*>("tabWidget"); QVERIFY(m_tabWidget); - m_plugin = m_mainWindow->findChild<FdoSecretsPlugin*>(); + m_plugin = FdoSecretsPlugin::getPlugin(); QVERIFY(m_plugin); m_mainWindow->show(); @@ -680,7 +680,7 @@ void TestGuiFdoSecrets::testCollectionCreate() QCOMPARE(spyCollectionCreated.count(), 1); { - auto args = spyCollectionCreated.takeFirst(); + args = spyCollectionCreated.takeFirst(); QCOMPARE(args.size(), 1); QCOMPARE(args.at(0).value<Collection*>(), coll); } @@ -754,7 +754,7 @@ void TestGuiFdoSecrets::testCollectionDelete() QCOMPARE(spyCollectionDeleted.count(), 1); { - auto args = spyCollectionDeleted.takeFirst(); + args = spyCollectionDeleted.takeFirst(); QCOMPARE(args.size(), 1); QCOMPARE(args.at(0).value<Collection*>(), rawColl); } @@ -977,7 +977,7 @@ void TestGuiFdoSecrets::testItemDelete() QCOMPARE(spyItemDeleted.count(), 1); { - auto args = spyItemDeleted.takeFirst(); + args = spyItemDeleted.takeFirst(); QCOMPARE(args.size(), 1); QCOMPARE(args.at(0).value<Item*>(), rawItem); } diff --git a/utils/keepassxc-snap-helper.sh b/utils/keepassxc-snap-helper.sh index 206accaf1..ecb290daa 100755 --- a/utils/keepassxc-snap-helper.sh +++ b/utils/keepassxc-snap-helper.sh @@ -20,29 +20,30 @@ set -e DEBUG=false -JSON_BASE=$(cat << EOF +JSON_FIREFOX=$(cat << EOF { "name": "org.keepassxc.keepassxc_browser", "description": "KeePassXC integration with native messaging support", "path": "/snap/bin/keepassxc.proxy", "type": "stdio", - __EXT__ + "allowed_extensions": [ + "keepassxc-browser@keepassxc.org" + ] } EOF ) -JSON_FIREFOX=$(cat << EOF -"allowed_extensions": [ - "keepassxc-browser@keepassxc.org" - ] -EOF -) - JSON_CHROME=$(cat << EOF -"allowed_origins": [ +{ + "name": "org.keepassxc.keepassxc_browser", + "description": "KeePassXC integration with native messaging support", + "path": "/snap/bin/keepassxc.proxy", + "type": "stdio", + "allowed_origins": [ "chrome-extension://iopaggbpplllidnfmcghoonnokmjoicf/", "chrome-extension://oboonakemofpalcgghocfoadofidjkkk/" ] +} EOF ) @@ -52,12 +53,12 @@ INSTALL_DIR="" INSTALL_FILE="org.keepassxc.keepassxc_browser.json" buildJson() { - if [[ ! -z $1 ]]; then + if [ -n "$1" ]; then # Insert Firefox data - JSON_OUT="${JSON_BASE/__EXT__/$JSON_FIREFOX}" + JSON_OUT=$JSON_FIREFOX else # Insert Chrome data - JSON_OUT="${JSON_BASE/__EXT__/$JSON_CHROME}" + JSON_OUT=$JSON_CHROME fi }