diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..5dc8fc3b03 --- /dev/null +++ b/.clang-format @@ -0,0 +1,89 @@ +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: false +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: true + AfterFunction: true + AfterControlStatement: false + AfterEnum: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IndentCaseLabels: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: true +SortIncludes: true +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... + diff --git a/.gitattributes b/.gitattributes index 9d1ecabf4e..9df1af7910 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7,3 +7,7 @@ src/version.h.cmake export-subst snapcraft.yaml export-ignore make_release.sh export-ignore AppImage-Recipe.sh export-ignore + +# github-linguist language hints +*.h linguist-language=C++ +*.cpp linguist-language=C++ diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index c83ca4e537..b9852f3c99 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,11 +3,11 @@ ## Description -## Motivation and Context +## Motivation and context -## How Has This Been Tested? +## How has this been tested? @@ -29,5 +29,6 @@ - ✅ I have read the **CONTRIBUTING** document. **[REQUIRED]** - ✅ My code follows the code style of this project. **[REQUIRED]** - ✅ All new and existing tests passed. **[REQUIRED]** +- ✅ I have compiled and verified my code with `-DWITH_ASAN=ON`. **[REQUIRED]** - ✅ My change requires a change to the documentation and I have updated it accordingly. - ✅ I have added tests to cover my changes. diff --git a/.gitignore b/.gitignore index 3a63e97052..0521a42e3d 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ release*/ .idea/ *.iml *.kdev4 + +\.vscode/ diff --git a/.travis.yml b/.travis.yml index 34bc0add58..e24d1d1786 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,15 +13,15 @@ compiler: - gcc env: - - CONFIG=Release - - CONFIG=Debug + - CONFIG=Release ASAN_OPTIONS=detect_odr_violation=1:leak_check_at_exit=0 + - CONFIG=Debug ASAN_OPTIONS=detect_odr_violation=1:leak_check_at_exit=0 git: depth: 3 before_install: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq update; fi - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake libmicrohttpd10 libmicrohttpd-dev libxi-dev qtbase5-dev libqt5x11extras5-dev qttools5-dev qttools5-dev-tools libgcrypt20-dev zlib1g-dev libxtst-dev xvfb; fi + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake libclang-common-3.5-dev libxi-dev qtbase5-dev libqt5x11extras5-dev qttools5-dev qttools5-dev-tools libgcrypt20-dev zlib1g-dev libxtst-dev xvfb libyubikey-dev libykpers-1-dev; fi - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; fi - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq cmake || brew install cmake; fi - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq qt5 || brew install qt5; fi @@ -32,7 +32,7 @@ before_script: - mkdir build && pushd build script: - - cmake -DCMAKE_BUILD_TYPE=${CONFIG} -DWITH_GUI_TESTS=ON -DWITH_XC_HTTP=ON -DWITH_XC_AUTOTYPE=ON -DWITH_XC_YUBIKEY=ON $CMAKE_ARGS .. + - cmake -DCMAKE_BUILD_TYPE=${CONFIG} -DWITH_GUI_TESTS=ON -DWITH_ASAN=ON -DWITH_XC_HTTP=ON -DWITH_XC_AUTOTYPE=ON -DWITH_XC_YUBIKEY=ON $CMAKE_ARGS .. - make -j2 - if [ "$TRAVIS_OS_NAME" = "linux" ]; then make test ARGS+="-E testgui --output-on-failure"; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then xvfb-run -a --server-args="-screen 0 800x600x24" make test ARGS+="-R testgui --output-on-failure"; fi diff --git a/CHANGELOG b/CHANGELOG index a293715985..6c2cc9dfaa 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,36 @@ +2.2.0 (2017-06-23) +========================= + +- Added YubiKey 2FA integration for unlocking databases [#127] +- Added TOTP support [#519] +- Added CSV import tool [#146, #490] +- Added KeePassXC CLI tool [#254] +- Added diceware password generator [#373] +- Added support for entry references [#370, #378] +- Added support for Twofish encryption [#167] +- Enabled DEP and ASLR for in-memory protection [#371] +- Enabled single instance mode [#510] +- Enabled portable mode [#645] +- Enabled database lock on screensaver and session lock [#545] +- Redesigned welcome screen with common features and recent databases [#292] +- Multiple updates to search behavior [#168, #213, #374, #471, #603, #654] +- Added auto-type fields {CLEARFIELD}, {SPACE}, {{}, {}} [#267, #427, #480] +- Fixed auto-type errors on Linux [#550] +- Prompt user prior to executing a cmd:// URL [#235] +- Entry attributes can be protected (hidden) [#220] +- Added extended ascii to password generator [#538] +- Added new database icon to toolbar [#289] +- Added context menu entry to empty recycle bin in databases [#520] +- Added "apply" button to entry and group edit windows [#624] +- Added macOS tray icon and enabled minimize on close [#583] +- Fixed issues with unclean shutdowns [#170, #580] +- Changed keyboard shortcut to create new database to CTRL+SHIFT+N [#515] +- Compare window title to entry URLs [#556] +- Implemented inline error messages [#162] +- Ignore group expansion and other minor changes when making database "dirty" [#464] +- Updated license and copyright information on souce files [#632] +- Added contributors list to about dialog [#629] + 2.1.4 (2017-04-09) ========================= diff --git a/CMakeLists.txt b/CMakeLists.txt index 8148dd0d65..6276761057 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,5 @@ # Copyright (C) 2010 Felix Geyer +# Copyright (C) 2017 KeePassXC Team # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -25,6 +26,9 @@ cmake_minimum_required(VERSION 2.8.12) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +# Support Visual Studio Code +include(CMakeToolsHelpers OPTIONAL) + include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) include(CheckCXXSourceCompiles) @@ -32,14 +36,21 @@ include(CheckCXXSourceCompiles) option(WITH_TESTS "Enable building of unit tests" ON) option(WITH_GUI_TESTS "Enable building of GUI tests" OFF) option(WITH_DEV_BUILD "Use only for development. Disables/warns about deprecated methods." OFF) -option(WITH_COVERAGE "Use to build with coverage tests. (GCC ONLY)." OFF) +option(WITH_ASAN "Enable address sanitizer checks (Linux only)" OFF) +option(WITH_COVERAGE "Use to build with coverage tests (GCC only)." OFF) +option(WITH_APP_BUNDLE "Enable Application Bundle for OS X" ON) + +option(WITH_XC_AUTOTYPE "Include Auto-Type." ON) +option(WITH_XC_HTTP "Include KeePassHTTP and Custom Icon Downloads." OFF) +option(WITH_XC_YUBIKEY "Include YubiKey support." OFF) -option(WITH_XC_AUTOTYPE "Include Autotype." OFF) -option(WITH_XC_HTTP "Include KeePassHTTP." OFF) -option(WITH_XC_YUBIKEY "Include Yubikey support." OFF) +# Process ui files automatically from source files +set(CMAKE_AUTOUIC ON) -set(KEEPASSXC_VERSION "2.1.4") -set(KEEPASSXC_VERSION_NUM "2.1.4") +set(KEEPASSXC_VERSION_MAJOR "2") +set(KEEPASSXC_VERSION_MINOR "2") +set(KEEPASSXC_VERSION_PATCH "0") +set(KEEPASSXC_VERSION "${KEEPASSXC_VERSION_MAJOR}.${KEEPASSXC_VERSION_MINOR}.${KEEPASSXC_VERSION_PATCH}") if("${CMAKE_C_COMPILER}" MATCHES "clang$" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_COMPILER_IS_CLANG 1) @@ -68,18 +79,39 @@ endmacro(add_gcc_compiler_flags) add_definitions(-DQT_NO_EXCEPTIONS -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII) -add_gcc_compiler_flags("-fno-common -fstack-protector --param=ssp-buffer-size=4") +if(WITH_APP_BUNDLE) + add_definitions(-DWITH_APP_BUNDLE) +endif() + +add_gcc_compiler_flags("-fno-common") add_gcc_compiler_flags("-Wall -Wextra -Wundef -Wpointer-arith -Wno-long-long") add_gcc_compiler_flags("-Wformat=2 -Wmissing-format-attribute") add_gcc_compiler_flags("-fvisibility=hidden") add_gcc_compiler_cxxflags("-fvisibility-inlines-hidden") +if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8.999) OR CMAKE_COMPILER_IS_CLANGXX) + add_gcc_compiler_flags("-fstack-protector-strong") +else() + add_gcc_compiler_flags("-fstack-protector --param=ssp-buffer-size=4") +endif() + add_gcc_compiler_cxxflags("-fno-exceptions -fno-rtti") add_gcc_compiler_cxxflags("-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual") add_gcc_compiler_cflags("-Wchar-subscripts -Wwrite-strings") +if(WITH_ASAN) + if(NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") + message(FATAL_ERROR "WITH_ASAN is only supported on Linux at the moment.") + endif() + + add_gcc_compiler_flags("-fsanitize=address -DWITH_ASAN") + + if(NOT (CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)) + add_gcc_compiler_flags("-fsanitize=leak -DWITH_LSAN") + endif() +endif() string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER) -if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel)) +if (CMAKE_BUILD_TYPE_LOWER MATCHES "(release|relwithdebinfo|minsizerel)") add_gcc_compiler_flags("-D_FORTIFY_SOURCE=2") endif() @@ -105,10 +137,14 @@ if(CMAKE_COMPILER_IS_GNUCC) endif() if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + if (CMAKE_COMPILER_IS_CLANGXX) + add_gcc_compiler_flags("-Qunused-arguments") + endif() + add_gcc_compiler_flags("-pie -fPIE") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-add-needed -Wl,--as-needed -Wl,--no-undefined") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro,-z,now") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-add-needed -Wl,--as-needed") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro,-z,now") endif() add_gcc_compiler_cxxflags("-std=c++11") @@ -127,30 +163,37 @@ if(MINGW) set(CMAKE_RC_COMPILER_INIT windres) enable_language(RC) set(CMAKE_RC_COMPILE_OBJECT " -O coff -i -o ") - link_libraries(ws2_32 wsock32) + if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")) + # Enable DEP and ASLR + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--nxcompat -Wl,--dynamicbase") + endif() endif() -if(APPLE OR MINGW) +if(APPLE AND WITH_APP_BUNDLE OR MINGW) set(PROGNAME KeePassXC) else() set(PROGNAME keepassxc) endif() -if(APPLE AND "${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr/local") +if(APPLE AND WITH_APP_BUNDLE AND "${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr/local") set(CMAKE_INSTALL_PREFIX "/Applications") endif() if(MINGW) + set(CLI_INSTALL_DIR ".") set(BIN_INSTALL_DIR ".") set(PLUGIN_INSTALL_DIR ".") set(DATA_INSTALL_DIR "share") -elseif(APPLE) +elseif(APPLE AND WITH_APP_BUNDLE) + set(CLI_INSTALL_DIR "/usr/local/bin") set(BIN_INSTALL_DIR ".") set(PLUGIN_INSTALL_DIR "${PROGNAME}.app/Contents/PlugIns") set(DATA_INSTALL_DIR "${PROGNAME}.app/Contents/Resources") else() include(GNUInstallDirs) + set(CLI_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}") set(BIN_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}") set(PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/keepassxc") set(DATA_INSTALL_DIR "${CMAKE_INSTALL_DATADIR}/keepassxc") @@ -161,6 +204,7 @@ if(WITH_TESTS) endif(WITH_TESTS) find_package(Qt5Core 5.2 REQUIRED) +find_package(Qt5Network 5.2 REQUIRED) find_package(Qt5Concurrent 5.2 REQUIRED) find_package(Qt5Widgets 5.2 REQUIRED) find_package(Qt5Test 5.2 REQUIRED) @@ -194,6 +238,13 @@ if(NOT ZLIB_SUPPORTS_GZIP) message(FATAL_ERROR "zlib 1.2.x or higher is required to use the gzip format") endif() +# Optional +if(WITH_XC_YUBIKEY) + find_package(YubiKey REQUIRED) + + include_directories(SYSTEM ${YUBIKEY_INCLUDE_DIRS}) +endif() + if(UNIX) check_cxx_source_compiles("#include int main() { prctl(PR_SET_DUMPABLE, 0); return 0; }" @@ -222,7 +273,6 @@ include(FeatureSummary) add_subdirectory(src) add_subdirectory(share) -add_subdirectory(utils) if(WITH_TESTS) add_subdirectory(tests) endif(WITH_TESTS) @@ -232,6 +282,6 @@ if(PRINT_SUMMARY) feature_summary(WHAT ALL) else() # This will only print ENABLED and DISABLED feature - print_enabled_features() - print_disabled_features() + feature_summary(WHAT ENABLED_FEATURES DESCRIPTION "Enabled features:") + feature_summary(WHAT DISABLED_FEATURES DESCRIPTION "Disabled features:") endif() diff --git a/COPYING b/COPYING index 9322a0e37d..481aaf726d 100644 --- a/COPYING +++ b/COPYING @@ -1,5 +1,5 @@ -KeePassX - http://www.keepassx.org/ -Copyright (C) 2010-2012 Felix Geyer +KeePassXC - http://www.keepassxc.org/ +Copyright (C) 2016-2017 KeePassXC Team This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,9 +14,9 @@ GNU General Public License for more details. -------------------------------------------------------------------- Format-Specification: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ -Upstream-Name: KeePassX -Upstream-Contact: Felix Geyer -Source: http://www.keepassx.org/ +Upstream-Name: KeePassXC +Upstream-Contact: KeePassXC Team +Source: http://www.keepassxc.org/ Copyright: 2010-2012, Felix Geyer 2011-2012, Florian Geyer @@ -27,20 +27,46 @@ Copyright: 2010-2012, Felix Geyer 2000-2008, Tom Sato 2013, Laszlo Papp 2013, David Faure - 2016, KeePassXC Team + 2016-2017, KeePassXC Team License: GPL-2 or GPL-3 +Comment: The "KeePassXC Team" in every copyright notice is formed by the following people: + - droidmonkey + - phoerious + - TheZ3ro + - louib + - weslly + Every other contributor is listed on https://github.com/keepassxreboot/keepassxc/graphs/contributors + Files: cmake/GNUInstallDirs.cmake Copyright: 2011 Nikita Krupen'ko 2011 Kitware, Inc. License: BSD-3-clause +Files: cmake/CodeCoverage.cmake +Copyright: 2012 - 2015, Lars Bilke +License: BSD-3-clause + +Files: cmake/FindYubiKey.cmake +Copyright: 2014 Kyle Manna +License: GPL-2 or GPL-3 + +Files: cmake/GenerateProductVersion.cmake +Copyright: 2015 halex2005 +License: MIT + +Files: cmake/CodeCoverage.cmake +Copyright: 2012 - 2015, Lars Bilke +License: BSD-3-clause + Files: share/icons/application/*/apps/keepassxc.png share/icons/application/scalable/apps/keepassxc.svgz share/icons/application/*/apps/keepassxc-dark.png share/icons/application/scalable/apps/keepassxc-dark.svgz share/icons/application/*/apps/keepassxc-locked.png share/icons/application/scalable/apps/keepassxc-locked.svgz + share/icons/application/*/apps/keepassxc-unlocked.png + share/icons/application/scalable/apps/keepassxc-unlocked.svgz share/icons/application/*/mimetypes/application-x-keepassxc.png share/icons/application/scalable/mimetypes/application-x-keepassxc.svgz Copyright: 2016, Lorenzo Stella @@ -51,6 +77,8 @@ Files: share/icons/application/*/actions/auto-type.png share/icons/application/*/actions/entry-clone.png share/icons/application/*/actions/entry-edit.png share/icons/application/*/actions/entry-new.png + share/icons/application/*/actions/group-empty-trash.png + share/icons/application/*/actions/help-about.png share/icons/application/*/actions/password-generate.png share/icons/database/C00_Password.png share/icons/database/C01_Package_Network.png @@ -136,18 +164,25 @@ Files: share/icons/application/*/actions/application-exit.png share/icons/application/*/actions/document-encrypt.png share/icons/application/*/actions/document-new.png share/icons/application/*/actions/document-open.png + share/icons/application/*/actions/document-properties.png share/icons/application/*/actions/document-save.png share/icons/application/*/actions/document-save-as.png share/icons/application/*/actions/edit-clear-locationbar-ltr.png share/icons/application/*/actions/edit-clear-locationbar-rtl.png + share/icons/application/*/actions/key-enter.png share/icons/application/*/actions/password-generator.png share/icons/application/*/actions/password-copy.png share/icons/application/*/actions/password-show-*.png share/icons/application/*/actions/system-search.png share/icons/application/*/actions/username-copy.png + share/icons/application/*/actions/view-history.png + share/icons/application/*/apps/internet-web-browser.png + share/icons/application/*/apps/preferences-desktop-icons.png + share/icons/application/*/categories/preferences-other.png share/icons/application/*/status/dialog-error.png share/icons/application/*/status/dialog-information.png share/icons/application/*/status/dialog-warning.png + share/icons/application/*/status/security-high.png share/icons/svg/*.svgz Copyright: 2007, Nuno Pinheiro 2007, David Vignoni @@ -194,7 +229,20 @@ Copyright: 2009-2010, Iowa State University License: Boost-1.0 Files: src/zxcvbn/zxcvbn.* - src/utils/entropy-meter.cpp Copyright: 2015, Tony Evans - 2016, KeePassXC Team License: BSD 3-clause + +Files: src/http/qhttp/* +Copyright: 2014, Amir Zamani +License: MIT + +Files: src/gui/KMessageWidget.h + src/gui/KMessageWidget.cpp +Copyright: 2011 Aurélien Gâteau + 2014 Dominik Haumann +License: LGPL-2.1 + +Files: src/totp/base32.cpp + src/totp/base32.h +Copyright: 2010 Google Inc. +License: Apache 2.0 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 9623b60dd5..8602d44a39 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,10 +32,12 @@ RUN set -x \ qt58base \ qt58tools \ qt58x11extras \ - libmicrohttpd-dev \ libxi-dev \ libxtst-dev \ zlib1g-dev \ + libyubikey-dev \ + libykpers-1-dev \ + xvfb \ wget \ file \ fuse \ diff --git a/README.md b/README.md index e892f1b017..bf214d3c1f 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,33 @@ -# KeePassXC - KeePass Cross-platform Community Edition +# KeePassXC [![Travis Build Status](https://travis-ci.org/keepassxreboot/keepassxc.svg?branch=develop)](https://travis-ci.org/keepassxreboot/keepassxc) [![Coverage Status](https://coveralls.io/repos/github/keepassxreboot/keepassxc/badge.svg)](https://coveralls.io/github/keepassxreboot/keepassxc) -[![Travis Build Status](https://travis-ci.org/keepassxreboot/keepassxc.svg?branch=develop)](https://travis-ci.org/keepassxreboot/keepassxc) [![Coverage Status](https://coveralls.io/repos/github/keepassxreboot/keepassxc/badge.svg)](https://coveralls.io/github/keepassxreboot/keepassxc) +KeePass Cross-platform Community Edition ## About -KeePassXC is a fork of [KeePassX](https://www.keepassx.org/) that [aims to incorporate stalled pull requests, features, and bug fixes that have never made it into the main KeePassX repository](https://github.com/keepassxreboot/keepassx/issues/43). +[KeePassXC](https://keepassxc.org) is a community fork of [KeePassX](https://www.keepassx.org/) with the goal to extend and improve it with new features and bugfixes to provide a feature-rich, fully cross-platform and modern open-source password manager. ## Additional features compared to KeePassX -- Autotype on all three major platforms (Linux, Windows, OS X) +- Auto-Type on all three major platforms (Linux, Windows, OS X) - Stand-alone password generator - Password strength meter -- Use website's favicons as entry icons +- YubiKey HMAC-SHA1 authentication for unlocking databases +- Using website favicons as entry icons - Merging of databases - Automatic reload when the database changed on disk -- KeePassHTTP support for use with [PassIFox](https://addons.mozilla.org/en-us/firefox/addon/passifox/) in Mozilla Firefox and [chromeIPass](https://chrome.google.com/webstore/detail/chromeipass/ompiailgknfdndiefoaoiligalphfdae) in Google Chrome or Chromium. +- KeePassHTTP support for use with [PassIFox](https://addons.mozilla.org/en-us/firefox/addon/passifox/) in Mozilla Firefox and [chromeIPass](https://chrome.google.com/webstore/detail/chromeipass/ompiailgknfdndiefoaoiligalphfdae) in Google Chrome or Chromium, and [passafari](https://github.com/mmichaa/passafari.safariextension/) in Safari. +- Many bug fixes For a full list of features and changes, read the [CHANGELOG](CHANGELOG) document. ### Note about KeePassHTTP -KeePassHTTP is not a highly secure protocol and has certain flaw which allow an attacker to decrypt your passwords when they manage to intercept communication between a KeePassHTTP server and PassIFox/chromeIPass over a network connection (see [here](https://github.com/pfn/keepasshttp/issues/258) and [here](https://github.com/keepassxreboot/keepassxc/issues/147)). KeePassXC therefore strictly limits communication between itself and the browser plugin to your local computer. As long as your computer is not compromised, your passwords are fairly safe that way, but still use it at your own risk! +KeePassHTTP is not a highly secure protocol and has certain flaw which allow an attacker to decrypt your passwords when they manage to intercept communication between a KeePassHTTP server and PassIFox/chromeIPass over a network connection (see [here](https://github.com/pfn/keepasshttp/issues/258) and [here](https://github.com/keepassxreboot/keepassxc/issues/147)). KeePassXC therefore strictly limits communication between itself and the browser plugin to your local computer. As long as your computer is not compromised, your passwords are fairly safe that way, but use it at your own risk! ### Installation Pre-compiled binaries can be found on the [downloads page](https://keepassxc.org/download). Additionally, individual Linux distributions may ship their own versions, so please check out your distribution's package list to see if KeePassXC is available. -### Building KeePassXC yourself +### Building KeePassXC -*More detailed instructions are available in the INSTALL file or on the [Wiki page](https://github.com/keepassxreboot/keepassx/wiki/Install-Instruction-from-Source).* +*More detailed instructions are available in the INSTALL file or on the [Wiki page](https://github.com/keepassxreboot/keepassxc/wiki/Building-KeePassXC).* First, you must download the KeePassXC [source tarball](https://keepassxc.org/download#source) or check out the latest version from our [Git repository](https://github.com/keepassxreboot/keepassxc). @@ -43,9 +45,9 @@ To update the project from within the project's folder, you can run the followin git pull ``` -Once you have downloaded the source code, you can `cd` into the source code directory and build and install KeePassXC with +Once you have downloaded the source code, you can `cd` into the source code directory, build and install KeePassXC: -``` +```bash mkdir build cd build cmake -DWITH_TESTS=OFF .. @@ -53,13 +55,24 @@ make -j8 sudo make install ``` -To enable autotype, add `-DWITH_XC_AUTOTYPE=ON` to the `cmake` command. KeePassHTTP support is compiled in by adding `-DWITH_XC_HTTP=ON`. If these options are not specified, KeePassXC will be built without these plugins. +cmake accepts the following options: +``` + -DWITH_XC_AUTOTYPE=[ON|OFF] Enable/Disable Auto-Type (default: ON) + -DWITH_XC_HTTP=[ON|OFF] Enable/Disable KeePassHTTP and custom icon downloads (default: OFF) + -DWITH_XC_YUBIKEY=[ON|OFF] Enable/Disable YubiKey HMAC-SHA1 authentication support (default: OFF) + + -DWITH_TESTS=[ON|OFF] Enable/Disable building of unit tests (default: ON) + -DWITH_GUI_TESTS=[ON|OFF] Enable/Disable building of GUI tests (default: OFF) + -DWITH_DEV_BUILD=[ON|OFF] Enable/Disable deprecated method warnings (default: OFF) + -DWITH_ASAN=[ON|OFF] Enable/Disable address sanitizer checks (Linux only) (default: OFF) + -DWITH_COVERAGE=[ON|OFF] Enable/Disable coverage tests (GCC only) (default: OFF) +``` ### 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 write to our [Google Groups](https://groups.google.com/forum/#!forum/keepassx-reboot) forum. +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. You can of course also directly contribute your own code. We are happy to accept your pull requests. -Please read the [CONTRIBUTING](.github/CONTRIBUTING.md) document for further information. +Please read the [CONTRIBUTING document](.github/CONTRIBUTING.md) for further information. diff --git a/cmake/FindLibGPGError.cmake b/cmake/FindLibGPGError.cmake index fe9ef91232..c1e1b86862 100644 --- a/cmake/FindLibGPGError.cmake +++ b/cmake/FindLibGPGError.cmake @@ -1,3 +1,17 @@ +# Copyright (C) 2017 KeePassXC Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 or (at your option) +# version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . find_path(GPGERROR_INCLUDE_DIR gpg-error.h) diff --git a/cmake/FindLibMicroHTTPD.cmake b/cmake/FindLibMicroHTTPD.cmake deleted file mode 100644 index f319280431..0000000000 --- a/cmake/FindLibMicroHTTPD.cmake +++ /dev/null @@ -1,9 +0,0 @@ - -find_path(MHD_INCLUDE_DIR microhttpd.h) - -find_library(MHD_LIBRARIES microhttpd) - -mark_as_advanced(MHD_LIBRARIES MHD_INCLUDE_DIR) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(LibMicroHTTPD DEFAULT_MSG MHD_LIBRARIES MHD_INCLUDE_DIR) diff --git a/cmake/FindYubiKey.cmake b/cmake/FindYubiKey.cmake new file mode 100644 index 0000000000..e5e0bb6816 --- /dev/null +++ b/cmake/FindYubiKey.cmake @@ -0,0 +1,27 @@ +# Copyright (C) 2014 Kyle Manna +# +# 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_path(YUBIKEY_CORE_INCLUDE_DIR yubikey.h) +find_path(YUBIKEY_PERS_INCLUDE_DIR ykcore.h PATH_SUFFIXES ykpers-1) +set(YUBIKEY_INCLUDE_DIRS ${YUBIKEY_CORE_INCLUDE_DIR} ${YUBIKEY_PERS_INCLUDE_DIR}) + +find_library(YUBIKEY_CORE_LIBRARY yubikey) +find_library(YUBIKEY_PERS_LIBRARY ykpers-1) +set(YUBIKEY_LIBRARIES ${YUBIKEY_CORE_LIBRARY} ${YUBIKEY_PERS_LIBRARY}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(YubiKey DEFAULT_MSG YUBIKEY_LIBRARIES YUBIKEY_INCLUDE_DIRS) + +mark_as_advanced(YUBIKEY_LIBRARIES YUBIKEY_INCLUDE_DIRS) diff --git a/release-tool b/release-tool index 7bc54cda06..a08e9601bf 100755 --- a/release-tool +++ b/release-tool @@ -16,8 +16,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -echo -e "\e[1m\e[32mKeePassXC\e[0m Release Preparation Helper" -echo -e "Copyright (C) 2017 KeePassXC Team \n" +printf "\e[1m\e[32mKeePassXC\e[0m Release Preparation Helper\n" +printf "Copyright (C) 2017 KeePassXC Team \n\n" # ----------------------------------------------------------------------- @@ -37,7 +37,7 @@ DOCKER_CONTAINER_NAME="keepassxc-build-container" CMAKE_OPTIONS="" COMPILER="g++" MAKE_OPTIONS="-j8" -BUILD_PLUGINS="autotype" +BUILD_PLUGINS="autotype http yubikey" INSTALL_PREFIX="/usr/local" BUILD_SOURCE_TARBALL=true ORIG_BRANCH="" @@ -50,19 +50,20 @@ printUsage() { local cmd if [ "" == "$1" ] || [ "help" == "$1" ]; then cmd="COMMAND" - elif [ "merge" == "$1" ] || [ "build" == "$1" ] || [ "sign" == "$1" ]; then + elif [ "check" == "$1" ] || [ "merge" == "$1" ] || [ "build" == "$1" ] || [ "sign" == "$1" ]; then cmd="$1" else logError "Unknown command: '$1'\n" cmd="COMMAND" fi - echo -e "\e[1mUsage:\e[0m $(basename $0) $cmd [options]" + printf "\e[1mUsage:\e[0m $(basename $0) $cmd [--version x.y.z] [options]\n" if [ "COMMAND" == "$cmd" ]; then cat << EOF Commands: + check Perform a dry-run check, nothing is changed merge Merge release branch into main branch and create release tags build Build and package binary release from sources sign Sign previously compiled release packages @@ -126,15 +127,30 @@ EOF } logInfo() { - echo -e "\e[1m[ \e[34mINFO\e[39m ]\e[0m $1" + printf "\e[1m[ \e[34mINFO\e[39m ]\e[0m $1\n" } logError() { - echo -e "\e[1m[ \e[31mERROR\e[39m ]\e[0m $1" >&2 + printf "\e[1m[ \e[31mERROR\e[39m ]\e[0m $1\n" >&2 } init() { + if [ "" == "$RELEASE_NAME" ]; then + logError "Missing arguments, --version is required!\n" + printUsage "check" + exit 1 + fi + + if [ "" == "$TAG_NAME" ]; then + TAG_NAME="$RELEASE_NAME" + fi + + if [ "" == "$SOURCE_BRANCH" ]; then + SOURCE_BRANCH="release/${RELEASE_NAME}" + fi + ORIG_CWD="$(pwd)" + SRC_DIR="$(realpath "$SRC_DIR")" cd "$SRC_DIR" > /dev/null 2>&1 ORIG_BRANCH="$(git rev-parse --abbrev-ref HEAD 2> /dev/null)" cd "$ORIG_CWD" @@ -214,15 +230,23 @@ checkTargetBranchExists() { checkVersionInCMake() { local app_name_upper="$(echo "$APP_NAME" | tr '[:lower:]' '[:upper:]')" - - grep -q "${app_name_upper}_VERSION \"${RELEASE_NAME}\"" CMakeLists.txt + local major_num="$(echo ${RELEASE_NAME} | cut -f1 -d.)" + local minor_num="$(echo ${RELEASE_NAME} | cut -f2 -d.)" + local patch_num="$(echo ${RELEASE_NAME} | cut -f3 -d.)" + + grep -q "${app_name_upper}_VERSION_MAJOR \"${major_num}\"" CMakeLists.txt + if [ $? -ne 0 ]; then + exitError "${app_name_upper}_VERSION_MAJOR not updated to '${major_num}' in CMakeLists.txt!" + fi + + grep -q "${app_name_upper}_VERSION_MINOR \"${minor_num}\"" CMakeLists.txt if [ $? -ne 0 ]; then - exitError "${app_name_upper}_VERSION version not updated to '${RELEASE_NAME}' in CMakeLists.txt!" + exitError "${app_name_upper}_VERSION_MINOR not updated to '${minor_num}' in CMakeLists.txt!" fi - grep -q "${app_name_upper}_VERSION_NUM \"${RELEASE_NAME}\"" CMakeLists.txt + grep -q "${app_name_upper}_VERSION_PATCH \"${patch_num}\"" CMakeLists.txt if [ $? -ne 0 ]; then - exitError "${app_name_upper}_VERSION_NUM version not updated to '${RELEASE_NAME}' in CMakeLists.txt!" + exitError "${app_name_upper}_VERSION_PATCH not updated to '${patch_num}' in CMakeLists.txt!" fi } @@ -242,11 +266,57 @@ checkTransifexCommandExists() { if [ 0 -ne $? ]; then exitError "Transifex tool 'tx' not installed! Please install it using 'pip install transifex-client'" fi + + command -v lupdate-qt5 > /dev/null + if [ 0 -ne $? ]; then + exitError "Qt Linguist tool (lupdate-qt5) is not installed! Please install using 'apt install qttools5-dev-tools'" + fi +} + +checkSnapcraft() { + if [ ! -f snapcraft.yaml ]; then + echo "No snapcraft file found!" + return + fi + + grep -qPzo "version: ${RELEASE_NAME}" snapcraft.yaml + if [ $? -ne 0 ]; then + exitError "snapcraft.yaml has not been updated to the '${RELEASE_NAME}' release!" + fi +} + +performChecks() { + logInfo "Performing basic checks..." + + checkSourceDirExists + + logInfo "Changing to source directory..." + cd "${SRC_DIR}" + + logInfo "Validating toolset and repository..." + + checkTransifexCommandExists + checkGitRepository + checkReleaseDoesNotExist + checkWorkingTreeClean + checkSourceBranchExists + checkTargetBranchExists + + logInfo "Checking out '${SOURCE_BRANCH}'..." + git checkout "$SOURCE_BRANCH" + + logInfo "Attempting to find '${RELEASE_NAME}' in various files..." + + checkVersionInCMake + checkChangeLog + checkSnapcraft + + logInfo "\e[1m\e[32mAll checks passed!\e[0m" } # re-implement realpath for OS X (thanks mschrag) # https://superuser.com/questions/205127/ -if $(command -v realpath > /dev/null); then +if ! $(command -v realpath > /dev/null); then realpath() { pushd . > /dev/null if [ -d "$1" ]; then @@ -269,6 +339,28 @@ fi trap exitTrap SIGINT SIGTERM +# ----------------------------------------------------------------------- +# check command +# ----------------------------------------------------------------------- +check() { + while [ $# -ge 1 ]; do + local arg="$1" + case "$arg" in + -v|--version) + RELEASE_NAME="$2" + shift ;; + esac + shift + done + + init + + performChecks + + cleanup + + logInfo "Congrats! You can successfully merge, build, and sign KeepassXC." +} # ----------------------------------------------------------------------- # merge command @@ -317,44 +409,9 @@ merge() { shift done - if [ "" == "$RELEASE_NAME" ]; then - logError "Missing arguments, --version is required!\n" - printUsage "merge" - exit 1 - fi - - if [ "" == "$TAG_NAME" ]; then - TAG_NAME="$RELEASE_NAME" - fi - - if [ "" == "$SOURCE_BRANCH" ]; then - SOURCE_BRANCH="release/${RELEASE_NAME}" - fi - init - SRC_DIR="$(realpath "$SRC_DIR")" - - logInfo "Performing basic checks..." - - checkSourceDirExists - - logInfo "Changing to source directory..." - cd "${SRC_DIR}" - - checkTransifexCommandExists - checkGitRepository - checkReleaseDoesNotExist - checkWorkingTreeClean - checkSourceBranchExists - checkTargetBranchExists - checkVersionInCMake - checkChangeLog - - logInfo "All checks pass, getting our hands dirty now!" - - logInfo "Checking out source branch..." - git checkout "$SOURCE_BRANCH" + performChecks logInfo "Updating language files..." ./share/translations/update.sh @@ -372,15 +429,15 @@ merge() { fi fi + CHANGELOG=$(grep -Pzo "(?<=${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n)=+\n\n?(?:.|\n)+?\n(?=\n)" \ + CHANGELOG | grep -Pzo '(?<=\n\n)(.|\n)+' | tr -d \\0) + COMMIT_MSG="Release ${RELEASE_NAME}" + logInfo "Checking out target branch '${TARGET_BRANCH}'..." git checkout "$TARGET_BRANCH" logInfo "Merging '${SOURCE_BRANCH}' into '${TARGET_BRANCH}'..." - CHANGELOG=$(grep -Pzo "(?<=${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n)=+\n\n?(?:.|\n)+?\n(?=\n)" \ - CHANGELOG | grep -Pzo '(?<=\n\n)(.|\n)+' | tr -d \\0) - COMMIT_MSG="Release ${RELEASE_NAME}" - git merge "$SOURCE_BRANCH" --no-ff -m "$COMMIT_MSG" -m "${CHANGELOG}" "$SOURCE_BRANCH" -S"$GPG_GIT_KEY" logInfo "Creating tag '${TAG_NAME}'..." @@ -466,36 +523,13 @@ build() { esac shift done - - if [ "" == "$RELEASE_NAME" ]; then - logError "Missing arguments, --version is required!\n" - printUsage "build" - exit 1 - fi - - if [ "" == "$TAG_NAME" ]; then - TAG_NAME="$RELEASE_NAME" - fi - + init + + performChecks - SRC_DIR="$(realpath "$SRC_DIR")" OUTPUT_DIR="$(realpath "$OUTPUT_DIR")" - logInfo "Performing basic checks..." - - checkSourceDirExists - - logInfo "Changing to source directory..." - cd "${SRC_DIR}" - - checkTagExists - checkGitRepository - checkWorkingTreeClean - checkOutputDirDoesNotExist - - logInfo "All checks pass, getting our hands dirty now!" - logInfo "Checking out release tag '${TAG_NAME}'..." git checkout "$TAG_NAME" @@ -656,7 +690,9 @@ sign() { fi logInfo "Creating digest for file '${f}'..." - sha256sum "$f" > "${f}.DIGEST" + local rp="$(realpath "$f")" + local bname="$(basename "$f")" + (cd "$(dirname "$rp")"; sha256sum "$bname" > "${bname}.DIGEST") done logInfo "All done!" @@ -675,7 +711,7 @@ if [ "" == "$MODE" ]; then elif [ "help" == "$MODE" ]; then printUsage "$1" exit -elif [ "merge" == "$MODE" ] || [ "build" == "$MODE" ] || [ "sign" == "$MODE" ]; then +elif [ "check" == "$MODE" ] || [ "merge" == "$MODE" ] || [ "build" == "$MODE" ] || [ "sign" == "$MODE" ]; then $MODE "$@" else printUsage "$MODE" diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index 37e4bdd684..a609add796 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -1,4 +1,5 @@ # Copyright (C) 2011 Felix Geyer +# Copyright (C) 2017 KeePassXC Team # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -15,6 +16,9 @@ add_subdirectory(translations) +file(GLOB wordlists_files "wordlists/*.wordlist") +install(FILES ${wordlists_files} DESTINATION ${DATA_INSTALL_DIR}/wordlists) + file(GLOB DATABASE_ICONS icons/database/*.png) install(FILES ${DATABASE_ICONS} DESTINATION ${DATA_INSTALL_DIR}/icons/database) @@ -22,10 +26,10 @@ install(FILES ${DATABASE_ICONS} DESTINATION ${DATA_INSTALL_DIR}/icons/database) if(UNIX AND NOT APPLE) install(DIRECTORY icons/application/ DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor FILES_MATCHING PATTERN "keepassx*.png" PATTERN "keepassx*.svgz" - PATTERN "status" EXCLUDE PATTERN "actions" EXCLUDE) + PATTERN "status" EXCLUDE PATTERN "actions" EXCLUDE PATTERN "categories" EXCLUDE) install(DIRECTORY icons/application/ DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor FILES_MATCHING PATTERN "application-x-keepassxc.png" PATTERN "application-x-keepassxc.svgz" - PATTERN "status" EXCLUDE PATTERN "actions" EXCLUDE) + PATTERN "status" EXCLUDE PATTERN "actions" EXCLUDE PATTERN "categories" EXCLUDE) install(FILES linux/keepassxc.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) install(FILES linux/keepassxc.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages) endif(UNIX AND NOT APPLE) @@ -86,6 +90,22 @@ add_custom_target(icons COMMAND inkscape -z -w 256 -h 256 icons/application/scalable/apps/keepassxc-locked.svgz -e icons/application/256x256/apps/keepassxc-locked.png + # SVGZ to PNGs for KeePassXC + COMMAND inkscape -z -w 16 -h 16 + icons/application/scalable/apps/keepassxc-unlocked.svgz -e icons/application/16x16/apps/keepassxc-unlocked.png + COMMAND inkscape -z -w 24 -h 24 + icons/application/scalable/apps/keepassxc-unlocked.svgz -e icons/application/24x24/apps/keepassxc-unlocked.png + COMMAND inkscape -z -w 32 -h 32 + icons/application/scalable/apps/keepassxc-unlocked.svgz -e icons/application/32x32/apps/keepassxc-unlocked.png + COMMAND inkscape -z -w 48 -h 48 + icons/application/scalable/apps/keepassxc-unlocked.svgz -e icons/application/48x48/apps/keepassxc-unlocked.png + COMMAND inkscape -z -w 64 -h 64 + icons/application/scalable/apps/keepassxc-unlocked.svgz -e icons/application/64x64/apps/keepassxc-unlocked.png + COMMAND inkscape -z -w 128 -h 128 + icons/application/scalable/apps/keepassxc-unlocked.svgz -e icons/application/128x128/apps/keepassxc-unlocked.png + COMMAND inkscape -z -w 256 -h 256 + icons/application/scalable/apps/keepassxc-unlocked.svgz -e icons/application/256x256/apps/keepassxc-unlocked.png + # SVGZ to PNGs for KeePassXC MIME-Type COMMAND inkscape -z -w 16 -h 16 icons/application/scalable/mimetypes/application-x-keepassxc.svgz -e icons/application/16x16/mimetypes/application-x-keepassxc.png diff --git a/share/icons/application/128x128/apps/keepassxc-unlocked.png b/share/icons/application/128x128/apps/keepassxc-unlocked.png new file mode 100644 index 0000000000..69b0fe24ee Binary files /dev/null and b/share/icons/application/128x128/apps/keepassxc-unlocked.png differ diff --git a/share/icons/application/16x16/actions/group-empty-trash.png b/share/icons/application/16x16/actions/group-empty-trash.png new file mode 100644 index 0000000000..aa9d7321f9 Binary files /dev/null and b/share/icons/application/16x16/actions/group-empty-trash.png differ diff --git a/share/icons/application/16x16/actions/message-close.png b/share/icons/application/16x16/actions/message-close.png new file mode 100644 index 0000000000..4b2f9ca4d7 Binary files /dev/null and b/share/icons/application/16x16/actions/message-close.png differ diff --git a/share/icons/application/16x16/apps/keepassxc-unlocked.png b/share/icons/application/16x16/apps/keepassxc-unlocked.png new file mode 100644 index 0000000000..2164f0335e Binary files /dev/null and b/share/icons/application/16x16/apps/keepassxc-unlocked.png differ diff --git a/share/icons/application/22x22/actions/document-new.png b/share/icons/application/22x22/actions/document-new.png new file mode 100644 index 0000000000..9ff24e2b28 Binary files /dev/null and b/share/icons/application/22x22/actions/document-new.png differ diff --git a/share/icons/application/22x22/actions/message-close.png b/share/icons/application/22x22/actions/message-close.png new file mode 100644 index 0000000000..4b2f9ca4d7 Binary files /dev/null and b/share/icons/application/22x22/actions/message-close.png differ diff --git a/share/icons/application/24x24/apps/keepassxc-unlocked.png b/share/icons/application/24x24/apps/keepassxc-unlocked.png new file mode 100644 index 0000000000..68c6cabc18 Binary files /dev/null and b/share/icons/application/24x24/apps/keepassxc-unlocked.png differ diff --git a/share/icons/application/256x256/apps/keepassxc-unlocked.png b/share/icons/application/256x256/apps/keepassxc-unlocked.png new file mode 100644 index 0000000000..d1c1178133 Binary files /dev/null and b/share/icons/application/256x256/apps/keepassxc-unlocked.png differ diff --git a/share/icons/application/32x32/actions/document-edit.png b/share/icons/application/32x32/actions/document-edit.png new file mode 100644 index 0000000000..eb327b0a10 Binary files /dev/null and b/share/icons/application/32x32/actions/document-edit.png differ diff --git a/share/icons/application/32x32/actions/document-properties.png b/share/icons/application/32x32/actions/document-properties.png new file mode 100644 index 0000000000..a6d13863d8 Binary files /dev/null and b/share/icons/application/32x32/actions/document-properties.png differ diff --git a/share/icons/application/32x32/actions/key-enter.png b/share/icons/application/32x32/actions/key-enter.png new file mode 100644 index 0000000000..60d11e2f11 Binary files /dev/null and b/share/icons/application/32x32/actions/key-enter.png differ diff --git a/share/icons/application/32x32/actions/view-history.png b/share/icons/application/32x32/actions/view-history.png new file mode 100644 index 0000000000..a67c689ac5 Binary files /dev/null and b/share/icons/application/32x32/actions/view-history.png differ diff --git a/share/icons/application/32x32/apps/internet-web-browser.png b/share/icons/application/32x32/apps/internet-web-browser.png new file mode 100644 index 0000000000..b4106a58b3 Binary files /dev/null and b/share/icons/application/32x32/apps/internet-web-browser.png differ diff --git a/share/icons/application/32x32/apps/keepassxc-unlocked.png b/share/icons/application/32x32/apps/keepassxc-unlocked.png new file mode 100644 index 0000000000..de06bf03ae Binary files /dev/null and b/share/icons/application/32x32/apps/keepassxc-unlocked.png differ diff --git a/share/icons/application/32x32/apps/preferences-desktop-icons.png b/share/icons/application/32x32/apps/preferences-desktop-icons.png new file mode 100644 index 0000000000..dcd605b254 Binary files /dev/null and b/share/icons/application/32x32/apps/preferences-desktop-icons.png differ diff --git a/share/icons/application/32x32/categories/preferences-other.png b/share/icons/application/32x32/categories/preferences-other.png new file mode 100644 index 0000000000..acafe44c68 Binary files /dev/null and b/share/icons/application/32x32/categories/preferences-other.png differ diff --git a/share/icons/application/32x32/status/security-high.png b/share/icons/application/32x32/status/security-high.png new file mode 100644 index 0000000000..7178893c2d Binary files /dev/null and b/share/icons/application/32x32/status/security-high.png differ diff --git a/share/icons/application/48x48/apps/keepassxc-unlocked.png b/share/icons/application/48x48/apps/keepassxc-unlocked.png new file mode 100644 index 0000000000..06a563d1a7 Binary files /dev/null and b/share/icons/application/48x48/apps/keepassxc-unlocked.png differ diff --git a/share/icons/application/64x64/apps/keepassxc-unlocked.png b/share/icons/application/64x64/apps/keepassxc-unlocked.png new file mode 100644 index 0000000000..8ade0e85e3 Binary files /dev/null and b/share/icons/application/64x64/apps/keepassxc-unlocked.png differ diff --git a/share/icons/application/scalable/apps/keepassxc-unlocked.svgz b/share/icons/application/scalable/apps/keepassxc-unlocked.svgz new file mode 100644 index 0000000000..84ce139046 Binary files /dev/null and b/share/icons/application/scalable/apps/keepassxc-unlocked.svgz differ diff --git a/share/icons/svg/document-properties.svgz b/share/icons/svg/document-properties.svgz new file mode 100644 index 0000000000..7f166d7f28 Binary files /dev/null and b/share/icons/svg/document-properties.svgz differ diff --git a/share/icons/svg/internet-web-browser.svgz b/share/icons/svg/internet-web-browser.svgz new file mode 100644 index 0000000000..f48f1415c2 Binary files /dev/null and b/share/icons/svg/internet-web-browser.svgz differ diff --git a/share/icons/svg/key-enter.svgz b/share/icons/svg/key-enter.svgz new file mode 100644 index 0000000000..7176b5acb7 Binary files /dev/null and b/share/icons/svg/key-enter.svgz differ diff --git a/share/icons/svg/message-close.svg b/share/icons/svg/message-close.svg new file mode 100644 index 0000000000..44b643072e --- /dev/null +++ b/share/icons/svg/message-close.svg @@ -0,0 +1,65 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/share/icons/svg/preferences-desktop-icons.svgz b/share/icons/svg/preferences-desktop-icons.svgz new file mode 100644 index 0000000000..1cd0a05265 Binary files /dev/null and b/share/icons/svg/preferences-desktop-icons.svgz differ diff --git a/share/icons/svg/preferences-other.svgz b/share/icons/svg/preferences-other.svgz new file mode 100644 index 0000000000..4abeca3763 Binary files /dev/null and b/share/icons/svg/preferences-other.svgz differ diff --git a/share/icons/svg/security-high.svgz b/share/icons/svg/security-high.svgz new file mode 100644 index 0000000000..5edee37344 Binary files /dev/null and b/share/icons/svg/security-high.svgz differ diff --git a/share/icons/svg/view-history.svgz b/share/icons/svg/view-history.svgz new file mode 100644 index 0000000000..fff230f666 Binary files /dev/null and b/share/icons/svg/view-history.svgz differ diff --git a/share/keepassxc.ini b/share/keepassxc.ini new file mode 100644 index 0000000000..f7ff52cbc0 --- /dev/null +++ b/share/keepassxc.ini @@ -0,0 +1,57 @@ +[General] +ShowToolbar=true +RememberLastDatabases=true +RememberLastKeyFiles=true +OpenPreviousDatabasesOnStartup=true +AutoSaveAfterEveryChange=false +AutoSaveOnExit=false +AutoReloadOnChange=true +MinimizeOnCopy=false +UseGroupIconOnEntryCreation=true +IgnoreGroupExpansion=false +AutoTypeEntryTitleMatch=true +GlobalAutoTypeKey=0 +GlobalAutoTypeModifiers=0 +LastOpenedDatabases=@Invalid() + +[GUI] +Language=system +ShowTrayIcon=false +MinimizeToTray=false +MinimizeOnClose=false +MinimizeOnStartup=false +MainWindowGeometry="@ByteArray(\x1\xd9\xd0\xcb\0\x2\0\0\0\0\x2(\0\0\0\xbd\0\0\x5W\0\0\x3;\0\0\x2\x30\0\0\0\xdc\0\0\x5O\0\0\x3\x33\0\0\0\0\0\0\0\0\a\x80)" +SplitterState=@Invalid() +EntryListColumnSizes=@Invalid() +EntrySearchColumnSizes=@Invalid() + +[security] +autotypeask=true +clearclipboard=true +clearclipboardtimeout=10 +lockdatabaseidle=false +lockdatabaseidlesec=240 +lockdatabaseminimize=false +lockdatabasescreenlock=true +passwordscleartext=false +passwordsrepeat=false + +[Http] +Enabled=false +ShowNotification=true +BestMatchOnly=false +UnlockDatabase=true +MatchUrlScheme=true +SortByUsername=false +Port=19455 +AlwaysAllowAccess=false +AlwaysAllowUpdate=false +SearchInAllDatabases=false +SupportKphFields=true +generator\LowerCase=true +generator\UpperCase=true +generator\Numbers=true +generator\SpecialChars=false +generator\ExcludeAlike=true +generator\EnsureEvery=true +generator\Length=16 diff --git a/share/macosx/Info.plist.cmake b/share/macosx/Info.plist.cmake index db5b8501e2..ea1a9bc2c6 100644 --- a/share/macosx/Info.plist.cmake +++ b/share/macosx/Info.plist.cmake @@ -4,6 +4,8 @@ NSPrincipalClass NSApplication + CFBundleAllowMixedLocalizations + CFBundleDevelopmentRegion English CFBundleDisplayName @@ -27,7 +29,7 @@ CFBundleVersion ${KEEPASSXC_VERSION_NUM} NSHumanReadableCopyright - Copyright 2016 KeePassXC Development Team + Copyright 2016-2017 KeePassXC Development Team CFBundleDocumentTypes diff --git a/share/translations/keepassx_cs.ts b/share/translations/keepassx_cs.ts index f54a1db8ef..cdd273667a 100644 --- a/share/translations/keepassx_cs.ts +++ b/share/translations/keepassx_cs.ts @@ -2,26 +2,106 @@ AboutDialog - Revision - Revize + About KeePassXC + O aplikaci KeePassXC - Using: - S použitím: + About + O aplikaci - About KeePassXC - O aplikaci KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + - Extensions: + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 - Rozšíření: - + + + + Revision: %1 + + + + Libraries: + - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC je šířeno pod GNU obecnou veřejnou licencí (GPL) verze 2 a (případně) 3. + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -120,10 +200,6 @@ Umožnit přístup? Create Key File... Vytvořit soubor s klíčem… - - Error - Chyba - Unable to create Key File : Nedaří se vytvořit soubor s klíčem: @@ -132,10 +208,6 @@ Umožnit přístup? Select a key file Vyberte soubor s klíčem - - Question - Dotaz - Do you really want to use an empty string as password? Opravdu ponechat bez hesla, tedy nechráněné? @@ -144,10 +216,6 @@ Umožnit přístup? Different passwords supplied. Nepodařilo se vám zadat heslo stejně do obou kolonek. - - Failed to set key file - Nepodařilo se nastavit soubor s klíčem - Failed to set %1 as the Key file: %2 @@ -158,6 +226,163 @@ Umožnit přístup? &Key file Soubor s &klíčem + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Chyba + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Chyba + + + Unable to calculate master key + Nedaří se spočítat hlavní klíč + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -177,10 +402,6 @@ Umožnit přístup? Browse Procházet - - Error - Chyba - Unable to open the database. Databázi se nedaří otevřít. @@ -201,6 +422,14 @@ Umožnit přístup? Select key file Vyberte soubor s klíčem + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -277,6 +506,18 @@ Nyní je možné ji uložit. Use recycle bin Namísto mazání přesouvat do Koše + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -296,10 +537,6 @@ Nyní je možné ji uložit. Open database Otevřít databázi - - Warning - Varování - File not found! Soubor nebyl nalezen! @@ -330,10 +567,6 @@ Save changes? „%1“ bylo změněno. Uložit změny? - - Error - Chyba - Writing the database failed. Zápis do databáze se nezdařil. @@ -426,6 +659,14 @@ Chcete ji přesto otevřít? Open read-only Otevřít pouze pro čtení + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -465,10 +706,6 @@ Chcete ji přesto otevřít? Do you really want to delete the group "%1" for good? Opravdu chcete nenávratně smazat skupinu „%1“? - - Error - Chyba - Unable to calculate master key Nedaří se spočítat hlavní klíč @@ -529,14 +766,18 @@ Chcete ji přesto otevřít? The database file has changed and you have unsaved changes.Do you want to merge your changes? Soubor s databází byl změněn a vaše změny do něj nejsou uloženy. Přejete si své změny začlenit? - - Autoreload Failed - Automatické opětovné načtení se nezdařilo - Could not open the new database file while attempting to autoreload this database. Nepodařilo se otevřít nový soubor s databází během pokusu o opětovné načtení této. + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -576,10 +817,6 @@ Chcete ji přesto otevřít? Edit entry Upravit záznam - - Error - Chyba - Different passwords supplied. Nepodařilo se vám zadat heslo stejně do obou kolonek. @@ -622,6 +859,22 @@ Chcete ji přesto otevřít? 1 year 1 rok + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -633,10 +886,6 @@ Chcete ji přesto otevřít? Add Přidat - - Edit - Upravit - Remove Odebrat @@ -653,6 +902,18 @@ Chcete ji přesto otevřít? Open Otevřít + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -688,6 +949,10 @@ Chcete ji přesto otevřít? Set custo&m sequence: Nastavit vlastní posloupnost: + + Window Associations + + EditEntryWidgetHistory @@ -797,16 +1062,16 @@ Chcete ji přesto otevřít? Hledat - Auto-type + Auto-Type Automatické vyplňování - Use default auto-type sequence of parent group - Použít výchozí posloupnost automatického vyplňování od nadřazené skupiny + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Nastavit výchozí posloupnost automatického vyplňování + Set default Auto-Type se&quence + @@ -831,10 +1096,6 @@ Chcete ji přesto otevřít? Select Image Vyberte obrázek - - Can't delete icon! - Ikonu nelze smazat! - Error Chyba @@ -851,10 +1112,6 @@ Chcete ji přesto otevřít? Can't read icon Ikonu se nedaří načíst - - Can't delete icon. Still used by %1 items. - Ikonu nelze smazat, protože je používaná ještě %1 dalšími záznamy. - &Use default icon Po&užít výchozí ikonu @@ -863,6 +1120,14 @@ Chcete ji přesto otevřít? Use custo&m icon Použít svou vlastní ikonu + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -934,6 +1199,11 @@ Chcete ji přesto otevřít? URL URL adresa + + Ref: + Reference abbreviation + + Group @@ -992,9 +1262,16 @@ Chcete ji přesto otevřít? Ensure that the password contains characters from every group Zajistit aby heslo obsahovalo znaky ze všech zvolených skupin znaků + + + KMessageWidget + + &Close + + - Accept - Přijmout + Close message + @@ -1003,10 +1280,6 @@ Chcete ji přesto otevřít? Import KeePass1 database Importovat databázi ve formátu KeePass verze 1 - - Error - Chyba - Unable to open the database. Databázi se nedaří otevřít. @@ -1071,6 +1344,10 @@ This is a one-way migration. You won't be able to open the imported databas Můžete ho importovat pomocí Databáze → Importovat databázi ve formátu KeePass 1. Jedná se o jednosměrný převod. Databázi, vzniklou z importu, nepůjde otevřít ve staré verzi KeePassX 0.4. + + Unable to issue challenge-response. + + Main @@ -1082,13 +1359,17 @@ Jedná se o jednosměrný převod. Databázi, vzniklou z importu, nepůjde otev KeePassXC - Error KeePassXC – chyba + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - Databáze - Open database Otevřít databázi @@ -1121,10 +1402,6 @@ Jedná se o jednosměrný převod. Databázi, vzniklou z importu, nepůjde otev Toggle window Zobrazit/skrýt okno - - Tools - Nástroje - KeePass 2 Database Databáze ve formátu KeePass 2 @@ -1137,10 +1414,6 @@ Jedná se o jednosměrný převod. Databázi, vzniklou z importu, nepůjde otev Save repaired database Uložit opravenou databázi - - Error - Chyba - Writing the database failed. Zápis do databáze se nezdařil. @@ -1233,14 +1506,26 @@ Jedná se o jednosměrný převod. Databázi, vzniklou z importu, nepůjde otev &Database settings Nastavení &databáze - - &Import KeePass 1 database - &Importovat databázi ve formátu KeePass 1 - &Clone entry Klonovat záznam + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find Najít @@ -1293,6 +1578,46 @@ Jedná se o jednosměrný převod. Databázi, vzniklou z importu, nepůjde otev Password Generator Generátor hesel + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Importovat databázi aplikace KeePass verze 1 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1308,12 +1633,6 @@ Jedná se o jednosměrný převod. Databázi, vzniklou z importu, nepůjde otev Sh&ow a notification when credentials are requested Z&obrazit oznámení když jsou požadovány přihlašovací údaje - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - &Odpovídající schémata URL adres -Je odpovídáno pouze záznamy se stejným schématem (http://, https://, ftp://, atp.) - Sort matching entries by &username Seřadit odpovídající záznamy dle &uživatelského jména @@ -1322,10 +1641,6 @@ Je odpovídáno pouze záznamy se stejným schématem (http://, https://, ftp:// Re&move all stored permissions from entries in active database Z právě otevřené databáze odebrat veškerá uložená oprávnění - - Password generator - Generátor hesel - Advanced Pokročilé @@ -1342,10 +1657,6 @@ Je odpovídáno pouze záznamy se stejným schématem (http://, https://, ftp:// Searc&h in all opened databases for matching entries Vy&hledat odpovídající záznamy ve všech otevřených databázích - - Only the selected database has to be connected with a client! - Je třeba, aby ke klientovi byly připojené pouze vybrané databáze! - HTTP Port: HTTP port: @@ -1362,12 +1673,6 @@ Je odpovídáno pouze záznamy se stejným schématem (http://, https://, ftp:// Sort &matching entries by title Seřadit odpovídající záznamy dle názvu - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - Zapnout protokol KeePassXC HTTP -Toto je zapotřebí pro přístup do databáze z doplňku ChromeIPass nebo PassIFox pro webové prohlížeče - KeePassXC will listen to this port on 127.0.0.1 KeePassXC bude očekávat spojení na tomto portu na adrese 127.0.0.1 (localhost) @@ -1381,21 +1686,11 @@ Toto je zapotřebí pro přístup do databáze z doplňku ChromeIPass nebo PassI Using default port 19455. Není možné navázat na porty s číslem nižším, než 1024! Náhradně bude použit port 19455. - - - &Return only best matching entries for a URL instead -of all entries for the whole domain - Odpovědět pouze záznamy, které nejlépe odpovídají dané -URL ad&rese namísto záznamů pro celou doménu R&emove all shared encryption keys from active database Z právě otevřené databáze od&ebrat veškeré sdílené šifrovací klíče - - The following options can be dangerous. Change them only if you know what you are doing. - Následující předvolby mohou být nebezpečné. Měňte je pouze pokud víte, co děláte! - &Return advanced string fields which start with "KPH: " Odpovědět také kolonkami pok&ročilých textových řetězců které začínají na „KPH:“ @@ -1404,6 +1699,43 @@ URL ad&rese namísto záznamů pro celou doménu Automatically creating or updating string fields is not supported. Automatická vytváření nebo aktualizace nejsou u textových kolonek podporované! + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Generátor hesel + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + PasswordGeneratorWidget @@ -1495,12 +1827,101 @@ URL ad&rese namísto záznamů pro celou doménu Excellent Skvělé + + Password + Heslo + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - Http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Skupina + + + Title + Titulek + + + Username + Uživatelské jméno + + + Password + Heslo + + + URL + URL adresa + + + Notes + Poznámky + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1547,14 +1968,18 @@ URL ad&rese namísto záznamů pro celou doménu Search Hledat - - Find - Najít - Clear Vyčistit + + Search... + + + + Limit search to selected group + + Service @@ -1661,6 +2086,10 @@ jedinečný název pro identifikaci a potvrďte ho. Security Zabezpečení + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1688,10 +2117,6 @@ jedinečný název pro identifikaci a potvrďte ho. Global Auto-Type shortcut Klávesová zkratka pro všeobecné automatické vyplňování - - Use entry title to match windows for global auto-type - Všeobecné automatické vyplňování provádět na základě shody titulku záznamu s titulkem okna. - Language Jazyk @@ -1704,10 +2129,6 @@ jedinečný název pro identifikaci a potvrďte ho. Hide window to system tray when minimized Minimalizovat okno aplikace do oznamovací oblasti systémového panelu - - Remember last key files - Pamatovat si nedávno otevřené soubory s klíči - Load previous databases on startup Při spouštění aplikace načíst minule otevřené databáze @@ -1724,6 +2145,30 @@ jedinečný název pro identifikaci a potvrďte ho. Minimize window at application startup Spouštět aplikaci s minimalizovaným oknem + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Automatické vyplňování + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1743,10 +2188,6 @@ jedinečný název pro identifikaci a potvrďte ho. Show passwords in cleartext by default Hesla vždy viditelná (nezakrývat hvězdičkami) - - Always ask before performing auto-type - Před provedením automatického vyplnění se vždy dotázat - Lock databases after minimizing the window Při minimalizaci okna uzamknout databáze @@ -1755,6 +2196,80 @@ jedinečný název pro identifikaci a potvrďte ho. Don't require password repeat when it is visible Pokud je viditelné, nevyžadovat zopakování zadání hesla + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + sek. + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1766,8 +2281,32 @@ jedinečný název pro identifikaci a potvrďte ho. WelcomeWidget - Welcome! - Vítejte! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Nedávno otevřené databáze @@ -1792,5 +2331,69 @@ jedinečný název pro identifikaci a potvrďte ho. filenames of the password databases to open (*.kdbx) soubory s databázemi hesel k otevření (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_da.ts b/share/translations/keepassx_da.ts index 3828f05ebe..0e2f63c338 100644 --- a/share/translations/keepassx_da.ts +++ b/share/translations/keepassx_da.ts @@ -1,33 +1,143 @@ - + AboutDialog - About KeePassX - Om KeePassX + About KeePassXC + + + + About + Om + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + - KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassX distribueres under betingelserne i GNU General Public License (GPL) version 2 eller (efter eget valg) version 3. + Version %1 + + + + + Revision: %1 + + + + Libraries: + - Revision - Revision + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + - Using: - Bruger: + Enabled extensions: + - AutoType + AccessControlDialog + + Remember this decision + + + + Allow + + + + Deny + + - Auto-Type - KeePassX - Auto-indsæt - KeePassX + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + + + + KeePassXC HTTP Confirm Access + + + + AutoType Couldn't find an entry that matches the window title: Kunne ikke finde en post, der matcher vinduets titel: + + Auto-Type - KeePassXC + + AutoTypeAssociationsModel @@ -46,14 +156,14 @@ AutoTypeSelectDialog - - Auto-Type - KeePassX - Auto-indsæt - KeePassX - Select entry to Auto-Type: Vælg post til Auto-Indsæt: + + Auto-Type - KeePassXC + + ChangeMasterKeyWidget @@ -69,10 +179,6 @@ Repeat password: Gentag kodeord - - Key file - Nøglefil - Browse Gennemse @@ -93,10 +199,6 @@ Create Key File... Opret Nøglefil... - - Error - Fejl - Unable to create Key File : Kan ikke oprette Nøglefil : @@ -105,10 +207,6 @@ Select a key file Vælg en nøglefil - - Question - Spørgsmål - Do you really want to use an empty string as password? Vil du virkelig bruge en tom streng som kodeord? @@ -117,16 +215,173 @@ Different passwords supplied. Andre kodeord leveret. - - Failed to set key file - Kan ikke sætte nøglefil - Failed to set %1 as the Key file: %2 Kunne ikke sætte %1 som Nøglefil: %2 + + &Key file + + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Fejl + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Fejl + + + Unable to calculate master key + Kan ikke beregne hovednøgle + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -146,10 +401,6 @@ Browse Gennemse - - Error - Fejl - Unable to open the database. Kan ikke åbne databasen. @@ -170,6 +421,14 @@ Select key file Vælg nøglefil + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -226,10 +485,6 @@ Du kan gemme den nu. Default username: Standard brugernavn: - - Use recycle bin: - Brug skraldespand: - MiB MB @@ -246,6 +501,22 @@ Du kan gemme den nu. Max. history size: Maks. historikstørrelse: + + Use recycle bin + + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -265,10 +536,6 @@ Du kan gemme den nu. Open database Åben database - - Warning - Advarsel - File not found! Filen blev ikke fundet! @@ -299,10 +566,6 @@ Save changes? "%1" blev ændret. Gem disse ændringer? - - Error - Fejl - Writing the database failed. Kan ikke skrive til databasen. @@ -319,12 +582,6 @@ Gem disse ændringer? locked låst - - The database you are trying to open is locked by another instance of KeePassX. -Do you want to open it anyway? Alternatively the database is opened read-only. - Den database, du prøver at åbne er låst af en anden forekomst af KeePassX. -Vil du åbne den alligevel? Alternativt åbnes databasen skrivebeskyttet. - Lock database Lås database @@ -368,37 +625,66 @@ Kassér ændringer og luk alligevel? Kan ikke skrive til CSV-fil. - The database you are trying to save as is locked by another instance of KeePassX. -Do you want to save it anyway? - Databasen som du prøver at gemme er låst af en anden instans af KeePassX. -Vil du alligevel gemme? + Unable to open the database. + Kan ikke åbne databasen. - Unable to open the database. + Merge database - - - DatabaseWidget - Change master key - Skift hovednøgle + The database you are trying to save as is locked by another instance of KeePassXC. +Do you want to save it anyway? + - Delete entry? - Slet post? + Passwords + - Do you really want to delete the entry "%1" for good? - Vil du virkelig slette posten "%1" permanent? + Database already opened + - Delete entries? - Slet poster? + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + - Do you really want to delete %1 entries for good? - Vil du virkelig slette %1 poster permanent? + Open read-only + + + + File opened in read only mode. + + + + Open CSV file + + + + + DatabaseWidget + + Change master key + Skift hovednøgle + + + Delete entry? + Slet post? + + + Do you really want to delete the entry "%1" for good? + Vil du virkelig slette posten "%1" permanent? + + + Delete entries? + Slet poster? + + + Do you really want to delete %1 entries for good? + Vil du virkelig slette %1 poster permanent? Move entries to recycle bin? @@ -416,14 +702,6 @@ Vil du alligevel gemme? Do you really want to delete the group "%1" for good? Ønsker du at slette gruppen "%1" permanent? - - Current group - Nuværende gruppe - - - Error - Fejl - Unable to calculate master key Kan ikke beregne hovednøgle @@ -436,6 +714,66 @@ Vil du alligevel gemme? Do you really want to move entry "%1" to the recycle bin? + + Searching... + + + + No current database. + + + + No source database, nothing to do. + + + + Search Results (%1) + + + + No Results + + + + Execute command? + + + + Do you really want to execute the following command?<br><br>%1<br> + + + + Remember my choice + + + + Autoreload Request + + + + The database file has changed. Do you want to load the changes? + + + + Merge Request + + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + + + + Could not open the new database file while attempting to autoreload this database. + + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -475,10 +813,6 @@ Vil du alligevel gemme? Edit entry Rediger post - - Error - Fejl - Different passwords supplied. Andre kodeord leveret. @@ -520,6 +854,22 @@ Vil du alligevel gemme? 1 year Et år + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -531,10 +881,6 @@ Vil du alligevel gemme? Add Tilføj - - Edit - Rediger - Remove Fjern @@ -551,6 +897,18 @@ Vil du alligevel gemme? Open Åben + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -558,14 +916,6 @@ Vil du alligevel gemme? Enable Auto-Type for this entry Aktivér Auto-Indsæt for denne post - - Inherit default Auto-Type sequence from the group - Nedarv standard Auto-Indsæt sekvens fra gruppe - - - Use custom Auto-Type sequence: - Brug brugerdefineret Auto-indsæt sekvens: - + + @@ -579,12 +929,24 @@ Vil du alligevel gemme? Vinduestitel: - Use default sequence - Brug standardsekvens + Inherit default Auto-Type sequence from the &group + + + + &Use custom Auto-Type sequence: + + + + Use default se&quence + + + + Set custo&m sequence: + - Set custom sequence: - Definér brugervalgt sekvens: + Window Associations + @@ -624,10 +986,6 @@ Vil du alligevel gemme? Repeat: Gentag: - - Gen. - Generer - URL: URL: @@ -699,28 +1057,20 @@ Vil du alligevel gemme? Søg - Auto-type - Auto-indsæt + Auto-Type + Auto-Indsæt - Use default auto-type sequence of parent group - Brug standard Auto-Indsæt sekvens fra forældregruppe + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Definér standard auto-indsæt sekvens + Set default Auto-Type se&quence + EditWidgetIcons - - Use default icon - Brug standardikon - - - Use custom icon - Brug brugerbestemt ikon - Add custom icon Tilføj brugerbestemt ikon @@ -742,19 +1092,35 @@ Vil du alligevel gemme? Vælg Billede - Can't delete icon! - Kan ikke slette ikon! + Error + Fejl - - Can't delete icon. Still used by %n item(s). - Kan ikke slette ikonet. Det anvendes stadig af %n element.Kan ikke slette ikonet. Det anvendes stadig af %n elementer. + + Download favicon + - Error + Unable to fetch favicon. + + + + Can't read icon + + + + &Use default icon - Can't read icon: + Use custo&m icon + + + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? @@ -777,6 +1143,13 @@ Vil du alligevel gemme? Uuid: + + Entry + + - Clone + + + EntryAttributesModel @@ -821,6 +1194,11 @@ Vil du alligevel gemme? URL URL + + Ref: + Reference abbreviation + + Group @@ -829,16 +1207,74 @@ Vil du alligevel gemme? Skraldespand + + HttpPasswordGeneratorWidget + + Length: + Længde: + + + Character Types + Tegntyper + + + Upper Case Letters + Store Bogstaver + + + A-Z + + + + Lower Case Letters + Små Bogstaver + + + a-z + + + + Numbers + Numre + + + 0-9 + + + + Special Characters + Specialtegn + + + /*_& ... + + + + Exclude look-alike characters + Udeluk lool-alike tegn + + + Ensure that the password contains characters from every group + Vær sikker på at dit kodeord indeholder tegn fra alle grupper + + + + KMessageWidget + + &Close + + + + Close message + + + KeePass1OpenWidget Import KeePass1 database Importér KeePass1 database - - Error - Fejl - Unable to open the database. Kan ikke åbne databasen. @@ -872,7 +1308,7 @@ Vil du alligevel gemme? Wrong key or database file is corrupt. - + Forkert nøgle eller databasefil er korrupt. @@ -903,6 +1339,10 @@ This is a one-way migration. You won't be able to open the imported databas Du kan importere den ved at klikke på Database > 'Importér KeePass 1 database'. Dette er en envejs konvertering. Du vil ikke være i stand til at åbne den importerede database med den gamle KeePassX 0.4 version. + + Unable to issue challenge-response. + + Main @@ -911,454 +1351,918 @@ Dette er en envejs konvertering. Du vil ikke være i stand til at åbne den impo Fatal fejl ved test af kryptografiske funktioner. - KeePassX - Error - KeePassX - Fejl + KeePassXC - Error + + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + MainWindow - Database - Database + Open database + Åben database - Recent databases - Seneste databaser + Database settings + Databaseindstillinger - Help - Hjælp + Copy username to clipboard + Kopiér brugernavn til udklipsholder - Entries - Poster + Copy password to clipboard + Kopiér kodeord til udklipsholder - Copy attribute to clipboard - Kopiér attribut til udklipsholder + Settings + Indstillinger - Groups - Grupper + Show toolbar + Vis værktøjslinie - View - Vis + read-only + skrivebeskyttet - Quit - Afslut + Toggle window + Skift vindue - About - Om + KeePass 2 Database + KeePass 2 Database - Open database - Åben database + All files + Alle filer - Save database - Gem database - + Save repaired database + Gem repareret database + - Close database - Luk databasen + Writing the database failed. + Skrivning til database fejler. - New database - Ny database + &Recent databases + - Add new entry - Tilføj ny post + He&lp + - View/Edit entry - Vis/Rediger post + E&ntries + - Delete entry - Slet post + Copy att&ribute to clipboard + - Add new group - Tilføj ny gruppe + &Groups + - Edit group - Rediger gruppe + &View + - Delete group - Slet gruppe + &Quit + - Save database as - Gem database som + &About + - Change master key - Skift hovednøgle + &Open database + - Database settings - Databaseindstillinger + &Save database + - Import KeePass 1 database - Importér KeePass 1 database + &Close database + - Clone entry - Klon post + &New database + - Find - Find + Merge from KeePassX database + - Copy username to clipboard - Kopiér brugernavn til udklipsholder + &Add new entry + - Copy password to clipboard - Kopiér kodeord til udklipsholder + &View/Edit entry + - Settings - Indstillinger + &Delete entry + - Perform Auto-Type - Udfør Auto-indsæt + &Add new group + - Open URL - Åben URL + &Edit group + - Lock databases - Lås databaser + &Delete group + - Title - Titel + Sa&ve database as + - URL - URL + Change &master key + - Notes - Noter + &Database settings + - Show toolbar - Vis værktøjslinie + &Clone entry + - read-only - skrivebeskyttet + Timed one-time password + - Toggle window - Skift vindue + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + - Tools - Værktøj + &Find + - Copy username - Kopiér brugernavn + Copy &username + - Copy password - Kopiér kodeord + Cop&y password + - Export to CSV file - Eksportér til CSV-fil + &Settings + - Repair database - Reparer database + &Perform Auto-Type + - KeePass 2 Database - KeePass 2 Database + &Open URL + - All files - Alle filer + &Lock databases + - Save repaired database - Gem repareret database + &Title + - Error - Fejl + &URL + - Writing the database failed. - Skrivning til database fejler. + &Notes + - - - PasswordGeneratorWidget - Password: - Kodeord: + &Export to CSV file + - Length: - Længde: + Re&pair database + - Character Types - Tegntyper + Password Generator + - Upper Case Letters - Store Bogstaver + Clear history + - Lower Case Letters - Små Bogstaver + &Database + - Numbers - Numre + Import + - Special Characters - Specialtegn + &Tools + - Exclude look-alike characters - Udeluk lool-alike tegn + Import KeePass 1 database + Importér KeePass 1 database - Ensure that the password contains characters from every group - Vær sikker på at dit kodeord indeholder tegn fra alle grupper + Import CSV file + - Accept - Acceptér + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + - QCommandLineParser + OptionDialog - Displays version information. - Vis versionsinformation + Dialog + - Displays this help. - Vis denne hjælp. + General + Generelt - Unknown option '%1'. - Ukendt valgmulighed '%1'. + Sh&ow a notification when credentials are requested + - Unknown options: %1. - Ukendt valgmuligheder '%1'. + Sort matching entries by &username + - Missing value after '%1'. - Manglende værdi efter '%1'. + Re&move all stored permissions from entries in active database + - Unexpected value after '%1'. - Uventet værdi efter '%1'. + Advanced + Avanceret - [options] - [Valgmuligheder] + Always allow &access to entries + - Usage: %1 - Brug: %1 + Always allow &updating entries + - Options: - Muligheder: + Searc&h in all opened databases for matching entries + - Arguments: - Argumenter: + HTTP Port: + - - - QSaveFile - Existing file %1 is not writable - Eksisterende fil %1 er ikke skrivbar + Default port: 19455 + - Writing canceled by application - Skrivning afbrudt af programmet + Re&quest to unlock the database if it is locked + - Partial write. Partition full? - Delvis gemt. Diskafsnit fyldt op? + Sort &matching entries by title + - - - QtIOCompressor - Internal zlib error when compressing: - Intern zlib-fejl ved komprimering: + KeePassXC will listen to this port on 127.0.0.1 + - Error writing to underlying device: - Fejl ved skrivning til enhed: + Cannot bind to privileged ports + - Error opening underlying device: - Fejl ved åbning fra enhed: + Cannot bind to privileged ports below 1024! +Using default port 19455. + - Error reading data from underlying device: - Fejl ved læsning af data fra underliggende enhed: + R&emove all shared encryption keys from active database + - Internal zlib error when decompressing: - Intern zlib-fejl ved dekomprimering: + &Return advanced string fields which start with "KPH: " + - - - QtIOCompressor::open - The gzip format not supported in this version of zlib. - Gzip-format understøttes ikke i denne version af zlib. + Automatically creating or updating string fields is not supported. + - Internal zlib error: - Intern zlib fejl: + This is required for accessing your databases from ChromeIPass or PassIFox + - - - SearchWidget - Find: - Find: + Enable KeePassHTTP server + - Case sensitive - Versalfølsom + Only returns the best matches for a specific URL instead of all entries for the whole domain. + - Current group - Nuværende gruppe + &Return only best matching entries + - Root group - Rodgruppe + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + - - - SettingsWidget - Application Settings - Programindstillinger + &Match URL schemes + - General - Generelt + Password Generator + - Security - Sikkerhed + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + - SettingsWidgetGeneral + PasswordGeneratorWidget - Remember last databases - Husk seneste databaser + Password: + Kodeord: - Open previous databases on startup - Åben foregående databaser ved opstart + Character Types + Tegntyper - Automatically save on exit - Gem automatisk ved afslutning + Upper Case Letters + Store Bogstaver - Automatically save after every change - Gem automatisk ved ændringer + Lower Case Letters + Små Bogstaver - Minimize when copying to clipboard - Minimér ved kopiering til udklipsholder + Numbers + Numre - Use group icon on entry creation - Brug gruppeikon ved oprettelse af post + Special Characters + Specialtegn - Global Auto-Type shortcut - Global Auto-Indsæt genvej + Exclude look-alike characters + Udeluk lool-alike tegn - Use entry title to match windows for global auto-type - Brug titel på post til at matche global aito-indsæt + Accept + Acceptér - Language - Sprog + %p% + - Show a system tray icon - Vis et ikon i systembakken + strength + - Hide window to system tray when minimized - Skjul vindue i systembakken når det er minimeret + entropy + - Remember last key files - Husk de sidste nøglefiler + &Length: + - Hide window to system tray instead of App Exit + Pick characters from every group - Hide window to system tray on App start + Generate - - - SettingsWidgetSecurity - Clear clipboard after - Ryd udklipsholder efter + Close + - sec - sek + Apply + - Lock databases after inactivity of - Lås databaserne efter inaktivitet i + Entropy: %1 bit + - Show passwords in cleartext by default - Vis kodeord i klartekst som standard + Password Quality: %1 + - Always ask before performing auto-type - Spørg altid før auto-indsæt + Poor + - - - UnlockDatabaseWidget + + Weak + + + + Good + + + + Excellent + + + + Password + Kodeord + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + + + + QObject + + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Gruppe + + + Title + Titel + + + Username + Brugernavn + + + Password + Kodeord + + + URL + URL + + + Notes + Noter + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + + + + + QtIOCompressor + + Internal zlib error when compressing: + Intern zlib-fejl ved komprimering: + + + Error writing to underlying device: + Fejl ved skrivning til enhed: + + + Error opening underlying device: + Fejl ved åbning fra enhed: + + + Error reading data from underlying device: + Fejl ved læsning af data fra underliggende enhed: + + + Internal zlib error when decompressing: + Intern zlib-fejl ved dekomprimering: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + Gzip-format understøttes ikke i denne version af zlib. + + + Internal zlib error: + Intern zlib fejl: + + + + SearchWidget + + Case Sensitive + + + + Search + Søg + + + Clear + + + + Search... + + + + Limit search to selected group + + + + + Service + + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + + + + Do you want to update the information in %1 - %2? + + + + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + + + + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + + + + No shared encryption-keys found in KeePassHttp Settings. + + + + The active database does not contain an entry of KeePassHttp Settings. + + + + Removing stored permissions... + + + + Abort + + + + Successfully removed permissions from %1 %2. + + + + The active database does not contain an entry with permissions. + + + + KeePassXC: New key association request + + + + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + + + + KeePassXC: Overwrite existing key? + + + + KeePassXC: Update Entry + + + + KeePassXC: Database locked! + + + + KeePassXC: Removed keys from database + + + + KeePassXC: No keys found + + + + KeePassXC: Settings not available! + + + + KeePassXC: Removed permissions + + + + KeePassXC: No entry with permissions found! + + + + + SettingsWidget + + Application Settings + Programindstillinger + + + General + Generelt + + + Security + Sikkerhed + + + Access error for config file %1 + + + + + SettingsWidgetGeneral + + Remember last databases + Husk seneste databaser + + + Automatically save on exit + Gem automatisk ved afslutning + + + Automatically save after every change + Gem automatisk ved ændringer + + + Minimize when copying to clipboard + Minimér ved kopiering til udklipsholder + + + Use group icon on entry creation + Brug gruppeikon ved oprettelse af post + + + Global Auto-Type shortcut + Global Auto-Indsæt genvej + + + Language + Sprog + + + Show a system tray icon + Vis et ikon i systembakken + + + Hide window to system tray when minimized + Skjul vindue i systembakken når det er minimeret + + + Load previous databases on startup + + + + Automatically reload the database when modified externally + + + + Hide window to system tray instead of app exit + + + + Minimize window at application startup + + + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Auto-Indsæt + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + + + + SettingsWidgetSecurity + + Clear clipboard after + Ryd udklipsholder efter + + + sec + sek + + + Lock databases after inactivity of + Lås databaserne efter inaktivitet i + + + Show passwords in cleartext by default + Vis kodeord i klartekst som standard + + + Lock databases after minimizing the window + + + + Don't require password repeat when it is visible + + + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + sek + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + + + + UnlockDatabaseWidget Unlock database Lås database op @@ -1367,20 +2271,36 @@ Dette er en envejs konvertering. Du vil ikke være i stand til at åbne den impo WelcomeWidget - Welcome! - Velkommen! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + - - - main - KeePassX - cross-platform password manager - KeePassX - cross-platform password manager + Import from CSV + - filename of the password database to open (*.kdbx) - filnavn på databasen der skal åbnes (* .kdbx) + Recent databases + Seneste databaser + + + main path to a custom config file sti til brugerdefineret indstillingsfil @@ -1389,5 +2309,81 @@ Dette er en envejs konvertering. Du vil ikke være i stand til at åbne den impo key file of the database databasens nøglefil + + KeePassXC - cross-platform password manager + + + + read password of the database from stdin + + + + filenames of the password databases to open (*.kdbx) + + + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_de.ts b/share/translations/keepassx_de.ts index 30d5330d75..f885b64849 100644 --- a/share/translations/keepassx_de.ts +++ b/share/translations/keepassx_de.ts @@ -2,26 +2,109 @@ AboutDialog - Revision - Revision + About KeePassXC + Über KeePassXC - Using: - Verwendet: + About + Über - About KeePassXC - Über KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + - Extensions: + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + Debug-Info + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + In Zwischenablage kopieren + + + Version %1 - Erweiterungen: + Version %1 - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC wird unter den Bedingungen der GNU General Public License (GPL) Version 2 oder Version 3 (je nach Ihrer Auswahl) vertrieben. + Revision: %1 + Revision: %1 + + + Libraries: + Bibliotheken: + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + Betriebssystem: %1 +CPU-Architektur: %2 +Kernel: %3 %4 + + + Enabled extensions: + Aktivierte Erweiterungen: @@ -120,10 +203,6 @@ Bitte wählen Sie, ob Sie den Zugriff erlauben möchten. Create Key File... Erzeuge eine Schlüsseldatei... - - Error - Fehler - Unable to create Key File : Erzeugen der Schlüsseldatei nicht möglich: @@ -132,10 +211,6 @@ Bitte wählen Sie, ob Sie den Zugriff erlauben möchten. Select a key file Schlüsseldatei auswählen - - Question - Frage - Do you really want to use an empty string as password? Wollen Sie wirklich eine leere Zeichenkette als Passwort verwenden? @@ -144,10 +219,6 @@ Bitte wählen Sie, ob Sie den Zugriff erlauben möchten. Different passwords supplied. Unterschiedliche Passwörter eingegeben. - - Failed to set key file - Festlegen der Schlüsseldatei nicht möglich. - Failed to set %1 as the Key file: %2 @@ -157,6 +228,163 @@ Bitte wählen Sie, ob Sie den Zugriff erlauben möchten. &Key file &Schlüsseldatei + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Fehler + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Fehler + + + Unable to calculate master key + Berechnung des "master keys" gescheitert + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -176,10 +404,6 @@ Bitte wählen Sie, ob Sie den Zugriff erlauben möchten. Browse Durchsuchen - - Error - Fehler - Unable to open the database. Öffnen der Datenbank nicht möglich. @@ -200,6 +424,14 @@ Bitte wählen Sie, ob Sie den Zugriff erlauben möchten. Select key file Schlüsseldatei auswählen + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -276,6 +508,18 @@ sie kann nun gespeichert werden. Use recycle bin Papierkorb verwenden + + AES: 256 Bit (default) + AES: 256 Bit (Standard) + + + Twofish: 256 Bit + Twofish: 256 Bit + + + Algorithm: + Algorithmus: + DatabaseTabWidget @@ -295,10 +539,6 @@ sie kann nun gespeichert werden. Open database Datenbank öffnen - - Warning - Warnung - File not found! Datei nicht gefunden! @@ -329,10 +569,6 @@ Save changes? "%1" wurde geändert. Änderungen speichern? - - Error - Fehler - Writing the database failed. Schreiben der Datenbank fehlgeschlagen. @@ -425,6 +661,14 @@ Möchten Sie diese dennoch öffnen? Open read-only Schreibgeschützt öffnen + + File opened in read only mode. + Datei ist schreibgeschützt + + + Open CSV file + + DatabaseWidget @@ -464,10 +708,6 @@ Möchten Sie diese dennoch öffnen? Do you really want to delete the group "%1" for good? Wollen Sie die Gruppe "%1" wirklich löschen? - - Error - Fehler - Unable to calculate master key Berechnung des "master keys" gescheitert @@ -528,14 +768,18 @@ Möchten Sie diese dennoch öffnen? The database file has changed and you have unsaved changes.Do you want to merge your changes? Die Datenbankdatei wurde geändert und Sie haben noch nicht gespeicherte Änderungen. Wollen Sie Ihre Änderungen zusammenführen? - - Autoreload Failed - Autoreload fehlgeschlagen - Could not open the new database file while attempting to autoreload this database. Die neue Datenbankdatei konnte nicht geöffnet werden, während versucht wurde, diese neu zu laden. + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -575,10 +819,6 @@ Möchten Sie diese dennoch öffnen? Edit entry Eintrag bearbeiten - - Error - Fehler - Different passwords supplied. Unterschiedliche Passwörter eingegeben. @@ -620,6 +860,22 @@ Möchten Sie diese dennoch öffnen? 1 year 1 Jahr + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -631,10 +887,6 @@ Möchten Sie diese dennoch öffnen? Add Hinzufügen - - Edit - Bearbeiten - Remove Entfernen @@ -651,6 +903,18 @@ Möchten Sie diese dennoch öffnen? Open Offen + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -686,6 +950,10 @@ Möchten Sie diese dennoch öffnen? Set custo&m sequence: B&enutzerdefinierte Sequenz: + + Window Associations + Fenster-Einstellungen + EditEntryWidgetHistory @@ -795,15 +1063,15 @@ Möchten Sie diese dennoch öffnen? Suche - Auto-type + Auto-Type Auto-Type - Use default auto-type sequence of parent group + &Use default Auto-Type sequence of parent group Verwende Standard-A&uto-Type-Sequenz der übergeordneten Gruppe - Set default auto-type sequence + Set default Auto-Type se&quence Standard-Auto-Type-Se&quenz setzen @@ -829,10 +1097,6 @@ Möchten Sie diese dennoch öffnen? Select Image Bild auswählen - - Can't delete icon! - Symbol kann nicht gelöscht werden! - Error Fehler @@ -849,10 +1113,6 @@ Möchten Sie diese dennoch öffnen? Can't read icon Icon kann nicht gelesen werden - - Can't delete icon. Still used by %1 items. - Icon kann nicht gelöscht werden. Es wird noch von %1 Einträgen verwendet. - &Use default icon &Standardsymbol verwenden @@ -861,6 +1121,14 @@ Möchten Sie diese dennoch öffnen? Use custo&m icon B&enutzerdefiniertes Symbol verwenden + + Confirm Delete + Löschen bestätigen + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + Dieses Icon wird noch von %1 Einträgen verwendet und würde mit dem Standard-Icon ersetzt. Sind Sie sicher, dass die fortfahren wollen? + EditWidgetProperties @@ -932,6 +1200,11 @@ Möchten Sie diese dennoch öffnen? URL URL + + Ref: + Reference abbreviation + + Group @@ -990,9 +1263,16 @@ Möchten Sie diese dennoch öffnen? Ensure that the password contains characters from every group Sicherstellen, dass das Passwort Zeichen aus allen Gruppen enthält. + + + KMessageWidget - Accept - Akzeptieren + &Close + S&chließen + + + Close message + Meldung schließen @@ -1001,10 +1281,6 @@ Möchten Sie diese dennoch öffnen? Import KeePass1 database KeePass 1 Datenbank importieren - - Error - Fehler - Unable to open the database. Öffnen der Datenbank nicht möglich. @@ -1069,6 +1345,10 @@ This is a one-way migration. You won't be able to open the imported databas Zum Importieren gehen Sie auf Datenbank > 'KeePass 1 Datenbank importieren'. Dieser Vorgang ist nur in eine Richtung möglich. Die importierte Datenbank kann später nicht mehr mit der alten KeePassX Version 0.4 geöffnet werden. + + Unable to issue challenge-response. + + Main @@ -1080,13 +1360,17 @@ Dieser Vorgang ist nur in eine Richtung möglich. Die importierte Datenbank kann KeePassXC - Error KeePassXC - Fehler + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - Datenbank - Open database Datenbank öffnen @@ -1119,10 +1403,6 @@ Dieser Vorgang ist nur in eine Richtung möglich. Die importierte Datenbank kann Toggle window Fenster zeigen/verstecken - - Tools - Tools - KeePass 2 Database KeePass 2 Datenbank @@ -1135,10 +1415,6 @@ Dieser Vorgang ist nur in eine Richtung möglich. Die importierte Datenbank kann Save repaired database Reparierte Datenbank speichern - - Error - Fehler - Writing the database failed. Schreiben der Datenbank fehlgeschlagen. @@ -1231,14 +1507,26 @@ Dieser Vorgang ist nur in eine Richtung möglich. Die importierte Datenbank kann &Database settings &Datenbankeinstellungen - - &Import KeePass 1 database - &KeePass 1 Datenbank importieren - &Clone entry Eintrag &klonen + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find &Suchen @@ -1291,6 +1579,46 @@ Dieser Vorgang ist nur in eine Richtung möglich. Die importierte Datenbank kann Password Generator Passwortgenerator + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + KeePass 1 Datenbank importieren + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1306,12 +1634,6 @@ Dieser Vorgang ist nur in eine Richtung möglich. Die importierte Datenbank kann Sh&ow a notification when credentials are requested Zeig&e eine Benachrichtigung, wenn Anmeldedaten angefordert werden. - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - Passendes URL Schema -Nur Einträge mit dem gleichen Schema (http://, https://, ftp://, ...) werden angezeigt - Sort matching entries by &username Sortiere gefundene Einträge nach &Benutzername @@ -1320,10 +1642,6 @@ Nur Einträge mit dem gleichen Schema (http://, https://, ftp://, ...) werden an Re&move all stored permissions from entries in active database Entferne alle gespeicherten Berechtigungen für Einträge in der aktiven Datenbank - - Password generator - Passwortgenerator - Advanced Fortgeschritten @@ -1340,10 +1658,6 @@ Nur Einträge mit dem gleichen Schema (http://, https://, ftp://, ...) werden an Searc&h in all opened databases for matching entries Suche in allen offenen Datenbanken nach übereinstimmenden Einträgen - - Only the selected database has to be connected with a client! - Nur die ausgewählte Datenbank muss mit dem Client verbunden sein. - HTTP Port: HTTP-Port: @@ -1360,12 +1674,6 @@ Nur Einträge mit dem gleichen Schema (http://, https://, ftp://, ...) werden an Sort &matching entries by title Sortiere gefundene Einträge nach Titel - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - KeepassXC-HTTP-Protokoll aktivieren -Dies ist für den Zugriff auf Ihre Datenbanken von ChromeIPass oder Passifox notwendig. - KeePassXC will listen to this port on 127.0.0.1 KeePassXC überwacht diesen Port auf 127.0.0.1 @@ -1380,20 +1688,10 @@ Using default port 19455. Privilegierte Ports unterhalb von 1024 können nicht überwacht werden. Es wird der Standard-Port 19455 verwendet. - - &Return only best matching entries for a URL instead -of all entries for the whole domain - Zeige nur die am besten passenden Einträge für eine URL anstatt aller Einträge der ganzen Domäne. - R&emove all shared encryption keys from active database &Entferne alle freigegebenen Chiffrierschlüssel aus der aktiven Datenbank - - The following options can be dangerous. Change them only if you know what you are doing. - Die folgenden Optionen können gefährlich sein! -Ändern Sie diese nur, wenn Sie wissen, was Sie tun. - &Return advanced string fields which start with "KPH: " Zeige auch erweiterte Zeichenfelder, welche mit "KPH: " beginnen @@ -1402,6 +1700,44 @@ of all entries for the whole domain Automatically creating or updating string fields is not supported. Automatisches Erstellen und Aktualisieren von Zeichenfeldern wird nicht unterstützt! + + This is required for accessing your databases from ChromeIPass or PassIFox + Dies wird benötigt, um auf Ihre Datenbanken in ChromeIPass oder PassIFox zuzugreifen. + + + Enable KeePassHTTP server + KeePassHTTP-Server aktivieren + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + Zeige nur die am besten passenden Einträge für eine URL anstatt aller Einträge der ganzen Domäne. + + + &Return only best matching entries + Nur beste Treffer anzeigen + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + Nur Einträge mit dem gleichen Schema (http://, https://, ftp://, …) anzeigen + + + &Match URL schemes + URL-Schema verwenden + + + Password Generator + Passwortgenerator + + + Only the selected database has to be connected with a client. + Nur die ausgewählte Datenbank muss mit dem Client verbunden sein. + + + The following options can be dangerous! +Change them only if you know what you are doing. + Die folgenden Optionen können gefährlich sein! +Ändern Sie diese nur, wenn Sie wissen, was Sie tun. + PasswordGeneratorWidget @@ -1493,12 +1829,101 @@ of all entries for the whole domain Excellent Ausgezeichnet + + Password + Passwort + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - Http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Gruppe + + + Title + Titel + + + Username + Benutzername + + + Password + Passwort + + + URL + URL + + + Notes + Notizen + + + Browser Integration + Browser-Integration + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1545,14 +1970,18 @@ of all entries for the whole domain Search Suche - - Find - Suchen - Clear Löschen + + Search... + + + + Limit search to selected group + + Service @@ -1660,6 +2089,10 @@ Namen und akzeptieren Sie. Security Sicherheit + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1687,10 +2120,6 @@ Namen und akzeptieren Sie. Global Auto-Type shortcut Globale Tastenkombination für Auto-Type - - Use entry title to match windows for global auto-type - Verwende Eintragstitel, um entsprechende Fenster für globales Auto-Type zu finden - Language Sprache @@ -1703,10 +2132,6 @@ Namen und akzeptieren Sie. Hide window to system tray when minimized Fenster verstecken wenn minimiert - - Remember last key files - Letzte Schlüsseldateien merken - Load previous databases on startup Letzte Datenbank beim Starten laden @@ -1723,6 +2148,30 @@ Namen und akzeptieren Sie. Minimize window at application startup Fenster beim Programmstart minimieren + + Basic Settings + Grundeinstellungen + + + Remember last key files and security dongles + Letzte Schlüsseldateien und Sicherheits-Dongles merken + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Auto-Type + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + Immer vor einem Auto-Type fragen + SettingsWidgetSecurity @@ -1742,10 +2191,6 @@ Namen und akzeptieren Sie. Show passwords in cleartext by default Passwörter standardmäßig in Klartext anzeigen - - Always ask before performing auto-type - Immer vor einem Auto-Type fragen - Lock databases after minimizing the window Datenbank sperren nach dem Minimieren des Fensters @@ -1754,6 +2199,80 @@ Namen und akzeptieren Sie. Don't require password repeat when it is visible Keine erneute Passworteingabe verlangen wenn das Passwort sichtbar ist. + + Timeouts + Timeouts + + + Convenience + Komfort + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + sek + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1765,8 +2284,32 @@ Namen und akzeptieren Sie. WelcomeWidget - Welcome! - Willkommen! + Welcome to KeePassXC + Willkommen bei KeePassXC + + + Start storing your passwords securely in a KeePassXC database + Speichern Sie Ihre Passwörter sicher in einer KeePassXC-Datenbank + + + Create new database + Neue Datenbank erstellen + + + Open existing database + Existierende Datenbank öffnen + + + Import from KeePass 1 + Aus KeePass 1 importieren + + + Import from CSV + + + + Recent databases + Zuletzt verwendete Datenbanken @@ -1791,5 +2334,69 @@ Namen und akzeptieren Sie. filenames of the password databases to open (*.kdbx) Dateinamen der zu öffnenden Datenbanken (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_el.ts b/share/translations/keepassx_el.ts index 4e554df9e3..ffd6131bca 100644 --- a/share/translations/keepassx_el.ts +++ b/share/translations/keepassx_el.ts @@ -1,33 +1,143 @@ - + AboutDialog - About KeePassX - Σχετικά με το KeepPassX + About KeePassXC + + + + About + Σχετικά + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + - KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassX διανέμεται υπό τον όρο από το GNU γενικής δημόσιας άδειας (GPL) έκδοση 2 ή (κατ ' επιλογή σας) έκδοση 3. + Version %1 + + + + + Revision: %1 + + + + Libraries: + - Revision - Αναθεώρηση + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + - Using: - Χρήση: + Enabled extensions: + - AutoType + AccessControlDialog + + Remember this decision + + + + Allow + + + + Deny + + - Auto-Type - KeePassX - Αυτόματη-Γραφή - KeePassX + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + + + + KeePassXC HTTP Confirm Access + + + + AutoType Couldn't find an entry that matches the window title: Αποτυχία να βρεθεί μια καταχώρηση που να ταιριάζει με τον τίτλο του παραθύρου: + + Auto-Type - KeePassXC + + AutoTypeAssociationsModel @@ -37,23 +147,23 @@ Sequence - Ακολουθεία + Ακολουθία Default sequence - Προεπιλεγμένη ακολουθεία + Προεπιλεγμένη ακολουθία AutoTypeSelectDialog - - Auto-Type - KeePassX - Αυτόματη-Γραφή - KeePassX - Select entry to Auto-Type: Επιλέξτε καταχώρηση για αυτόματη γραφή: + + Auto-Type - KeePassXC + + ChangeMasterKeyWidget @@ -69,10 +179,6 @@ Repeat password: Επαναλάβετε τον κωδικό: - - Key file - Αρχείο κλειδί - Browse Αναζήτηση @@ -93,10 +199,6 @@ Create Key File... Δημιουργεία αρχείου κλειδιού... - - Error - Σφάλμα - Unable to create Key File : Αποτυχία δημιουργεία αρχείου κλειδιού: @@ -105,10 +207,6 @@ Select a key file Επιλέξτε ένα αρχείο κλειδί - - Question - Ερώτηση - Do you really want to use an empty string as password? Θέλετε στα αλήθεια να χρησιμοποιήσετε μια άδεια σειρά σαν κωδικό; @@ -117,15 +215,172 @@ Different passwords supplied. Έχετε εισάγει διαφορετικούς κωδικούς. - - Failed to set key file - Αποτυχία ορισμού αρχείου κλειδιού - Failed to set %1 as the Key file: %2 Αποτυχία ορισμού του %1 ως αρχείου κλειδιού + + &Key file + + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Σφάλμα + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Σφάλμα + + + Unable to calculate master key + Σε θέση να υπολογίσει το κύριο κλειδί + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -145,10 +400,6 @@ Browse Αναζήτηση - - Error - Σφάλμα - Unable to open the database. Αδύνατο να ανοιχτεί η βάση δεδομένων. @@ -169,6 +420,14 @@ Select key file Επιλέξτε αρχείο κλειδί + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -224,10 +483,6 @@ You can now save it. Default username: Προεπιλεγμένο όνομα χρήστη: - - Use recycle bin: - Χρήση καλαθιού αχρήστων: - MiB MiB @@ -244,6 +499,22 @@ You can now save it. Max. history size: Μέγιστο μέγεθος ιστορικού: + + Use recycle bin + + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -263,10 +534,6 @@ You can now save it. Open database Άνοιγμα βάσης δεδομένων - - Warning - Προειδοποίηση - File not found! Αρχείο δεν βρέθηκε! @@ -297,10 +564,6 @@ Save changes? "%1" έχει τροποποιηθή. Αποθήκευση αλλαγών; - - Error - Σφάλμα - Writing the database failed. Εγγραφή της βάσης δεδομένων απέτυχε. @@ -317,12 +580,6 @@ Save changes? locked κλειδωμένο - - The database you are trying to open is locked by another instance of KeePassX. -Do you want to open it anyway? Alternatively the database is opened read-only. - Η βάση δεδομένω που προσπαθείται να ανοίξετε ειναι κλειδωμένη από μια άλλη διεργασία του KeePassX. -Θέλετε να την ανοίξετε ούτως η άλλως; Αλλίως η βαση δεδομένων θα ανοιχτή μόνο για ανάγνωση. - Lock database Κλείδωμα βάσης δεδομένων @@ -365,41 +622,70 @@ Discard changes and close anyway? Writing the CSV file failed. Γράψιμο στο αρχείο CSV απέτυχε. - - The database you are trying to save as is locked by another instance of KeePassX. -Do you want to save it anyway? - Η βάση δεδομένων που πρασπαθείται να αποθηκεύσετε είναι κλειδωμένη από μία άλλη διεργασία KeePassX. -Θέλετε να την αποθηκεύσετε ούτως η άλλως; - Unable to open the database. Δεν είναι δυνατό να ανοίξει τη βάση δεδομένων. - - - DatabaseWidget - Change master key - Αλλαγή πρωτεύοντος κλειδιού + Merge database + - Delete entry? - Διαγραφή καταχώρησης; + The database you are trying to save as is locked by another instance of KeePassXC. +Do you want to save it anyway? + - Do you really want to delete the entry "%1" for good? - Θέλετε πραγματικά να διαγράψετε την καταχώρηση "%1" μόνιμα; + Passwords + - Delete entries? - Διαγραφή καταχωρήσεων; + Database already opened + - Do you really want to delete %1 entries for good? - Θέλετε πραγματικά να διαγράψετε %1 καταχωρήσεις για πάντα; + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + - Move entries to recycle bin? + Open read-only + + + + File opened in read only mode. + + + + Open CSV file + + + + + DatabaseWidget + + Change master key + Αλλαγή πρωτεύοντος κλειδιού + + + Delete entry? + Διαγραφή καταχώρησης; + + + Do you really want to delete the entry "%1" for good? + Θέλετε πραγματικά να διαγράψετε την καταχώρηση "%1" μόνιμα; + + + Delete entries? + Διαγραφή καταχωρήσεων; + + + Do you really want to delete %1 entries for good? + Θέλετε πραγματικά να διαγράψετε %1 καταχωρήσεις για πάντα; + + + Move entries to recycle bin? Μετακίνηση καταχωρήσεων στο καλάθι των αχρήστων; @@ -414,14 +700,6 @@ Do you want to save it anyway? Do you really want to delete the group "%1" for good? Θέλετε στα αλήθεια να διαγράψετε την ομάδα "%1" μόνιμα; - - Current group - Τρέχων ομάδα - - - Error - Σφάλμα - Unable to calculate master key Σε θέση να υπολογίσει το κύριο κλειδί @@ -434,6 +712,66 @@ Do you want to save it anyway? Do you really want to move entry "%1" to the recycle bin? Θέλετε πραγματικά να κινηθεί εισόδου "%1" στον κάδο ανακύκλωσης; + + Searching... + + + + No current database. + + + + No source database, nothing to do. + + + + Search Results (%1) + + + + No Results + + + + Execute command? + + + + Do you really want to execute the following command?<br><br>%1<br> + + + + Remember my choice + + + + Autoreload Request + + + + The database file has changed. Do you want to load the changes? + + + + Merge Request + + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + + + + Could not open the new database file while attempting to autoreload this database. + + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -473,10 +811,6 @@ Do you want to save it anyway? Edit entry Επεξεργασία καταχώρησης - - Error - Σφάλμα - Different passwords supplied. Παρέχονται διαφορετικοί κωδικοί. @@ -519,6 +853,22 @@ Do you want to save it anyway? 1 year 1 χρόνο + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -530,10 +880,6 @@ Do you want to save it anyway? Add Πρόσθεση - - Edit - Επεξεργασία - Remove Αφαίρεση @@ -550,6 +896,18 @@ Do you want to save it anyway? Open Άνοιγμα + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -557,14 +915,6 @@ Do you want to save it anyway? Enable Auto-Type for this entry Ενεργοποίηση Αυτόματης-Γραφής για αυτήν την καταχώρηση - - Inherit default Auto-Type sequence from the group - Χρησιμοποίηση προεπιλεγμένης ακολουθείας Αυτόματης-Γραφής απο την ομάδα - - - Use custom Auto-Type sequence: - Χρησιμοποίηση προσαρμοσμένης ακολουθείας Αυτόματης Γραφής: - + + @@ -578,12 +928,24 @@ Do you want to save it anyway? Τίτλος Παραθύρου: - Use default sequence - Χρησιμοποίηση προεπιλεγμένης ακολουθείας + Inherit default Auto-Type sequence from the &group + + + + &Use custom Auto-Type sequence: + + + + Use default se&quence + + + + Set custo&m sequence: + - Set custom sequence: - Ορισμός προσαρμοσμένης ακολουθείας: + Window Associations + @@ -623,10 +985,6 @@ Do you want to save it anyway? Repeat: Επαναλάβετε: - - Gen. - - URL: URL: @@ -698,28 +1056,20 @@ Do you want to save it anyway? Αναζήτηση - Auto-type - Αυτόματη-γραφή + Auto-Type + Αυτόματη-Γραφή - Use default auto-type sequence of parent group - Χρησιμοποίηση προεπιλεγμένης ακολουθείας αυτόματης γραφής της μητρικής ομάδας + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Ορισμός προεπιλεγμένης ακολουθείας αυτόματης-γραφής + Set default Auto-Type se&quence + EditWidgetIcons - - Use default icon - Χρήση προεπιλεγμένου εικονιδίου - - - Use custom icon - Χρήση προσαρμοσμένου εικονιδίου - Add custom icon Πρόσθεση προσαρμοσμένου εικονιδίου @@ -741,20 +1091,36 @@ Do you want to save it anyway? Επιλογή εικόνας - Can't delete icon! - Αποτυχία διαγραφής εικονίδιου! + Error + Σφάλμα - - Can't delete icon. Still used by %n item(s). - + + Download favicon + - Error - Σφάλμα + Unable to fetch favicon. + + + + Can't read icon + + + + &Use default icon + - Can't read icon: - Δεν μπορεί να διαβάσει το εικονίδιο: + Use custo&m icon + + + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + @@ -776,6 +1142,13 @@ Do you want to save it anyway? UUID: + + Entry + + - Clone + + + EntryAttributesModel @@ -820,6 +1193,11 @@ Do you want to save it anyway? URL URL + + Ref: + Reference abbreviation + + Group @@ -828,16 +1206,74 @@ Do you want to save it anyway? Καλάθι ανακύκλωσης + + HttpPasswordGeneratorWidget + + Length: + Μήκος: + + + Character Types + Τύποι χαρακτήρων + + + Upper Case Letters + Κεφαλαία γράμματα + + + A-Z + + + + Lower Case Letters + Πεζά γράμματα + + + a-z + + + + Numbers + Αριθμοί + + + 0-9 + + + + Special Characters + Ειδικοί χαρακτήρες + + + /*_& ... + + + + Exclude look-alike characters + Εξαίρεση χαρακτήρων που μοίαζουν + + + Ensure that the password contains characters from every group + Βεβαιωθείται οτι ο κωδικός περιέχει χαρακτήρες απο κάθε ομάδα + + + + KMessageWidget + + &Close + + + + Close message + + + KeePass1OpenWidget Import KeePass1 database Εισαγωγή βάσης δεδομένων KeePass1 - - Error - Σφάλμα - Unable to open the database. Αποτυχία ανοίγματος βάσης δεδομένων. @@ -899,6 +1335,10 @@ You can import it by clicking on Database > 'Import KeePass 1 database'. This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + + Unable to issue challenge-response. + + Main @@ -907,483 +1347,1039 @@ This is a one-way migration. You won't be able to open the imported databas Ανεπανόρθωτο σφάλμα κατά τον έλεγχο των κρυπτογραφικών λειτουργιών. - KeePassX - Error - KeePassX - Σφάλμα + KeePassXC - Error + KeePassXC - Σφάλμα + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + MainWindow - Database - Βάση Δεδομένων + Open database + Άνοιγμα Βάσης Δεδομένων - Recent databases - Πρόσφατες βάσεις δεδομένων + Database settings + Ρυθμίσεις βάσης δεδομένων - Help - Βοήθεια + Copy username to clipboard + Αντιγραφή όνομα χρήστη στο πρόχειρο - Entries - Καταχωρήσεις + Copy password to clipboard + Αντιγραφή κωδικού στο πρόχειρο - Copy attribute to clipboard - Αντιγραφή χαρακτηριστικού στο πρόχειρο + Settings + Ρύθμίσεις - Groups - Ομάδες + Show toolbar + Εμφάνιση γραμμής εργαλείων - View - Προβολή + read-only + Μόνο για ανάγνωση - Quit - Έξοδος + Toggle window + Εναλλαγή παραθύρων - About - Σχετικά + KeePass 2 Database + Βάση Δεδομένων KeePass 2 - Open database - Άνοιγμα Βάσης Δεδομένων + All files + Όλα τα αρχεία + + + Save repaired database + Αποθήκευση επιδιορθωμένη βάση δεδομένων + + + Writing the database failed. + Εγγραφή της βάσης δεδομένων απέτυχε. + + + &Recent databases + + + + He&lp + + + + E&ntries + + + + Copy att&ribute to clipboard + + + + &Groups + + + + &View + + + + &Quit + + + + &About + + + + &Open database + + + + &Save database + + + + &Close database + + + + &New database + + + + Merge from KeePassX database + + + + &Add new entry + + + + &View/Edit entry + + + + &Delete entry + + + + &Add new group + + + + &Edit group + + + + &Delete group + + + + Sa&ve database as + + + + Change &master key + + + + &Database settings + + + + &Clone entry + + + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + + + &Find + + + + Copy &username + + + + Cop&y password + + + + &Settings + + + + &Perform Auto-Type + + + + &Open URL + + + + &Lock databases + + + + &Title + + + + &URL + + + + &Notes + + + + &Export to CSV file + + + + Re&pair database + + + + Password Generator + + + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Εισαγωγή βάσης δεδομένων KeePass1 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + + + + OptionDialog + + Dialog + + + + General + Γενικά + + + Sh&ow a notification when credentials are requested + + + + Sort matching entries by &username + + + + Re&move all stored permissions from entries in active database + + + + Advanced + Για προχωρημένους + + + Always allow &access to entries + + + + Always allow &updating entries + + + + Searc&h in all opened databases for matching entries + + + + HTTP Port: + + + + Default port: 19455 + + + + Re&quest to unlock the database if it is locked + + + + Sort &matching entries by title + + + + KeePassXC will listen to this port on 127.0.0.1 + + + + Cannot bind to privileged ports + + + + Cannot bind to privileged ports below 1024! +Using default port 19455. + + + + R&emove all shared encryption keys from active database + + + + &Return advanced string fields which start with "KPH: " + + + + Automatically creating or updating string fields is not supported. + + + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + + + + PasswordGeneratorWidget + + Password: + Κωδικός: + + + Character Types + Τύποι χαρακτήρων + + + Upper Case Letters + Κεφαλαία γράμματα + + + Lower Case Letters + Πεζά γράμματα + + + Numbers + Αριθμοί + + + Special Characters + Ειδικοί χαρακτήρες + + + Exclude look-alike characters + Εξαίρεση χαρακτήρων που μοίαζουν + + + Accept + Αποδοχή + + + %p% + + + + strength + + + + entropy + + + + &Length: + + + + Pick characters from every group + + + + Generate + + + + Close + + + + Apply + + + + Entropy: %1 bit + + + + Password Quality: %1 + + + + Poor + + + + Weak + + + + Good + + + + Excellent + + + + Password + Κωδικός + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + + + + QObject + + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Όμαδα + + + Title + Τίτλος + + + Username + Όνομα χρήστη + + + Password + Κωδικός + + + URL + URL + + + Notes + Σημειώσεις + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + + + + + QtIOCompressor + + Internal zlib error when compressing: + + + + Error writing to underlying device: + Σφάλμα κατά την εγγραφή για την υποκείμενη συσκευή: + + + Error opening underlying device: + Σφάλμα άνοιγμα υποκείμενη συσκευή: + + + Error reading data from underlying device: + Σφάλμα κατά την ανάγνωση δεδομένων από υποκείμενη συσκευή: + + + Internal zlib error when decompressing: + + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + + + + Internal zlib error: + + + + + SearchWidget + + Case Sensitive + + + + Search + Αναζήτηση - Save database - Αποθήκευση Βάσης Δεδομένων + Clear + - Close database - Κλείσιμο Βάσης Δεδομένων + Search... + - New database - Νέα Βάση Δεδομένων + Limit search to selected group + + + + Service - Add new entry - Πρόσθεση νέα καταχώρησης + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + - View/Edit entry - Προβολή/επεξεργασία καταχώρησης + Do you want to update the information in %1 - %2? + - Delete entry - Διαγραφή Καταχώρησης + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + - Add new group - Πρόσθεση νέας ομάδας + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + - Edit group - Επεξεργασία Ομάδας + No shared encryption-keys found in KeePassHttp Settings. + - Delete group - Διαγραφή ομάδας + The active database does not contain an entry of KeePassHttp Settings. + - Save database as - Αποθήκευση βάσης δεδομένων ως + Removing stored permissions... + - Change master key - Αλλαγή πρωτεύοντος κλειδιού + Abort + - Database settings - Ρυθμίσεις βάσης δεδομένων + Successfully removed permissions from %1 %2. + - Import KeePass 1 database - Εισαγωγή βάσης δεδομένων KeePass1 + The active database does not contain an entry with permissions. + - Clone entry - Κλωνοποίηση Καταχώρησης + KeePassXC: New key association request + - Find - Εύρεση + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + - Copy username to clipboard - Αντιγραφή όνομα χρήστη στο πρόχειρο + KeePassXC: Overwrite existing key? + - Copy password to clipboard - Αντιγραφή κωδικού στο πρόχειρο + KeePassXC: Update Entry + - Settings - Ρύθμίσεις + KeePassXC: Database locked! + - Perform Auto-Type - Εκτέλεση Αυτόματης-Γραφής + KeePassXC: Removed keys from database + - Open URL - Άνοιγμα ιστοσελίδας + KeePassXC: No keys found + - Lock databases - Κλείδωμα βάσεων δεδομένων + KeePassXC: Settings not available! + - Title - Τίτλος + KeePassXC: Removed permissions + - URL - URL + KeePassXC: No entry with permissions found! + + + + SettingsWidget - Notes - Σημειώσεις + Application Settings + Ρυθμίσεις Εφαρμογής - Show toolbar - Εμφάνιση γραμμής εργαλείων + General + Γενικά - read-only - Μόνο για ανάγνωση + Security + Ασφάλεια - Toggle window - Εναλλαγή παραθύρων + Access error for config file %1 + + + + SettingsWidgetGeneral - Tools - Εργαλεία + Remember last databases + Θυμηθείτε την τελευταία βάσεις δεδομένων - Copy username - Αντιγραφή όνομα χρήστη + Automatically save on exit + Αυτόματη αποθήκευση κατα την έξοδο - Copy password - Αντιγραφή κωδικού + Automatically save after every change + Αυτόματη Αποθήκευση μετά απο κάθε αλλαγή - Export to CSV file - Εξαγωγή σε αρχείο CSV + Minimize when copying to clipboard + Ελαχιστοποίηση οταν αντιγράφετε στο πρόχειρο - Repair database - Επισκευή βάσης δεδομένων + Use group icon on entry creation + Χρησιμοποίηση εικονιδίου ομάδας κατα την δημιουργία καταχώρησης - KeePass 2 Database + Global Auto-Type shortcut - All files - Όλα τα αρχεία - - - Save repaired database - Αποθήκευση επιδιορθωμένη βάση δεδομένων + Language + Γλώσσα - Error - Σφάλμα + Show a system tray icon + Δείχνουν ένα εικονίδιο του δίσκου συστήματος - Writing the database failed. - Εγγραφή της βάσης δεδομένων απέτυχε. + Hide window to system tray when minimized + - - - PasswordGeneratorWidget - Password: - Κωδικός: + Load previous databases on startup + - Length: - Μήκος: + Automatically reload the database when modified externally + - Character Types - Τύποι χαρακτήρων + Hide window to system tray instead of app exit + - Upper Case Letters - Κεφαλαία γράμματα + Minimize window at application startup + - Lower Case Letters - Πεζά γράμματα + Basic Settings + - Numbers - Αριθμοί + Remember last key files and security dongles + - Special Characters - Ειδικοί χαρακτήρες + Don't mark database as modified for non-data changes (e.g., expanding groups) + - Exclude look-alike characters - Εξαίρεση χαρακτήρων που μοίαζουν + Auto-Type + Αυτόματη-Γραφή - Ensure that the password contains characters from every group - Βεβαιωθείται οτι ο κωδικός περιέχει χαρακτήρες απο κάθε ομάδα + Use entry title and URL to match windows for global Auto-Type + - Accept - Αποδοχή + Always ask before performing Auto-Type + - QCommandLineParser - - Displays version information. - Προβολή πληροφοριών έκδοσης. - + SettingsWidgetSecurity - Displays this help. - Δείχνει αυτήν την βοήθεια. + Clear clipboard after + Εκκαθάριση πρόχειρου μετά από - Unknown option '%1'. - Άγνωστη επιλογή '%1'. + sec + δευτερόλεπτα - Unknown options: %1. - Άγνωστο επιλογές: %1. + Lock databases after inactivity of + Κλείδωμα βάσης δεδομένων μετα απο ανενεργεία - Missing value after '%1'. - Τιμή που λείπει μετά από '%1'. + Show passwords in cleartext by default + - Unexpected value after '%1'. - Μη αναμενόμενη τιμή μετά από '%1'. + Lock databases after minimizing the window + - [options] - [επιλογές] + Don't require password repeat when it is visible + - Usage: %1 - Χρήση: %1 + Timeouts + - Options: - Επιλογές: + Convenience + - Arguments: - Επιχειρήματα: + Lock databases when session is locked or lid is closed + - QSaveFile + SetupTotpDialog - Existing file %1 is not writable - Υπάρχον αρχείο %1 δεν είναι εγγράψιμο + Setup TOTP + - Writing canceled by application - Γράψιμο ακυρώθηκε από την εφαρμογή + Key: + - Partial write. Partition full? + Use custom settings - - - QtIOCompressor - Internal zlib error when compressing: + Note: Change these settings only if you know what you are doing. - Error writing to underlying device: - Σφάλμα κατά την εγγραφή για την υποκείμενη συσκευή: + Time step: + - Error opening underlying device: - Σφάλμα άνοιγμα υποκείμενη συσκευή: + 8 digits + - Error reading data from underlying device: - Σφάλμα κατά την ανάγνωση δεδομένων από υποκείμενη συσκευή: + 6 digits + - Internal zlib error when decompressing: + Code size: + + sec + δευτερόλεπτα + - QtIOCompressor::open + TotpDialog - The gzip format not supported in this version of zlib. + Timed Password - Internal zlib error: + 000000 - - - SearchWidget - Find: - Εύρεση + Copy + - Case sensitive - Διάκριση πεζών-κεφαλαίων + Expires in + - Current group - Τρέχων ομάδα + seconds + + + + UnlockDatabaseWidget - Root group - Ομάδα ρίζα + Unlock database + Ξεκλείδωμα βάσης δεδομένων - SettingsWidget + WelcomeWidget - Application Settings - Ρυθμίσεις Εφαρμογής + Welcome to KeePassXC + - General - Γενικά + Start storing your passwords securely in a KeePassXC database + - Security - Ασφάλεια + Create new database + - - - SettingsWidgetGeneral - Remember last databases - Θυμηθείτε την τελευταία βάσεις δεδομένων + Open existing database + - Open previous databases on startup - Άνοιγμα προηγούμενων βάσεω δεδομένων κατα την εκκίνηση + Import from KeePass 1 + - Automatically save on exit - Αυτόματη αποθήκευση κατα την έξοδο + Import from CSV + - Automatically save after every change - Αυτόματη Αποθήκευση μετά απο κάθε αλλαγή + Recent databases + Πρόσφατες βάσεις δεδομένων + + + main - Minimize when copying to clipboard - Ελαχιστοποίηση οταν αντιγράφετε στο πρόχειρο + path to a custom config file + - Use group icon on entry creation - Χρησιμοποίηση εικονιδίου ομάδας κατα την δημιουργία καταχώρησης + key file of the database + Αρχείο κλειδί της βάσεως δεδομένων - Global Auto-Type shortcut + KeePassXC - cross-platform password manager - Use entry title to match windows for global auto-type - Χρησιμοποιήστε εγγραφή τίτλου ώστε να ταιριάζει με windows για παγκόσμια αυτόματος-τύπο + read password of the database from stdin + - Language - Γλώσσα + filenames of the password databases to open (*.kdbx) + - Show a system tray icon - Δείχνουν ένα εικονίδιο του δίσκου συστήματος + Copy a password to the clipboard + - Hide window to system tray when minimized + Path of the database. - Remember last key files + Use a GUI prompt unlocking the database. - Hide window to system tray instead of App Exit + Name of the entry to clip. - Hide window to system tray on App start + Extract and print the content of a database. - - - SettingsWidgetSecurity - Clear clipboard after - Εκκαθάριση πρόχειρου μετά από + Path of the database to extract. + - sec - δευτερόλεπτα + Name of the command to execute. + - Lock databases after inactivity of - Κλείδωμα βάσης δεδομένων μετα απο ανενεργεία + List database entries. + - Show passwords in cleartext by default + Path of the group to list. Default is / - Always ask before performing auto-type - Πάντα να ρωτάτε πριν να εκτελείται η αυτόματη γραφή + Print the UUIDs of the entries and groups. + - - - UnlockDatabaseWidget - Unlock database - Ξεκλείδωμα βάσης δεδομένων + Merge two databases. + - - - WelcomeWidget - Welcome! - Καλως ήρθατε! + Path of the database to merge into. + - - - main - KeePassX - cross-platform password manager + Path of the database to merge from. - filename of the password database to open (*.kdbx) - Όνομα της βάσης δεδομένων κωδικών για άνοιγμα (*.kdbx) + Use the same password for both database files. + - path to a custom config file + Show a password. - key file of the database - Αρχείο κλειδί της βάσεως δεδομένων + Name of the entry to show. + \ No newline at end of file diff --git a/share/translations/keepassx_en.ts b/share/translations/keepassx_en.ts index d10bff0de5..7b014b632c 100644 --- a/share/translations/keepassx_en.ts +++ b/share/translations/keepassx_en.ts @@ -4,24 +4,105 @@ AboutDialog - Revision + About KeePassXC - Using: + About - About KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard - Extensions: + Version %1 - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. + Revision: %1 + + + + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: @@ -121,40 +202,185 @@ Please select whether you want to allow access. - Error + Unable to create Key File : - Unable to create Key File : + Select a key file - Select a key file + Do you really want to use an empty string as password? - Question + Different passwords supplied. - Do you really want to use an empty string as password? + Failed to set %1 as the Key file: +%2 - Different passwords supplied. + &Key file - Failed to set key file + Cha&llenge Response - Failed to set %1 as the Key file: -%2 + Refresh - &Key file + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + + + + Unable to calculate master key + + + + + CsvParserModel + + byte, + + + + rows, + + + + columns @@ -176,10 +402,6 @@ Please select whether you want to allow access. Browse - - Error - - Unable to open the database. @@ -200,6 +422,14 @@ Please select whether you want to allow access. Select key file + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -275,6 +505,18 @@ You can now save it. Use recycle bin + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -294,10 +536,6 @@ You can now save it. Open database - - Warning - - File not found! @@ -327,10 +565,6 @@ You can now save it. Save changes? - - Error - - Writing the database failed. @@ -415,6 +649,14 @@ Do you want to open it anyway? Open read-only + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -457,10 +699,6 @@ Do you want to open it anyway? Do you really want to delete the group "%1" for good? - - Error - - Unable to calculate master key @@ -522,11 +760,15 @@ Do you want to open it anyway? - Autoreload Failed + Could not open the new database file while attempting to autoreload this database. - Could not open the new database file while attempting to autoreload this database. + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? @@ -568,10 +810,6 @@ Do you want to open it anyway? Edit entry - - Error - - Different passwords supplied. @@ -619,6 +857,22 @@ Do you want to open it anyway? 1 year + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -630,10 +884,6 @@ Do you want to open it anyway? Add - - Edit - - Remove @@ -650,6 +900,18 @@ Do you want to open it anyway? Open + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -685,6 +947,10 @@ Do you want to open it anyway? Set custo&m sequence: + + Window Associations + + EditEntryWidgetHistory @@ -794,15 +1060,15 @@ Do you want to open it anyway? - Auto-type + Auto-Type - Use default auto-type sequence of parent group + &Use default Auto-Type sequence of parent group - Set default auto-type sequence + Set default Auto-Type se&quence @@ -828,10 +1094,6 @@ Do you want to open it anyway? Select Image - - Can't delete icon! - - Error @@ -849,15 +1111,19 @@ Do you want to open it anyway? - Can't delete icon. Still used by %1 items. + &Use default icon - &Use default icon + Use custo&m icon - Use custo&m icon + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? @@ -931,6 +1197,11 @@ Do you want to open it anyway? URL + + Ref: + Reference abbreviation + + Group @@ -989,8 +1260,15 @@ Do you want to open it anyway? Ensure that the password contains characters from every group + + + KMessageWidget + + &Close + + - Accept + Close message @@ -1001,11 +1279,7 @@ Do you want to open it anyway? - Error - - - - Unable to open the database. + Unable to open the database. @@ -1065,6 +1339,10 @@ You can import it by clicking on Database > 'Import KeePass 1 database&a This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + + Unable to issue challenge-response. + + Main @@ -1076,13 +1354,17 @@ This is a one-way migration. You won't be able to open the imported databas KeePassXC - Error - - - MainWindow - Database + The lock file could not be created. Single-instance mode disabled. + + Another instance of KeePassXC is already running. + + + + + MainWindow Open database @@ -1115,10 +1397,6 @@ This is a one-way migration. You won't be able to open the imported databas Toggle window - - Tools - - KeePass 2 Database @@ -1131,10 +1409,6 @@ This is a one-way migration. You won't be able to open the imported databas Save repaired database - - Error - - Writing the database failed. @@ -1228,11 +1502,23 @@ This is a one-way migration. You won't be able to open the imported databas - &Import KeePass 1 database + &Clone entry - &Clone entry + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP @@ -1287,6 +1573,46 @@ This is a one-way migration. You won't be able to open the imported databas Password Generator + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1302,11 +1628,6 @@ This is a one-way migration. You won't be able to open the imported databas Sh&ow a notification when credentials are requested - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - - Sort matching entries by &username @@ -1315,10 +1636,6 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< Re&move all stored permissions from entries in active database - - Password generator - - Advanced @@ -1335,10 +1652,6 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< Searc&h in all opened databases for matching entries - - Only the selected database has to be connected with a client! - - HTTP Port: @@ -1355,11 +1668,6 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< Sort &matching entries by title - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - - KeePassXC will listen to this port on 127.0.0.1 @@ -1374,24 +1682,52 @@ Using default port 19455. - &Return only best matching entries for a URL instead -of all entries for the whole domain + R&emove all shared encryption keys from active database - R&emove all shared encryption keys from active database + &Return advanced string fields which start with "KPH: " + + + + Automatically creating or updating string fields is not supported. - The following options can be dangerous. Change them only if you know what you are doing. + This is required for accessing your databases from ChromeIPass or PassIFox - &Return advanced string fields which start with "KPH: " + Enable KeePassHTTP server - Automatically creating or updating string fields is not supported. + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. @@ -1485,11 +1821,100 @@ of all entries for the whole domain Excellent + + Password + + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + + + + Title + + + + Username + + + + Password + + + + URL + + + + Notes + + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive @@ -1538,11 +1963,15 @@ of all entries for the whole domain - Find + Clear - Clear + Search... + + + + Limit search to selected group @@ -1647,6 +2076,10 @@ give it a unique name to identify and accept it. Security + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1674,10 +2107,6 @@ give it a unique name to identify and accept it. Global Auto-Type shortcut - - Use entry title to match windows for global auto-type - - Language @@ -1690,10 +2119,6 @@ give it a unique name to identify and accept it. Hide window to system tray when minimized - - Remember last key files - - Load previous databases on startup @@ -1710,6 +2135,30 @@ give it a unique name to identify and accept it. Minimize window at application startup + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1730,15 +2179,85 @@ give it a unique name to identify and accept it. - Always ask before performing auto-type + Lock databases after minimizing the window - Lock databases after minimizing the window + Don't require password repeat when it is visible - Don't require password repeat when it is visible + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds @@ -1752,7 +2271,31 @@ give it a unique name to identify and accept it. WelcomeWidget - Welcome! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases @@ -1778,5 +2321,69 @@ give it a unique name to identify and accept it. filenames of the password databases to open (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + diff --git a/share/translations/keepassx_es.ts b/share/translations/keepassx_es.ts index 4a9a46c387..16138ecf22 100644 --- a/share/translations/keepassx_es.ts +++ b/share/translations/keepassx_es.ts @@ -2,26 +2,106 @@ AboutDialog - Revision - Revisión + About KeePassXC + Acerca de KeePassXC - Using: - Usando: + About + Acerca de - About KeePassXC - Acerca de KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + - Extensions: + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 - Extensiones: - + + + + Revision: %1 + + + + Libraries: + - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC se distribuye bajo la Licencia Pública General de GNU (GPL) versión 2 o versión 3 (si así lo prefiere). + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -120,10 +200,6 @@ Por favor seleccione si desea autorizar su acceso. Create Key File... Crear un Archivo Llave .... - - Error - Error - Unable to create Key File : No se puede crear el Archivo Llave: @@ -132,10 +208,6 @@ Por favor seleccione si desea autorizar su acceso. Select a key file Seleccione un archivo llave - - Question - Pregunta - Do you really want to use an empty string as password? ¿Realmente desea usar una cadena vacía como contraseña? @@ -144,10 +216,6 @@ Por favor seleccione si desea autorizar su acceso. Different passwords supplied. Las contraseñas ingresadas son distintas. - - Failed to set key file - No se pudo establecer el archivo llave. - Failed to set %1 as the Key file: %2 @@ -158,6 +226,163 @@ Por favor seleccione si desea autorizar su acceso. &Key file &Archivo llave + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Error + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Error + + + Unable to calculate master key + No se puede calcular la clave maestra + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -177,10 +402,6 @@ Por favor seleccione si desea autorizar su acceso. Browse Navegar - - Error - Error - Unable to open the database. Incapaz de abrir la base de datos. @@ -201,6 +422,14 @@ Por favor seleccione si desea autorizar su acceso. Select key file Seleccionar archivo llave + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -277,6 +506,18 @@ Ahora puede guardarla. Use recycle bin Usar papelera de reciclaje + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -296,10 +537,6 @@ Ahora puede guardarla. Open database Abrir base de datos - - Warning - Advertencia - File not found! ¡Archivo no encontrado! @@ -330,10 +567,6 @@ Save changes? "%1" ha sido modificado. ¿Guardar cambios? - - Error - Error - Writing the database failed. La escritura de la base de datos falló. @@ -425,6 +658,14 @@ Do you want to open it anyway? Open read-only Abrir como sólo lectura + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -464,10 +705,6 @@ Do you want to open it anyway? Do you really want to delete the group "%1" for good? ¿Realmente quiere eliminar el grupo "%1" de forma definitiva? - - Error - Error - Unable to calculate master key No se puede calcular la llave maestra @@ -528,14 +765,18 @@ Do you want to open it anyway? The database file has changed and you have unsaved changes.Do you want to merge your changes? El archivo de la base de datos ha cambiado y usted tiene modificaciones sin guardar. ¿Desea unir sus modificaciones? - - Autoreload Failed - La recarga automática falló - Could not open the new database file while attempting to autoreload this database. No se pudo abrir el nuevo archivo de la base de datos mientras se intentaba recargar la base de datos actual. + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -575,10 +816,6 @@ Do you want to open it anyway? Edit entry Editar entrada - - Error - Error - Different passwords supplied. Las contraseñas ingresadas son distintas. @@ -621,6 +858,22 @@ Do you want to open it anyway? 1 year 1 año + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -632,10 +885,6 @@ Do you want to open it anyway? Add Añadir - - Edit - Editar - Remove Eliminar @@ -652,6 +901,18 @@ Do you want to open it anyway? Open Abrir + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -687,6 +948,10 @@ Do you want to open it anyway? Set custo&m sequence: Definir secuencia personalizada: + + Window Associations + + EditEntryWidgetHistory @@ -796,16 +1061,16 @@ Do you want to open it anyway? Buscar - Auto-type - Auto-escritura + Auto-Type + Auto-Escritura - Use default auto-type sequence of parent group - Usar secuencia de auto-escritura por defecto del grupo padre + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Definir secuencia de Auto-Escritura por defecto + Set default Auto-Type se&quence + @@ -830,10 +1095,6 @@ Do you want to open it anyway? Select Image Seleccionar imagen - - Can't delete icon! - ¡No se puede eliminar el ícono! - Error Error @@ -850,10 +1111,6 @@ Do you want to open it anyway? Can't read icon No se puede leer el ícono - - Can't delete icon. Still used by %1 items. - No se puede eliminar el icono. Utilizado aún en %1 elementos - &Use default icon &Usar icono por defecto @@ -862,6 +1119,14 @@ Do you want to open it anyway? Use custo&m icon Usar icono &personalizado + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -933,6 +1198,11 @@ Do you want to open it anyway? URL URL + + Ref: + Reference abbreviation + + Group @@ -991,9 +1261,16 @@ Do you want to open it anyway? Ensure that the password contains characters from every group Asegurar que la contraseña contiene caracteres de todos los grupos + + + KMessageWidget - Accept - Aceptar + &Close + + + + Close message + @@ -1002,10 +1279,6 @@ Do you want to open it anyway? Import KeePass1 database Importar base de datos KeePass1 - - Error - Error - Unable to open the database. Incapaz de abrir la base de datos. @@ -1070,6 +1343,10 @@ This is a one-way migration. You won't be able to open the imported databas Puede importarla haciendo click en 'Base de datos' > 'Importar base de datos de Keepass 1'. Esta migración es en un único sentido. No podrá abrir la base importada con la vieja versión 0.4 de KeePassX. + + Unable to issue challenge-response. + + Main @@ -1081,13 +1358,17 @@ Esta migración es en un único sentido. No podrá abrir la base importada con l KeePassXC - Error KeePassXC - Error + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - Base de datos - Open database Abrir base de datos @@ -1120,10 +1401,6 @@ Esta migración es en un único sentido. No podrá abrir la base importada con l Toggle window Cambiar a ventana - - Tools - Herramientas - KeePass 2 Database Base de datos de KeePass 2 @@ -1136,10 +1413,6 @@ Esta migración es en un único sentido. No podrá abrir la base importada con l Save repaired database Guardar base de datos reparada - - Error - Error - Writing the database failed. Fallo al escribir la base de datos. @@ -1232,14 +1505,26 @@ Esta migración es en un único sentido. No podrá abrir la base importada con l &Database settings Configuración de la base de &datos - - &Import KeePass 1 database - &Importar base de datos KeePass 1 - &Clone entry &Clonar entrada + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find &Buscar @@ -1292,6 +1577,46 @@ Esta migración es en un único sentido. No podrá abrir la base importada con l Password Generator Generador de contraseñas + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Importar base de datos KeePass 1 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1307,12 +1632,6 @@ Esta migración es en un único sentido. No podrá abrir la base importada con l Sh&ow a notification when credentials are requested M&ostrar una notificación cuando se pidan credenciales - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - &Coincidir esquemas URL -Solo se muestran entradas con el mismo esquema (http://, https://, ftp://, ...) - Sort matching entries by &username Ordenar entradas por nombre de &usuario @@ -1321,10 +1640,6 @@ Solo se muestran entradas con el mismo esquema (http://, https://, ftp://, ...)< Re&move all stored permissions from entries in active database Eli&minar todos los permisos guardados de las entradas de la base de datos activa - - Password generator - Generador de contraseñas - Advanced Avanzado @@ -1341,10 +1656,6 @@ Solo se muestran entradas con el mismo esquema (http://, https://, ftp://, ...)< Searc&h in all opened databases for matching entries Buscar entradas que coincidan en todas las bases de datos abiertas - - Only the selected database has to be connected with a client! - ¡Solo la base de datos seleccionada necesita conectarse con un cliente! - HTTP Port: Puerto HTTP: @@ -1361,12 +1672,6 @@ Solo se muestran entradas con el mismo esquema (http://, https://, ftp://, ...)< Sort &matching entries by title Ordenar entradas por &título - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - Habilitar el protocolo KeepassXC HTTP -Necesario para acceder a tus bases de datos desde ChromeIPass o PassIFox - KeePassXC will listen to this port on 127.0.0.1 KeePassXC escuchará por este puerto en 127.0.0.1 @@ -1380,21 +1685,11 @@ Necesario para acceder a tus bases de datos desde ChromeIPass o PassIFox ¡No se puede asociar a puertos con privilegios debajo de 1024! Usando el puerto por defecto 19455 - - - &Return only best matching entries for a URL instead -of all entries for the whole domain - Mostra&r solo las mejores coincidencias para una URL -en vez de todas las entradas para el dominio completo R&emove all shared encryption keys from active database &Eliminar todas las claves de cifrado compartidas de la base de datos activa - - The following options can be dangerous. Change them only if you know what you are doing. - Las siguientes opciones pueden ocasionar problemas. Cámbielas solo si sabe lo que está haciendo. - &Return advanced string fields which start with "KPH: " Mostra&r campos de caracteres avanzados que comiencen con "KPH: " @@ -1403,6 +1698,43 @@ en vez de todas las entradas para el dominio completo Automatically creating or updating string fields is not supported. No se permite crear o actualizar campos de caracteres automáticamente. + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Generador de contraseñas + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + PasswordGeneratorWidget @@ -1456,7 +1788,7 @@ en vez de todas las entradas para el dominio completo Pick characters from every group - Elige caracteres de todos los grupos + Elegir caracteres de todos los grupos Generate @@ -1494,12 +1826,101 @@ en vez de todas las entradas para el dominio completo Excellent Excelente + + Password + Contraseña + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - Http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Grupo + + + Title + Título + + + Username + Nombre de usuario: + + + Password + Contraseña + + + URL + URL + + + Notes + Notas + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1546,14 +1967,18 @@ en vez de todas las entradas para el dominio completo Search Buscar - - Find - Buscar - Clear Limpiar + + Search... + + + + Limit search to selected group + + Service @@ -1660,6 +2085,10 @@ asigne un nombre único para identificarla y acepte. Security Seguridad + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1687,10 +2116,6 @@ asigne un nombre único para identificarla y acepte. Global Auto-Type shortcut Atajo global de Auto-Escritura - - Use entry title to match windows for global auto-type - Usar el título de la entrada para coincidir con la ventana para la auto-escritura global - Language Idioma @@ -1703,10 +2128,6 @@ asigne un nombre único para identificarla y acepte. Hide window to system tray when minimized Ocultar la ventana a la bandeja del sistema cuando se minimiza - - Remember last key files - Recordar últimos archivos llave - Load previous databases on startup Abrir base de datos anterior al inicio @@ -1723,6 +2144,30 @@ asigne un nombre único para identificarla y acepte. Minimize window at application startup Minimizar la ventana al iniciar + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Auto-Escritura + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1742,10 +2187,6 @@ asigne un nombre único para identificarla y acepte. Show passwords in cleartext by default Mostrar contraseñas en texto claro por defecto - - Always ask before performing auto-type - Preguntar siempre antes de realizar auto-escritura - Lock databases after minimizing the window Bloquear base de datos al minimizar la ventana @@ -1754,6 +2195,80 @@ asigne un nombre único para identificarla y acepte. Don't require password repeat when it is visible No pedir repetición de la contraseña cuando está visible + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + segundos + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1765,8 +2280,32 @@ asigne un nombre único para identificarla y acepte. WelcomeWidget - Welcome! - ¡Bienvenid@! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Bases de datos recientes @@ -1791,5 +2330,69 @@ asigne un nombre único para identificarla y acepte. filenames of the password databases to open (*.kdbx) nombre de archivo de la base de datos de contraseñas a abrir (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_fi.ts b/share/translations/keepassx_fi.ts new file mode 100644 index 0000000000..aefa69b1d6 --- /dev/null +++ b/share/translations/keepassx_fi.ts @@ -0,0 +1,2384 @@ + + + AboutDialog + + About KeePassXC + Tietoja ohjelmasta KeePassXC + + + About + + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 + + + + + Revision: %1 + + + + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + + + + + AccessControlDialog + + Remember this decision + Muista tämä valinta + + + Allow + Salli + + + Deny + Estä + + + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + %1 pyytää pääsyä seuraavien alkioiden salasanoihin. +Ole hyvä ja valitse sallitaanko pääsy. + + + KeePassXC HTTP Confirm Access + + + + + AutoType + + Couldn't find an entry that matches the window title: + Ikkunan nimeä vastaavaa merkintää ei löytynyt: + + + Auto-Type - KeePassXC + Automaattitäydennys - KeePassXC + + + + AutoTypeAssociationsModel + + Window + Ikkuna + + + Sequence + Sekvenssi + + + Default sequence + Oletussekvenssi + + + + AutoTypeSelectDialog + + Select entry to Auto-Type: + Valitse merkintä automaattitäydennystä varten: + + + Auto-Type - KeePassXC + Automaattitäydennys - KeePassXC + + + + ChangeMasterKeyWidget + + Password + Salasana + + + Enter password: + Syötä salasana: + + + Repeat password: + Toista salasana: + + + Browse + Selaa + + + Create + Luo + + + Key files + Avaintiedostot + + + All files + Kaikki tiedostot + + + Create Key File... + Luo avaintiedosto... + + + Unable to create Key File : + Avaintiedoston luonti ei onnistunut: + + + Select a key file + Valitse avaintiedosto + + + Do you really want to use an empty string as password? + Haluatko varmasti asettaa tyhjän merkkijonon salasanaksi? + + + Different passwords supplied. + Annetut salasanat eivät täsmää. + + + Failed to set %1 as the Key file: +%2 + + + + &Key file + Avaintiedosto + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Virhe + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Virhe + + + Unable to calculate master key + Pääavaimen laskeminen ei onnistu + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + + + + DatabaseOpenWidget + + Enter master key + Syötä pääsalasana + + + Key File: + Avaintiedosto: + + + Password: + Salasana + + + Browse + Selaa + + + Unable to open the database. + Tietokannan avaaminen ei onnistunut. + + + Can't open key file + Avaintiedostoa ei voitu avata + + + All files + Kaikki tiedostot + + + Key files + Avaintiedostot + + + Select key file + Valitse avaintiedosto + + + Refresh + + + + Challenge Response: + + + + + DatabaseRepairWidget + + Repair database + Korjaa tietokanta + + + Error + Virhe + + + Can't open key file + Avaintiedoston avaaminen epäonnistui + + + Database opened fine. Nothing to do. + Tietokannan avaaminen onnistui. Ei tehtävää. + + + Unable to open the database. + Tietokannan avaaminen epäonnistui. + + + Success + Onnistui! + + + The database has been successfully repaired +You can now save it. + Tietokanta korjattiin onnistuneesti. +Voit nyt tallentaa sen. + + + Unable to repair the database. + Tietokannan korjaus epäonnistui. + + + + DatabaseSettingsWidget + + Database name: + Tietokannan nimi: + + + Database description: + Tietokannan kuvaus: + + + Transform rounds: + Muunnoskierroksia: + + + Default username: + Oletuskäyttäjänimi: + + + MiB + MiB + + + Benchmark + Suorituskykytesti + + + Max. history items: + Maks. historia-alkioiden lukumäärä: + + + Max. history size: + Maks. historian koko: + + + Use recycle bin + Käytä roskakoria + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + + + + DatabaseTabWidget + + Root + Juuri + + + KeePass 2 Database + KeePass 2 -tietokanta + + + All files + Kaikki tiedostot + + + Open database + Avaa tietokanta + + + File not found! + Tiedostoa ei löytynyt! + + + Open KeePass 1 database + Avaa KeePass 1 -tietokanta + + + KeePass 1 database + KeePass 1 -tietokanta + + + All files (*) + Kaikki tiedostot(*) + + + Close? + Sulje? + + + Save changes? + Tallenna muutokset? + + + "%1" was modified. +Save changes? + + + + Writing the database failed. + Tietokannan kirjoitus levylle epäonnistui. + + + Save database as + Tallenna tietokanta nimellä + + + New database + Uusi tietokanta + + + locked + Lukittu + + + Lock database + Lukitse tietokanta + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Tietokantaa ei voida lukita, sillä se on muokkaustilassa. +Paina Peruuta jos haluat viimeistellä muutoksesi, muussa tapauksessa muutoksesi hylätään. + + + This database has never been saved. +You can save the database or stop locking it. + + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" on muokkaustilassa. +Hylkää muutokset ja sulje? + + + Export database to CSV file + Vie tietokanta CSV-tiedostoon + + + CSV file + CSV-tiedosto + + + Writing the CSV file failed. + CSV-tiedoston kirjoitus levylle epäonnistui. + + + Unable to open the database. + Tietokannan avaaminen ei onnistunut. + + + Merge database + Yhdistä tietokanta + + + The database you are trying to save as is locked by another instance of KeePassXC. +Do you want to save it anyway? + Tietokanta jota yrität avata on avoinna toisessa KeePassXC-ikkunassa. +Haluatko tallentaa tietokannan siitä huolimatta? + + + Passwords + Salasanat + + + Database already opened + Tietokanta on jo avattu + + + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + + + + Open read-only + Avaa "vain luku"-tilassa + + + File opened in read only mode. + + + + Open CSV file + + + + + DatabaseWidget + + Change master key + Vaihda pääsalasana + + + Delete entry? + Poista merkintä? + + + Do you really want to delete the entry "%1" for good? + Haluatko varmasti poistaa merkinnän "%1", lopullisesti? + + + Delete entries? + Poista alkiot? + + + Do you really want to delete %1 entries for good? + Haluatko varmasti poistaa alkiot %1, lopullisesti? + + + Move entries to recycle bin? + Siirrä alkiot roskakoriin? + + + Do you really want to move %n entry(s) to the recycle bin? + Haluatko varmasti siirtää %n kappaletta alkioita roskakoriin?Haluatko varmasti siirtää %n merkintää roskakoriin? + + + Delete group? + Poista ryhmä? + + + Do you really want to delete the group "%1" for good? + Haluatko varmasti poistaa ryhmän "%1", lopullisesti? + + + Unable to calculate master key + Pääavaimen laskeminen ei onnistu + + + Move entry to recycle bin? + Siirrä merkintä roskakoriin? + + + Do you really want to move entry "%1" to the recycle bin? + + + + Searching... + Etsitään... + + + No current database. + + + + No source database, nothing to do. + + + + Search Results (%1) + Etsinnän tulokset (%1) + + + No Results + Ei tuloksia. + + + Execute command? + Suorita komento? + + + Do you really want to execute the following command?<br><br>%1<br> + + + + Remember my choice + Muista valintani + + + Autoreload Request + + + + The database file has changed. Do you want to load the changes? + + + + Merge Request + + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + + + + Could not open the new database file while attempting to autoreload this database. + + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + + + + EditEntryWidget + + Entry + Merkintä + + + Advanced + Lisäasetukset + + + Icon + Kuvake + + + Auto-Type + Automaattitäydennys + + + Properties + Ominaisuudet + + + History + Historia + + + Entry history + Alkioiden historia + + + Add entry + Lisää alkio + + + Edit entry + Muokkaa alkiota + + + Different passwords supplied. + Annetut salasanat eivät täsmää. + + + New attribute + Uusi attribuutti + + + Select file + Valitse tiedosto + + + Unable to open file + Tiedoston avaus ei onnistu + + + Save attachment + Tallenna liite + + + Unable to save the attachment: + + Liitteen tallentaminen ei onnistu: + + + + Tomorrow + Huomenna + + + %n week(s) + %n viikkoa%n viikkoa + + + %n month(s) + %n kuukautta%n kuukautta + + + 1 year + + + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + + + + EditEntryWidgetAdvanced + + Additional attributes + + + + Add + Lisää + + + Remove + Poista + + + Attachments + Liitteet + + + Save + Tallenna + + + Open + Avaa + + + Edit Name + + + + Protect + + + + Reveal + + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + Salli automaattitäydennys tälle merkinnälle + + + + + + + + + - + - + + + Window title: + Ikkunan otsikko: + + + Inherit default Auto-Type sequence from the &group + Peri automaattitäydennyksen oletussekvenssi &ryhmältä + + + &Use custom Auto-Type sequence: + + + + Use default se&quence + + + + Set custo&m sequence: + + + + Window Associations + + + + + EditEntryWidgetHistory + + Show + Näytä + + + Restore + Palauta + + + Delete + Poista + + + Delete all + Poista kaikki + + + + EditEntryWidgetMain + + Title: + Otsikko: + + + Username: + Käyttäjänimi + + + Password: + Salasana + + + Repeat: + Toista: + + + URL: + URL: + + + Expires + Erääntyy + + + Presets + Esiasetus + + + Notes: + Muistiinpanot: + + + + EditGroupWidget + + Group + Ryhmä + + + Icon + Kuvake + + + Properties + Ominaisuudet + + + Add group + Lisää ryhmä + + + Edit group + Muokkaa ryhmää + + + Enable + Kytke päälle + + + Disable + Kytke pois päältä + + + Inherit from parent group (%1) + Peri ylemmältä ryhmältä (%1) + + + + EditGroupWidgetMain + + Name + Nimi + + + Notes + Muistiinpanot + + + Expires + Erääntyy + + + Search + Etsi + + + Auto-Type + Automaattitäydennys + + + &Use default Auto-Type sequence of parent group + + + + Set default Auto-Type se&quence + + + + + EditWidgetIcons + + Add custom icon + + + + Delete custom icon + + + + Images + Kuvat + + + All files + Kaikki tiedostot + + + Select Image + Valitse kuva + + + Error + Virhe + + + Download favicon + Lataa favicon + + + Unable to fetch favicon. + Faviconin noutaminen ei onnistu + + + Can't read icon + Kuvaketta ei voida lukea + + + &Use default icon + + + + Use custo&m icon + + + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + + + + EditWidgetProperties + + Created: + Luotu: + + + Modified: + Muokattu: + + + Accessed: + Käytetty: + + + Uuid: + UUID: + + + + Entry + + - Clone + - Klooni + + + + EntryAttributesModel + + Name + Nimi + + + + EntryHistoryModel + + Last modified + Viimeksi muokattu + + + Title + Otsikko + + + Username + Käyttäjätunnus + + + URL + URL + + + + EntryModel + + Group + Ryhmä + + + Title + Otsikko + + + Username + Käyttäjätunnus + + + URL + URL + + + Ref: + Reference abbreviation + + + + + Group + + Recycle Bin + Roskakori + + + + HttpPasswordGeneratorWidget + + Length: + Pituus: + + + Character Types + Merkkityypit + + + Upper Case Letters + Isot kirjaimet + + + A-Z + A-Z + + + Lower Case Letters + Pienet kirjaimet + + + a-z + a-z + + + Numbers + Numerot + + + 0-9 + 0-9 + + + Special Characters + Erikoismerkit + + + /*_& ... + /*_& ... + + + Exclude look-alike characters + Poissulje samannäköiset merkit + + + Ensure that the password contains characters from every group + Varmista, että salasana sisältää merkkejä jokaisesta ryhmästä + + + + KMessageWidget + + &Close + + + + Close message + + + + + KeePass1OpenWidget + + Import KeePass1 database + Tuo KeePass 1 -tietokanta + + + Unable to open the database. + Tietokannan avaaminen ei onnistunut. + + + + KeePass1Reader + + Unable to read keyfile. + Avaintiedoston luku ei onnistu + + + Not a KeePass database. + Tiedosto ei ole KeePass-tietokanta + + + Unsupported encryption algorithm. + Tukematon salausalgoritmi. + + + Unsupported KeePass database version. + Tukematon KeePass-tietokantaversio + + + Root + Juuri + + + Unable to calculate master key + Pääavaimen laskeminen ei onnistu + + + Wrong key or database file is corrupt. + Väärä avain tai tietokanta on korruptoitunut. + + + + KeePass2Reader + + Not a KeePass database. + Tiedosto ei ole KeePass-tietokanta + + + Unsupported KeePass database version. + Tukematon KeePass-tietokantaversio + + + Wrong key or database file is corrupt. + Väärä avain tai tietokanta on korruptoitunut. + + + Unable to calculate master key + Pääavaimen laskeminen ei onnistu + + + The selected file is an old KeePass 1 database (.kdb). + +You can import it by clicking on Database > 'Import KeePass 1 database'. +This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + + + + Unable to issue challenge-response. + + + + + Main + + Fatal error while testing the cryptographic functions. + + + + KeePassXC - Error + KeePassXC - Virhe + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + + + + MainWindow + + Open database + Avaa tietokanta + + + Database settings + Tietokannan asetukset + + + Copy username to clipboard + Kopioi käyttäjätunnus leikepöydälle + + + Copy password to clipboard + Kopioi salasana leikepöydälle + + + Settings + Asetukset + + + Show toolbar + Näytä työkalupalkki + + + read-only + vain-luku + + + Toggle window + + + + KeePass 2 Database + Keepass 2 -tietokanta + + + All files + Kaikki tiedostot + + + Save repaired database + Tallenna korjattu tietokanta + + + Writing the database failed. + Tietokannan kirjoitus levylle epäonnistui. + + + &Recent databases + Viimeisimmät tietokannat + + + He&lp + Apua + + + E&ntries + + + + Copy att&ribute to clipboard + + + + &Groups + Ryhmät + + + &View + Näkymä + + + &Quit + Lopeta + + + &About + Tietoja + + + &Open database + Avaa tietokanta + + + &Save database + Tallenna tietokanta + + + &Close database + Sulje tietokanta + + + &New database + Uusi tietokanta + + + Merge from KeePassX database + + + + &Add new entry + Lisää merkintä + + + &View/Edit entry + Näytä/muokkaa merkintää + + + &Delete entry + Poista merkintä + + + &Add new group + Lisää uusi ryhmä + + + &Edit group + Muokkaa ryhmää + + + &Delete group + Poista ryhmä + + + Sa&ve database as + Tallenna tietokanta nimellä + + + Change &master key + Vaihda pääsalasana + + + &Database settings + Tietokannan asetukset + + + &Clone entry + Kloonaa merkintä + + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + + + &Find + Etsi + + + Copy &username + Kopioi käyttäjätunnus + + + Cop&y password + Kopioi salasana + + + &Settings + Asetukset + + + &Perform Auto-Type + Suorita automaattitäydennys + + + &Open URL + Avaa URL + + + &Lock databases + Lukitse tietokannat + + + &Title + Otsikko + + + &URL + URL + + + &Notes + Muistiinpanot + + + &Export to CSV file + Vie CSV-tiedostoon + + + Re&pair database + Korjaa tietokanta + + + Password Generator + Salasanageneraattori + + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + + + + OptionDialog + + Dialog + Dialogi + + + General + Yleistä + + + Sh&ow a notification when credentials are requested + + + + Sort matching entries by &username + + + + Re&move all stored permissions from entries in active database + + + + Advanced + Lisää.. + + + Always allow &access to entries + + + + Always allow &updating entries + + + + Searc&h in all opened databases for matching entries + + + + HTTP Port: + HTTP-portti: + + + Default port: 19455 + Oletusportti: 19455 + + + Re&quest to unlock the database if it is locked + + + + Sort &matching entries by title + + + + KeePassXC will listen to this port on 127.0.0.1 + + + + Cannot bind to privileged ports + + + + Cannot bind to privileged ports below 1024! +Using default port 19455. + + + + R&emove all shared encryption keys from active database + + + + &Return advanced string fields which start with "KPH: " + + + + Automatically creating or updating string fields is not supported. + + + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Salasanageneraattori + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + + + + PasswordGeneratorWidget + + Password: + Salasana + + + Character Types + Merkkityypit + + + Upper Case Letters + Isot kirjaimet + + + Lower Case Letters + Pienet kirjaimet + + + Numbers + Numerot + + + Special Characters + Erikoismerkit + + + Exclude look-alike characters + Poissulje samannäköiset merkit + + + Accept + Hyväksy + + + %p% + + + + strength + + + + entropy + entropia + + + &Length: + + + + Pick characters from every group + + + + Generate + Generoi + + + Close + Sulje + + + Apply + + + + Entropy: %1 bit + + + + Password Quality: %1 + + + + Poor + Huono + + + Weak + Heikko + + + Good + Hyvä + + + Excellent + Erinomainen + + + Password + Salasana + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + + + + QObject + + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Ryhmä + + + Title + Otsikko + + + Username + Käyttäjätunnus + + + Password + Salasana + + + URL + URL + + + Notes + Muistiinpanot + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + + + + + QtIOCompressor + + Internal zlib error when compressing: + Sisäinen zlib virhe pakatessa: + + + Error writing to underlying device: + + + + Error opening underlying device: + + + + Error reading data from underlying device: + + + + Internal zlib error when decompressing: + + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + gzip-formaatti ei ole tuettu tässä zlib-versiossa. + + + Internal zlib error: + Sisäinen zlib-virhe: + + + + SearchWidget + + Case Sensitive + Kirjainkoko on merkitsevä + + + Search + Etsi + + + Clear + Tyhjennä + + + Search... + + + + Limit search to selected group + + + + + Service + + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + + + + Do you want to update the information in %1 - %2? + + + + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + + + + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + + + + No shared encryption-keys found in KeePassHttp Settings. + + + + The active database does not contain an entry of KeePassHttp Settings. + + + + Removing stored permissions... + + + + Abort + Keskeytä + + + Successfully removed permissions from %1 %2. + + + + The active database does not contain an entry with permissions. + + + + KeePassXC: New key association request + + + + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + + + + KeePassXC: Overwrite existing key? + + + + KeePassXC: Update Entry + + + + KeePassXC: Database locked! + + + + KeePassXC: Removed keys from database + + + + KeePassXC: No keys found + + + + KeePassXC: Settings not available! + + + + KeePassXC: Removed permissions + + + + KeePassXC: No entry with permissions found! + + + + + SettingsWidget + + Application Settings + + + + General + Yleistä + + + Security + Turvallisuus + + + Access error for config file %1 + + + + + SettingsWidgetGeneral + + Remember last databases + Muista viimeisimmät tietokannat + + + Automatically save on exit + Tallenna automaattisesti suljettaessa + + + Automatically save after every change + Tallenna automaattisesti jokaisen muutoksen jälkeen + + + Minimize when copying to clipboard + Pienennä ikkuna kopioidessa leikepöydälle + + + Use group icon on entry creation + Käytä ryhmän kuvaketta merkintää luodessa + + + Global Auto-Type shortcut + Globaalin automaattitäydennyksen pikanäppäin + + + Language + Kieli + + + Show a system tray icon + Näytä ilmoitusalueen kuvake + + + Hide window to system tray when minimized + Piiloita pienennetty ikkuna ilmoitusalueelle + + + Load previous databases on startup + Lataa edelliset tietokannat käynnistäessä + + + Automatically reload the database when modified externally + Lataa tietokanta automaattisesti uudelleen jos tietokantaa muokattiin muualla + + + Hide window to system tray instead of app exit + Piiloita ikkuna ilmoitusalueelle sulkemisen sijaan + + + Minimize window at application startup + Pienennä ikkuna ohjelman käynnistyessä + + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Automaattitäydennys + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + + + + SettingsWidgetSecurity + + Clear clipboard after + Tyhjennä leikepöytä kun on kulunut + + + sec + s. + + + Lock databases after inactivity of + Lukitse tietokannat jos on oltu joutilaana + + + Show passwords in cleartext by default + Näytä salasanat oletuksena selkokielisenä + + + Lock databases after minimizing the window + Lukitse tietokanta ikkunan pienennyksen jälkeen + + + Don't require password repeat when it is visible + Älä vaadi salasanan toistoa jos salasana on näkyvillä + + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + s. + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + + + + UnlockDatabaseWidget + + Unlock database + Avaa tietokannan lukitus + + + + WelcomeWidget + + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + + + + + main + + path to a custom config file + + + + key file of the database + + + + KeePassXC - cross-platform password manager + + + + read password of the database from stdin + + + + filenames of the password databases to open (*.kdbx) + + + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + + + \ No newline at end of file diff --git a/share/translations/keepassx_fr.ts b/share/translations/keepassx_fr.ts index cccd183b5d..7c14f5ef16 100644 --- a/share/translations/keepassx_fr.ts +++ b/share/translations/keepassx_fr.ts @@ -2,26 +2,106 @@ AboutDialog - Revision - Révision + About KeePassXC + À propos de KeePassXC - Using: - Utilise : + About + À propos - About KeePassXC - À propos de KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + - Extensions: + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 - Extensions : - + - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC est distribué suivant les termes de la GNU Licence Publique Générale (GNU GPL) version 2 ou version 3 de la licence (à votre gré). + Revision: %1 + + + + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -120,10 +200,6 @@ Veuillez sélectionner si vous souhaitez autoriser l’accès. Create Key File... Créer un fichier-clé... - - Error - Erreur - Unable to create Key File : Impossible de créer un fichier-clé : @@ -132,10 +208,6 @@ Veuillez sélectionner si vous souhaitez autoriser l’accès. Select a key file Choisir un fichier-clé - - Question - Question - Do you really want to use an empty string as password? Voulez-vous vraiment utiliser une chaîne vide comme mot de passe ? @@ -144,10 +216,6 @@ Veuillez sélectionner si vous souhaitez autoriser l’accès. Different passwords supplied. Les mots de passe ne sont pas identiques. - - Failed to set key file - Impossible de définir le fichier-clé - Failed to set %1 as the Key file: %2 @@ -158,6 +226,163 @@ Veuillez sélectionner si vous souhaitez autoriser l’accès. &Key file Fichier-clé + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Erreur + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Erreur + + + Unable to calculate master key + Impossible de calculer la clé maître + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -177,10 +402,6 @@ Veuillez sélectionner si vous souhaitez autoriser l’accès. Browse Naviguer - - Error - Erreur - Unable to open the database. Impossible d'ouvrir la base de données. @@ -201,6 +422,14 @@ Veuillez sélectionner si vous souhaitez autoriser l’accès. Select key file Choisissez un fichier-clé + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -277,6 +506,18 @@ Vous pouvez maintenant la sauvegarder. Use recycle bin Utiliser la corbeille + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -296,10 +537,6 @@ Vous pouvez maintenant la sauvegarder. Open database Ouvrir la base de données - - Warning - Attention - File not found! Fichier introuvable ! @@ -330,10 +567,6 @@ Save changes? "%1" a été modifié. Enregistrer les modifications ? - - Error - Erreur - Writing the database failed. Une erreur s'est produite lors de l'écriture de la base de données. @@ -426,6 +659,14 @@ Voulez vous l'ouvrir quand même ? Open read-only Ouvrir en lecture seule + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -465,10 +706,6 @@ Voulez vous l'ouvrir quand même ? Do you really want to delete the group "%1" for good? Voulez-vous supprimer le groupe "%1" définitivement ? - - Error - Erreur - Unable to calculate master key Impossible de calculer la clé maître @@ -529,14 +766,18 @@ Voulez vous l'ouvrir quand même ? The database file has changed and you have unsaved changes.Do you want to merge your changes? Le fichier de la base de données à changé et vous avez des modification non-enregistrés. Voulez-vous fusionner vos modifications? - - Autoreload Failed - Échec du rafraîchissement automatique - Could not open the new database file while attempting to autoreload this database. La nouvelle base de données ne peux être ouverte pendant qu'un rafraîchissement automatique de l'actuelle est en cours. + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -576,10 +817,6 @@ Voulez vous l'ouvrir quand même ? Edit entry Modifier l'entrée - - Error - Erreur - Different passwords supplied. Les mots de passe ne sont pas identiques. @@ -622,6 +859,22 @@ Voulez vous l'ouvrir quand même ? 1 year 1 an + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -633,10 +886,6 @@ Voulez vous l'ouvrir quand même ? Add Ajouter - - Edit - Modifier - Remove Supprimer @@ -653,6 +902,18 @@ Voulez vous l'ouvrir quand même ? Open Ouvrir + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -688,6 +949,10 @@ Voulez vous l'ouvrir quand même ? Set custo&m sequence: Définir une séquence personnalisée : + + Window Associations + + EditEntryWidgetHistory @@ -797,16 +1062,16 @@ Voulez vous l'ouvrir quand même ? Chercher - Auto-type + Auto-Type Remplissage automatique - Use default auto-type sequence of parent group - Utiliser la séquence de remplissage automatique par défaut du groupe parent + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Définir une séquence de remplissage automatique par défaut + Set default Auto-Type se&quence + @@ -831,10 +1096,6 @@ Voulez vous l'ouvrir quand même ? Select Image Choisir une image - - Can't delete icon! - Impossible de supprimer l'icône ! - Error Erreur @@ -851,10 +1112,6 @@ Voulez vous l'ouvrir quand même ? Can't read icon Impossible de lire l'icône - - Can't delete icon. Still used by %1 items. - Impossible de supprimer l'icône. Encore utilisée par 1% éléments. - &Use default icon Utiliser l'icône par défaut @@ -863,6 +1120,14 @@ Voulez vous l'ouvrir quand même ? Use custo&m icon Utiliser une icône personnalisée + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -934,6 +1199,11 @@ Voulez vous l'ouvrir quand même ? URL URL + + Ref: + Reference abbreviation + + Group @@ -992,9 +1262,16 @@ Voulez vous l'ouvrir quand même ? Ensure that the password contains characters from every group S'assurer que le mot de passe contienne des caractères de chaque groupe + + + KMessageWidget - Accept - Accepter + &Close + + + + Close message + @@ -1003,10 +1280,6 @@ Voulez vous l'ouvrir quand même ? Import KeePass1 database Importer une base de données au format KeePass1 - - Error - Erreur - Unable to open the database. Impossible d'ouvrir la base de données. @@ -1071,6 +1344,10 @@ This is a one-way migration. You won't be able to open the imported databas Vous pouvez l'importer en cliquant sur "Base de données" > "Importer une base de données KeePass 1". Ceci est une migration à sens unique. Vous ne serez plus en mesure d'ouvrir la base de données importée avec l'ancienne version KeePassX version 0.4. + + Unable to issue challenge-response. + + Main @@ -1082,13 +1359,17 @@ Ceci est une migration à sens unique. Vous ne serez plus en mesure d'ouvri KeePassXC - Error KeePassXC - Erreur + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - Base de données - Open database Ouvrir une base de données @@ -1121,10 +1402,6 @@ Ceci est une migration à sens unique. Vous ne serez plus en mesure d'ouvri Toggle window Basculer de fenêtre - - Tools - Outils - KeePass 2 Database Base de données KeePass 2 @@ -1137,10 +1414,6 @@ Ceci est une migration à sens unique. Vous ne serez plus en mesure d'ouvri Save repaired database Sauvegarder la base de données réparée - - Error - Erreur - Writing the database failed. Une erreur s'est produite lors de l'écriture de la base de données. @@ -1175,7 +1448,7 @@ Ceci est une migration à sens unique. Vous ne serez plus en mesure d'ouvri &About - &A propos + &À propos &Open database @@ -1233,14 +1506,26 @@ Ceci est une migration à sens unique. Vous ne serez plus en mesure d'ouvri &Database settings Paramètre de la base de &données - - &Import KeePass 1 database - &Importer 1 base de données KeePass - &Clone entry Cloner l'entrée + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find Trouver @@ -1293,6 +1578,46 @@ Ceci est une migration à sens unique. Vous ne serez plus en mesure d'ouvri Password Generator Générateur de mot de passe + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Importer une base de données KeePass 1 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1308,12 +1633,6 @@ Ceci est une migration à sens unique. Vous ne serez plus en mesure d'ouvri Sh&ow a notification when credentials are requested Montrer une notification quand les références sont demandées - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - & Cible des types d'URL -Seules les entrées de même type (http://, https://, ftp://, ...) sont retournées - Sort matching entries by &username Trier les entrées correspondantes par nom d'&utilisateur @@ -1322,10 +1641,6 @@ Seules les entrées de même type (http://, https://, ftp://, ...) sont retourn Re&move all stored permissions from entries in active database Supprimer toutes les permissions enregistrées des entrées de la base de données active - - Password generator - Générateur de mots de passe - Advanced Avancé @@ -1342,10 +1657,6 @@ Seules les entrées de même type (http://, https://, ftp://, ...) sont retourn Searc&h in all opened databases for matching entries Cherc&her dans toutes les bases de données ouvertes les entrées correspondantes - - Only the selected database has to be connected with a client! - Seule la base de données sélectionnée doit être connectée à un client ! - HTTP Port: Port HTTP: @@ -1356,18 +1667,12 @@ Seules les entrées de même type (http://, https://, ftp://, ...) sont retourn Re&quest to unlock the database if it is locked - Demander de déverrouiller la base de données lorsque celle-ci est verrouiller + Demander de déverrouiller la base de données lorsque celle-ci est verrouillée Sort &matching entries by title Trier les entrées correspondantes par titre - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - Activer le protocole HTTP de KeePassXC -Ce protocole est nécessaire si vous souhaitez accéder à vos bases de données avec ChromeIPas ou PassIFox - KeePassXC will listen to this port on 127.0.0.1 KeepassXC va écouter ce port sur 127.0.0.1 @@ -1381,21 +1686,11 @@ Ce protocole est nécessaire si vous souhaitez accéder à vos bases de données Using default port 19455. Liaison impossible avec les ports privilégiés, ceux avant 1024 ! Restauration du port 19455 par défaut. - - - &Return only best matching entries for a URL instead -of all entries for the whole domain - & Retourne seulement les meilleures entrées correspondantes pour une URL, -au lieu de toutes pour le domaine entier R&emove all shared encryption keys from active database Supprimer toutes les clés de chiffrement partagées de la base de données active - - The following options can be dangerous. Change them only if you know what you are doing. - La modification de ces préférences peuvent entrainer des problèmes de sécurité. Ne continuez que si vous savez ce que vous faites ! - &Return advanced string fields which start with "KPH: " & Retourne les champs avancés de type chaîne qui commencent par "KPH:" @@ -1404,6 +1699,43 @@ au lieu de toutes pour le domaine entier Automatically creating or updating string fields is not supported. La création ou la mise a jour automatique ne sont pas pris en charge pour les champs de chaines de caractères ! + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Générateur de mot de passe + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + PasswordGeneratorWidget @@ -1495,12 +1827,101 @@ au lieu de toutes pour le domaine entier Excellent Excellent + + Password + Mot de passe + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - Http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Groupe + + + Title + Titre + + + Username + Nom d'utilisateur + + + Password + Mot de passe + + + URL + URL + + + Notes + Notes + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1547,14 +1968,18 @@ au lieu de toutes pour le domaine entier Search Chercher - - Find - Trouver - Clear Effacer + + Search... + + + + Limit search to selected group + + Service @@ -1661,6 +2086,10 @@ attribuez lui un nom unique pour l'identifier et acceptez la. Security Sécurité + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1688,10 +2117,6 @@ attribuez lui un nom unique pour l'identifier et acceptez la. Global Auto-Type shortcut Raccourci de remplissage automatique global - - Use entry title to match windows for global auto-type - Utiliser le titre d’entrée pour correspondre à windows pour auto-type global - Language Langue @@ -1704,17 +2129,13 @@ attribuez lui un nom unique pour l'identifier et acceptez la. Hide window to system tray when minimized Réduire la fenêtre vers la zone de notification lors de sa réduction - - Remember last key files - Se rappeler les derniers fichiers-clés ouverts - Load previous databases on startup Charger les bases de données précédentes au démarrage Automatically reload the database when modified externally - Recharger automatiquement la base de données quand celle-ci est modifier depuis l'extérieur + Recharger automatiquement la base de données quand celle-ci est modifiée depuis l'extérieur Hide window to system tray instead of app exit @@ -1724,6 +2145,30 @@ attribuez lui un nom unique pour l'identifier et acceptez la. Minimize window at application startup Minimiser la fenêtre lors du démarrage de l'application + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Remplissage automatique + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1743,10 +2188,6 @@ attribuez lui un nom unique pour l'identifier et acceptez la. Show passwords in cleartext by default Afficher les mots de passe en clair par défaut - - Always ask before performing auto-type - Toujours demander avant d'effectuer un remplissage automatique - Lock databases after minimizing the window Verrouiller la base de données lorsque la fenêtre est minimisée @@ -1755,6 +2196,80 @@ attribuez lui un nom unique pour l'identifier et acceptez la. Don't require password repeat when it is visible Ne pas demander de répéter le mot de passe lorsque celui-ci est visible + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + s + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1766,8 +2281,32 @@ attribuez lui un nom unique pour l'identifier et acceptez la. WelcomeWidget - Welcome! - Bienvenue ! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Bases de données récentes @@ -1792,5 +2331,69 @@ attribuez lui un nom unique pour l'identifier et acceptez la. filenames of the password databases to open (*.kdbx) noms de fichiers des bases de données de mot de passe à ouvrir (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_id.ts b/share/translations/keepassx_id.ts index 25cc301ecb..cddd1b6eee 100644 --- a/share/translations/keepassx_id.ts +++ b/share/translations/keepassx_id.ts @@ -1,33 +1,143 @@ - + AboutDialog - About KeePassX - Tentang KeePassX + About KeePassXC + + + + About + Tentang + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + - KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassX disebarluaskan dibawah ketentuan dari Lisensi Publik Umum GNU (GPL) versi 2 atau (sesuai pilihan Anda) versi 3. + Version %1 + + + + + Revision: %1 + + + + Libraries: + - Revision - Revisi + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + - Using: - Menggunakan: + Enabled extensions: + - AutoType + AccessControlDialog + + Remember this decision + + + + Allow + + + + Deny + + - Auto-Type - KeePassX - Ketik-Otomatis - KeePassX + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + + + + KeePassXC HTTP Confirm Access + + + + AutoType Couldn't find an entry that matches the window title: Tidak bisa menemukan entri yang cocok dengan judul jendela: + + Auto-Type - KeePassXC + + AutoTypeAssociationsModel @@ -46,14 +156,14 @@ AutoTypeSelectDialog - - Auto-Type - KeePassX - Ketik-Otomatis - KeePassX - Select entry to Auto-Type: Pilih entri untuk Ketik-Otomatis: + + Auto-Type - KeePassXC + + ChangeMasterKeyWidget @@ -69,10 +179,6 @@ Repeat password: Ulangi sandi: - - Key file - Berkas kunci - Browse Telusuri @@ -93,10 +199,6 @@ Create Key File... Buat Berkas Kunci... - - Error - Galat - Unable to create Key File : Tidak bisa membuat Berkas Kunci : @@ -105,10 +207,6 @@ Select a key file Pilih berkas kunci - - Question - Pertanyaan - Do you really want to use an empty string as password? Apakah Anda benar-benar ingin menggunakan lema kosong sebagai sandi? @@ -117,16 +215,173 @@ Different passwords supplied. Sandi berbeda. - - Failed to set key file - Gagal menetapkan berkas kunci - Failed to set %1 as the Key file: %2 Gagal menetapkan %1 sebagai berkas Kunci: %2 + + &Key file + + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Galat + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Galat + + + Unable to calculate master key + Tidak bisa mengkalkulasi kunci utama + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -146,10 +401,6 @@ Browse Telusuri - - Error - Galat - Unable to open the database. Tidak bisa membuka basis data. @@ -170,6 +421,14 @@ Select key file Pilih berkas kunci + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -226,10 +485,6 @@ Anda bisa menyimpannya sekarang. Default username: Nama pengguna baku: - - Use recycle bin: - Gunakan tong sampah: - MiB MiB @@ -246,6 +501,22 @@ Anda bisa menyimpannya sekarang. Max. history size: Maks. ukuran riwayat: + + Use recycle bin + + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -265,10 +536,6 @@ Anda bisa menyimpannya sekarang. Open database Buka basis data - - Warning - Peringatan - File not found! Berkas tidak ditemukan! @@ -299,10 +566,6 @@ Save changes? "%1" telah dimodifikasi. Simpan perubahan? - - Error - Galat - Writing the database failed. Gagal membuat basis data. @@ -319,12 +582,6 @@ Simpan perubahan? locked terkunci - - The database you are trying to open is locked by another instance of KeePassX. -Do you want to open it anyway? Alternatively the database is opened read-only. - Basis data yang Anda coba buka terkunci oleh KeePassX lain yang sedang berjalan. -Apakah Anda tetap ingin membukanya? Alternatif lain buka basis data baca-saja. - Lock database Kunci basis data @@ -368,37 +625,66 @@ Tetap buang ubahan dan tutup? Gagal membuat berkas CSV. - The database you are trying to save as is locked by another instance of KeePassX. -Do you want to save it anyway? - Basis data yang Anda coba buka terkunci oleh KeePassX lain yang sedang berjalan. -Apakah Anda tetap ingin menyimpannya? + Unable to open the database. + Tidak bisa membuka basis data. - Unable to open the database. + Merge database - - - DatabaseWidget - Change master key - Ubah kunci utama + The database you are trying to save as is locked by another instance of KeePassXC. +Do you want to save it anyway? + - Delete entry? - Hapus entri? + Passwords + - Do you really want to delete the entry "%1" for good? - Apakah Anda benar-benar ingin menghapus entri "%1" untuk selamanya? + Database already opened + - Delete entries? - Hapus entri? + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + - Do you really want to delete %1 entries for good? - Apakah Anda benar-benar ingin menghapus entri %1 untuk selamanya? + Open read-only + + + + File opened in read only mode. + + + + Open CSV file + + + + + DatabaseWidget + + Change master key + Ubah kunci utama + + + Delete entry? + Hapus entri? + + + Do you really want to delete the entry "%1" for good? + Apakah Anda benar-benar ingin menghapus entri "%1" untuk selamanya? + + + Delete entries? + Hapus entri? + + + Do you really want to delete %1 entries for good? + Apakah Anda benar-benar ingin menghapus entri %1 untuk selamanya? Move entries to recycle bin? @@ -416,14 +702,6 @@ Apakah Anda tetap ingin menyimpannya? Do you really want to delete the group "%1" for good? Apakah Anda benar-benar ingin menghapus grup "%1" untuk selamanya? - - Current group - Grup saat ini - - - Error - Galat - Unable to calculate master key Tidak bisa mengkalkulasi kunci utama @@ -436,6 +714,66 @@ Apakah Anda tetap ingin menyimpannya? Do you really want to move entry "%1" to the recycle bin? + + Searching... + + + + No current database. + + + + No source database, nothing to do. + + + + Search Results (%1) + + + + No Results + + + + Execute command? + + + + Do you really want to execute the following command?<br><br>%1<br> + + + + Remember my choice + + + + Autoreload Request + + + + The database file has changed. Do you want to load the changes? + + + + Merge Request + + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + + + + Could not open the new database file while attempting to autoreload this database. + + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -475,10 +813,6 @@ Apakah Anda tetap ingin menyimpannya? Edit entry Sunting entri - - Error - Galat - Different passwords supplied. Sandi berbeda. @@ -521,6 +855,22 @@ Apakah Anda tetap ingin menyimpannya? 1 year 1 tahun + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -532,10 +882,6 @@ Apakah Anda tetap ingin menyimpannya? Add Tambah - - Edit - Sunting - Remove Buang @@ -552,6 +898,18 @@ Apakah Anda tetap ingin menyimpannya? Open Buka + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -559,14 +917,6 @@ Apakah Anda tetap ingin menyimpannya? Enable Auto-Type for this entry Aktifkan Ketik-Otomatis untuk entri ini - - Inherit default Auto-Type sequence from the group - Mengikuti urutan Ketik-Otomatis baku grup - - - Use custom Auto-Type sequence: - Gunakan urutan Ketik-Otomatis ubahsuai: - + + @@ -580,12 +930,24 @@ Apakah Anda tetap ingin menyimpannya? Judul jendela: - Use default sequence - Gunakan urutan baku + Inherit default Auto-Type sequence from the &group + + + + &Use custom Auto-Type sequence: + + + + Use default se&quence + + + + Set custo&m sequence: + - Set custom sequence: - Tetapkan urutan ubahsuai: + Window Associations + @@ -625,10 +987,6 @@ Apakah Anda tetap ingin menyimpannya? Repeat: Ulangi: - - Gen. - Gen. - URL: URL: @@ -700,28 +1058,20 @@ Apakah Anda tetap ingin menyimpannya? Cari - Auto-type - Ketik-otomatis + Auto-Type + Ketik-Otomatis - Use default auto-type sequence of parent group - Gunakan urutan ketik-otomatis baku grup induk + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Tetapkan urutan ketik-otomatis baku + Set default Auto-Type se&quence + EditWidgetIcons - - Use default icon - Gunakan ikon baku - - - Use custom icon - Gunakan ikon ubahsuai - Add custom icon Tambah ikon ubahsuai @@ -743,19 +1093,35 @@ Apakah Anda tetap ingin menyimpannya? Pilih gambar - Can't delete icon! - Tidak bisa menghapus ikon! + Error + Galat - - Can't delete icon. Still used by %n item(s). - Tidak bisa menghapus ikon. Masih digunakan oleh %n item. + + Download favicon + - Error + Unable to fetch favicon. + + + + Can't read icon + + + + &Use default icon + + + + Use custo&m icon - Can't read icon: + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? @@ -778,6 +1144,13 @@ Apakah Anda tetap ingin menyimpannya? Uuid: + + Entry + + - Clone + + + EntryAttributesModel @@ -822,6 +1195,11 @@ Apakah Anda tetap ingin menyimpannya? URL URL + + Ref: + Reference abbreviation + + Group @@ -830,16 +1208,74 @@ Apakah Anda tetap ingin menyimpannya? Tong Sampah + + HttpPasswordGeneratorWidget + + Length: + Panjang: + + + Character Types + Tipe Karakter + + + Upper Case Letters + Huruf Besar + + + A-Z + + + + Lower Case Letters + Huruf Kecil + + + a-z + + + + Numbers + Angka + + + 0-9 + + + + Special Characters + Karakter Spesial + + + /*_& ... + + + + Exclude look-alike characters + Kecualikan karakter mirip + + + Ensure that the password contains characters from every group + Pastikan sandi berisi karakter dari setiap grup + + + + KMessageWidget + + &Close + + + + Close message + + + KeePass1OpenWidget Import KeePass1 database Impor basis data KeePass1 - - Error - Galat - Unable to open the database. Tidak bisa membuka basis data. @@ -873,7 +1309,7 @@ Apakah Anda tetap ingin menyimpannya? Wrong key or database file is corrupt. - + Kunci salah atau berkas basis data rusak. @@ -904,6 +1340,10 @@ This is a one-way migration. You won't be able to open the imported databas Anda bisa mengimpornya dengan mengklik Basis Data > 'Impor basis data KeePass 1'. Ini adalah migrasi satu arah. Anda tidak akan bisa lagi membuka basis data yang diimpor dengan versi lama KeePassX 0.4. + + Unable to issue challenge-response. + + Main @@ -912,450 +1352,914 @@ Ini adalah migrasi satu arah. Anda tidak akan bisa lagi membuka basis data yang Galat saat menguji fungsi kriptografi. - KeePassX - Error - KeePassX - Galat + KeePassXC - Error + + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + MainWindow - Database - Basis data + Open database + Buka basis data - Recent databases - Basis data baru-baru ini + Database settings + Pengaturan basis data - Help - Bantuan + Copy username to clipboard + Salin nama pengguna ke papan klip - Entries - Entri + Copy password to clipboard + Salin sandi ke papan klip - Copy attribute to clipboard - Salin atribut ke papan klip + Settings + Pengaturan - Groups - Grup + Show toolbar + Tampilkan bilah alat - View - Lihat + read-only + baca-saja - Quit - Keluar + Toggle window + Jungkit jendela - About - Tentang + KeePass 2 Database + Basis Data KeePass 2 - Open database - Buka basis data - + All files + Semua Berkas + - Save database - Simpan basis data + Save repaired database + Simpan basis data yang sudah diperbaiki - Close database - Tutup basis data + Writing the database failed. + Gagal menyimpan basis data. - New database - Basis data baru + &Recent databases + - Add new entry - Tambah entri baru + He&lp + - View/Edit entry - Lihat/Sunting entri + E&ntries + - Delete entry - Hapus entri + Copy att&ribute to clipboard + - Add new group - Tambah grup baru + &Groups + - Edit group - Sunting grup + &View + - Delete group - Hapus grup + &Quit + - Save database as - Simpan basis data sebagai + &About + - Change master key - Ubah kunci utama + &Open database + - Database settings - Pengaturan basis data + &Save database + - Import KeePass 1 database - Impor basis data KeePass 1 + &Close database + - Clone entry - Duplikat entri + &New database + - Find - Temukan + Merge from KeePassX database + - Copy username to clipboard - Salin nama pengguna ke papan klip + &Add new entry + - Copy password to clipboard - Salin sandi ke papan klip + &View/Edit entry + - Settings - Pengaturan + &Delete entry + - Perform Auto-Type - Lakukan Ketik-Otomatis + &Add new group + - Open URL - Buka URL + &Edit group + - Lock databases - Kunci basis data + &Delete group + - Title - Judul + Sa&ve database as + - URL - URL + Change &master key + - Notes - Catatan + &Database settings + - Show toolbar - Tampilkan bilah alat + &Clone entry + - read-only - baca-saja + Timed one-time password + - Toggle window - Jungkit jendela + Setup TOTP + + + + Copy &TOTP + - Tools - Perkakas + Show TOTP + - Copy username - Salin nama pengguna + &Find + - Copy password - Salin sandi + Copy &username + - Export to CSV file - Ekspor ke berkas CSV + Cop&y password + - Repair database - Perbaiki basis data + &Settings + - KeePass 2 Database - Basis Data KeePass 2 + &Perform Auto-Type + - All files - Semua Berkas + &Open URL + - Save repaired database - Simpan basis data yang sudah diperbaiki + &Lock databases + - Error - Galat + &Title + - Writing the database failed. - Gagal menyimpan basis data. + &URL + - - - PasswordGeneratorWidget - Password: - Sandi: + &Notes + - Length: - Panjang: + &Export to CSV file + - Character Types - Tipe Karakter + Re&pair database + - Upper Case Letters - Huruf Besar + Password Generator + - Lower Case Letters - Huruf Kecil + Clear history + - Numbers - Angka + &Database + - Special Characters - Karakter Spesial + Import + - Exclude look-alike characters - Kecualikan karakter mirip + &Tools + - Ensure that the password contains characters from every group - Pastikan sandi berisi karakter dari setiap grup + Import KeePass 1 database + Impor basis data KeePass 1 - Accept - Terima + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + - QCommandLineParser + OptionDialog - Displays version information. - Tampilkan informasi versi. + Dialog + - Displays this help. - Tampilkan bantuan ini. + General + Umum - Unknown option '%1'. - Opsi tidak diketahui '%1'. + Sh&ow a notification when credentials are requested + - Unknown options: %1. - Opsi tidak diketahui: %1. + Sort matching entries by &username + - Missing value after '%1'. - Nilai hilang setelah '%1'. + Re&move all stored permissions from entries in active database + - Unexpected value after '%1'. - Nilai tidak terduga setelah '%1'. + Advanced + Tingkat Lanjut - [options] - [opsi] + Always allow &access to entries + - Usage: %1 - Penggunaan: %1 + Always allow &updating entries + - Options: - Opsi: + Searc&h in all opened databases for matching entries + - Arguments: - Argumen: + HTTP Port: + - - - QSaveFile - Existing file %1 is not writable - Berkas yang ada %1 tidak bisa ditulis + Default port: 19455 + - Writing canceled by application - Penulisan dibatalkan oleh aplikasi + Re&quest to unlock the database if it is locked + - Partial write. Partition full? - Penulisan parsial. Partisi penuh? + Sort &matching entries by title + - - - QtIOCompressor - Internal zlib error when compressing: - Galat zlib internal ketika memampatkan: + KeePassXC will listen to this port on 127.0.0.1 + - Error writing to underlying device: - Terjadi kesalahan saat menyimpan ke perangkat: + Cannot bind to privileged ports + - Error opening underlying device: - Terjadi kesalahan saat membuka perangkat: + Cannot bind to privileged ports below 1024! +Using default port 19455. + - Error reading data from underlying device: - Terjadi kesalahan saat membaca data dari perangkat: + R&emove all shared encryption keys from active database + - Internal zlib error when decompressing: - Galat zlib internal ketika dekompres: + &Return advanced string fields which start with "KPH: " + - - - QtIOCompressor::open - The gzip format not supported in this version of zlib. - Format gzip tidak didukung pada versi zlib ini. + Automatically creating or updating string fields is not supported. + - Internal zlib error: - Galat zlib internal: + This is required for accessing your databases from ChromeIPass or PassIFox + - - - SearchWidget - Find: - Temukan: + Enable KeePassHTTP server + - Case sensitive - Sensitif besar kecil huruf + Only returns the best matches for a specific URL instead of all entries for the whole domain. + - Current group - Grup saat ini + &Return only best matching entries + - Root group - Grup root + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + - - - SettingsWidget - Application Settings - Pengaturan Aplikasi + &Match URL schemes + - General - Umum + Password Generator + - Security - Keamanan + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + - SettingsWidgetGeneral + PasswordGeneratorWidget - Remember last databases - Ingat basis data terakhir + Password: + Sandi: - Open previous databases on startup - Buka basis data sebelumnya saat mulai + Character Types + Tipe Karakter - Automatically save on exit - Otomatis simpan ketika keluar + Upper Case Letters + Huruf Besar - Automatically save after every change - Otomatis simpan setelah setiap perubahan + Lower Case Letters + Huruf Kecil - Minimize when copying to clipboard - Minimalkan ketika menyalin ke papan klip + Numbers + Angka - Use group icon on entry creation - Gunakan ikon grup pada pembuatan entri + Special Characters + Karakter Spesial - Global Auto-Type shortcut - Pintasan global Ketik-Otomatis + Exclude look-alike characters + Kecualikan karakter mirip - Use entry title to match windows for global auto-type - Gunakan judul entri untuk mencocokkan jendela untuk ketik-otomatis global + Accept + Terima - Language - Bahasa + %p% + - Show a system tray icon - Tampilkan ikon baki sistem + strength + - Hide window to system tray when minimized - Sembunyikan jendela ke baki sistem ketika diminimalkan + entropy + - Remember last key files - Ingat berkas kunci terakhir + &Length: + - Hide window to system tray instead of App Exit + Pick characters from every group - Hide window to system tray on App start + Generate - - - SettingsWidgetSecurity - Clear clipboard after - Kosongkan papan klip setelah + Close + - sec - det + Apply + - Lock databases after inactivity of - Kunci basis data setelah tidak aktif selama + Entropy: %1 bit + - Show passwords in cleartext by default - Tampilkan teks sandi secara baku + Password Quality: %1 + - Always ask before performing auto-type - Selalu tanya sebelum melakukan ketik-otomatis + Poor + + + + Weak + + + + Good + + + + Excellent + + + + Password + Sandi + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + + + + QObject + + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Grup + + + Title + Judul + + + Username + Nama pengguna + + + Password + Sandi + + + URL + URL + + + Notes + Catatan + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + + + + + QtIOCompressor + + Internal zlib error when compressing: + Galat zlib internal ketika memampatkan: + + + Error writing to underlying device: + Terjadi kesalahan saat menyimpan ke perangkat: + + + Error opening underlying device: + Terjadi kesalahan saat membuka perangkat: + + + Error reading data from underlying device: + Terjadi kesalahan saat membaca data dari perangkat: + + + Internal zlib error when decompressing: + Galat zlib internal ketika dekompres: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + Format gzip tidak didukung pada versi zlib ini. + + + Internal zlib error: + Galat zlib internal: + + + + SearchWidget + + Case Sensitive + + + + Search + Cari + + + Clear + + + + Search... + + + + Limit search to selected group + + + + + Service + + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + + + + Do you want to update the information in %1 - %2? + + + + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + + + + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + + + + No shared encryption-keys found in KeePassHttp Settings. + + + + The active database does not contain an entry of KeePassHttp Settings. + + + + Removing stored permissions... + + + + Abort + + + + Successfully removed permissions from %1 %2. + + + + The active database does not contain an entry with permissions. + + + + KeePassXC: New key association request + + + + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + + + + KeePassXC: Overwrite existing key? + + + + KeePassXC: Update Entry + + + + KeePassXC: Database locked! + + + + KeePassXC: Removed keys from database + + + + KeePassXC: No keys found + + + + KeePassXC: Settings not available! + + + + KeePassXC: Removed permissions + + + + KeePassXC: No entry with permissions found! + + + + + SettingsWidget + + Application Settings + Pengaturan Aplikasi + + + General + Umum + + + Security + Keamanan + + + Access error for config file %1 + + + + + SettingsWidgetGeneral + + Remember last databases + Ingat basis data terakhir + + + Automatically save on exit + Otomatis simpan ketika keluar + + + Automatically save after every change + Otomatis simpan setelah setiap perubahan + + + Minimize when copying to clipboard + Minimalkan ketika menyalin ke papan klip + + + Use group icon on entry creation + Gunakan ikon grup pada pembuatan entri + + + Global Auto-Type shortcut + Pintasan global Ketik-Otomatis + + + Language + Bahasa + + + Show a system tray icon + Tampilkan ikon baki sistem + + + Hide window to system tray when minimized + Sembunyikan jendela ke baki sistem ketika diminimalkan + + + Load previous databases on startup + + + + Automatically reload the database when modified externally + + + + Hide window to system tray instead of app exit + + + + Minimize window at application startup + + + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Ketik-Otomatis + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + + + + SettingsWidgetSecurity + + Clear clipboard after + Kosongkan papan klip setelah + + + sec + det + + + Lock databases after inactivity of + Kunci basis data setelah tidak aktif selama + + + Show passwords in cleartext by default + Tampilkan teks sandi secara baku + + + Lock databases after minimizing the window + + + + Don't require password repeat when it is visible + + + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + det + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + @@ -1368,20 +2272,36 @@ Ini adalah migrasi satu arah. Anda tidak akan bisa lagi membuka basis data yang WelcomeWidget - Welcome! - Selamat datang! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + - - - main - KeePassX - cross-platform password manager - KeePassX - pengelola sandi lintas platform + Import from CSV + - filename of the password database to open (*.kdbx) - nama berkas dari basis data sandi untuk dibuka (*.kdbx) + Recent databases + Basis data baru-baru ini + + + main path to a custom config file jalur ke berkas konfig ubahsuai @@ -1390,5 +2310,81 @@ Ini adalah migrasi satu arah. Anda tidak akan bisa lagi membuka basis data yang key file of the database berkas kunci dari basis data + + KeePassXC - cross-platform password manager + + + + read password of the database from stdin + + + + filenames of the password databases to open (*.kdbx) + + + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_it.ts b/share/translations/keepassx_it.ts index 7919428381..f5f7fede3a 100644 --- a/share/translations/keepassx_it.ts +++ b/share/translations/keepassx_it.ts @@ -2,26 +2,106 @@ AboutDialog - Revision - Revisione + About KeePassXC + A proposito di KeePassXC - Using: - Utilizzare: + About + Informazioni - About KeePassXC - A proposito di KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + - Extensions: + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 - Estensioni: - + - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC è distribuito sotto i termini della licenza GNU General Public License (GPL) versione 2 o (come opzione) versione 3. + Revision: %1 + + + + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -120,10 +200,6 @@ Perfavore seleziona se vuoi consentire l'accesso. Create Key File... Crea file chiave... - - Error - Errore - Unable to create Key File : Impossibile creare file chiave: @@ -132,10 +208,6 @@ Perfavore seleziona se vuoi consentire l'accesso. Select a key file Seleziona il file chiave - - Question - Domanda - Do you really want to use an empty string as password? Vuoi veramente usare una stringa vuota come password? @@ -144,10 +216,6 @@ Perfavore seleziona se vuoi consentire l'accesso. Different passwords supplied. Sono state fornite password differenti. - - Failed to set key file - Fallimento a impostare il file chiave - Failed to set %1 as the Key file: %2 @@ -158,6 +226,163 @@ Perfavore seleziona se vuoi consentire l'accesso. &Key file &File chiave + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Errore + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Errore + + + Unable to calculate master key + Impossibile calcolare la chiave principale + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -177,10 +402,6 @@ Perfavore seleziona se vuoi consentire l'accesso. Browse Sfoglia - - Error - Errore - Unable to open the database. Impossibile aprire il database. @@ -201,6 +422,14 @@ Perfavore seleziona se vuoi consentire l'accesso. Select key file Seleziona file chiave + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -277,6 +506,18 @@ Adesso puoi salvarlo. Use recycle bin Usa il cestino + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -296,10 +537,6 @@ Adesso puoi salvarlo. Open database Apri database - - Warning - Attenzione - File not found! File non trovato! @@ -330,10 +567,6 @@ Save changes? "%1" è stata modificato. Salvare le modifiche? - - Error - Errore - Writing the database failed. Scrittura del database non riuscita. @@ -425,6 +658,14 @@ Vuoi aprilo comunque? Open read-only Aperto in sola lettura + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -464,10 +705,6 @@ Vuoi aprilo comunque? Do you really want to delete the group "%1" for good? Vuoi veramente eliminare il gruppo "%1"? - - Error - Errore - Unable to calculate master key Impossibile calcolare la chiave principale @@ -528,14 +765,18 @@ Vuoi aprilo comunque? The database file has changed and you have unsaved changes.Do you want to merge your changes? Il file del database è cambiato e ci sono delle modifiche non salvate. Vuoi unire i tuoi cambiamenti. - - Autoreload Failed - Aggiornamento fallito - Could not open the new database file while attempting to autoreload this database. Non è stato possibile aprire il nuovo database mentre si tentava il caricamento automatico di questo database. + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -575,10 +816,6 @@ Vuoi aprilo comunque? Edit entry Modificare voce - - Error - Errore - Different passwords supplied. Sono state immesse password differenti. @@ -621,6 +858,22 @@ Vuoi aprilo comunque? 1 year Un anno + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -632,10 +885,6 @@ Vuoi aprilo comunque? Add Aggiungi - - Edit - Modifica - Remove Rimuovi @@ -652,6 +901,18 @@ Vuoi aprilo comunque? Open Apri + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -687,6 +948,10 @@ Vuoi aprilo comunque? Set custo&m sequence: Imposta sequenza &personalizzata: + + Window Associations + + EditEntryWidgetHistory @@ -796,16 +1061,16 @@ Vuoi aprilo comunque? Cerca - Auto-type + Auto-Type Auto-Type - Use default auto-type sequence of parent group - Usa la sequenza auto-type del gruppo genitore + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Imposta la sequenza auto-type + Set default Auto-Type se&quence + @@ -830,10 +1095,6 @@ Vuoi aprilo comunque? Select Image Seleziona immagine - - Can't delete icon! - Non puoi eliminare l'icona! - Error Errore @@ -850,10 +1111,6 @@ Vuoi aprilo comunque? Can't read icon Impossibile leggere l'icona - - Can't delete icon. Still used by %1 items. - Non puoi eliminare l'icona. Utilizzata da %1 voce. - &Use default icon &Usa icona predefinita @@ -862,6 +1119,14 @@ Vuoi aprilo comunque? Use custo&m icon Usa &icona personalizzata + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -933,6 +1198,11 @@ Vuoi aprilo comunque? URL URL + + Ref: + Reference abbreviation + + Group @@ -991,9 +1261,16 @@ Vuoi aprilo comunque? Ensure that the password contains characters from every group Verifica che la password contenga caratteri di ogni gruppo + + + KMessageWidget - Accept - Accetta + &Close + + + + Close message + @@ -1002,10 +1279,6 @@ Vuoi aprilo comunque? Import KeePass1 database Importa database KeePass1 - - Error - Errore - Unable to open the database. Impossibile aprire il database. @@ -1070,6 +1343,10 @@ This is a one-way migration. You won't be able to open the imported databas Puoi importarlo facendo clic su Database > 'Importa database KeePass 1'. Questa è una migrazione in una sola direzione. Non potrai aprire il database importato con la vecchia versione 0.4 di KeePassX. + + Unable to issue challenge-response. + + Main @@ -1081,13 +1358,17 @@ Questa è una migrazione in una sola direzione. Non potrai aprire il database im KeePassXC - Error KeePassXC - Errore + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - Database - Open database Apri database @@ -1120,10 +1401,6 @@ Questa è una migrazione in una sola direzione. Non potrai aprire il database im Toggle window Cambia finestra - - Tools - Strumenti - KeePass 2 Database Database KeePass 2 @@ -1136,10 +1413,6 @@ Questa è una migrazione in una sola direzione. Non potrai aprire il database im Save repaired database Salva il database riparato - - Error - Errore - Writing the database failed. Scrittura del database non riuscita. @@ -1232,14 +1505,26 @@ Questa è una migrazione in una sola direzione. Non potrai aprire il database im &Database settings Impostazioni &Database - - &Import KeePass 1 database - &Importa database KeePass 1 - &Clone entry &Clona elemento + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find &Trova @@ -1292,6 +1577,46 @@ Questa è una migrazione in una sola direzione. Non potrai aprire il database im Password Generator Generatore Password + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Importa database KeePass 1 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1307,12 +1632,6 @@ Questa è una migrazione in una sola direzione. Non potrai aprire il database im Sh&ow a notification when credentials are requested M&ostra una notifica quando sono richeste le credenziali - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - &Schema URL -Solo le voci con lo stesso schema (http://, https://, ftp://, ...) sono selezionate - Sort matching entries by &username Ordina le voci trovate per &nome utente @@ -1321,10 +1640,6 @@ Solo le voci con lo stesso schema (http://, https://, ftp://, ...) sono selezion Re&move all stored permissions from entries in active database R&imuovi tutti i permessi presenti dalle voci nel database attivo - - Password generator - Generatore di password - Advanced Avanzate @@ -1341,10 +1656,6 @@ Solo le voci con lo stesso schema (http://, https://, ftp://, ...) sono selezion Searc&h in all opened databases for matching entries Cerc&a in tutti i database aperti per la ricerca delle voci - - Only the selected database has to be connected with a client! - Solo i database selezionati sono connessi con il client! - HTTP Port: Porta HTTP: @@ -1361,12 +1672,6 @@ Solo le voci con lo stesso schema (http://, https://, ftp://, ...) sono selezion Sort &matching entries by title Ordina le voci per &titolo - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - Abilita il protocollo KeePassXC HTTP -Richiesto per accedere al tuo database da ChromeIPass o PassIFox - KeePassXC will listen to this port on 127.0.0.1 KeePassXC rimarrà in ascolto su questa porta su 127.0.0.1 @@ -1380,20 +1685,10 @@ Richiesto per accedere al tuo database da ChromeIPass o PassIFox Using default port 19455. Non è possibile collegarsi a porte sotto la 1024! Utilizza la porta predefinita 19455. - - - &Return only best matching entries for a URL instead -of all entries for the whole domain - &Ritorna solo solo le voci più idonee alla URL invece -di tutte le voci del dominio R&emove all shared encryption keys from active database - R&imuovi tutte le chiavi di condivisione criptate dal database attivo - - - The following options can be dangerous. Change them only if you know what you are doing. - Le opzioni seguenti sono pericolose. Cambia solo se sai cosa stai facendo. + R&imuovi tutte le chiavi condivise di cifratura dal database attivo &Return advanced string fields which start with "KPH: " @@ -1401,7 +1696,44 @@ di tutte le voci del dominio Automatically creating or updating string fields is not supported. - Crea automaticamente o aggiorna i campi stringa non supportati. + La creazione o l'aggiornamento automatico dei campi stringa non è supportato. + + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Generatore Password + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + @@ -1494,12 +1826,101 @@ di tutte le voci del dominio Excellent Eccellente + + Password + Password + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Gruppo + + + Title + Titolo + + + Username + Nome utente + + + Password + Password + + + URL + URL + + + Notes + Note + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1546,14 +1967,18 @@ di tutte le voci del dominio Search Cerca - - Find - Trova - Clear Pulisci + + Search... + + + + Limit search to selected group + + Service @@ -1660,6 +2085,10 @@ imposta un nome unico per identificarla ed accettarla. Security Sicurezza + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1687,10 +2116,6 @@ imposta un nome unico per identificarla ed accettarla. Global Auto-Type shortcut Scorciatoia Auto-Type globale - - Use entry title to match windows for global auto-type - Usa il titolo delle voci per trovare le finestre per l'auto-type globale - Language Lingua @@ -1703,10 +2128,6 @@ imposta un nome unico per identificarla ed accettarla. Hide window to system tray when minimized Nascondi la finestra nell'area di notifica del sistema quando viene minimizzata - - Remember last key files - Ricorda l'ultimo file chiave - Load previous databases on startup Carica i database precedenti all'avvio @@ -1723,6 +2144,30 @@ imposta un nome unico per identificarla ed accettarla. Minimize window at application startup Minimizza la finestra all'avvio della applicazione + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Auto-Type + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1742,10 +2187,6 @@ imposta un nome unico per identificarla ed accettarla. Show passwords in cleartext by default Mostra la password in chiaro in maniera predefinita - - Always ask before performing auto-type - Chiedi sempre di di effettuare auto-type - Lock databases after minimizing the window Blocca il database dopo la minimizzazione della finestra @@ -1754,6 +2195,80 @@ imposta un nome unico per identificarla ed accettarla. Don't require password repeat when it is visible Non richiedere di ripetere la password quando è visibile + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + sec + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1765,8 +2280,32 @@ imposta un nome unico per identificarla ed accettarla. WelcomeWidget - Welcome! - Benvenuto! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Database recenti @@ -1791,5 +2330,69 @@ imposta un nome unico per identificarla ed accettarla. filenames of the password databases to open (*.kdbx) i nomi dei file dei database delle password da aprire (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_ja.ts b/share/translations/keepassx_ja.ts index 182ed99480..c134fb9238 100644 --- a/share/translations/keepassx_ja.ts +++ b/share/translations/keepassx_ja.ts @@ -1,33 +1,143 @@ - + AboutDialog - About KeePassX - KeePassX について + About KeePassXC + + + + About + このソフトウェアについて + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + - KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXはGNU General Public License (GPL) version 2 または version 3 (どちらかを選択)の条件で配布されます。 + Version %1 + + + + + Revision: %1 + + + + Libraries: + - Revision - リビジョン + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + - Using: - 利用中: + Enabled extensions: + - AutoType + AccessControlDialog + + Remember this decision + + + + Allow + + + + Deny + + - Auto-Type - KeePassX - 自動入力 - KeePassX + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + + + + KeePassXC HTTP Confirm Access + + + + AutoType Couldn't find an entry that matches the window title: ウィンドウタイトルに一致するエントリーが見つかりませんでした: + + Auto-Type - KeePassXC + + AutoTypeAssociationsModel @@ -46,14 +156,14 @@ AutoTypeSelectDialog - - Auto-Type - KeePassX - 自動入力 - KeePassX - Select entry to Auto-Type: 自動入力するエントリーを選択してください: + + Auto-Type - KeePassXC + + ChangeMasterKeyWidget @@ -69,10 +179,6 @@ Repeat password: パスワードを再入力: - - Key file - キーファイル - Browse 参照 @@ -93,10 +199,6 @@ Create Key File... キーファイルを作成... - - Error - エラー - Unable to create Key File : キーファイルを作成できませんでした: @@ -105,10 +207,6 @@ Select a key file キーファイルを選択 - - Question - 質問 - Do you really want to use an empty string as password? 本当に空のパスワード文字列で使いますか? @@ -117,16 +215,173 @@ Different passwords supplied. 異なるパスワードが入力されました。 - - Failed to set key file - キーファイルのセットに失敗しました - Failed to set %1 as the Key file: %2 %1 をキーファイルとしてセットできませんでした: %2 + + &Key file + + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + エラー + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + エラー + + + Unable to calculate master key + マスターキーを計算できません + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -146,10 +401,6 @@ Browse 参照 - - Error - エラー - Unable to open the database. データベースを開けませんでした。 @@ -170,6 +421,14 @@ Select key file キーファイルを選択 + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -226,10 +485,6 @@ You can now save it. Default username: ユーザー名の初期値: - - Use recycle bin: - ゴミ箱を使う: - MiB MiB @@ -246,6 +501,22 @@ You can now save it. Max. history size: 最大履歴データサイズ: + + Use recycle bin + + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -265,10 +536,6 @@ You can now save it. Open database データベースを開く - - Warning - 警告 - File not found! ファイルが見つかりません! @@ -299,10 +566,6 @@ Save changes? "%1" は編集されています。 変更を保存しますか? - - Error - エラー - Writing the database failed. データベースが保存できませんでした。 @@ -319,12 +582,6 @@ Save changes? locked ロック済み - - The database you are trying to open is locked by another instance of KeePassX. -Do you want to open it anyway? Alternatively the database is opened read-only. - 開こうとしたデータベースは別のKeePassXプログラムからロックされています。 -とにかく開きますか? データベースを読み取り専用で開きます。 - Lock database データベースをロックする @@ -368,37 +625,66 @@ Discard changes and close anyway? CSVファイルの書き込みに失敗しました。 - The database you are trying to save as is locked by another instance of KeePassX. -Do you want to save it anyway? - 保存しようとしたデータベースは別のKeePassXプログラムからロックされています。 -とにかく保存しますか? + Unable to open the database. + データベースを開けませんでした。 - Unable to open the database. + Merge database - - - DatabaseWidget - Change master key - マスターキーを変更する + The database you are trying to save as is locked by another instance of KeePassXC. +Do you want to save it anyway? + - Delete entry? - エントリーを削除してよいですか? + Passwords + - Do you really want to delete the entry "%1" for good? - 本当にエントリー "%1" を永遠に消去しますか? + Database already opened + - Delete entries? - 複数のエントリーを削除してよいですか? + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + - Do you really want to delete %1 entries for good? - 本当に %1 個のエントリーを永遠に消去しますか? + Open read-only + + + + File opened in read only mode. + + + + Open CSV file + + + + + DatabaseWidget + + Change master key + マスターキーを変更する + + + Delete entry? + エントリーを削除してよいですか? + + + Do you really want to delete the entry "%1" for good? + 本当にエントリー "%1" を永遠に消去しますか? + + + Delete entries? + 複数のエントリーを削除してよいですか? + + + Do you really want to delete %1 entries for good? + 本当に %1 個のエントリーを永遠に消去しますか? Move entries to recycle bin? @@ -416,14 +702,6 @@ Do you want to save it anyway? Do you really want to delete the group "%1" for good? グループ "%1" を完全に削除しますがよろしいですか? - - Current group - 現在のグループ - - - Error - エラー - Unable to calculate master key マスターキーを計算できませんでした @@ -436,6 +714,66 @@ Do you want to save it anyway? Do you really want to move entry "%1" to the recycle bin? + + Searching... + + + + No current database. + + + + No source database, nothing to do. + + + + Search Results (%1) + + + + No Results + + + + Execute command? + + + + Do you really want to execute the following command?<br><br>%1<br> + + + + Remember my choice + + + + Autoreload Request + + + + The database file has changed. Do you want to load the changes? + + + + Merge Request + + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + + + + Could not open the new database file while attempting to autoreload this database. + + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -475,10 +813,6 @@ Do you want to save it anyway? Edit entry エントリーを編集 - - Error - エラー - Different passwords supplied. 異なるパスワードが入力されました。 @@ -521,6 +855,22 @@ Do you want to save it anyway? 1 year 1年 + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -532,10 +882,6 @@ Do you want to save it anyway? Add 追加 - - Edit - 編集 - Remove 削除 @@ -552,6 +898,18 @@ Do you want to save it anyway? Open 開く + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -559,14 +917,6 @@ Do you want to save it anyway? Enable Auto-Type for this entry エントリーの自動入力を有効にする - - Inherit default Auto-Type sequence from the group - 自動入力手順をグループから引き継ぐ - - - Use custom Auto-Type sequence: - カスタムの自動入力手順を使う: - + + @@ -580,12 +930,24 @@ Do you want to save it anyway? ウインドウタイトル: - Use default sequence - デフォルトの手順を使う + Inherit default Auto-Type sequence from the &group + + + + &Use custom Auto-Type sequence: + + + + Use default se&quence + + + + Set custo&m sequence: + - Set custom sequence: - カスタムの手順を入力: + Window Associations + @@ -625,10 +987,6 @@ Do you want to save it anyway? Repeat: パスワード確認: - - Gen. - 生成 - URL: URL: @@ -700,28 +1058,20 @@ Do you want to save it anyway? 検索 - Auto-type + Auto-Type 自動入力 - Use default auto-type sequence of parent group - 親グループのデフォルトの自動入力手順を使う + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - デフォルトの自動入力手順をセット + Set default Auto-Type se&quence + EditWidgetIcons - - Use default icon - デフォルトアイコンから選択 - - - Use custom icon - カスタムアイコンから選択 - Add custom icon カスタムアイコンを追加 @@ -743,19 +1093,35 @@ Do you want to save it anyway? 画像を選択 - Can't delete icon! - アイコンを削除できません! + Error + エラー - - Can't delete icon. Still used by %n item(s). - %n個のアイテムから使われているので、アイコンを削除できません。 + + Download favicon + - Error + Unable to fetch favicon. + + + + Can't read icon + + + + &Use default icon - Can't read icon: + Use custo&m icon + + + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? @@ -778,6 +1144,13 @@ Do you want to save it anyway? UUID: + + Entry + + - Clone + + + EntryAttributesModel @@ -822,6 +1195,11 @@ Do you want to save it anyway? URL URL + + Ref: + Reference abbreviation + + Group @@ -830,16 +1208,74 @@ Do you want to save it anyway? ゴミ箱 + + HttpPasswordGeneratorWidget + + Length: + 文字数: + + + Character Types + 文字種 + + + Upper Case Letters + 大文字 + + + A-Z + + + + Lower Case Letters + 小文字 + + + a-z + + + + Numbers + 数字 + + + 0-9 + + + + Special Characters + 特殊な文字 + + + /*_& ... + + + + Exclude look-alike characters + よく似た文字を除外する + + + Ensure that the password contains characters from every group + 使用する文字種の文字が必ず含まれるようにする + + + + KMessageWidget + + &Close + + + + Close message + + + KeePass1OpenWidget Import KeePass1 database KeePass1 データベースをインポートする - - Error - エラー - Unable to open the database. データベースを開けませんでした。 @@ -873,7 +1309,7 @@ Do you want to save it anyway? Wrong key or database file is corrupt. - + キーが間違っているかデータベースファイルが破損しています。 @@ -904,6 +1340,10 @@ This is a one-way migration. You won't be able to open the imported databas データベース > 'KeePass 1 データベースをインポート' をクリックすることでインポートできます。 これは一方向の移行操作であり、インポートされたデータベースは古い KeePassX 0.4 のバージョンでは開くことはできません。 + + Unable to issue challenge-response. + + Main @@ -912,453 +1352,917 @@ This is a one-way migration. You won't be able to open the imported databas 暗号化機能のテスト中に致命的なエラーが発生しました。 - KeePassX - Error - KeePassX - エラー + KeePassXC - Error + + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + MainWindow - Database - データベース + Open database + データベースを開く - Recent databases - 最近使ったデータベース + Database settings + データベースの設定 - Help - ヘルプ + Copy username to clipboard + ユーザー名をコピー - Entries - エントリー + Copy password to clipboard + パスワードをコピー - Copy attribute to clipboard - クリップボードにコピーする + Settings + 設定 - Groups - グループ + Show toolbar + ツールバーを表示 - View - 表示 + read-only + 読み取り専用 - Quit - 終了 + Toggle window + ウィンドウ切替 - About - このソフトウェアについて + KeePass 2 Database + KeePass 2 データベース - Open database - データベースを開く - + All files + 全てのファイル + - Save database - データベースを保存 + Save repaired database + 修復されたデータベースを保存する - Close database - データベースを閉じる + Writing the database failed. + データベースの書き込みに失敗しました。 - New database - 新規データベース + &Recent databases + - Add new entry - 新規エントリーの追加 + He&lp + - View/Edit entry - エントリーの表示/編集 + E&ntries + - Delete entry - エントリーの削除 + Copy att&ribute to clipboard + - Add new group - 新規グループの追加 + &Groups + - Edit group - グループの編集 + &View + - Delete group - グループの削除 + &Quit + - Save database as - ファイル名をつけてデータベースを保存 + &About + - Change master key - マスターキーを変更 + &Open database + - Database settings - データベースの設定 + &Save database + - Import KeePass 1 database - KeePass1 データベースをインポートする + &Close database + - Clone entry - エントリーの複製 + &New database + - Find - 検索 + Merge from KeePassX database + - Copy username to clipboard - ユーザー名をコピー + &Add new entry + - Copy password to clipboard - パスワードをコピー + &View/Edit entry + - Settings - 設定 + &Delete entry + - Perform Auto-Type - 自動入力の実行 + &Add new group + - Open URL - URLを開く + &Edit group + - Lock databases - データベースをロック + &Delete group + - Title - タイトル + Sa&ve database as + - URL - URL + Change &master key + - Notes - メモ + &Database settings + - Show toolbar - ツールバーを表示 + &Clone entry + - read-only - 読み取り専用 + Timed one-time password + - Toggle window - ウィンドウ切替 + Setup TOTP + - Tools - ツール + Copy &TOTP + - Copy username - ユーザ名をコピー + Show TOTP + - Copy password - パスワードをコピー + &Find + - Export to CSV file - CSVファイルへエクスポート + Copy &username + - Repair database - データベースを修復する + Cop&y password + - KeePass 2 Database - KeePass 2 データベース + &Settings + - All files - 全てのファイル + &Perform Auto-Type + - Save repaired database - 修復されたデータベースを保存する + &Open URL + - Error - エラー + &Lock databases + - Writing the database failed. - データベースの書き込みに失敗しました。 + &Title + - - - PasswordGeneratorWidget - Password: - パスワード: + &URL + - Length: - 文字数: + &Notes + - Character Types - 文字種 + &Export to CSV file + - Upper Case Letters - 大文字 + Re&pair database + - Lower Case Letters - 小文字 + Password Generator + - Numbers - 数字 + Clear history + - Special Characters - 特殊な文字 + &Database + - Exclude look-alike characters - よく似た文字を除外する + Import + - Ensure that the password contains characters from every group - 使用する文字種の文字が必ず含まれるようにする + &Tools + - Accept - 適用 + Import KeePass 1 database + KeePass1 データベースをインポートする + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + - QCommandLineParser + OptionDialog - Displays version information. - バージョン情報を表示する。 + Dialog + - Displays this help. - このヘルプを表示する。 + General + 一般 - Unknown option '%1'. - '%1' は不明なオプションです。 + Sh&ow a notification when credentials are requested + - Unknown options: %1. - %1 は不明なオプションです。 + Sort matching entries by &username + - Missing value after '%1'. - '%1' の後に値が見つかりません。 + Re&move all stored permissions from entries in active database + - Unexpected value after '%1'. - '%1' の後に予期しない値があります。 + Advanced + 詳細設定 - [options] - [オプション] + Always allow &access to entries + - Usage: %1 - 使い方: %1 + Always allow &updating entries + - Options: - オプション: + Searc&h in all opened databases for matching entries + - Arguments: - 引数: + HTTP Port: + - - - QSaveFile - Existing file %1 is not writable - 存在するファイル %1 は書き込みできません + Default port: 19455 + - Writing canceled by application - アプリケーションにより書き込みがキャンセルされました + Re&quest to unlock the database if it is locked + - Partial write. Partition full? - 一部しか書き込めませんでした。パーティションがいっぱいかも? + Sort &matching entries by title + - - - QtIOCompressor - Internal zlib error when compressing: - 圧縮時に内部zlibエラーが発生しました: + KeePassXC will listen to this port on 127.0.0.1 + - Error writing to underlying device: - 基本デバイスへの書き込み時にエラーが発生しました: + Cannot bind to privileged ports + - Error opening underlying device: - 基本デバイスを開く時にエラーが発生しました: + Cannot bind to privileged ports below 1024! +Using default port 19455. + - Error reading data from underlying device: - 基本デバイスから読み込み時にエラーが発生しました: + R&emove all shared encryption keys from active database + - Internal zlib error when decompressing: - 解凍時に内部zlibエラーが発生しました: + &Return advanced string fields which start with "KPH: " + - - - QtIOCompressor::open - The gzip format not supported in this version of zlib. - zlibの現在のバージョンがgzip形式をサポートしていません。 + Automatically creating or updating string fields is not supported. + - Internal zlib error: - 内部のzlibエラー: + This is required for accessing your databases from ChromeIPass or PassIFox + - - - SearchWidget - Find: - 検索: + Enable KeePassHTTP server + - Case sensitive - 大文字と小文字を区別 + Only returns the best matches for a specific URL instead of all entries for the whole domain. + - Current group - 現在のグループ + &Return only best matching entries + - Root group - 全て + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + - - - SettingsWidget - Application Settings - アプリケーション設定 + &Match URL schemes + - General - 一般 + Password Generator + - Security - セキュリティ + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + - SettingsWidgetGeneral + PasswordGeneratorWidget - Remember last databases - 最近使用したデータベースを記憶する + Password: + パスワード: - Open previous databases on startup - KeePassX起動時に前回使用したデータベースを開く + Character Types + 文字種 - Automatically save on exit - 終了時に自動的に保存する + Upper Case Letters + 大文字 - Automatically save after every change - 変更するごとに自動的に保存 + Lower Case Letters + 小文字 - Minimize when copying to clipboard - クリップボードにコピーしたら最小化 + Numbers + 数字 - Use group icon on entry creation - エントリーを作成したらグループのアイコンを使う + Special Characters + 特殊な文字 - Global Auto-Type shortcut - 全体の自動入力ショートカット + Exclude look-alike characters + よく似た文字を除外する - Use entry title to match windows for global auto-type - グローバル自動入力の際に、エントリーのタイトルとウィンドウのマッチングを行う + Accept + 適用 - Language - 言語 + %p% + - Show a system tray icon - システムトレイアイコンを表示 + strength + - Hide window to system tray when minimized - 最小化された際にシステムトレイへ格納する + entropy + - Remember last key files - 最後のキーファイルを記憶 + &Length: + - Hide window to system tray instead of App Exit + Pick characters from every group - Hide window to system tray on App start + Generate - - - SettingsWidgetSecurity - Clear clipboard after - 次の時間が過ぎたらクリップボードを消去 + Close + - sec - + Apply + - Lock databases after inactivity of - 未操作の時間が続いたらデータベースをロック + Entropy: %1 bit + - Show passwords in cleartext by default - パスワードはデフォルトで平文表示にする + Password Quality: %1 + - Always ask before performing auto-type - 自動入力の実行前に常に確認する + Poor + - - + + Weak + + + + Good + + + + Excellent + + + + Password + パスワード + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + + + + QObject + + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + グループ + + + Title + タイトル + + + Username + ユーザー名 + + + Password + パスワード + + + URL + URL + + + Notes + メモ + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + + + + + QtIOCompressor + + Internal zlib error when compressing: + 圧縮時に内部zlibエラーが発生しました: + + + Error writing to underlying device: + 基本デバイスへの書き込み時にエラーが発生しました: + + + Error opening underlying device: + 基本デバイスを開く時にエラーが発生しました: + + + Error reading data from underlying device: + 基本デバイスから読み込み時にエラーが発生しました: + + + Internal zlib error when decompressing: + 解凍時に内部zlibエラーが発生しました: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + zlibの現在のバージョンがgzip形式をサポートしていません。 + + + Internal zlib error: + 内部のzlibエラー: + + + + SearchWidget + + Case Sensitive + + + + Search + 検索 + + + Clear + + + + Search... + + + + Limit search to selected group + + + + + Service + + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + + + + Do you want to update the information in %1 - %2? + + + + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + + + + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + + + + No shared encryption-keys found in KeePassHttp Settings. + + + + The active database does not contain an entry of KeePassHttp Settings. + + + + Removing stored permissions... + + + + Abort + + + + Successfully removed permissions from %1 %2. + + + + The active database does not contain an entry with permissions. + + + + KeePassXC: New key association request + + + + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + + + + KeePassXC: Overwrite existing key? + + + + KeePassXC: Update Entry + + + + KeePassXC: Database locked! + + + + KeePassXC: Removed keys from database + + + + KeePassXC: No keys found + + + + KeePassXC: Settings not available! + + + + KeePassXC: Removed permissions + + + + KeePassXC: No entry with permissions found! + + + + + SettingsWidget + + Application Settings + アプリケーション設定 + + + General + 一般 + + + Security + セキュリティ + + + Access error for config file %1 + + + + + SettingsWidgetGeneral + + Remember last databases + 最近使用したデータベースを記憶する + + + Automatically save on exit + 終了時に自動的に保存する + + + Automatically save after every change + 変更するごとに自動的に保存 + + + Minimize when copying to clipboard + クリップボードにコピーしたら最小化 + + + Use group icon on entry creation + エントリーを作成したらグループのアイコンを使う + + + Global Auto-Type shortcut + 全体の自動入力ショートカット + + + Language + 言語 + + + Show a system tray icon + システムトレイアイコンを表示 + + + Hide window to system tray when minimized + 最小化された際にシステムトレイへ格納する + + + Load previous databases on startup + + + + Automatically reload the database when modified externally + + + + Hide window to system tray instead of app exit + + + + Minimize window at application startup + + + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + 自動入力 + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + + + + SettingsWidgetSecurity + + Clear clipboard after + 次の時間が過ぎたらクリップボードを消去 + + + sec + + + + Lock databases after inactivity of + 未操作の時間が続いたらデータベースをロック + + + Show passwords in cleartext by default + パスワードはデフォルトで平文表示にする + + + Lock databases after minimizing the window + + + + Don't require password repeat when it is visible + + + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + + + UnlockDatabaseWidget Unlock database @@ -1368,20 +2272,36 @@ This is a one-way migration. You won't be able to open the imported databas WelcomeWidget - Welcome! - ようこそ! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + - - - main - KeePassX - cross-platform password manager - KeePassX - クロスプラットフォーム パスワードマネージャー + Import from CSV + - filename of the password database to open (*.kdbx) - 開くパスワードデータベースのファイル名 (*.kdbx) + Recent databases + 最近使ったデータベース + + + main path to a custom config file カスタム設定ファイルへのパス @@ -1390,5 +2310,81 @@ This is a one-way migration. You won't be able to open the imported databas key file of the database データベースのキーファイル + + KeePassXC - cross-platform password manager + + + + read password of the database from stdin + + + + filenames of the password databases to open (*.kdbx) + + + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_kk.ts b/share/translations/keepassx_kk.ts new file mode 100644 index 0000000000..0ceda89719 --- /dev/null +++ b/share/translations/keepassx_kk.ts @@ -0,0 +1,2390 @@ + + + AboutDialog + + About KeePassXC + + + + About + + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 + + + + + Revision: %1 + + + + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + + + + + AccessControlDialog + + Remember this decision + + + + Allow + + + + Deny + + + + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + + + + KeePassXC HTTP Confirm Access + + + + + AutoType + + Couldn't find an entry that matches the window title: + Терезе атауына сай келетін жазбаны табу мүмкін емес: + + + Auto-Type - KeePassXC + + + + + AutoTypeAssociationsModel + + Window + Терезе + + + Sequence + Тізбек + + + Default sequence + Үнсіз келісім тізбегі + + + + AutoTypeSelectDialog + + Select entry to Auto-Type: + Автотеру үшін жазбаны таңдаңыз: + + + Auto-Type - KeePassXC + + + + + ChangeMasterKeyWidget + + Password + Пароль + + + Enter password: + Парольді енгізіңіз: + + + Repeat password: + Парольді қайталаңыз: + + + Browse + Шолу + + + Create + Жасау + + + Key files + Кілттер файлдары + + + All files + Барлық файлдар + + + Create Key File... + Кілттер файлын жасау... + + + Unable to create Key File : + Кілттер файлын жасау мүмкін емес: + + + Select a key file + Кілттер файлын таңдаңыз + + + Do you really want to use an empty string as password? + Пароль ретінде бос жолды қолдануды шынымен қалайсыз ба? + + + Different passwords supplied. + Әр түрлі парольдер көрсетілді. + + + Failed to set %1 as the Key file: +%2 + %1 файлын кілттер файлы ретінде орнату қатесі: +%2 + + + &Key file + + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Қате + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Қате + + + Unable to calculate master key + Басты парольді есептеу мүмкін емес + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + + + + DatabaseOpenWidget + + Enter master key + Басты парольді енгізіңіз: + + + Key File: + Кілттер файлы: + + + Password: + Пароль: + + + Browse + Шолу + + + Unable to open the database. + Дерекқорды ашу мүмкін емес. + + + Can't open key file + Кілттер файлын ашу мүмкін емес + + + All files + Барлық файлдар + + + Key files + Кілттер файлдары + + + Select key file + Кілттер файлын таңдаңыз + + + Refresh + + + + Challenge Response: + + + + + DatabaseRepairWidget + + Repair database + Дерекқорды жөндеу + + + Error + Қате + + + Can't open key file + Кілттер файлын ашу мүмкін емес + + + Database opened fine. Nothing to do. + Дерекқор сәтті ашылды. Басқа орындайтын әрекеттер жоқ. + + + Unable to open the database. + Дерекқорды ашу мүмкін емес. + + + Success + Сәтті + + + The database has been successfully repaired +You can now save it. + Дерекқор қалпына сәтті келтірілді. +Енді оны сақтауыңызға болады. + + + Unable to repair the database. + Дерекқорды жөндеу мүмкін емес. + + + + DatabaseSettingsWidget + + Database name: + Дерекқор аты: + + + Database description: + Дерекқор сипаттамасы: + + + Transform rounds: + Түрлендірулер саны: + + + Default username: + Үнсіз келісім пайдаланушы аты: + + + MiB + МиБ + + + Benchmark + Сынау + + + Max. history items: + Макс. тарих саны: + + + Max. history size: + Макс. тарих өлшемі: + + + Use recycle bin + + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + + + + DatabaseTabWidget + + Root + Түбір + + + KeePass 2 Database + KeePass 2 дерекқоры + + + All files + Барлық файлдар + + + Open database + Дерекқорды ашу + + + File not found! + Файл табылмады! + + + Open KeePass 1 database + KeePass 1 дерекқорын ашу + + + KeePass 1 database + KeePass 1 дерекқоры + + + All files (*) + Барлық файлдар (*) + + + Close? + Жабу керек пе? + + + Save changes? + Өзгерістерді сақтау керек пе? + + + "%1" was modified. +Save changes? + "%1" өзгертілген. +Өзгерістерді сақтау керек пе? + + + Writing the database failed. + Дерекқорға жазу сәтсіз аяқталды. + + + Save database as + Дерекқорды қалайша сақтау + + + New database + Жаңа дерекқор + + + locked + блокталған + + + Lock database + Дерекқорды блоктау + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Дерекқорды блоктау мүмкін емес, өйткені сіз оны қазір түзетудесіз. +Өзгерістерді аяқтау үшін бас тартуды басыңыз, немесе оларды елемеңіз. + + + This database has never been saved. +You can save the database or stop locking it. + Дерекқор ешқашан сақталмаған. +Сіз дерекқорды сақтай аласыз, немесе оның блокауын алып тастай аласыз. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Дерекқор өзгертілген. +Оны блоктау алдында өзгерістерді сақтау керек пе? +Сақтамасаңыз, өзгерістер жоғалады. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" қазір түзету режимінде. +Оған қарамастан, өзгерістерді елемей, оны жабу керек пе? + + + Export database to CSV file + Дерекқорды CSV файлына экспорттау + + + CSV file + CSV файлы + + + Writing the CSV file failed. + CSV файлына жазу сәтсіз аяқталды. + + + Unable to open the database. + Дерекқорды ашу мүмкін емес. + + + Merge database + + + + The database you are trying to save as is locked by another instance of KeePassXC. +Do you want to save it anyway? + + + + Passwords + + + + Database already opened + + + + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + + + + Open read-only + + + + File opened in read only mode. + + + + Open CSV file + + + + + DatabaseWidget + + Change master key + Басты парольді өзгерту + + + Delete entry? + Жазбаны өшіру керек пе? + + + Do you really want to delete the entry "%1" for good? + "%1" жазбасын өшіруді шынымен қалайсыз ба? + + + Delete entries? + Жазбаларды өшіру керек пе? + + + Do you really want to delete %1 entries for good? + %1 жазбаны өшіруді шынымен қалайсыз ба? + + + Move entries to recycle bin? + Жазбаларды қоқыс шелегіне тастау керек пе? + + + Do you really want to move %n entry(s) to the recycle bin? + %n жазбаны қоқыс шелегіне тастауды шынымен қалайсыз ба? + + + Delete group? + Топты өшіру керек пе? + + + Do you really want to delete the group "%1" for good? + "%1" тобын өшіруді шынымен қалайсыз ба? + + + Unable to calculate master key + Басты парольді есептеу мүмкін емес + + + Move entry to recycle bin? + Жазбаны қоқыс шелегіне тастау керек пе? + + + Do you really want to move entry "%1" to the recycle bin? + "%1" жазбасын қоқыс шелегіне тастауды шынымен қалайсыз ба? + + + Searching... + + + + No current database. + + + + No source database, nothing to do. + + + + Search Results (%1) + + + + No Results + + + + Execute command? + + + + Do you really want to execute the following command?<br><br>%1<br> + + + + Remember my choice + + + + Autoreload Request + + + + The database file has changed. Do you want to load the changes? + + + + Merge Request + + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + + + + Could not open the new database file while attempting to autoreload this database. + + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + + + + EditEntryWidget + + Entry + Жазба + + + Advanced + Кеңейтілген + + + Icon + Таңбаша + + + Auto-Type + Автотеру + + + Properties + Қасиеттері + + + History + Тарихы + + + Entry history + Жазба тарихы + + + Add entry + Жазбаны қосу + + + Edit entry + Жазбаны түзету + + + Different passwords supplied. + Әр түрлі парольдер көрсетілді. + + + New attribute + Жаңа атрибут + + + Select file + Файлды таңдау + + + Unable to open file + Файлды ашу мүмкін емес + + + Save attachment + Салынымды сақтау + + + Unable to save the attachment: + + Салынымды сақтау мүмкін емес: + + + + Tomorrow + Ертең + + + %n week(s) + %n апта + + + %n month(s) + %n ай + + + 1 year + 1 жыл + + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + + + + EditEntryWidgetAdvanced + + Additional attributes + Қосымша атрибуттар + + + Add + Қосу + + + Remove + Өшіру + + + Attachments + Салынымдар + + + Save + Сақтау + + + Open + Ашу + + + Edit Name + + + + Protect + + + + Reveal + + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + Бұл жазба үшін автотеруді іске қосу + + + + + + + + + - + - + + + Window title: + Терезе атауы: + + + Inherit default Auto-Type sequence from the &group + + + + &Use custom Auto-Type sequence: + + + + Use default se&quence + + + + Set custo&m sequence: + + + + Window Associations + + + + + EditEntryWidgetHistory + + Show + Көрсету + + + Restore + Қалпына келтіру + + + Delete + Өшіру + + + Delete all + Барлығын өшіру + + + + EditEntryWidgetMain + + Title: + Атауы: + + + Username: + Пайдаланушы аты: + + + Password: + Пароль: + + + Repeat: + Қайталау: + + + URL: + URL: + + + Expires + Мерзімі аяқталады + + + Presets + Сақталған баптаулар + + + Notes: + Естеліктер: + + + + EditGroupWidget + + Group + Топ + + + Icon + Таңбаша + + + Properties + Қасиеттері + + + Add group + Топты қосу + + + Edit group + Топты түзету + + + Enable + Іске қосу + + + Disable + Сөндіру + + + Inherit from parent group (%1) + Аталық топтан мұралау (%1) + + + + EditGroupWidgetMain + + Name + Аты + + + Notes + Естеліктер + + + Expires + Мерзімі аяқталады + + + Search + Іздеу + + + Auto-Type + Автотеру + + + &Use default Auto-Type sequence of parent group + + + + Set default Auto-Type se&quence + + + + + EditWidgetIcons + + Add custom icon + Таңдауыңызша таңбашаны қосу + + + Delete custom icon + Таңдауыңызша таңбашаны өшіру + + + Images + Суреттер + + + All files + Барлық файлдар + + + Select Image + Суретті таңдау + + + Error + Қате + + + Download favicon + + + + Unable to fetch favicon. + + + + Can't read icon + + + + &Use default icon + + + + Use custo&m icon + + + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + + + + EditWidgetProperties + + Created: + Жасалған: + + + Modified: + Өзгертілген: + + + Accessed: + Қатынаған: + + + Uuid: + Uuid: + + + + Entry + + - Clone + + + + + EntryAttributesModel + + Name + Аты + + + + EntryHistoryModel + + Last modified + Соңғы өзгертілген + + + Title + Атауы + + + Username + Пайдаланушы аты + + + URL + URL + + + + EntryModel + + Group + Топ + + + Title + Атауы + + + Username + Пайдаланушы аты + + + URL + URL + + + Ref: + Reference abbreviation + + + + + Group + + Recycle Bin + Қоқыс шелегі + + + + HttpPasswordGeneratorWidget + + Length: + + + + Character Types + Таңбалар түрлері + + + Upper Case Letters + Бас әріптер + + + A-Z + + + + Lower Case Letters + Кіші әріптер + + + a-z + + + + Numbers + Сандар + + + 0-9 + + + + Special Characters + Арнайы таңбалар + + + /*_& ... + + + + Exclude look-alike characters + Ұқсайтын таңбаларға жол бермеу + + + Ensure that the password contains characters from every group + + + + + KMessageWidget + + &Close + + + + Close message + + + + + KeePass1OpenWidget + + Import KeePass1 database + KeePass1 дерекқорын импорттау + + + Unable to open the database. + Дерекқорды ашу мүмкін емес. + + + + KeePass1Reader + + Unable to read keyfile. + Кілттер файлын оқу мүмкін емес. + + + Not a KeePass database. + KeePass дерекқоры емес. + + + Unsupported encryption algorithm. + Шифрлеу алгоритміне қолдау жоқ. + + + Unsupported KeePass database version. + KeePass дерекқоры нұсқасына қолдау жоқ. + + + Root + Түбір + + + Unable to calculate master key + Басты парольді есептеу мүмкін емес + + + Wrong key or database file is corrupt. + Пароль қате, немесе дерекқор файлы зақымдалған. + + + + KeePass2Reader + + Not a KeePass database. + KeePass дерекқоры емес. + + + Unsupported KeePass database version. + KeePass дерекқоры нұсқасына қолдау жоқ. + + + Wrong key or database file is corrupt. + Пароль қате, немесе дерекқор файлы зақымдалған. + + + Unable to calculate master key + Басты парольді есептеу мүмкін емес + + + The selected file is an old KeePass 1 database (.kdb). + +You can import it by clicking on Database > 'Import KeePass 1 database'. +This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + Таңдалған файл ескі KeePass 1 дерекқоры (.kdb) болып табылады. + +Оны Дерекқор > 'KeePass 1 дерекқорын импорттау' арқылы импорттай аласыз. +Бұл - бір жақты миграция. Одан кейін сіз импортталған дерекқорды ескі KeePassX 0.4 нұсқасымен аша алмайтын боласыз. + + + Unable to issue challenge-response. + + + + + Main + + Fatal error while testing the cryptographic functions. + Криптографиялық функцияларды сынау кезіндегі қатаң қате орын алды. + + + KeePassXC - Error + + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + + + + MainWindow + + Open database + Дерекқорды ашу + + + Database settings + Дерекқор баптаулары + + + Copy username to clipboard + Пайдаланушы атын алмасу буферіне көшіріп алу + + + Copy password to clipboard + Парольді алмасу буферіне көшіріп алу + + + Settings + Баптаулар + + + Show toolbar + Саймандар панелін көрсету + + + read-only + тек оқу + + + Toggle window + Терезені көрсету/жасыру + + + KeePass 2 Database + KeePass 2 дерекқоры + + + All files + Барлық файлдар + + + Save repaired database + Жөнделген дерекқорды сақтау + + + Writing the database failed. + Дерекқорды жазу сәтсіз аяқталды. + + + &Recent databases + + + + He&lp + + + + E&ntries + + + + Copy att&ribute to clipboard + + + + &Groups + + + + &View + + + + &Quit + + + + &About + + + + &Open database + + + + &Save database + + + + &Close database + + + + &New database + + + + Merge from KeePassX database + + + + &Add new entry + + + + &View/Edit entry + + + + &Delete entry + + + + &Add new group + + + + &Edit group + + + + &Delete group + + + + Sa&ve database as + + + + Change &master key + + + + &Database settings + + + + &Clone entry + + + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + + + &Find + + + + Copy &username + + + + Cop&y password + + + + &Settings + + + + &Perform Auto-Type + + + + &Open URL + + + + &Lock databases + + + + &Title + + + + &URL + + + + &Notes + + + + &Export to CSV file + + + + Re&pair database + + + + Password Generator + + + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + + + + OptionDialog + + Dialog + + + + General + Жалпы + + + Sh&ow a notification when credentials are requested + + + + Sort matching entries by &username + + + + Re&move all stored permissions from entries in active database + + + + Advanced + Кеңейтілген + + + Always allow &access to entries + + + + Always allow &updating entries + + + + Searc&h in all opened databases for matching entries + + + + HTTP Port: + + + + Default port: 19455 + + + + Re&quest to unlock the database if it is locked + + + + Sort &matching entries by title + + + + KeePassXC will listen to this port on 127.0.0.1 + + + + Cannot bind to privileged ports + + + + Cannot bind to privileged ports below 1024! +Using default port 19455. + + + + R&emove all shared encryption keys from active database + + + + &Return advanced string fields which start with "KPH: " + + + + Automatically creating or updating string fields is not supported. + + + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + + + + PasswordGeneratorWidget + + Password: + Пароль: + + + Character Types + Таңбалар түрлері + + + Upper Case Letters + Бас әріптер + + + Lower Case Letters + Кіші әріптер + + + Numbers + Сандар + + + Special Characters + Арнайы таңбалар + + + Exclude look-alike characters + Ұқсайтын таңбаларға жол бермеу + + + Accept + Қабылдау + + + %p% + + + + strength + + + + entropy + + + + &Length: + + + + Pick characters from every group + + + + Generate + + + + Close + + + + Apply + + + + Entropy: %1 bit + + + + Password Quality: %1 + + + + Poor + + + + Weak + + + + Good + + + + Excellent + + + + Password + Пароль + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + + + + QObject + + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Топ + + + Title + Атауы + + + Username + Пайдаланушы аты + + + Password + Пароль + + + URL + URL + + + Notes + Естеліктер + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + + + + + QtIOCompressor + + Internal zlib error when compressing: + Сығу кезінде zlib ішкі қатесі орын алған: + + + Error writing to underlying device: + Астындағы құрылғыға жазу қатесі: + + + Error opening underlying device: + Астындағы құрылғыны ашу қатесі: + + + Error reading data from underlying device: + Астындағы құрылғыдан деректерді оқу қатесі: + + + Internal zlib error when decompressing: + Тарқату кезінде zlib ішкі қатесі орын алған: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + zlib-тің бұл нұсқасы gzip пішімін қолдамайды. + + + Internal zlib error: + Ішкі zlib қатесі: + + + + SearchWidget + + Case Sensitive + + + + Search + Іздеу + + + Clear + + + + Search... + + + + Limit search to selected group + + + + + Service + + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + + + + Do you want to update the information in %1 - %2? + + + + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + + + + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + + + + No shared encryption-keys found in KeePassHttp Settings. + + + + The active database does not contain an entry of KeePassHttp Settings. + + + + Removing stored permissions... + + + + Abort + + + + Successfully removed permissions from %1 %2. + + + + The active database does not contain an entry with permissions. + + + + KeePassXC: New key association request + + + + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + + + + KeePassXC: Overwrite existing key? + + + + KeePassXC: Update Entry + + + + KeePassXC: Database locked! + + + + KeePassXC: Removed keys from database + + + + KeePassXC: No keys found + + + + KeePassXC: Settings not available! + + + + KeePassXC: Removed permissions + + + + KeePassXC: No entry with permissions found! + + + + + SettingsWidget + + Application Settings + Қолданба баптаулары + + + General + Жалпы + + + Security + Қауіпсіздік + + + Access error for config file %1 + + + + + SettingsWidgetGeneral + + Remember last databases + Соңғы дерекқорларды есте сақтау: + + + Automatically save on exit + Шығу кезінде автосақтау + + + Automatically save after every change + Әр өзгерістен кейін автосақтау + + + Minimize when copying to clipboard + Алмасу буферіне көшіру кезінде қолданбаны қайыру + + + Use group icon on entry creation + Жазбаны жасау кезінде топ таңбашасын қолдану + + + Global Auto-Type shortcut + Глобалды автотеру жарлығы + + + Language + Тіл + + + Show a system tray icon + Жүйелік трей таңбашасын қолдану + + + Hide window to system tray when minimized + Қолданба қайырылған кезде терезені жүйелік трейге жасыру + + + Load previous databases on startup + + + + Automatically reload the database when modified externally + + + + Hide window to system tray instead of app exit + + + + Minimize window at application startup + + + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Автотеру + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + + + + SettingsWidgetSecurity + + Clear clipboard after + Алмасу буферін тазалау алдындағы кідіріс + + + sec + сек + + + Lock databases after inactivity of + Дерекқорларды белсенділік жоқ кезде блоктау алдындағы кідіріс + + + Show passwords in cleartext by default + Парольдерді үнсіз келісім бойынша ашық мәтінмен көрсету + + + Lock databases after minimizing the window + + + + Don't require password repeat when it is visible + + + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + сек + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + + + + UnlockDatabaseWidget + + Unlock database + Дерекқорды блоктаудан босату + + + + WelcomeWidget + + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + + + + + main + + path to a custom config file + таңдауыңызша баптаулар файлына дейінгі жол + + + key file of the database + дерекқордың кілттер файлы + + + KeePassXC - cross-platform password manager + + + + read password of the database from stdin + + + + filenames of the password databases to open (*.kdbx) + + + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + + + \ No newline at end of file diff --git a/share/translations/keepassx_ko.ts b/share/translations/keepassx_ko.ts index 208c92a09a..f89dc32dbf 100644 --- a/share/translations/keepassx_ko.ts +++ b/share/translations/keepassx_ko.ts @@ -1,33 +1,143 @@ - + AboutDialog - About KeePassX - KeePassX 정보 + About KeePassXC + + + + About + 정보 + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + - KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassX는 GNU General Public License(GPL) 버전 2 혹은 버전 3(선택적)으로 배포됩니다. + Version %1 + + + + + Revision: %1 + + + + Libraries: + - Revision - 리비전 + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + - Using: - 사용: + Enabled extensions: + - AutoType + AccessControlDialog + + Remember this decision + + + + Allow + + + + Deny + + - Auto-Type - KeePassX - 자동 입력 - KeePassX + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + + + + KeePassXC HTTP Confirm Access + + + + AutoType Couldn't find an entry that matches the window title: 창 제목과 일치하는 항목을 찾을 수 없습니다: + + Auto-Type - KeePassXC + + AutoTypeAssociationsModel @@ -46,14 +156,14 @@ AutoTypeSelectDialog - - Auto-Type - KeePassX - 자동 입력 - KeePassX - Select entry to Auto-Type: 자동으로 입력할 항목 선택: + + Auto-Type - KeePassXC + + ChangeMasterKeyWidget @@ -69,10 +179,6 @@ Repeat password: 암호 확인: - - Key file - 키 파일 - Browse 찾아보기 @@ -93,10 +199,6 @@ Create Key File... 키 파일 만들기... - - Error - 오류 - Unable to create Key File : 키 파일을 만들 수 없습니다: @@ -105,10 +207,6 @@ Select a key file 키 파일 선택 - - Question - 질문 - Do you really want to use an empty string as password? 빈 문자열을 암호로 사용하시겠습니까? @@ -117,15 +215,172 @@ Different passwords supplied. 다른 암호를 입력하였습니다. - - Failed to set key file - 키 파일을 설정할 수 없음 - Failed to set %1 as the Key file: %2 %1을(를) 키 파일로 설정할 수 없습니다: %2 + + &Key file + + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + 오류 + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + 오류 + + + Unable to calculate master key + 마스터 키를 계산할 수 없습니다 + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -145,10 +400,6 @@ Browse 찾아보기 - - Error - 오류 - Unable to open the database. 데이터베이스를 열 수 없습니다. @@ -169,6 +420,14 @@ Select key file 키 파일 선택 + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -225,10 +484,6 @@ You can now save it. Default username: 기본 사용자 이름: - - Use recycle bin: - 휴지통 사용: - MiB MiB @@ -245,6 +500,22 @@ You can now save it. Max. history size: 최대 과거 항목 크기: + + Use recycle bin + + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -264,10 +535,6 @@ You can now save it. Open database 데이터베이스 열기 - - Warning - 경고 - File not found! 파일을 찾을 수 없습니다! @@ -297,10 +564,6 @@ You can now save it. Save changes? "%1"이(가) 변경되었습니다. 저장하시겠습니까? - - Error - 오류 - Writing the database failed. 데이터베이스에 쓸 수 없습니다. @@ -317,12 +580,6 @@ Save changes? locked 잠김 - - The database you are trying to open is locked by another instance of KeePassX. -Do you want to open it anyway? Alternatively the database is opened read-only. - 열려고 하는 데이터베이스를 다른 KeePassX 인스턴스에서 잠갔습니다. -그래도 여시겠습니까? 읽기 전용으로 열 수도 있습니다. - Lock database 데이터베이스 잠금 @@ -366,37 +623,66 @@ Discard changes and close anyway? CSV 파일에 기록할 수 없습니다. - The database you are trying to save as is locked by another instance of KeePassX. -Do you want to save it anyway? - 저장하려고 하는 데이터베이스를 다른 KeePassX 인스턴스에서 잠갔습니다. -그래도 저장하시겠습니까? + Unable to open the database. + 데이터베이스를 열 수 없습니다. - Unable to open the database. + Merge database - - - DatabaseWidget - Change master key - 마스터 키 변경 + The database you are trying to save as is locked by another instance of KeePassXC. +Do you want to save it anyway? + - Delete entry? - 항목을 삭제하시겠습니까? + Passwords + - Do you really want to delete the entry "%1" for good? - 정말 항목 "%1"을(를) 삭제하시겠습니까? + Database already opened + - Delete entries? - 항목을 삭제하시겠습니까? + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + - Do you really want to delete %1 entries for good? - 정말 항목 %1개를 삭제하시겠습니까? + Open read-only + + + + File opened in read only mode. + + + + Open CSV file + + + + + DatabaseWidget + + Change master key + 마스터 키 변경 + + + Delete entry? + 항목을 삭제하시겠습니까? + + + Do you really want to delete the entry "%1" for good? + 정말 항목 "%1"을(를) 삭제하시겠습니까? + + + Delete entries? + 항목을 삭제하시겠습니까? + + + Do you really want to delete %1 entries for good? + 정말 항목 %1개를 삭제하시겠습니까? Move entries to recycle bin? @@ -414,14 +700,6 @@ Do you want to save it anyway? Do you really want to delete the group "%1" for good? 정말 그룹 "%1"을(를) 삭제하시겠습니까? - - Current group - 현재 그룹 - - - Error - 오류 - Unable to calculate master key 마스터 키를 계산할 수 없음 @@ -434,6 +712,66 @@ Do you want to save it anyway? Do you really want to move entry "%1" to the recycle bin? + + Searching... + + + + No current database. + + + + No source database, nothing to do. + + + + Search Results (%1) + + + + No Results + + + + Execute command? + + + + Do you really want to execute the following command?<br><br>%1<br> + + + + Remember my choice + + + + Autoreload Request + + + + The database file has changed. Do you want to load the changes? + + + + Merge Request + + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + + + + Could not open the new database file while attempting to autoreload this database. + + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -473,10 +811,6 @@ Do you want to save it anyway? Edit entry 항목 편집 - - Error - 오류 - Different passwords supplied. 다른 암호를 입력하였습니다. @@ -518,6 +852,22 @@ Do you want to save it anyway? 1 year 1년 + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -529,10 +879,6 @@ Do you want to save it anyway? Add 추가 - - Edit - 편집 - Remove 삭제 @@ -549,6 +895,18 @@ Do you want to save it anyway? Open 열기 + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -556,14 +914,6 @@ Do you want to save it anyway? Enable Auto-Type for this entry 이 항목 자동 입력 사용 - - Inherit default Auto-Type sequence from the group - 그룹의 기본 자동 입력 시퀀스 사용 - - - Use custom Auto-Type sequence: - 사용자 정의 자동 입력 시퀀스 사용: - + + @@ -577,12 +927,24 @@ Do you want to save it anyway? 창 제목: - Use default sequence - 기본 시퀀스 사용 + Inherit default Auto-Type sequence from the &group + + + + &Use custom Auto-Type sequence: + + + + Use default se&quence + + + + Set custo&m sequence: + - Set custom sequence: - 사용자 정의 시퀀스 설정: + Window Associations + @@ -622,10 +984,6 @@ Do you want to save it anyway? Repeat: 암호 확인: - - Gen. - 생성 - URL: URL: @@ -697,28 +1055,20 @@ Do you want to save it anyway? 찾기 - Auto-type + Auto-Type 자동 입력 - Use default auto-type sequence of parent group - 부모 그룹의 기본 자동 입력 시퀀스 사용 + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - 기본 자동 입력 시퀀스 설정 + Set default Auto-Type se&quence + EditWidgetIcons - - Use default icon - 기본 아이콘 사용 - - - Use custom icon - 사용자 정의 아이콘 사용 - Add custom icon 사용자 정의 아이콘 추가 @@ -740,19 +1090,35 @@ Do you want to save it anyway? 그림 선택 - Can't delete icon! - 아이콘을 삭제할 수 없습니다! + Error + 오류 - - Can't delete icon. Still used by %n item(s). - 아이콘을 삭제할 수 없습니다. 항목 %n개에서 사용 중입니다. + + Download favicon + - Error + Unable to fetch favicon. + + + + Can't read icon + + + + &Use default icon - Can't read icon: + Use custo&m icon + + + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? @@ -775,6 +1141,13 @@ Do you want to save it anyway? UUID: + + Entry + + - Clone + + + EntryAttributesModel @@ -819,6 +1192,11 @@ Do you want to save it anyway? URL URL + + Ref: + Reference abbreviation + + Group @@ -827,16 +1205,74 @@ Do you want to save it anyway? 휴지통 + + HttpPasswordGeneratorWidget + + Length: + 길이: + + + Character Types + 문자 종류 + + + Upper Case Letters + 대문자 + + + A-Z + + + + Lower Case Letters + 소문자 + + + a-z + + + + Numbers + 숫자 + + + 0-9 + + + + Special Characters + 특수 문자 + + + /*_& ... + + + + Exclude look-alike characters + 비슷하게 생긴 문자 제외 + + + Ensure that the password contains characters from every group + 모든 그룹에서 최소 1글자 이상 포함 + + + + KMessageWidget + + &Close + + + + Close message + + + KeePass1OpenWidget Import KeePass1 database KeePass1 데이터베이스 가져오기 - - Error - 오류 - Unable to open the database. 데이터베이스를 열 수 없습니다. @@ -870,7 +1306,7 @@ Do you want to save it anyway? Wrong key or database file is corrupt. - + 키가 잘못되었거나 데이터베이스가 손상되었습니다. @@ -901,6 +1337,10 @@ This is a one-way migration. You won't be able to open the imported databas 데이터베이스 > 'KeePass 1 데이터베이스 가져오기' 항목을 선택해서 변환해야 합니다. 변환은 한 방향으로만 이루어지며, 가져온 데이터베이스는 KeePassX 0.4 버전으로 더 이상 열 수 없습니다. + + Unable to issue challenge-response. + + Main @@ -909,453 +1349,917 @@ This is a one-way migration. You won't be able to open the imported databas 암호화 함수를 시험하는 중 오류가 발생하였습니다. - KeePassX - Error - KeePassX - 오류 + KeePassXC - Error + + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + MainWindow - Database - 데이터베이스 + Open database + 데이터베이스 열기 - Recent databases - 최근 데이터베이스 + Database settings + 데이터베이스 설정 - Help - 도움말 + Copy username to clipboard + 클립보드에 사용자 이름 복사 - Entries - 항목 + Copy password to clipboard + 클립보드에 암호 복사 - Copy attribute to clipboard - 클립보드에 속성 복사 + Settings + 설정 - Groups - 그룹 + Show toolbar + 도구 모음 보이기 - View - 보기 + read-only + 읽기 전용 - Quit - 끝내기 + Toggle window + 창 전환 - About - 정보 + KeePass 2 Database + KeePass 2 데이터베이스 - Open database - 데이터베이스 열기 + All files + 모든 파일 - Save database - 데이터베이스 저장 + Save repaired database + 복구한 데이터베이스 저장 - Close database - 데이터베이스 닫기 + Writing the database failed. + 데이터베이스에 쓸 수 없습니다. - New database - 새 데이터베이스 + &Recent databases + - Add new entry - 새 항목 추가 + He&lp + - View/Edit entry - 항목 보기/편집 + E&ntries + - Delete entry - 항목 삭제 + Copy att&ribute to clipboard + - Add new group - 새 그룹 추가 + &Groups + - Edit group - 그룹 편집 + &View + - Delete group - 그룹 삭제 + &Quit + - Save database as - 다른 이름으로 데이터베이스 저장 + &About + - Change master key - 마스터 키 변경 + &Open database + - Database settings - 데이터베이스 설정 + &Save database + - Import KeePass 1 database - KeePass 1 데이터베이스 가져오기 + &Close database + - Clone entry - 항목 복제 + &New database + - Find - 찾기 + Merge from KeePassX database + - Copy username to clipboard - 클립보드에 사용자 이름 복사 + &Add new entry + - Copy password to clipboard - 클립보드에 암호 복사 + &View/Edit entry + - Settings - 설정 + &Delete entry + - Perform Auto-Type - 자동 입력 실행 + &Add new group + - Open URL - URL 열기 + &Edit group + - Lock databases - 데이터베이스 잠금 + &Delete group + - Title - 제목 + Sa&ve database as + - URL - URL + Change &master key + - Notes - 메모 + &Database settings + - Show toolbar - 도구 모음 보이기 + &Clone entry + - read-only - 읽기 전용 + Timed one-time password + - Toggle window - 창 전환 + Setup TOTP + + + + Copy &TOTP + - Tools - 도구 + Show TOTP + - Copy username - 사용자 이름 복사 + &Find + - Copy password - 암호 복사 + Copy &username + - Export to CSV file - CSV 파일로 내보내기 + Cop&y password + - Repair database - 데이터베이스 복구 + &Settings + - KeePass 2 Database - KeePass 2 데이터베이스 + &Perform Auto-Type + - All files - 모든 파일 + &Open URL + - Save repaired database - 복구한 데이터베이스 저장 + &Lock databases + - Error - 오류 + &Title + - Writing the database failed. - 데이터베이스에 쓸 수 없습니다. + &URL + - - - PasswordGeneratorWidget - Password: - 암호: + &Notes + - Length: - 길이: + &Export to CSV file + - Character Types - 문자 종류 + Re&pair database + - Upper Case Letters - 대문자 + Password Generator + - Lower Case Letters - 소문자 + Clear history + - Numbers - 숫자 + &Database + - Special Characters - 특수 문자 + Import + - Exclude look-alike characters - 비슷하게 생긴 문자 제외 + &Tools + - Ensure that the password contains characters from every group - 모든 그룹에서 최소 1글자 이상 포함 + Import KeePass 1 database + KeePass 1 데이터베이스 가져오기 - Accept - 사용 + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + - QCommandLineParser + OptionDialog - Displays version information. - 버전 정보를 표시합니다. + Dialog + - Displays this help. - 이 도움말을 표시합니다. + General + 일반 - Unknown option '%1'. - 알 수 없는 옵션 '%1'. + Sh&ow a notification when credentials are requested + - Unknown options: %1. - 알 수 없는 옵션 '%1'. + Sort matching entries by &username + - Missing value after '%1'. - '%1' 다음에 값이 없습니다. + Re&move all stored permissions from entries in active database + - Unexpected value after '%1'. - '%1' 다음에 예상하지 못한 값이 왔습니다. + Advanced + 고급 - [options] - [옵션] + Always allow &access to entries + - Usage: %1 - 사용 방법: %1 + Always allow &updating entries + - Options: - 옵션: + Searc&h in all opened databases for matching entries + - Arguments: - 인자: + HTTP Port: + - - - QSaveFile - Existing file %1 is not writable - 존재하는 파일 %1에 기록할 수 없음 + Default port: 19455 + - Writing canceled by application - 프로그램에서 쓰기 작업 취소함 + Re&quest to unlock the database if it is locked + - Partial write. Partition full? - 일부분만 기록되었습니다. 파티션이 가득 찼습니까? + Sort &matching entries by title + - - - QtIOCompressor - Internal zlib error when compressing: - 압축 중 내부 zlib 오류 발생: + KeePassXC will listen to this port on 127.0.0.1 + - Error writing to underlying device: - 장치에 기록하는 중 오류 발생: + Cannot bind to privileged ports + - Error opening underlying device: - 장치를 여는 중 오류 발생: + Cannot bind to privileged ports below 1024! +Using default port 19455. + - Error reading data from underlying device: - 장치에서 읽는 중 오류 발생: + R&emove all shared encryption keys from active database + - Internal zlib error when decompressing: - 압축 푸는 중 내부 zlib 오류 발생: + &Return advanced string fields which start with "KPH: " + - - - QtIOCompressor::open - The gzip format not supported in this version of zlib. - 이 버전의 zlib에서 gzip 형식을 지원하지 않습니다. + Automatically creating or updating string fields is not supported. + - Internal zlib error: - 내부 zlib 오류: + This is required for accessing your databases from ChromeIPass or PassIFox + - - - SearchWidget - Find: - 찾기: + Enable KeePassHTTP server + - Case sensitive - 대소문자 구분 + Only returns the best matches for a specific URL instead of all entries for the whole domain. + - Current group - 현재 그룹 + &Return only best matching entries + - Root group - 루트 그룹 + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + - - - SettingsWidget - Application Settings - 프로그램 설정 + &Match URL schemes + - General - 일반 + Password Generator + - Security - 보안 + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + - SettingsWidgetGeneral + PasswordGeneratorWidget - Remember last databases - 마지막 데이터베이스 기억 + Password: + 암호: - Open previous databases on startup - 시작할 때 이전 데이터베이스 열기 + Character Types + 문자 종류 - Automatically save on exit - 끝낼 때 자동 저장 + Upper Case Letters + 대문자 - Automatically save after every change - 항목을 변경할 때 자동 저장 + Lower Case Letters + 소문자 - Minimize when copying to clipboard - 클립보드에 복사할 때 최소화 + Numbers + 숫자 - Use group icon on entry creation - 항목을 만들 때 그룹 아이콘 사용 + Special Characters + 특수 문자 - Global Auto-Type shortcut - 전역 자동 입력 단축키 + Exclude look-alike characters + 비슷하게 생긴 문자 제외 - Use entry title to match windows for global auto-type - 전역 자동 입력 시 항목 제목과 일치하는 창 찾기 + Accept + 사용 - Language - 언어 + %p% + - Show a system tray icon - 시스템 트레이 아이콘 표시 + strength + - Hide window to system tray when minimized - 시스템 트레이로 최소화 + entropy + - Remember last key files - 마지막 키 파일 기억 + &Length: + - Hide window to system tray instead of App Exit + Pick characters from every group - Hide window to system tray on App start + Generate - - - SettingsWidgetSecurity - Clear clipboard after - 다음 시간 이후 클립보드 비우기 + Close + - sec - + Apply + - Lock databases after inactivity of - 다음 시간 동안 활동이 없을 때 데이터베이스 잠금 + Entropy: %1 bit + - Show passwords in cleartext by default - 기본값으로 암호를 평문으로 표시 + Password Quality: %1 + - Always ask before performing auto-type - 자동으로 입력하기 전에 항상 묻기 + Poor + - - + + Weak + + + + Good + + + + Excellent + + + + Password + 암호 + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + + + + QObject + + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + 그룹 + + + Title + 제목 + + + Username + 사용자 이름 + + + Password + 암호 + + + URL + URL + + + Notes + 메모 + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + + + + + QtIOCompressor + + Internal zlib error when compressing: + 압축 중 내부 zlib 오류 발생: + + + Error writing to underlying device: + 장치에 기록하는 중 오류 발생: + + + Error opening underlying device: + 장치를 여는 중 오류 발생: + + + Error reading data from underlying device: + 장치에서 읽는 중 오류 발생: + + + Internal zlib error when decompressing: + 압축 푸는 중 내부 zlib 오류 발생: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + 이 버전의 zlib에서 gzip 형식을 지원하지 않습니다. + + + Internal zlib error: + 내부 zlib 오류: + + + + SearchWidget + + Case Sensitive + + + + Search + 찾기 + + + Clear + + + + Search... + + + + Limit search to selected group + + + + + Service + + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + + + + Do you want to update the information in %1 - %2? + + + + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + + + + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + + + + No shared encryption-keys found in KeePassHttp Settings. + + + + The active database does not contain an entry of KeePassHttp Settings. + + + + Removing stored permissions... + + + + Abort + + + + Successfully removed permissions from %1 %2. + + + + The active database does not contain an entry with permissions. + + + + KeePassXC: New key association request + + + + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + + + + KeePassXC: Overwrite existing key? + + + + KeePassXC: Update Entry + + + + KeePassXC: Database locked! + + + + KeePassXC: Removed keys from database + + + + KeePassXC: No keys found + + + + KeePassXC: Settings not available! + + + + KeePassXC: Removed permissions + + + + KeePassXC: No entry with permissions found! + + + + + SettingsWidget + + Application Settings + 프로그램 설정 + + + General + 일반 + + + Security + 보안 + + + Access error for config file %1 + + + + + SettingsWidgetGeneral + + Remember last databases + 마지막 데이터베이스 기억 + + + Automatically save on exit + 끝낼 때 자동 저장 + + + Automatically save after every change + 항목을 변경할 때 자동 저장 + + + Minimize when copying to clipboard + 클립보드에 복사할 때 최소화 + + + Use group icon on entry creation + 항목을 만들 때 그룹 아이콘 사용 + + + Global Auto-Type shortcut + 전역 자동 입력 단축키 + + + Language + 언어 + + + Show a system tray icon + 시스템 트레이 아이콘 표시 + + + Hide window to system tray when minimized + 시스템 트레이로 최소화 + + + Load previous databases on startup + + + + Automatically reload the database when modified externally + + + + Hide window to system tray instead of app exit + + + + Minimize window at application startup + + + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + 자동 입력 + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + + + + SettingsWidgetSecurity + + Clear clipboard after + 다음 시간 이후 클립보드 비우기 + + + sec + + + + Lock databases after inactivity of + 다음 시간 동안 활동이 없을 때 데이터베이스 잠금 + + + Show passwords in cleartext by default + 기본값으로 암호를 평문으로 표시 + + + Lock databases after minimizing the window + + + + Don't require password repeat when it is visible + + + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + + + UnlockDatabaseWidget Unlock database @@ -1365,20 +2269,36 @@ This is a one-way migration. You won't be able to open the imported databas WelcomeWidget - Welcome! - 환영합니다! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + - - - main - KeePassX - cross-platform password manager - KeePassX - 크로스 플랫폼 암호 관리자 + Import from CSV + - filename of the password database to open (*.kdbx) - 열 암호 데이터베이스 파일 이름 (*.kdbx) + Recent databases + 최근 데이터베이스 + + + main path to a custom config file 사용자 정의 설정 파일 경로 @@ -1387,5 +2307,81 @@ This is a one-way migration. You won't be able to open the imported databas key file of the database 데이터베이스 키 파일 + + KeePassXC - cross-platform password manager + + + + read password of the database from stdin + + + + filenames of the password databases to open (*.kdbx) + + + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_lt.ts b/share/translations/keepassx_lt.ts index 152dad900b..a0836e035f 100644 --- a/share/translations/keepassx_lt.ts +++ b/share/translations/keepassx_lt.ts @@ -2,26 +2,107 @@ AboutDialog - Revision - Poversijis + About KeePassXC + Apie KeePassXC - Using: - Naudojama: + About + Apie - About KeePassXC - Apie KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + - Extensions: + Debug Info + Derinimo informacija + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + Kopijuoti į iškarpinę + + + Version %1 - Plėtiniai: + Versija %1 - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC yra platinama GNU Bendrosios Viešosios Licencijos (GPL) versijos 2 arba (jūsų pasirinkimu) versijos 3 sąlygomis. + Revision: %1 + Poversijis: %1 + + + Libraries: + Bibliotekos: + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -120,10 +201,6 @@ Pasirinkite, ar norite leisti prieigą. Create Key File... Sukurti rakto failą... - - Error - Klaida - Unable to create Key File : Nepavyko sukurti rakto failo : @@ -132,10 +209,6 @@ Pasirinkite, ar norite leisti prieigą. Select a key file Pasirinkite rakto failą - - Question - Klausimas - Do you really want to use an empty string as password? Ar tikrai norite naudoti tuščią eilutę kaip slaptažodį? @@ -144,10 +217,6 @@ Pasirinkite, ar norite leisti prieigą. Different passwords supplied. Pateikti skirtingi slaptažodžiai. - - Failed to set key file - Nepavyko nustatyti rakto failo - Failed to set %1 as the Key file: %2 @@ -158,6 +227,163 @@ Pasirinkite, ar norite leisti prieigą. &Key file &Rakto failas + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Klaida + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Klaida + + + Unable to calculate master key + Nepavyko apskaičiuoti pagrindinio rakto + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -177,10 +403,6 @@ Pasirinkite, ar norite leisti prieigą. Browse Naršyti - - Error - Klaida - Unable to open the database. Nepavyko atverti duomenų bazės. @@ -201,6 +423,14 @@ Pasirinkite, ar norite leisti prieigą. Select key file Pasirinkite rakto failą + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -277,6 +507,18 @@ Dabar galite ją įrašyti. Use recycle bin Naudoti šiukšlinę + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -296,10 +538,6 @@ Dabar galite ją įrašyti. Open database Atverti duomenų bazę - - Warning - Įspėjimas - File not found! Failas nerastas! @@ -330,10 +568,6 @@ Save changes? "%1" buvo pakeista. Įrašyti pakeitimus? - - Error - Klaida - Writing the database failed. Duomenų bazės rašymas nepavyko. @@ -425,6 +659,14 @@ Ar vis tiek norite ją atverti? Open read-only Atverti tik skaitymui + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -464,10 +706,6 @@ Ar vis tiek norite ją atverti? Do you really want to delete the group "%1" for good? Ar tikrai norite ištrinti grupę "%1"? - - Error - Klaida - Unable to calculate master key Nepavyko apskaičiuoti pagrindinio rakto @@ -528,14 +766,18 @@ Ar vis tiek norite ją atverti? The database file has changed and you have unsaved changes.Do you want to merge your changes? Duomenų bazės failas pasikeitė ir jūs turite neįrašytų pakeitimų. Ar norite sulieti savo pakeitimus? - - Autoreload Failed - Automatinis įkėlimas iš naujo nepavyko - Could not open the new database file while attempting to autoreload this database. Nepavyko atverti naujos duomenų bazės failo, bandant automatiškai iš naujo įkelti šią duomenų bazę. + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -575,10 +817,6 @@ Ar vis tiek norite ją atverti? Edit entry Keisti įrašą - - Error - Klaida - Different passwords supplied. Pateikti skirtingi slaptažodžiai. @@ -621,6 +859,22 @@ Ar vis tiek norite ją atverti? 1 year 1 metai + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -632,10 +886,6 @@ Ar vis tiek norite ją atverti? Add Pridėti - - Edit - Keisti - Remove Šalinti @@ -652,6 +902,18 @@ Ar vis tiek norite ją atverti? Open Atverti + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -687,6 +949,10 @@ Ar vis tiek norite ją atverti? Set custo&m sequence: Nustatyti tinkintą s&eką: + + Window Associations + + EditEntryWidgetHistory @@ -796,16 +1062,16 @@ Ar vis tiek norite ją atverti? Paieška - Auto-type + Auto-Type Automatinis rinkimas - Use default auto-type sequence of parent group - Naudoti numatytąją pirminės grupės automatinio rinkimo seką + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Nustatyti numatytąją automatinio rinkimo seką + Set default Auto-Type se&quence + @@ -830,10 +1096,6 @@ Ar vis tiek norite ją atverti? Select Image Pasirinkite paveikslą - - Can't delete icon! - Nepavyksta ištrinti piktogramos! - Error Klaida @@ -850,10 +1112,6 @@ Ar vis tiek norite ją atverti? Can't read icon Nepavyksta perskaityti piktogramos - - Can't delete icon. Still used by %1 items. - Nepavyksta ištrinti piktogramos. Vis dar naudojama %1 elementų. - &Use default icon Na&udoti numatytąją piktogramą @@ -862,6 +1120,14 @@ Ar vis tiek norite ją atverti? Use custo&m icon Naudoti tinkintą piktogra&mą + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -933,6 +1199,11 @@ Ar vis tiek norite ją atverti? URL URL + + Ref: + Reference abbreviation + + Group @@ -991,9 +1262,16 @@ Ar vis tiek norite ją atverti? Ensure that the password contains characters from every group Užtikrinti, kad slaptažodyje būtų simboliai iš kiekvienos grupės + + + KMessageWidget + + &Close + + - Accept - Priimti + Close message + @@ -1002,10 +1280,6 @@ Ar vis tiek norite ją atverti? Import KeePass1 database Importuoti KeePass1 duomenų bazę - - Error - Klaida - Unable to open the database. Nepavyko atverti duomenų bazės. @@ -1070,6 +1344,10 @@ This is a one-way migration. You won't be able to open the imported databas Jūs galite ją importuoti, nuspausdami Duomenų bazė > "Importuoti KeePass 1 duomenų bazę". Tai yra vienakryptis perkėlimas. Jūs negalėsite atverti importuotos duomenų bazės, naudodami senąją KeePassX 0.4 versija. + + Unable to issue challenge-response. + + Main @@ -1081,13 +1359,17 @@ Tai yra vienakryptis perkėlimas. Jūs negalėsite atverti importuotos duomenų KeePassXC - Error KeePassXC - Klaida + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - Duomenų bazė - Open database Atverti duomenų bazę @@ -1120,10 +1402,6 @@ Tai yra vienakryptis perkėlimas. Jūs negalėsite atverti importuotos duomenų Toggle window Perjungti langą - - Tools - Įrankiai - KeePass 2 Database KeePass 2 duomenų bazė @@ -1136,10 +1414,6 @@ Tai yra vienakryptis perkėlimas. Jūs negalėsite atverti importuotos duomenų Save repaired database Įrašyti pataisytą duomenų bazę - - Error - Klaida - Writing the database failed. Duomenų bazės rašymas nepavyko. @@ -1232,14 +1506,26 @@ Tai yra vienakryptis perkėlimas. Jūs negalėsite atverti importuotos duomenų &Database settings &Duomenų bazės nustatymai - - &Import KeePass 1 database - &Importuoti KeePass 1 duomenų bazę - &Clone entry &Dublikuoti įrašą + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find &Rasti @@ -1292,6 +1578,46 @@ Tai yra vienakryptis perkėlimas. Jūs negalėsite atverti importuotos duomenų Password Generator Slaptažodžių generatorius + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Importuoti KeePass 1 duomenų bazę + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1307,12 +1633,6 @@ Tai yra vienakryptis perkėlimas. Jūs negalėsite atverti importuotos duomenų Sh&ow a notification when credentials are requested R&odyti pranešimą, kai reikalaujama prisijungimo duomenų - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - &Atitikti URL schemas -Bus grąžinami įrašai tik su ta pačia schema (http://, https://, ftp://, ...) - Sort matching entries by &username Rikiuoti atitinkančius įrašus pagal na&udotojo vardą @@ -1321,10 +1641,6 @@ Bus grąžinami įrašai tik su ta pačia schema (http://, https://, ftp://, ... Re&move all stored permissions from entries in active database Šal&inti iš įrašų aktyvioje duomenų bazėje visus saugomus leidimus - - Password generator - Slaptažodžių generatorius - Advanced Išplėstiniai @@ -1341,10 +1657,6 @@ Bus grąžinami įrašai tik su ta pačia schema (http://, https://, ftp://, ... Searc&h in all opened databases for matching entries Ieš&koti atitinkančių įrašų visose atvertose duomenų bazėse - - Only the selected database has to be connected with a client! - Su klientu turi būti sujungta tik pasirinkta duomenų bazė! - HTTP Port: HTTP prievadas: @@ -1361,12 +1673,6 @@ Bus grąžinami įrašai tik su ta pačia schema (http://, https://, ftp://, ... Sort &matching entries by title Rikiuoti atitinkančius įrašus pagal &antraštę - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - Įjungti KeepassXC HTTP protokolą -Tai reikalinga, norint prie savo duomenų bazių gauti prieigą iš ChromeIPass ar PassIFox - KeePassXC will listen to this port on 127.0.0.1 KeePassXC klausysis šio prievado ties 127.0.0.1 @@ -1380,21 +1686,11 @@ Tai reikalinga, norint prie savo duomenų bazių gauti prieigą iš ChromeIPass Using default port 19455. Nepavyksta susieti su privilegijuotais prievadais žemiau 1024! Naudojamas numatytasis prievadas 19455. - - - &Return only best matching entries for a URL instead -of all entries for the whole domain - &Vietoj visų įrašų, skirtų visai sričiai, -grąžinti tik geriausiai atitinkančius įrašus, skirtus URL R&emove all shared encryption keys from active database Ša&linti iš aktyvios duomenų bazės visus bendrinamus šifravimo raktus - - The following options can be dangerous. Change them only if you know what you are doing. - Šios parinktys gali būti pavojingos. Keiskite jas tik tuo atveju, jeigu žinote ką darote! - &Return advanced string fields which start with "KPH: " &Grąžinti išplėstines eilutes, kurios prasideda "KPH: " @@ -1403,6 +1699,43 @@ grąžinti tik geriausiai atitinkančius įrašus, skirtus URL Automatically creating or updating string fields is not supported. Automatinis eilutės laukų kūrimas ar atnaujinimas nėra palaikomas. + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Slaptažodžių generatorius + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + PasswordGeneratorWidget @@ -1494,12 +1827,101 @@ grąžinti tik geriausiai atitinkančius įrašus, skirtus URL Excellent Puikus + + Password + Slaptažodis + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - Http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Grupė + + + Title + Antraštė + + + Username + Naudotojo vardas + + + Password + Slaptažodis + + + URL + URL + + + Notes + Pastabos + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1546,14 +1968,18 @@ grąžinti tik geriausiai atitinkančius įrašus, skirtus URL Search Paieška - - Find - Rasti - Clear Išvalyti + + Search... + + + + Limit search to selected group + + Service @@ -1661,6 +2087,10 @@ ir priimtumėte jį. Security Saugumas + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1688,10 +2118,6 @@ ir priimtumėte jį. Global Auto-Type shortcut Visuotinis automatinio rinkimo spartusis klavišas - - Use entry title to match windows for global auto-type - Naudoti įrašo antraštę, norint sutapatinti langus visuotiniam automatiniam rinkimui - Language Kalba @@ -1704,10 +2130,6 @@ ir priimtumėte jį. Hide window to system tray when minimized Suskleidus langą, slėpti jį į sistemos dėklą - - Remember last key files - Prisiminti paskutinius rakto failus - Load previous databases on startup Paleidžiant programą, įkelti ankstesnes duomenų bazes @@ -1724,6 +2146,30 @@ ir priimtumėte jį. Minimize window at application startup Paleidus programą, suskleisti langą + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Automatinis rinkimas + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1743,10 +2189,6 @@ ir priimtumėte jį. Show passwords in cleartext by default Pagal numatymą, rodyti slaptažodžius atviruoju tekstu - - Always ask before performing auto-type - Visuomet klausti prieš atliekant automatinį rinkimą - Lock databases after minimizing the window Suskleidus langą, užrakinti duomenų bazes @@ -1755,6 +2197,80 @@ ir priimtumėte jį. Don't require password repeat when it is visible Nereikalauti pakartoti slaptažodį, kai šis yra matomas + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + sek. + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1766,8 +2282,32 @@ ir priimtumėte jį. WelcomeWidget - Welcome! - Sveiki atvykę! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Paskiausios duomenų bazės @@ -1792,5 +2332,69 @@ ir priimtumėte jį. filenames of the password databases to open (*.kdbx) norimų atverti slaptažodžių duomenų bazių failų pavadinimai (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_nl_NL.ts b/share/translations/keepassx_nl_NL.ts index 33c4e62452..b15ff0a6a3 100644 --- a/share/translations/keepassx_nl_NL.ts +++ b/share/translations/keepassx_nl_NL.ts @@ -2,26 +2,106 @@ AboutDialog - Revision - Revisie + About KeePassXC + Over KeePassXC - Using: - Maakt gebruik van: + About + Over - About KeePassXC - Over KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + - Extensions: + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 - Extensies: - + + + + Revision: %1 + + + + Libraries: + - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC wordt verspreid onder de voorwaarden van de GNU General Public License (GPL) versie 2 of (als u wenst) versie 3. + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -120,10 +200,6 @@ Geef aan of u toegang wilt toestaan of niet. Create Key File... Sleutelbestand creëren... - - Error - Fout - Unable to create Key File : Het creëren van het sleutelbestand is mislukt: @@ -132,10 +208,6 @@ Geef aan of u toegang wilt toestaan of niet. Select a key file Kies een sleutelbestand - - Question - Vraag - Do you really want to use an empty string as password? Weet u zeker dat u een leeg veld als wachtwoord wilt gebruiken? @@ -144,10 +216,6 @@ Geef aan of u toegang wilt toestaan of niet. Different passwords supplied. U heeft verschillende wachtwoorden opgegeven. - - Failed to set key file - Het instellen van het sleutelbestand is mislukt - Failed to set %1 as the Key file: %2 @@ -158,6 +226,163 @@ Geef aan of u toegang wilt toestaan of niet. &Key file &Sleutelbestand + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Fout + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Fout + + + Unable to calculate master key + Niet mogelijk om hoofdsleutel te berekenen + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -177,10 +402,6 @@ Geef aan of u toegang wilt toestaan of niet. Browse Bladeren - - Error - Fout - Unable to open the database. Niet mogelijk om de database te openen. @@ -201,6 +422,14 @@ Geef aan of u toegang wilt toestaan of niet. Select key file Kies sleutelbestand + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -277,6 +506,18 @@ U kunt deze nu opslaan. Use recycle bin Prullenbak gebruiken + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -296,10 +537,6 @@ U kunt deze nu opslaan. Open database Database openen - - Warning - Waarschuwing - File not found! Bestand niet gevonden! @@ -330,10 +567,6 @@ Save changes? "%1" is gewijzigd. Opslaan? - - Error - Fout - Writing the database failed. Het opslaan van de database is mislukt. @@ -425,6 +658,14 @@ Wilt u toch doorgaan met openen? Open read-only Openen als alleen-lezen + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -464,10 +705,6 @@ Wilt u toch doorgaan met openen? Do you really want to delete the group "%1" for good? Weet u zeker dat u de groep "%1" wilt verwijderen? - - Error - Fout - Unable to calculate master key Niet mogelijk om hoofdsleutel te berekenen @@ -528,14 +765,18 @@ Wilt u toch doorgaan met openen? The database file has changed and you have unsaved changes.Do you want to merge your changes? Het database-bestand is gewijzigd en u heeft niet-opgeslagen wijzigingen. Wilt u uw wijzigingen samenvoegen? - - Autoreload Failed - Automatisch herladen mislukt - Could not open the new database file while attempting to autoreload this database. De nieuwe database kan niet worden geopend tijdens het automatisch herladen van deze database. + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -575,10 +816,6 @@ Wilt u toch doorgaan met openen? Edit entry Element wijzigen - - Error - Fout - Different passwords supplied. Verschillende wachtwoorden opgegeven. @@ -621,6 +858,22 @@ Wilt u toch doorgaan met openen? 1 year 1 jaar + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -632,10 +885,6 @@ Wilt u toch doorgaan met openen? Add Toevoegen - - Edit - Wijzigen - Remove Verwijderen @@ -652,6 +901,18 @@ Wilt u toch doorgaan met openen? Open Open + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -687,6 +948,10 @@ Wilt u toch doorgaan met openen? Set custo&m sequence: Stel aangepaste volgorde in: + + Window Associations + + EditEntryWidgetHistory @@ -796,16 +1061,16 @@ Wilt u toch doorgaan met openen? Zoeken - Auto-type - Auto-typen + Auto-Type + Auto-typen - KeePassX - Use default auto-type sequence of parent group - Gebruik standaard auto-typevolgorde van bovenliggende groep + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Stel standaard auto-typevolgorde in + Set default Auto-Type se&quence + @@ -830,10 +1095,6 @@ Wilt u toch doorgaan met openen? Select Image Kies afbeelding - - Can't delete icon! - Kan icoon niet verwijderen! - Error Fout @@ -850,10 +1111,6 @@ Wilt u toch doorgaan met openen? Can't read icon Kan icoon niet lezen - - Can't delete icon. Still used by %1 items. - Kan icoon niet verwijderen. Het wordt nog gebruikt door %1 elementen. - &Use default icon &Gebruik standaardicoon @@ -862,6 +1119,14 @@ Wilt u toch doorgaan met openen? Use custo&m icon Gebruik aangepast icoon + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -933,6 +1198,11 @@ Wilt u toch doorgaan met openen? URL URL + + Ref: + Reference abbreviation + + Group @@ -991,9 +1261,16 @@ Wilt u toch doorgaan met openen? Ensure that the password contains characters from every group Zorg ervoor dat het wachtwoord tekens uit iedere groep bevat + + + KMessageWidget - Accept - Accepteren + &Close + + + + Close message + @@ -1002,10 +1279,6 @@ Wilt u toch doorgaan met openen? Import KeePass1 database Importeer Keepass 1-database - - Error - Fout - Unable to open the database. Niet mogelijk om de database te openen. @@ -1070,6 +1343,10 @@ This is a one-way migration. You won't be able to open the imported databas U kunt het importeren door te klikken op Database > 'KeePass 1 database importeren'. Deze actie is niet omkeerbaar. U kunt de geimporteerde database niet meer openen met KeePassX 0.4. + + Unable to issue challenge-response. + + Main @@ -1081,13 +1358,17 @@ Deze actie is niet omkeerbaar. U kunt de geimporteerde database niet meer openen KeePassXC - Error KeePassX - Fout + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - Database - Open database Open database @@ -1120,10 +1401,6 @@ Deze actie is niet omkeerbaar. U kunt de geimporteerde database niet meer openen Toggle window Wissel venster - - Tools - Hulpmiddelen - KeePass 2 Database KeePass 2 Database @@ -1136,10 +1413,6 @@ Deze actie is niet omkeerbaar. U kunt de geimporteerde database niet meer openen Save repaired database Gerepareerde database opslaan - - Error - Fout - Writing the database failed. Opslaan van de database is mislukt. @@ -1232,14 +1505,26 @@ Deze actie is niet omkeerbaar. U kunt de geimporteerde database niet meer openen &Database settings &Database-instellingen - - &Import KeePass 1 database - &Importeer KeePass 1-database - &Clone entry &Kloon item + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find &Zoeken @@ -1292,6 +1577,46 @@ Deze actie is niet omkeerbaar. U kunt de geimporteerde database niet meer openen Password Generator Wachtwoord generator + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Importeer Keepass 1-database + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1307,12 +1632,6 @@ Deze actie is niet omkeerbaar. U kunt de geimporteerde database niet meer openen Sh&ow a notification when credentials are requested Toon een notificatie wanneer inloggegevens worden aangevraagd - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - &Gebruik URL-velden -Alleen items met hetzelfde schema (http://, https://, ftp://) worden gegeven. - Sort matching entries by &username Sorteer gegeven items op $gebruikersnaam @@ -1321,10 +1640,6 @@ Alleen items met hetzelfde schema (http://, https://, ftp://) worden gegeven.Re&move all stored permissions from entries in active database Verwijder alle opgeslagen permissies van items uit de actieve database - - Password generator - Wachtwoord generator - Advanced Geavanceerd @@ -1341,10 +1656,6 @@ Alleen items met hetzelfde schema (http://, https://, ftp://) worden gegeven.Searc&h in all opened databases for matching entries Zoek in alle geopende databases naar overeenkomende items - - Only the selected database has to be connected with a client! - Alleen de geselecteerde database heeft een verbinding nodig met een client! - HTTP Port: HTTP-poort: @@ -1361,12 +1672,6 @@ Alleen items met hetzelfde schema (http://, https://, ftp://) worden gegeven.Sort &matching entries by title Sorteer &overeenkomende items op titel - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - Schakel het KeePassXC HTTP-protocol in -Dit is vereist om databases vanuit ChromeIPass of PassIFox te bereiken. - KeePassXC will listen to this port on 127.0.0.1 KeePassXC zal op deze poort op 127.0.0.1 luisteren @@ -1380,21 +1685,11 @@ Dit is vereist om databases vanuit ChromeIPass of PassIFox te bereiken. Kan niet binden naar bevoorrechte poorten onder 1024! Standaardpoort 19455 wordt gebruikt. - - - &Return only best matching entries for a URL instead -of all entries for the whole domain - &Geef alleen de meest overeenkomende items voor een URL -in plaats van alle items voor het gehele domein R&emove all shared encryption keys from active database Verwijder alle gedeelde encryptiesleutels uit de actieve database - - The following options can be dangerous. Change them only if you know what you are doing. - De volgende opties kunnen gevaarlijk zijn. Verander deze dus alleen als je weet wat je doet. - &Return advanced string fields which start with "KPH: " &Geef geadvanceerde tekenreeks velden terug die met "KH: " beginnen. @@ -1403,6 +1698,43 @@ in plaats van alle items voor het gehele domein Automatically creating or updating string fields is not supported. Het automatisch aanmaken of wijzigen van tekenreeks velden wordt niet ondersteund. + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Wachtwoord generator + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + PasswordGeneratorWidget @@ -1494,12 +1826,101 @@ in plaats van alle items voor het gehele domein Excellent Uitstekend + + Password + Wachtwoord + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - HTTP + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Groep + + + Title + Titel + + + Username + Gebruikersnaam + + + Password + Wachtwoord + + + URL + URL + + + Notes + Opmerkingen + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1546,14 +1967,18 @@ in plaats van alle items voor het gehele domein Search Zoeken - - Find - Zoek - Clear Wissen + + Search... + + + + Limit search to selected group + + Service @@ -1659,6 +2084,10 @@ Geef het een unieke identificerende naam en accepteer de associate wanneer je de Security Beveiliging + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1686,10 +2115,6 @@ Geef het een unieke identificerende naam en accepteer de associate wanneer je de Global Auto-Type shortcut Globale sneltoets voor auto-typen - - Use entry title to match windows for global auto-type - Gebruik titel van item als vensternaam voor auto-typen - Language Taal @@ -1702,10 +2127,6 @@ Geef het een unieke identificerende naam en accepteer de associate wanneer je de Hide window to system tray when minimized Bij minimaliseren enkel icoon in systray tonen - - Remember last key files - Onthoud laatste sleutelbestanden - Load previous databases on startup Open vorige databases bij starten @@ -1722,6 +2143,30 @@ Geef het een unieke identificerende naam en accepteer de associate wanneer je de Minimize window at application startup Scherm minimaliseren bij het opstarten + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Auto-typen - KeePassX + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1741,10 +2186,6 @@ Geef het een unieke identificerende naam en accepteer de associate wanneer je de Show passwords in cleartext by default Laat wachtwoorden standaard zien - - Always ask before performing auto-type - Altijd vragen alvorens auto-type uit te voeren - Lock databases after minimizing the window Vergrendel databases na het minimaliseren van het scherm @@ -1753,6 +2194,80 @@ Geef het een unieke identificerende naam en accepteer de associate wanneer je de Don't require password repeat when it is visible Herhalen van wachtwoord niet vereisen als deze zichtbaar is + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + sec + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1764,8 +2279,32 @@ Geef het een unieke identificerende naam en accepteer de associate wanneer je de WelcomeWidget - Welcome! - Welkom! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Recente databases @@ -1790,5 +2329,69 @@ Geef het een unieke identificerende naam en accepteer de associate wanneer je de filenames of the password databases to open (*.kdbx) bestandsnamen van de te openen wachtwoorddatabases (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_pl.ts b/share/translations/keepassx_pl.ts index ba964d96a0..2462b13043 100644 --- a/share/translations/keepassx_pl.ts +++ b/share/translations/keepassx_pl.ts @@ -2,26 +2,106 @@ AboutDialog - Revision - Rewizja + About KeePassXC + O KeePassXC - Using: - Używa: + About + O - About KeePassXC - O KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + - Extensions: + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 - Rozszerzenia: - + - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC jest dystrybuowany zgodnie z warunkami licencji GNU General Public License (GPL) w wersji 2 lub (opcjonalnie) w wersji 3. + Revision: %1 + + + + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -120,10 +200,6 @@ Wybierz, czy chcesz zezwolić na dostęp. Create Key File... Utwórz plik klucza - - Error - Błąd - Unable to create Key File : Nie można utworzyć pliku klucza : @@ -132,10 +208,6 @@ Wybierz, czy chcesz zezwolić na dostęp. Select a key file Wybierz plik z kluczem - - Question - Pytanie - Do you really want to use an empty string as password? Czy naprawdę chcesz użyć pusty ciąg znaków jako hasło ? @@ -144,10 +216,6 @@ Wybierz, czy chcesz zezwolić na dostęp. Different passwords supplied. Podano różne hasła. - - Failed to set key file - Nie udało się ustawić pliku klucza - Failed to set %1 as the Key file: %2 @@ -158,6 +226,163 @@ Wybierz, czy chcesz zezwolić na dostęp. &Key file &Plik klucza + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Błąd + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Błąd + + + Unable to calculate master key + Nie mogę wyliczyć głównego klucza + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -177,10 +402,6 @@ Wybierz, czy chcesz zezwolić na dostęp. Browse Przeglądaj - - Error - Błąd - Unable to open the database. Nie można otworzyć bazy kluczy. @@ -201,6 +422,14 @@ Wybierz, czy chcesz zezwolić na dostęp. Select key file Wybierz plik z kluczem + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -277,6 +506,18 @@ Możesz teraz ją już zapisać. Use recycle bin Użyj kosza: + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -296,10 +537,6 @@ Możesz teraz ją już zapisać. Open database Otwórz bazę danych - - Warning - Ostrzeżenie - File not found! Nie znaleziono pliku! @@ -330,10 +567,6 @@ Save changes? "%1" został zmieniony. Zapisać zmiany? - - Error - Błąd - Writing the database failed. Błąd w zapisywaniu bazy kluczy. @@ -426,6 +659,14 @@ Czy chcesz ją otworzyć mimo to? Open read-only Otwórz tylko do odczytu + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -465,10 +706,6 @@ Czy chcesz ją otworzyć mimo to? Do you really want to delete the group "%1" for good? Czy na pewno całkowicie usunąć grupę "%1"? - - Error - Błąd - Unable to calculate master key Nie mogę wyliczyć głównego klucza @@ -529,14 +766,18 @@ Czy chcesz ją otworzyć mimo to? The database file has changed and you have unsaved changes.Do you want to merge your changes? Plik bazy danych został zmieniony, a masz niezapisane zmiany. Czy chcesz połączyć twoje zmiany? - - Autoreload Failed - Nieudane automatyczne przeładowanie - Could not open the new database file while attempting to autoreload this database. Nie można otworzyć nowego pliku bazy danych podczas próby automatycznego przeładowania tej bazy. + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -576,10 +817,6 @@ Czy chcesz ją otworzyć mimo to? Edit entry Edycja wpisu - - Error - Błąd - Different passwords supplied. Podano różne hasła. @@ -622,6 +859,22 @@ Czy chcesz ją otworzyć mimo to? 1 year 1 rok + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -633,10 +886,6 @@ Czy chcesz ją otworzyć mimo to? Add Dodaj - - Edit - Edytuj - Remove Usuń @@ -653,6 +902,18 @@ Czy chcesz ją otworzyć mimo to? Open Otwórz + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -688,6 +949,10 @@ Czy chcesz ją otworzyć mimo to? Set custo&m sequence: Ustaw niest&andardową sekwencję: + + Window Associations + + EditEntryWidgetHistory @@ -797,16 +1062,16 @@ Czy chcesz ją otworzyć mimo to? Szukaj - Auto-type + Auto-Type Auto-uzupełnianie - Use default auto-type sequence of parent group - Korzystaj z domyślnej sekwencji auto-uzupełniania z nadrzędnej grupy + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Ustaw domyślną sekwencję auto-uzupełniania + Set default Auto-Type se&quence + @@ -831,10 +1096,6 @@ Czy chcesz ją otworzyć mimo to? Select Image Wybierz obraz - - Can't delete icon! - Nie można usunąć ikony! - Error Błąd @@ -851,10 +1112,6 @@ Czy chcesz ją otworzyć mimo to? Can't read icon Nie można odczytać ikony - - Can't delete icon. Still used by %1 items. - Nie można usunąć ikony. Nadal używana przez %1 wpisów. - &Use default icon &Użyj ikony domyślnej @@ -863,6 +1120,14 @@ Czy chcesz ją otworzyć mimo to? Use custo&m icon Użyj niesta&ndardowej ikony + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -934,6 +1199,11 @@ Czy chcesz ją otworzyć mimo to? URL URL + + Ref: + Reference abbreviation + + Group @@ -992,9 +1262,16 @@ Czy chcesz ją otworzyć mimo to? Ensure that the password contains characters from every group Zapewnij, że hasło będzie zawierało znaki ze wszystkich grup + + + KMessageWidget - Accept - Zaakceptuj + &Close + + + + Close message + @@ -1003,10 +1280,6 @@ Czy chcesz ją otworzyć mimo to? Import KeePass1 database Importuj bazę danych KeePass1 - - Error - Błąd - Unable to open the database. Nie można otworzyć bazy kluczy. @@ -1071,6 +1344,10 @@ This is a one-way migration. You won't be able to open the imported databas Możesz zaimportować ją przez wybranie Baza > 'Importuj bazę danych KeePass 1'. Nie będzie można skonwertować nowej bazy do starego programu KeePassX 0.4. + + Unable to issue challenge-response. + + Main @@ -1082,13 +1359,17 @@ Nie będzie można skonwertować nowej bazy do starego programu KeePassX 0.4.KeePassXC - Error KeePassXC - Błąd + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - Baza danych - Open database Otwórz bazę danych @@ -1121,10 +1402,6 @@ Nie będzie można skonwertować nowej bazy do starego programu KeePassX 0.4.Toggle window Pokaż/ukryj okno - - Tools - Narzędzia - KeePass 2 Database Baza KeePass 2 @@ -1137,10 +1414,6 @@ Nie będzie można skonwertować nowej bazy do starego programu KeePassX 0.4.Save repaired database Zapisz naprawioną bazę - - Error - Błąd - Writing the database failed. Błąd przy zapisie bazy. @@ -1163,11 +1436,11 @@ Nie będzie można skonwertować nowej bazy do starego programu KeePassX 0.4. &Groups - %Grupy + &Grupy &View - Wi%dok + Wi&dok &Quit @@ -1233,14 +1506,26 @@ Nie będzie można skonwertować nowej bazy do starego programu KeePassX 0.4.&Database settings Ustawienia bazy &danych - - &Import KeePass 1 database - I&mportuj bazę danych KeePass 1 - &Clone entry &Sklonuj wpis + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find &Znajdź @@ -1293,6 +1578,46 @@ Nie będzie można skonwertować nowej bazy do starego programu KeePassX 0.4.Password Generator Generator hasła + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Importuj bazę danych KeePass 1 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1308,12 +1633,6 @@ Nie będzie można skonwertować nowej bazy do starego programu KeePassX 0.4.Sh&ow a notification when credentials are requested P&okaż powiadomienie, gdy wymagane są poświadczenia - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - &Dopasuj schematy URL -Tylko wpisy z tym samym schematem (http://, https://, ftp://, ...) są zwracane - Sort matching entries by &username Sortuj dopasowane wpisy według &użytkownika @@ -1322,10 +1641,6 @@ Tylko wpisy z tym samym schematem (http://, https://, ftp://, ...) są zwracane< Re&move all stored permissions from entries in active database U&suń wszystkie przechowywane uprawnienia z wpisów w aktywnej bazie danych - - Password generator - Generator hasła - Advanced Zaawansowane @@ -1342,10 +1657,6 @@ Tylko wpisy z tym samym schematem (http://, https://, ftp://, ...) są zwracane< Searc&h in all opened databases for matching entries Szuk&aj we wszystkich otwartych bazach dopasowanych wpisów - - Only the selected database has to be connected with a client! - Tylko wybrana baza danych musi być podłączona do klienta! - HTTP Port: Port HTTP: @@ -1362,12 +1673,6 @@ Tylko wpisy z tym samym schematem (http://, https://, ftp://, ...) są zwracane< Sort &matching entries by title Sortuj dopasowane wpisy według &tytułu - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - Włącz protokół HTTP KeepassXC -Jest to wymagane dla dostępu do twoich baz danych z ChromeIPass albo PassIFox - KeePassXC will listen to this port on 127.0.0.1 KeePassXC będzie nasłuchiwać ten port na 127.0.0.1 @@ -1381,21 +1686,11 @@ Jest to wymagane dla dostępu do twoich baz danych z ChromeIPass albo PassIFox Nie można powiązać do uprzywilejowanych portów poniżej 1024! Używam domyślnego portu 19455. - - - &Return only best matching entries for a URL instead -of all entries for the whole domain - &Zwracaj tylko najlepsze dopasowania wpisów dla URL zamiast -wszystkich wpisów całej domeny R&emove all shared encryption keys from active database U&suń wszystkie współdzielone klucze szyfrujące z aktywnej bazy danych - - The following options can be dangerous. Change them only if you know what you are doing. - Poniższe opcje mogą być niebezpieczne. Zmieniaj je tylko wtedy, gdy wiesz, co robisz. - &Return advanced string fields which start with "KPH: " &Zwracaj zaawansowane pola ciągów znaków, które zaczynają się od "KPH: " @@ -1404,6 +1699,43 @@ wszystkich wpisów całej domeny Automatically creating or updating string fields is not supported. Automatyczne tworzenie albo aktualizowanie pól ciągów znaków nie jest obsługiwane. + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Generator hasła + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + PasswordGeneratorWidget @@ -1453,7 +1785,7 @@ wszystkich wpisów całej domeny &Length: - %Długość: + &Długość: Pick characters from every group @@ -1495,12 +1827,101 @@ wszystkich wpisów całej domeny Excellent Znakomita + + Password + Hasło + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - HTTP + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Grupa + + + Title + Tytuł + + + Username + Użytkownik + + + Password + Hasło + + + URL + URL + + + Notes + Notatki + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1547,14 +1968,18 @@ wszystkich wpisów całej domeny Search Szukaj - - Find - Znajdź - Clear Wyczyść + + Search... + + + + Limit search to selected group + + Service @@ -1661,6 +2086,10 @@ nadaj unikatową nazwę do zidentyfikowania i zaakceptuj. Security Bezpieczeństwo + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1688,10 +2117,6 @@ nadaj unikatową nazwę do zidentyfikowania i zaakceptuj. Global Auto-Type shortcut Globalny skrót auto-uzupełnianie - - Use entry title to match windows for global auto-type - Wykorzystaj tytuł wpisu do dopasowania okien dla globalnego auto-wpisywania - Language Język @@ -1704,10 +2129,6 @@ nadaj unikatową nazwę do zidentyfikowania i zaakceptuj. Hide window to system tray when minimized Schowaj okno do zasobnika podczas minimalizacji - - Remember last key files - Zapamiętaj ostatnie pliki klucza - Load previous databases on startup Załaduj poprzednie bazy danych podczas uruchomienia @@ -1724,6 +2145,30 @@ nadaj unikatową nazwę do zidentyfikowania i zaakceptuj. Minimize window at application startup Minimalizuj okno podczas uruchomienia aplikacji + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Auto-uzupełnianie + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1743,10 +2188,6 @@ nadaj unikatową nazwę do zidentyfikowania i zaakceptuj. Show passwords in cleartext by default Domyślnie pokazuj hasła - - Always ask before performing auto-type - Zawsze pytaj przed wykonaniem auto-uzupełninia - Lock databases after minimizing the window Zablokuj bazę danych po zminimalizowaniu okna @@ -1755,6 +2196,80 @@ nadaj unikatową nazwę do zidentyfikowania i zaakceptuj. Don't require password repeat when it is visible Nie wymagaj powtarzania hasła, gdy jest widoczne + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + s + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1766,8 +2281,32 @@ nadaj unikatową nazwę do zidentyfikowania i zaakceptuj. WelcomeWidget - Welcome! - Witaj! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Niedawne bazy danych @@ -1792,5 +2331,69 @@ nadaj unikatową nazwę do zidentyfikowania i zaakceptuj. filenames of the password databases to open (*.kdbx) nazwy plików baz danych haseł do otwarcia (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_pt_BR.ts b/share/translations/keepassx_pt_BR.ts index 16bb4a32e0..a8b33de983 100644 --- a/share/translations/keepassx_pt_BR.ts +++ b/share/translations/keepassx_pt_BR.ts @@ -2,26 +2,106 @@ AboutDialog - Revision - Revisão + About KeePassXC + Sobre KeePassXC - Using: - Usando: + About + Sobre - About KeePassXC - Sobre KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + - Extensions: + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 - Extensões: - + - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC é distribuído nos termos da Licença Pública Geral (GPL), versão 2 ou (à sua escolha) versão 3, do GNU. + Revision: %1 + + + + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -120,10 +200,6 @@ Selecione se deseja permitir o acesso. Create Key File... Criar Arquivo-Chave... - - Error - Erro - Unable to create Key File : Não foi possível criar o Arquivo-Chave : @@ -132,10 +208,6 @@ Selecione se deseja permitir o acesso. Select a key file Escolha um arquivo-chave - - Question - Pergunta - Do you really want to use an empty string as password? Você realmente quer usar uma sequência vazia como senha? @@ -144,10 +216,6 @@ Selecione se deseja permitir o acesso. Different passwords supplied. Senhas diferentes fornecidas. - - Failed to set key file - Falha ao definir arquivo-chave - Failed to set %1 as the Key file: %2 @@ -158,6 +226,163 @@ Selecione se deseja permitir o acesso. &Key file &Arquivo-Chave + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Erro + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Erro + + + Unable to calculate master key + Não foi possível calcular a chave mestre + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -177,10 +402,6 @@ Selecione se deseja permitir o acesso. Browse Navegar - - Error - Erro - Unable to open the database. Não foi possível abrir o banco de dados. @@ -201,6 +422,14 @@ Selecione se deseja permitir o acesso. Select key file Escolha o arquivo-chave + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -277,6 +506,18 @@ Você pode salvá-lo agora. Use recycle bin Usar lixeira + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -296,10 +537,6 @@ Você pode salvá-lo agora. Open database Abrir banco de dados - - Warning - Aviso - File not found! Arquivo não localizado! @@ -330,10 +567,6 @@ Save changes? "%1" foi modificado. Salvar alterações? - - Error - Erro - Writing the database failed. Escrever no banco de dados falhou. @@ -426,6 +659,14 @@ Mesmo assim deseja salvá-la? Open read-only Abrir somente leitura + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -465,10 +706,6 @@ Mesmo assim deseja salvá-la? Do you really want to delete the group "%1" for good? Você realmente quer apagar o grupo "%1" para sempre? - - Error - Erro - Unable to calculate master key Não foi possível calcular chave mestra @@ -529,14 +766,18 @@ Mesmo assim deseja salvá-la? The database file has changed and you have unsaved changes.Do you want to merge your changes? A base de dados foi alterada e tem alterações não gravadas. Deseja juntar as suas alterações? - - Autoreload Failed - Carregamento Automático Falhou - Could not open the new database file while attempting to autoreload this database. Não foi possível abrir a nova base de dados ao tentar recarregar automaticamente essa base de dados. + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -576,10 +817,6 @@ Mesmo assim deseja salvá-la? Edit entry Editar entrada - - Error - Erro - Different passwords supplied. Senhas diferentes fornecidas. @@ -622,6 +859,22 @@ Mesmo assim deseja salvá-la? 1 year 1 ano + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -633,10 +886,6 @@ Mesmo assim deseja salvá-la? Add Adicionar - - Edit - Editar - Remove Remover @@ -653,6 +902,18 @@ Mesmo assim deseja salvá-la? Open Abrir + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -688,6 +949,10 @@ Mesmo assim deseja salvá-la? Set custo&m sequence: Definir sequência &personalizada: + + Window Associations + + EditEntryWidgetHistory @@ -797,16 +1062,16 @@ Mesmo assim deseja salvá-la? Buscar - Auto-type - Auto-digitar + Auto-Type + Auto-Digitação - Use default auto-type sequence of parent group - Usar sequência de auto-digitação padrão do grupo pai + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Definir sequência auto-digitação padrão + Set default Auto-Type se&quence + @@ -831,10 +1096,6 @@ Mesmo assim deseja salvá-la? Select Image Selecionar imagem - - Can't delete icon! - Não é possível apagar o ícone! - Error Erro @@ -851,10 +1112,6 @@ Mesmo assim deseja salvá-la? Can't read icon Não foi possível ler ícone - - Can't delete icon. Still used by %1 items. - Não é possível apagar ícone. Ainda usado por %1 itens. - &Use default icon &Usar ícone padrão @@ -863,6 +1120,14 @@ Mesmo assim deseja salvá-la? Use custo&m icon Usar ícone &personalizado + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -934,6 +1199,11 @@ Mesmo assim deseja salvá-la? URL URL + + Ref: + Reference abbreviation + + Group @@ -992,9 +1262,16 @@ Mesmo assim deseja salvá-la? Ensure that the password contains characters from every group Verificar se a senha contém caracteres de todos os grupos + + + KMessageWidget - Accept - Aceitar + &Close + + + + Close message + @@ -1003,10 +1280,6 @@ Mesmo assim deseja salvá-la? Import KeePass1 database Importar banco de dados KeePass1 - - Error - Erro - Unable to open the database. Não foi possível abrir o banco de dados. @@ -1071,6 +1344,10 @@ This is a one-way migration. You won't be able to open the imported databas Você pode importá-lo clicando em Banco de Dados > 'Importar banco de dados KeePass 1'. Esta é uma migração de uma via. Você não poderá abrir o banco de dados importado com a versão antiga do KeePassX 0.4. + + Unable to issue challenge-response. + + Main @@ -1082,13 +1359,17 @@ Esta é uma migração de uma via. Você não poderá abrir o banco de dados imp KeePassXC - Error KeePassXC - Erro + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - Banco de Dados - Open database Abrir banco de dados @@ -1121,10 +1402,6 @@ Esta é uma migração de uma via. Você não poderá abrir o banco de dados imp Toggle window Alternar Janela - - Tools - Ferramentas - KeePass 2 Database Banco de dados Keepass 2 @@ -1137,10 +1414,6 @@ Esta é uma migração de uma via. Você não poderá abrir o banco de dados imp Save repaired database Salvar banco de dados reparado - - Error - Erro - Writing the database failed. Escrita do banco de dados falhou. @@ -1233,14 +1506,26 @@ Esta é uma migração de uma via. Você não poderá abrir o banco de dados imp &Database settings &Definições da base de dados - - &Import KeePass 1 database - &Importar base de dados KeePass 1 - &Clone entry &Clonar entrada + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find &Encontrar @@ -1293,6 +1578,46 @@ Esta é uma migração de uma via. Você não poderá abrir o banco de dados imp Password Generator Gerador de Senha + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Importar banco de dados KeePass1 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1308,12 +1633,6 @@ Esta é uma migração de uma via. Você não poderá abrir o banco de dados imp Sh&ow a notification when credentials are requested M&ostrar uma notificação quando as credenciais forem solicitadas - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - &Esquemas de URL coincidentes -Somente entradas com o mesmo esquema (http://, https://, ftp://, ...) são mostradas - Sort matching entries by &username Ordenar entradas coincidentes por nome de &usuário @@ -1322,10 +1641,6 @@ Somente entradas com o mesmo esquema (http://, https://, ftp://, ...) são mostr Re&move all stored permissions from entries in active database R&emover todas as permissões armazenadas de entradas na base de dados ativa - - Password generator - Gerador de senha - Advanced Avançado @@ -1342,10 +1657,6 @@ Somente entradas com o mesmo esquema (http://, https://, ftp://, ...) são mostr Searc&h in all opened databases for matching entries Procurar em todas as base de dados abertas por entradas semel&hantes - - Only the selected database has to be connected with a client! - Somente a base de dados selecionada tem que ser conectada com um cliente! - HTTP Port: Porta HTTP: @@ -1362,12 +1673,6 @@ Somente entradas com o mesmo esquema (http://, https://, ftp://, ...) são mostr Sort &matching entries by title Ordenar &entradas por título - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - Habilitar o protocolo KeepassXC HTTP -Isso é necessário para acessar os seus bancos de dados usando o ChromeIPass ou PassIFox - KeePassXC will listen to this port on 127.0.0.1 KeePassXC irá escutar esta porta em 127.0.0.1 @@ -1381,21 +1686,11 @@ Isso é necessário para acessar os seus bancos de dados usando o ChromeIPass ou Using default port 19455. Não é possível ligar a portas privilegiadas abaixo de 1024! Usando porta padrão 19455. - - - &Return only best matching entries for a URL instead -of all entries for the whole domain - &Mostrar apenas as melhores entradas correspondentes para um URL em vez de -todas as entradas para o domínio completo R&emove all shared encryption keys from active database R&emover todas as chaves criptografadas compartilhadas da base de dados ativa - - The following options can be dangerous. Change them only if you know what you are doing. - As configurações abaixo podem ser perigosas. Altere-as somente se souber o que está fazendo. - &Return advanced string fields which start with "KPH: " &Mostrar também campos avançados que começam com "KPH: " @@ -1404,6 +1699,43 @@ todas as entradas para o domínio completo Automatically creating or updating string fields is not supported. Criação automática ou atualizações não são suportadas para os valores dos campos. + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Gerador de Senha + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + PasswordGeneratorWidget @@ -1495,12 +1827,101 @@ todas as entradas para o domínio completo Excellent Excelente + + Password + Senha + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - Http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Grupo + + + Title + Título + + + Username + Nome de usuário + + + Password + Senha + + + URL + URL + + + Notes + Notas + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1547,14 +1968,18 @@ todas as entradas para o domínio completo Search Pesquisar - - Find - Localizar - Clear Limpar + + Search... + + + + Limit search to selected group + + Service @@ -1661,6 +2086,10 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Security Segurança + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1688,10 +2117,6 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Global Auto-Type shortcut Atalho para Auto-Digitação Global - - Use entry title to match windows for global auto-type - Usar título da entrada para comparar janelas para auto-digitação global - Language Idioma @@ -1704,10 +2129,6 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Hide window to system tray when minimized Ocultar janela na bandeja de sistema quando minimizada - - Remember last key files - Lembrar dos últimos arquivos-chave - Load previous databases on startup Carregar bancos de dados anteriores na inicialização @@ -1724,6 +2145,30 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Minimize window at application startup Iniciar programa com janela minimizada + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Auto-Digitação + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1743,10 +2188,6 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Show passwords in cleartext by default Mostrar senhas em texto claro por padrão - - Always ask before performing auto-type - Sempre perguntar antes de realizar auto-digitação - Lock databases after minimizing the window Bloquear bancos de dados após minimizar a janela @@ -1755,6 +2196,80 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Don't require password repeat when it is visible Quando a senha for visível não pedir para repeti-la + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + seg + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1766,8 +2281,32 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. WelcomeWidget - Welcome! - Bem-vindo! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Bancos de dados recentes @@ -1792,5 +2331,69 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. filenames of the password databases to open (*.kdbx) nome de arquivo do banco de dados de senhas a ser aberto (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_pt_PT.ts b/share/translations/keepassx_pt_PT.ts index d2f1654017..2ceb726729 100644 --- a/share/translations/keepassx_pt_PT.ts +++ b/share/translations/keepassx_pt_PT.ts @@ -2,26 +2,106 @@ AboutDialog - Revision - Revisão + About KeePassXC + Sobre KeePassXC - Using: - Usando: + About + Sobre - About KeePassXC - Sobre KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + - Extensions: + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 - Extensões: - + + + + Revision: %1 + + + + Libraries: + - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC é distribuído sob os termos da GNU General Public License (GPL) versão 2 ou (em sua opção) versão 3. + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -120,10 +200,6 @@ Selecione se deseja permitir o acesso. Create Key File... Criar ficheiro chave - - Error - Erro - Unable to create Key File : Impossível criar ficheiro chave: @@ -132,10 +208,6 @@ Selecione se deseja permitir o acesso. Select a key file Seleccionar ficheiro chave - - Question - Questão - Do you really want to use an empty string as password? Pretende utilizar um valor sem conteúdo como senha ? @@ -144,10 +216,6 @@ Selecione se deseja permitir o acesso. Different passwords supplied. As senhas inseridas não coincidem. - - Failed to set key file - Falha ao definir o ficheiro chave - Failed to set %1 as the Key file: %2 @@ -158,6 +226,163 @@ Selecione se deseja permitir o acesso. &Key file Ficheiro &chave + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Erro + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Erro + + + Unable to calculate master key + Impossível calcular chave mestra: + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -177,10 +402,6 @@ Selecione se deseja permitir o acesso. Browse Procurar - - Error - Erro - Unable to open the database. Impossível abrir a base de dados. @@ -201,6 +422,14 @@ Selecione se deseja permitir o acesso. Select key file Seleccionar o ficheiro chave + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -277,6 +506,18 @@ Agora pode gravar. Use recycle bin Utilizar reciclagem + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -296,10 +537,6 @@ Agora pode gravar. Open database Abrir base de dados - - Warning - Aviso - File not found! Ficheiro não encontrado ! @@ -330,10 +567,6 @@ Save changes? "%1" foi modificado. Guardar alterações ? - - Error - Erro - Writing the database failed. Falha na escrita da base de dados. @@ -426,6 +659,14 @@ Você quer abri-lo de qualquer maneira? Open read-only Abrir como somente leitura + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -465,10 +706,6 @@ Você quer abri-lo de qualquer maneira? Do you really want to delete the group "%1" for good? Pretender realmente apagar o grupo "%1" para sempre ? - - Error - Erro - Unable to calculate master key Impossível calcular ficheiro chave @@ -530,14 +767,18 @@ Você quer abri-lo de qualquer maneira? The database file has changed and you have unsaved changes.Do you want to merge your changes? O ficheiro da base de dados foi alterado e tem alterações não gravadas. Deseja juntar as suas alterações? - - Autoreload Failed - Carregamento Automático Falhou - Could not open the new database file while attempting to autoreload this database. Não foi possível abrir a nova base de dados ao tentar recarregar automaticamente essa base de dados. + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -577,10 +818,6 @@ Você quer abri-lo de qualquer maneira? Edit entry Editar entrada - - Error - Erro - Different passwords supplied. As senhas inseridas não coincidem. @@ -622,6 +859,22 @@ Você quer abri-lo de qualquer maneira? 1 year 1 ano + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -633,10 +886,6 @@ Você quer abri-lo de qualquer maneira? Add Adicionar - - Edit - Editar - Remove Remover @@ -653,6 +902,18 @@ Você quer abri-lo de qualquer maneira? Open Abrir + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -688,6 +949,10 @@ Você quer abri-lo de qualquer maneira? Set custo&m sequence: Especificar sequência de personalizada: + + Window Associations + + EditEntryWidgetHistory @@ -797,16 +1062,16 @@ Você quer abri-lo de qualquer maneira? Procurar - Auto-type + Auto-Type Auto escrita - Use default auto-type sequence of parent group - Herdar sequência de auto escrita padrão do grupo relacionado + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Especificar sequência padrão de auto escrita + Set default Auto-Type se&quence + @@ -831,10 +1096,6 @@ Você quer abri-lo de qualquer maneira? Select Image Seleccionar imagem - - Can't delete icon! - Impossível apagar o icon - Error Erro @@ -851,10 +1112,6 @@ Você quer abri-lo de qualquer maneira? Can't read icon Não foi possível ler ícone - - Can't delete icon. Still used by %1 items. - Não é possível apagar ícone. Ainda usado por %1 itens. - &Use default icon &Utilizar icon padrão @@ -863,6 +1120,14 @@ Você quer abri-lo de qualquer maneira? Use custo&m icon Utilizar icon personalizado + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -934,6 +1199,11 @@ Você quer abri-lo de qualquer maneira? URL URL + + Ref: + Reference abbreviation + + Group @@ -992,9 +1262,16 @@ Você quer abri-lo de qualquer maneira? Ensure that the password contains characters from every group Verificar que a senha contém caracteres de todos os grupos + + + KMessageWidget + + &Close + + - Accept - Aceitar + Close message + @@ -1003,10 +1280,6 @@ Você quer abri-lo de qualquer maneira? Import KeePass1 database Importar de dados KeePass 1 - - Error - Erro - Unable to open the database. Impossível abrir a base de dados. @@ -1071,6 +1344,10 @@ This is a one-way migration. You won't be able to open the imported databas Pode importá-lo clicando em Base de dados> 'Importar base de dados KeePass 1'. Esta é uma migração unidirecional. Não será possível abrir a base de dados importada com a versão antiga do KeePassX 0.4. + + Unable to issue challenge-response. + + Main @@ -1082,13 +1359,17 @@ Esta é uma migração unidirecional. Não será possível abrir a base de dados KeePassXC - Error KeePassXC - Erro + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - Base de dados - Open database Abrir base de dados @@ -1121,10 +1402,6 @@ Esta é uma migração unidirecional. Não será possível abrir a base de dados Toggle window Alternar janela - - Tools - Ferramentas - KeePass 2 Database Base de dados KeePass 2 @@ -1137,10 +1414,6 @@ Esta é uma migração unidirecional. Não será possível abrir a base de dados Save repaired database Gravar base de dados reparada - - Error - Erro - Writing the database failed. Falha na escrita da base de dados. @@ -1233,14 +1506,26 @@ Esta é uma migração unidirecional. Não será possível abrir a base de dados &Database settings &Definições da base de dados - - &Import KeePass 1 database - &Importar de dados KeePass 1 - &Clone entry &Clonar entrada + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find &Encontrar @@ -1293,6 +1578,46 @@ Esta é uma migração unidirecional. Não será possível abrir a base de dados Password Generator Gerador de senhas + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Importar base de dados KeePass 1 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1308,12 +1633,6 @@ Esta é uma migração unidirecional. Não será possível abrir a base de dados Sh&ow a notification when credentials are requested M&ostrar uma notificação quando as credenciais forem solicitadas - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - &Esquemas de URL coincidentes -Somente entradas com o mesmo esquema (http://, https://, ftp://, ...) são mostradas - Sort matching entries by &username Ordenar entradas coincidentes por nome de &utilizador @@ -1322,10 +1641,6 @@ Somente entradas com o mesmo esquema (http://, https://, ftp://, ...) são mostr Re&move all stored permissions from entries in active database R&emover todas as permissões armazenadas de entradas na base de dados ativa - - Password generator - Gerador de senhas - Advanced Avançado @@ -1342,10 +1657,6 @@ Somente entradas com o mesmo esquema (http://, https://, ftp://, ...) são mostr Searc&h in all opened databases for matching entries Procurar em todas as base de dados abertas por entradas semel&hantes - - Only the selected database has to be connected with a client! - Somente a base de dados selecionada tem que ser conectada com um cliente! - HTTP Port: Porto HTTP: @@ -1362,12 +1673,6 @@ Somente entradas com o mesmo esquema (http://, https://, ftp://, ...) são mostr Sort &matching entries by title Ordenar entradas por título - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - Ativar o protocolo KeepassXC HTTP -Isso é necessário para acessar a sua base de dados a partir do ChromeIPass ou do PassIFox - KeePassXC will listen to this port on 127.0.0.1 KeePassXC vai escutar neste porto em 127.0.0.1 @@ -1381,21 +1686,11 @@ Isso é necessário para acessar a sua base de dados a partir do ChromeIPass ou Using default port 19455. Não é possível ligar a portos privilegiados abaixo de 1024! A utilizar porto por omissão 19455 - - - &Return only best matching entries for a URL instead -of all entries for the whole domain - &Mostrar apenas as melhores entradas correspondentes para um URL em vez -de todas as entradas para todo o domínio R&emove all shared encryption keys from active database R&emover todas as chaves encriptadas partilhadas da base de dados ativa - - The following options can be dangerous. Change them only if you know what you are doing. - As seguintes opções podem ser perigosas. Mudá-los apenas se você sabe o que está fazendo. - &Return advanced string fields which start with "KPH: " &Mostrar também campos avançados que começam com "KPH: " @@ -1404,6 +1699,43 @@ de todas as entradas para todo o domínio Automatically creating or updating string fields is not supported. Automaticamente criando ou atualizando os campos de sequência de caracteres não é suportado. + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Gerador de senhas + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + PasswordGeneratorWidget @@ -1495,12 +1827,101 @@ de todas as entradas para todo o domínio Excellent Excelente + + Password + Senha + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - Http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Grupo + + + Title + Título + + + Username + Nome de utilizador + + + Password + Senha + + + URL + URL + + + Notes + Notas + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1547,14 +1968,18 @@ de todas as entradas para todo o domínio Search Procurar - - Find - Encontrar - Clear Limpar + + Search... + + + + Limit search to selected group + + Service @@ -1661,6 +2086,10 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Security Segurança + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1688,10 +2117,6 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Global Auto-Type shortcut Atalho global de auto escrita - - Use entry title to match windows for global auto-type - Utilizar titulo de entrada para coincidir com janela de entrada de auto escrita global - Language Língua @@ -1704,10 +2129,6 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Hide window to system tray when minimized Esconder janela na barra de sistema quando minimizada - - Remember last key files - Lembrar os últimos ficheiro chave - Load previous databases on startup Carregar base de dados anterior no arranque @@ -1724,6 +2145,30 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Minimize window at application startup Minimizar janela no arranque da aplicação + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Auto escrita + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1743,10 +2188,6 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Show passwords in cleartext by default Revelar senhas em texto por padrão - - Always ask before performing auto-type - Confirmar antes de executar auto escrita - Lock databases after minimizing the window Trancar base de dados ao minimizar a janela @@ -1755,6 +2196,80 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. Don't require password repeat when it is visible Não exigir a repetição da senha quando ela estiver visível + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + seg + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1766,8 +2281,32 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. WelcomeWidget - Welcome! - Bem vindo/a ! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Base de dados recentes @@ -1792,5 +2331,69 @@ dar-lhe um nome único para identificá-lo e aceitá-lo. filenames of the password databases to open (*.kdbx) ficheiro chave para abrir a base de dados (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_ru.ts b/share/translations/keepassx_ru.ts index faca7e2f06..59fc73b376 100644 --- a/share/translations/keepassx_ru.ts +++ b/share/translations/keepassx_ru.ts @@ -2,26 +2,106 @@ AboutDialog - Revision - Ревизия + About KeePassXC + О KeePassXC - Using: - С помощью: + About + О программе - About KeePassXC - О KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + - Extensions: + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 - Расширения: - + - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC распространяется на условиях Стандартной общественной лицензии GNU (GPL) версии 2 или (на ваше усмотрение) версии 3. + Revision: %1 + + + + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -41,11 +121,12 @@ %1 has requested access to passwords for the following item(s). Please select whether you want to allow access. - %1 запросил доступ к паролям для следующего элемента(ов). Выберете, хотите ли вы разрешить доступ. + %1 запросил доступ к паролям для следующего элемента(ов). +Выберите, хотите ли Вы разрешить доступ. KeePassXC HTTP Confirm Access - Подтверждение доступа KeePassXC HTTP + Подтверждение доступа к KeePassXC HTTP @@ -56,7 +137,7 @@ Please select whether you want to allow access. Auto-Type - KeePassXC - Автоввод — KeePassXC + Автоввод - KeePassXC @@ -82,7 +163,7 @@ Please select whether you want to allow access. Auto-Type - KeePassXC - Автоввод — KeePassXC + Автоввод - KeePassXC @@ -119,10 +200,6 @@ Please select whether you want to allow access. Create Key File... Создать файл-ключ... - - Error - Ошибка - Unable to create Key File : Невозможно создать файл-ключ: @@ -131,10 +208,6 @@ Please select whether you want to allow access. Select a key file Выбрать файл-ключ - - Question - Вопрос - Do you really want to use an empty string as password? Вы действительно хотите использовать в качестве пароля пустую строку? @@ -143,10 +216,6 @@ Please select whether you want to allow access. Different passwords supplied. Пароли не совпадают. - - Failed to set key file - Не удалось установить файл-ключ - Failed to set %1 as the Key file: %2 @@ -155,7 +224,164 @@ Please select whether you want to allow access. &Key file - Файл—&ключ + Файл-&ключ + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Ошибка + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Ошибка + + + Unable to calculate master key + Невозможно вычислить мастер-пароль + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + @@ -176,10 +402,6 @@ Please select whether you want to allow access. Browse Обзор - - Error - Ошибка - Unable to open the database. Невозможно открыть хранилище. @@ -200,6 +422,14 @@ Please select whether you want to allow access. Select key file Выберите файл-ключ + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -217,7 +447,7 @@ Please select whether you want to allow access. Database opened fine. Nothing to do. - Хранилище открылось. Больше нечего делать. + Хранилище открылось прекрасно. Больше нечего делать. Unable to open the database. @@ -276,6 +506,18 @@ You can now save it. Use recycle bin Использовать корзину + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -295,10 +537,6 @@ You can now save it. Open database Открыть хранилище - - Warning - Внимание - File not found! Файл не найден! @@ -329,10 +567,6 @@ Save changes? «%1» изменён. Сохранить изменения? - - Error - Ошибка - Writing the database failed. Не удалось записать хранилище. @@ -402,8 +636,8 @@ Discard changes and close anyway? The database you are trying to save as is locked by another instance of KeePassXC. Do you want to save it anyway? - Хранилище, которые вы пытаетесь сохранить, заблокировано другим экземпляром KeePassXC. -Хотите сохранить во всех случаях? + Хранилище, в которое Вы пытаетесь сохранить, заблокировано другим экземпляром KeePassXC. +Хотите сохранить в любом случе? Passwords @@ -417,13 +651,22 @@ Do you want to save it anyway? The database you are trying to open is locked by another instance of KeePassXC. Do you want to open it anyway? - Хранилище, которые вы пытаетесь открыть, заблокировано другим экземпляром KeePassXC. -Хотите открыть во всех случаях? + Хранилище, которое Вы пытаетесь открыть, заблокировано другим экземпляром KeePassXC. + +Хотите открыть в любом случае? Open read-only Открыть в режиме "только чтение" + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -463,10 +706,6 @@ Do you want to open it anyway? Do you really want to delete the group "%1" for good? Вы действительно хотите навсегда удалить группу «%1»? - - Error - Ошибка - Unable to calculate master key Невозможно вычислить мастер-пароль @@ -477,7 +716,7 @@ Do you want to open it anyway? Do you really want to move entry "%1" to the recycle bin? - Действительно переместить запись "%1" в корзину? + Вы действительно хотите переместить запись "%1" в корзину? Searching... @@ -489,7 +728,7 @@ Do you want to open it anyway? No source database, nothing to do. - Нет исходного хранилища, нечего обрабатывать. + Нет исходного хранилища, нечего обрабатывать. Search Results (%1) @@ -509,15 +748,15 @@ Do you want to open it anyway? Remember my choice - Запомнить выбор + Запомнить мой выбор Autoreload Request - Запрос на автоматическую загрузку + Запрос на автозагрузку The database file has changed. Do you want to load the changes? - Хранилище было изменено. Вы хотите загрузить изменения? + Файл хранилища изменился. Вы хотите загрузить изменения? Merge Request @@ -525,15 +764,19 @@ Do you want to open it anyway? The database file has changed and you have unsaved changes.Do you want to merge your changes? - Файл хранилища был изменён, а так же присутствуют несохранённые изменения. Вы хотите объеденить изменения? + Файл хранилища изменился, а также присутствуют несохранённые изменения. Вы хотите объединить изменения? - Autoreload Failed - Ошибка автоматической загрузки + Could not open the new database file while attempting to autoreload this database. + Не удалось открыть новый файл хранилища при попытке автоматической перезагрузки этого хранилища. - Could not open the new database file while attempting to autoreload this database. - Не удаётся открыть новый файл хранилища при попытке автоматической загрузки этого файла. + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + @@ -574,10 +817,6 @@ Do you want to open it anyway? Edit entry Редактировать запись - - Error - Ошибка - Different passwords supplied. Пароли не совпадают. @@ -620,6 +859,22 @@ Do you want to open it anyway? 1 year 1 год + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -631,10 +886,6 @@ Do you want to open it anyway? Add Добавить - - Edit - Изменить - Remove Удалить @@ -651,6 +902,18 @@ Do you want to open it anyway? Open Открыть + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -686,6 +949,10 @@ Do you want to open it anyway? Set custo&m sequence: Установить сво&ю последовательность: + + Window Associations + + EditEntryWidgetHistory @@ -795,16 +1062,16 @@ Do you want to open it anyway? Поиск - Auto-type + Auto-Type Автоввод - Use default auto-type sequence of parent group - Используйте стандартный автоввод из последовательности родительской группы + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Последовательность автоввода указать по умолчанию + Set default Auto-Type se&quence + @@ -829,10 +1096,6 @@ Do you want to open it anyway? Select Image Выбор изображения - - Can't delete icon! - Не могу удалить значок! - Error Ошибка @@ -843,16 +1106,12 @@ Do you want to open it anyway? Unable to fetch favicon. - Не удалось получить значок сайта + Не удаётся получить значок сайта Can't read icon Не могу прочитать значок - - Can't delete icon. Still used by %1 items. - Не удается удалить значок, она продолжает использоваться %1 записями. - &Use default icon Использовать с&тандартный значок @@ -861,6 +1120,14 @@ Do you want to open it anyway? Use custo&m icon Использовать св&ой значок + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -885,7 +1152,7 @@ Do you want to open it anyway? Entry - Clone - - Колинировать + - Клон @@ -932,6 +1199,11 @@ Do you want to open it anyway? URL URL + + Ref: + Reference abbreviation + + Group @@ -976,7 +1248,7 @@ Do you want to open it anyway? Special Characters - Особые символы + Специальные символы /*_& ... @@ -984,15 +1256,22 @@ Do you want to open it anyway? Exclude look-alike characters - Исключить выглядящие похожие символы + Исключить визуально схожие символы Ensure that the password contains characters from every group - Убедитесь, что пароль содержит символы всех видов + Убедиться, что пароль содержит символы из каждой группы + + + KMessageWidget - Accept - Принять + &Close + + + + Close message + @@ -1001,10 +1280,6 @@ Do you want to open it anyway? Import KeePass1 database Импортировать хранилище KeePass 1 - - Error - Ошибка - Unable to open the database. Невозможно открыть хранилище. @@ -1069,6 +1344,10 @@ This is a one-way migration. You won't be able to open the imported databas Вы можете импортировать его, нажав на База Данных > 'Импорт KeePass 1 базы данных'. Это одностороннее перемещение. Вы не сможете открыть импортированный базу данных на старой версии KeePassX 0,4. + + Unable to issue challenge-response. + + Main @@ -1078,15 +1357,19 @@ This is a one-way migration. You won't be able to open the imported databas KeePassXC - Error - KeePassXC — Ошибка + KeePassXC - Ошибка + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + MainWindow - - Database - Хранилище - Open database Открыть хранилище @@ -1119,10 +1402,6 @@ This is a one-way migration. You won't be able to open the imported databas Toggle window Переключить окно - - Tools - Инструменты - KeePass 2 Database Хранилище KeePass 2 @@ -1135,10 +1414,6 @@ This is a one-way migration. You won't be able to open the imported databas Save repaired database Сохранить восстановленное хранилище - - Error - Ошибка - Writing the database failed. Не удалось записать хранилище. @@ -1193,7 +1468,7 @@ This is a one-way migration. You won't be able to open the imported databas Merge from KeePassX database - Объединить из хранилища KeePassX + Объединить с хранилищем KeePassX &Add new entry @@ -1225,20 +1500,32 @@ This is a one-way migration. You won't be able to open the imported databas Change &master key - Изменить мастер-пароль + Изменить мастер-ключ &Database settings - Параметры хранилища - - - &Import KeePass 1 database - Импортировать хранилище KeePass 1 + Настройки хранилища &Clone entry Клонировать запись + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find Найти @@ -1265,7 +1552,7 @@ This is a one-way migration. You won't be able to open the imported databas &Lock databases - Заблокировать хранилище + Заблокировать хранилища &Title @@ -1285,12 +1572,52 @@ This is a one-way migration. You won't be able to open the imported databas Re&pair database - Восстановление хранилища + Восстановить хранилище Password Generator Генератор паролей + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Импортировать хранилище KeePass 1 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1304,13 +1631,7 @@ This is a one-way migration. You won't be able to open the imported databas Sh&ow a notification when credentials are requested - Показывать уведомление при запросе данных для входа - - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - Совпадение со схемой URL -Возвращат&ь только записи с соответствующей схемой (http://, https://, ftp://, ...) + Показывать уведомление при запросе учётных данных Sort matching entries by &username @@ -1318,15 +1639,11 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< Re&move all stored permissions from entries in active database - Удалить все сохраненные права доступа из активного хранилища - - - Password generator - Генератор паролей + Удалить все сохранённые права доступа из записей активного хранилища Advanced - Расширенные + Продвинутые Always allow &access to entries @@ -1338,11 +1655,7 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< Searc&h in all opened databases for matching entries - Искать соответствующие записи по всем открытым хранилищам - - - Only the selected database has to be connected with a client! - Только выбранное хранилище должно быть соединено с клиентом! + Искать подходящие записи во всех открытых хранилищах HTTP Port: @@ -1358,49 +1671,71 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< Sort &matching entries by title - Сортировать совпавшие записи по названию - - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - Включить протокол KeepassXC HTTP -Это требуется для доступа к хранилищам из ChromeIPass или PassIFox + Сортировать совпадающие записи по названию KeePassXC will listen to this port on 127.0.0.1 - KeePassXC будет слушать указнный порт на 127.0.0.1 + KeePassXC будет слушать этот порт на 127.0.0.1 Cannot bind to privileged ports - Не удается выполнить привязку к привилегированным портам + Не удаётся выполнить привязку к привилегированным портам Cannot bind to privileged ports below 1024! Using default port 19455. - Не удается привязать к привилегированным портам с номерами меньше 1024! + Не удаётся привязать к привилегированным портам с номерами меньше 1024! Используется порт по умолчанию: 19455. - - &Return only best matching entries for a URL instead -of all entries for the whole domain - Возвращать толь&ко наиболее совпавшие с URL записи, а не все записи для домена - R&emove all shared encryption keys from active database &Удалить все общие ключи шифрования из активного хранилища - - The following options can be dangerous. Change them only if you know what you are doing. - Используйте эти настройки только если знаете, что делаете! - &Return advanced string fields which start with "KPH: " - Возвращать дополнительные стро&ковые поля, начинающиеся с "KPH: " + Возвращать продвинутые стро&ковые поля, начинающиеся с "KPH: " Automatically creating or updating string fields is not supported. Автоматическое создание или обновление полей, содержащих строки, не поддерживается. + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + Генератор паролей + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + PasswordGeneratorWidget @@ -1454,7 +1789,7 @@ of all entries for the whole domain Pick characters from every group - Выберете символы из каждой группы + Подобрать символы из каждой группы Generate @@ -1478,26 +1813,115 @@ of all entries for the whole domain Poor - Плохой + Плохое Weak - Слабый + Слабое Good - Хороший + Хорошее Excellent - Отличный + Отличное + + + Password + Пароль + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + QObject - Http - Http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Группа + + + Title + Заголовок + + + Username + Имя пользователя + + + Password + Пароль + + + URL + URL + + + Notes + Примечания + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1544,14 +1968,18 @@ of all entries for the whole domain Search Поиск - - Find - Найти - Clear Очистить + + Search... + + + + Limit search to selected group + + Service @@ -1569,7 +1997,7 @@ Do you want to overwrite it? The active database is locked! Please unlock the selected database or choose another one which is unlocked. Активное хранилище заблокировано! -Разблокируйте выбранное хранилище или выберите другое, незаблокированное. +Пожалуйста, разблокируйте выбранное хранилище или выберите другое, незаблокированное. Successfully removed %1 encryption-%2 from KeePassX/Http Settings. @@ -1585,11 +2013,11 @@ Please unlock the selected database or choose another one which is unlocked. Removing stored permissions... - Удаляются сохранённые права доступа... + Удаляю сохранённые права доступа... Abort - Отмена + Прервать Successfully removed permissions from %1 %2. @@ -1607,8 +2035,9 @@ Please unlock the selected database or choose another one which is unlocked.You have received an association request for the above key. If you would like to allow it access to your KeePassXC database give it a unique name to identify and accept it. - Вы получили запрос на ассоциацию указанного ключа. -Если вы хотите разрешить доступ к вашему хранилищу KeePassXC, дайте ему уникальное имя и примите запрос. + Вы получили запрос на ассоциацию вышеуказанного ключа. +Если Вы хотите разрешить доступ к Вашему хранилищу KeePassXC, +дайте ему уникальное имя, чтобы распознать и принять ключ. KeePassXC: Overwrite existing key? @@ -1632,7 +2061,7 @@ give it a unique name to identify and accept it. KeePassXC: Settings not available! - KeePassXC% Настройки недоступны! + KeePassXC: Настройки недоступны! KeePassXC: Removed permissions @@ -1640,7 +2069,7 @@ give it a unique name to identify and accept it. KeePassXC: No entry with permissions found! - KeePassXC: Не найдено записей с назначенными правами доступа! + KeePassXC: Не найдена запись с правами доступа! @@ -1657,6 +2086,10 @@ give it a unique name to identify and accept it. Security Безопасность + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1684,10 +2117,6 @@ give it a unique name to identify and accept it. Global Auto-Type shortcut Глобальное сочетание клавиш для автоввода - - Use entry title to match windows for global auto-type - Использовать заголовок записи для подбора окон для глобального автоввода - Language Язык @@ -1700,17 +2129,13 @@ give it a unique name to identify and accept it. Hide window to system tray when minimized При сворачивании прятать окно в область системных уведомлений - - Remember last key files - Запоминать последние файл-ключи - Load previous databases on startup - Открывать предыдущие хранилища при запуске + Загружать предыдущие хранилища при запуске Automatically reload the database when modified externally - Автоматически перечитывать хранилище при его изменении внешними приложениями + Автоматически перезагружать хранилище при его изменении извне Hide window to system tray instead of app exit @@ -1720,6 +2145,30 @@ give it a unique name to identify and accept it. Minimize window at application startup Сворачивать окно при запуске приложения + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Автоввод + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1739,17 +2188,87 @@ give it a unique name to identify and accept it. Show passwords in cleartext by default По умолчанию показывать пароль в открытую - - Always ask before performing auto-type - Всегда спрашивать перед тем, как производить автоввод - Lock databases after minimizing the window - Заблокировать хранилище при сворачивании окна + Блокировать хранилища после сворачивания окна Don't require password repeat when it is visible - Не требовать поворный ввод пароля когда он показывается + Не требовать повторный ввод пароля, когда он показывается + + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + сек + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + @@ -1762,8 +2281,32 @@ give it a unique name to identify and accept it. WelcomeWidget - Welcome! - Добро пожаловать! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Недавние хранилища @@ -1778,7 +2321,7 @@ give it a unique name to identify and accept it. KeePassXC - cross-platform password manager - KeePassXC — кросс-платформенный менеджер паролей + KeePassXC - кроссплатформенный менеджер паролей read password of the database from stdin @@ -1788,5 +2331,69 @@ give it a unique name to identify and accept it. filenames of the password databases to open (*.kdbx) имена файлов открываемого хранилища паролей (*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_sl_SI.ts b/share/translations/keepassx_sl_SI.ts index 164f84ac64..cba2c76217 100644 --- a/share/translations/keepassx_sl_SI.ts +++ b/share/translations/keepassx_sl_SI.ts @@ -1,33 +1,143 @@ - + AboutDialog - About KeePassX - O KeePassX + About KeePassXC + + + + About + O programu + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + - KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassX se razširja pod GNU General Public License (GPL) licenco verzija 2 ali (po želji) verzija 3. + Version %1 + + + + + Revision: %1 + + + + Libraries: + - Revision + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 - Using: + Enabled extensions: - AutoType + AccessControlDialog + + Remember this decision + + + + Allow + + + + Deny + + + + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + + - Auto-Type - KeePassX - Samodejno tipkanje - KeePassX + KeePassXC HTTP Confirm Access + + + + AutoType Couldn't find an entry that matches the window title: Ne najdem vnosa, ki bi ustrezal: + + Auto-Type - KeePassXC + + AutoTypeAssociationsModel @@ -46,14 +156,14 @@ AutoTypeSelectDialog - - Auto-Type - KeePassX - Samodejno tipkanje - KeePassX - Select entry to Auto-Type: Izberi vnos za samodejno tipkanje: + + Auto-Type - KeePassXC + + ChangeMasterKeyWidget @@ -69,10 +179,6 @@ Repeat password: Ponovi geslo: - - Key file - Datoteka s ključi - Browse Prebrskaj @@ -93,10 +199,6 @@ Create Key File... Ustvari datoteko s ključi... - - Error - Napaka - Unable to create Key File : Ustvarjanje datoteke s ključi ni uspelo: @@ -105,10 +207,6 @@ Select a key file Izberi datoteko s kljući - - Question - Vprašanje - Do you really want to use an empty string as password? Ali res želite uporabiti prazen niz kot geslo? @@ -117,16 +215,173 @@ Different passwords supplied. Vnešeni gesli sta različni. - - Failed to set key file - Nastavljanje datoteke s ključi ni uspelo - Failed to set %1 as the Key file: %2 Nastavljanje %1 kot datoteko s ključi ni uspelo: %2 + + &Key file + + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Napaka + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Napaka + + + Unable to calculate master key + Izračun glavnega ključa ni uspel + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -146,10 +401,6 @@ Browse Prebrskaj - - Error - Napaka - Unable to open the database. Odpiranje podatkovne baze ni uspelo. @@ -170,6 +421,14 @@ Select key file Izberi datoteko s ključi + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -179,11 +438,11 @@ Error - + Napaka Can't open key file - + Odpiranje datoteke s ključi ni uspelo Database opened fine. Nothing to do. @@ -191,7 +450,7 @@ Unable to open the database. - + Odpiranje podatkovne baze ni uspelo. Success @@ -225,10 +484,6 @@ You can now save it. Default username: Privzeto uporabniško ime: - - Use recycle bin: - Uporaba koša: - MiB MiB @@ -245,6 +500,22 @@ You can now save it. Max. history size: Max. velikost zgodovine: + + Use recycle bin + + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -264,10 +535,6 @@ You can now save it. Open database Odpri podatkovno bazo - - Warning - Opozorilo - File not found! Datoteke ni mogoče najti! @@ -298,10 +565,6 @@ Save changes? "%1" spremenjeno. Shrani spremembe? - - Error - Napaka - Writing the database failed. Zapis podatkovne baze ni uspel. @@ -318,12 +581,6 @@ Shrani spremembe? locked zaklenjeno - - The database you are trying to open is locked by another instance of KeePassX. -Do you want to open it anyway? Alternatively the database is opened read-only. - Podatkovna baza ki jo želite odpreti je že odprta v drugem KeePassX. -Ali jo vseeno želite odpreti? Lahko jo odprete tudi samo za branje. - Lock database Zakleni podatkovno bazo @@ -367,28 +624,58 @@ Zavrži spremembe in zapri? Pisanje v CSV datoteko ni uspelo - The database you are trying to save as is locked by another instance of KeePassX. -Do you want to save it anyway? + Unable to open the database. + Odpiranje podatkovne baze ni uspelo. + + + Merge database - Unable to open the database. + The database you are trying to save as is locked by another instance of KeePassXC. +Do you want to save it anyway? - - - DatabaseWidget - Change master key - Spremeni glavni ključ + Passwords + - Delete entry? - Izbris vnosa? + Database already opened + - Do you really want to delete the entry "%1" for good? - Ali res želite izbrisati "%1"? + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + + + + Open read-only + + + + File opened in read only mode. + + + + Open CSV file + + + + + DatabaseWidget + + Change master key + Spremeni glavni ključ + + + Delete entry? + Izbris vnosa? + + + Do you really want to delete the entry "%1" for good? + Ali res želite izbrisati "%1"? Delete entries? @@ -414,14 +701,6 @@ Do you want to save it anyway? Do you really want to delete the group "%1" for good? Ali res želite izbrisati skupino "%1"? - - Current group - Trenutna skupina - - - Error - Napaka - Unable to calculate master key Izračun glavnega ključa ni uspel @@ -434,6 +713,66 @@ Do you want to save it anyway? Do you really want to move entry "%1" to the recycle bin? + + Searching... + + + + No current database. + + + + No source database, nothing to do. + + + + Search Results (%1) + + + + No Results + + + + Execute command? + + + + Do you really want to execute the following command?<br><br>%1<br> + + + + Remember my choice + + + + Autoreload Request + + + + The database file has changed. Do you want to load the changes? + + + + Merge Request + + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + + + + Could not open the new database file while attempting to autoreload this database. + + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -473,10 +812,6 @@ Do you want to save it anyway? Edit entry Uredi vnos - - Error - Napaka - Different passwords supplied. Gesli se ne ujemata. @@ -518,6 +853,22 @@ Do you want to save it anyway? 1 year 1 leto + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -529,10 +880,6 @@ Do you want to save it anyway? Add Dodaj - - Edit - Uredi - Remove Odstrani @@ -549,6 +896,18 @@ Do you want to save it anyway? Open Odpri + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -556,14 +915,6 @@ Do you want to save it anyway? Enable Auto-Type for this entry Omogoči samodejno tipkanje za ta vnos - - Inherit default Auto-Type sequence from the group - Dedovanje privzete sekvence za samodejno tipkanje iz skupine - - - Use custom Auto-Type sequence: - Uporabi poljubno sekvenco za samodejno tipkanje: - + + @@ -577,12 +928,24 @@ Do you want to save it anyway? Naslov okna: - Use default sequence - Uporabi privzeto sekvenco + Inherit default Auto-Type sequence from the &group + + + + &Use custom Auto-Type sequence: + + + + Use default se&quence + + + + Set custo&m sequence: + - Set custom sequence: - Nastavi privzeto sekvenco: + Window Associations + @@ -622,10 +985,6 @@ Do you want to save it anyway? Repeat: Ponovi geslo: - - Gen. - Samodejno generiraj - URL: URL: @@ -697,28 +1056,20 @@ Do you want to save it anyway? Išči - Auto-type + Auto-Type Samodejno tipkanje - Use default auto-type sequence of parent group - Za samodejno tipkanje uporabi privzeto sekvenco nadrejene skupine + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Nastavi privzeto sekvenco za samodejno tipkanje + Set default Auto-Type se&quence + EditWidgetIcons - - Use default icon - Uporabi privzeto ikono - - - Use custom icon - Uporabi ikono po meri - Add custom icon Dodaj poljubno ikono @@ -740,19 +1091,35 @@ Do you want to save it anyway? Izberi sliko - Can't delete icon! - Ikone ni mogoče izbrisati! + Error + Napaka + + + Download favicon + - - Can't delete icon. Still used by %n item(s). - Ikone ni mogoče izbrisati. Uporablja jo še %n vnos.Ikone ni mogoče izbrisati. Uporabljata jo še %n vnosa.Ikone ni mogoče izbrisati. Uporabljajo jo še %n vnosi.Ikone ni mogoče izbrisati. Uporablja jo še %n vnosov. + + Unable to fetch favicon. + - Error + Can't read icon + + + + &Use default icon + + + + Use custo&m icon + + + + Confirm Delete - Can't read icon: + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? @@ -775,6 +1142,13 @@ Do you want to save it anyway? Uuid: + + Entry + + - Clone + + + EntryAttributesModel @@ -819,6 +1193,11 @@ Do you want to save it anyway? URL URL + + Ref: + Reference abbreviation + + Group @@ -827,16 +1206,74 @@ Do you want to save it anyway? Koš + + HttpPasswordGeneratorWidget + + Length: + Dolžina: + + + Character Types + Tipi znakov + + + Upper Case Letters + Velike črke + + + A-Z + + + + Lower Case Letters + Male črke + + + a-z + + + + Numbers + Številke + + + 0-9 + + + + Special Characters + Posebni znaki + + + /*_& ... + + + + Exclude look-alike characters + Izključi podobne znake + + + Ensure that the password contains characters from every group + Geslo naj vsebuje znake iz vsake skupine + + + + KMessageWidget + + &Close + + + + Close message + + + KeePass1OpenWidget Import KeePass1 database Uvozi KeePass1 podatkovno bazo - - Error - Napaka - Unable to open the database. Odpiranje podatkovne baze ni uspelo. @@ -870,7 +1307,7 @@ Do you want to save it anyway? Wrong key or database file is corrupt. - + Napačno geslo ali pa je podatkovna baza poškodovana. @@ -898,6 +1335,10 @@ You can import it by clicking on Database > 'Import KeePass 1 database'. This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + + Unable to issue challenge-response. + + Main @@ -906,483 +1347,1039 @@ This is a one-way migration. You won't be able to open the imported databas Napaka pri testiranju kriptografskih funkcij. - KeePassX - Error - KeePassX - Napaka + KeePassXC - Error + + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + MainWindow - Database - Podatkovna baza + Open database + Odpri podatkovno bazo - Recent databases - Nedavne podatkovne baze + Database settings + Nastavitve podatkovne baze - Help - Pomoč + Copy username to clipboard + Kopiraj uporabniško ime v odložišče - Entries - Vnosi + Copy password to clipboard + Kopiraj geslo v odložišče - Copy attribute to clipboard - Kopiraj atribut v odložišče + Settings + Nastavitve - Groups - Skupine + Show toolbar + Prikaži orodno vrstico - View - Pogled + read-only + samo za branje - Quit - Izhod + Toggle window + Preklopi okno - About - O programu + KeePass 2 Database + KeePass 2 podatkovna baza - Open database - Odpri podatkovno bazo + All files + Vse datoteke - Save database - Shrani podatkovno bazo + Save repaired database + - Close database - Zapri podatkovno bazo + Writing the database failed. + Zapis podatkovne baze ni uspel. - New database - Nova podatkovna baza + &Recent databases + - Add new entry - Dodaj vnos + He&lp + - View/Edit entry - Uredi vnos + E&ntries + - Delete entry - Izbriši vnos + Copy att&ribute to clipboard + - Add new group - Dodaj novo skupino + &Groups + - Edit group - Uredi skupino + &View + - Delete group - Izbriši skupino + &Quit + - Save database as - Shrani podatkovno bazo kot + &About + - Change master key - Spremeni glavni ključ + &Open database + - Database settings - Nastavitve podatkovne baze + &Save database + - Import KeePass 1 database - Uvozi KeePass 1 podatkovno bazo + &Close database + - Clone entry - Kloniraj vnos + &New database + - Find - Išči + Merge from KeePassX database + - Copy username to clipboard - Kopiraj uporabniško ime v odložišče + &Add new entry + - Copy password to clipboard - Kopiraj geslo v odložišče + &View/Edit entry + - Settings - Nastavitve + &Delete entry + - Perform Auto-Type - Izvedi samodejno tipkanje + &Add new group + - Open URL - Odpri URL + &Edit group + - Lock databases - Zakleni podatkovne baze + &Delete group + - Title - Naslov + Sa&ve database as + - URL - URL + Change &master key + - Notes - Opombe + &Database settings + - Show toolbar - Prikaži orodno vrstico + &Clone entry + - read-only - samo za branje + Timed one-time password + - Toggle window - Preklopi okno + Setup TOTP + - Tools - Orodja + Copy &TOTP + - Copy username - Kopiraj uporabniško ime + Show TOTP + - Copy password - Kopiraj geslo + &Find + - Export to CSV file - Izvozi v CSV datoteko + Copy &username + - Repair database + Cop&y password - KeePass 2 Database + &Settings - All files + &Perform Auto-Type - Save repaired database + &Open URL - Error + &Lock databases - Writing the database failed. + &Title - - - PasswordGeneratorWidget - Password: - Geslo: + &URL + - Length: - Dolžina: + &Notes + - Character Types - Tipi znakov + &Export to CSV file + - Upper Case Letters - Velike črke + Re&pair database + - Lower Case Letters - Male črke + Password Generator + - Numbers - Številke + Clear history + - Special Characters - Posebni znaki + &Database + - Exclude look-alike characters - Izključi podobne znake + Import + - Ensure that the password contains characters from every group - Geslo naj vsebuje znake iz vsake skupine + &Tools + - Accept - Sprejmi + Import KeePass 1 database + Uvozi KeePass 1 podatkovno bazo + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + - QCommandLineParser + OptionDialog - Displays version information. - Prikaže informacije o različici. + Dialog + - Displays this help. - Prikaže pomoč. + General + Splošno - Unknown option '%1'. - Neznana izbrira %1. + Sh&ow a notification when credentials are requested + - Unknown options: %1. - Neznane izbire: %1. + Sort matching entries by &username + - Missing value after '%1'. - Manjkajoča vrednost po '%1'. + Re&move all stored permissions from entries in active database + - Unexpected value after '%1'. - Nepričakovana vrednost po '%1'. + Advanced + Napredno - [options] - [možnosti] + Always allow &access to entries + - Usage: %1 - Uporaba: %1 + Always allow &updating entries + - Options: - Možnosti: + Searc&h in all opened databases for matching entries + - Arguments: - Argumenti: + HTTP Port: + + + + Default port: 19455 + - - - QSaveFile - Existing file %1 is not writable - Obstoječa datoteka %1 ni zapisljiva + Re&quest to unlock the database if it is locked + - Writing canceled by application - Aplikacija je prekinila pisanje + Sort &matching entries by title + - Partial write. Partition full? - Delno pisanje. Polna particija? + KeePassXC will listen to this port on 127.0.0.1 + - - - QtIOCompressor - Internal zlib error when compressing: - Notranja zlib napaka pri stiskanju: + Cannot bind to privileged ports + - Error writing to underlying device: - Napaka pri pisanju na napravo: + Cannot bind to privileged ports below 1024! +Using default port 19455. + - Error opening underlying device: - Napaka pri odpiranju naprave: + R&emove all shared encryption keys from active database + - Error reading data from underlying device: - Napak pri branju iz naprave: + &Return advanced string fields which start with "KPH: " + - Internal zlib error when decompressing: - Notranja zlib napaka pri dekompresiranju: + Automatically creating or updating string fields is not supported. + - - - QtIOCompressor::open - The gzip format not supported in this version of zlib. - Ta različica zlib ne podpira gzip formata. + This is required for accessing your databases from ChromeIPass or PassIFox + - Internal zlib error: - Notranja zlib napaka: + Enable KeePassHTTP server + - - - SearchWidget - Find: - Išči: + Only returns the best matches for a specific URL instead of all entries for the whole domain. + - Case sensitive - Razlikuj med velikimi in malimi črkami + &Return only best matching entries + - Current group - Trenutna skupina + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + - Root group - Korenska skupina + &Match URL schemes + - - - SettingsWidget - Application Settings - Nastavitve aplikacije + Password Generator + - General - Splošno + Only the selected database has to be connected with a client. + - Security - Varnost + The following options can be dangerous! +Change them only if you know what you are doing. + - SettingsWidgetGeneral + PasswordGeneratorWidget - Remember last databases - Zapomni si zadnje podatkovne baze + Password: + Geslo: - Open previous databases on startup - Odpri prejšnje podatkovne baze ob zagonu programa + Character Types + Tipi znakov - Automatically save on exit - Samodejno shrani ob izhodu + Upper Case Letters + Velike črke - Automatically save after every change - Samodejno shrani po vsaki spremembi + Lower Case Letters + Male črke - Minimize when copying to clipboard - Minimiziraj pri kopiranju v odložišče + Numbers + Številke - Use group icon on entry creation - Za nove vnose uporabi ikono skupine + Special Characters + Posebni znaki - Global Auto-Type shortcut - Globalna bližnjica za samodejno tipkanje + Exclude look-alike characters + Izključi podobne znake - Use entry title to match windows for global auto-type - Uporabi ujemanje naslova vnosa in naslova okna pri samodejnem tipkanju + Accept + Sprejmi - Language - Jezik + %p% + - Show a system tray icon - Pokaži ikono v sistemski vrstici + strength + - Hide window to system tray when minimized - Minimiziraj v sistemsko vrstico + entropy + - Remember last key files - Zapomni si zadnje datoteke s ključi + &Length: + - Hide window to system tray instead of App Exit + Pick characters from every group - Hide window to system tray on App start + Generate - - - SettingsWidgetSecurity - Clear clipboard after - Pobriši odložišče po + Close + - sec - sekundah + Apply + - Lock databases after inactivity of - Zakleni podatkovne baze po neaktivnosti + Entropy: %1 bit + - Show passwords in cleartext by default - Gesla privzeto v čistopisu + Password Quality: %1 + - Always ask before performing auto-type - Pred izvedbo samodejnega tipkanja vprašaj za potrditev + Poor + - - - UnlockDatabaseWidget - Unlock database - Odkleni podatkovno bazo + Weak + - - - WelcomeWidget - Welcome! - Dobrodošli! + Good + - - - main - KeePassX - cross-platform password manager - KeePassX - urejevalnik gesel za različne platforme + Excellent + - filename of the password database to open (*.kdbx) - končnica podatkovne baze (*.kdbx) + Password + Geslo - path to a custom config file - pot do konfiguracijske datoteke po meri + Extended ASCII + - key file of the database - datoteka s ključi podatkovne baze + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + + + + QObject + + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Skupina + + + Title + Naslov + + + Username + Uporabniško ime + + + Password + Geslo + + + URL + URL + + + Notes + Opombe + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + + + + + QtIOCompressor + + Internal zlib error when compressing: + Notranja zlib napaka pri stiskanju: + + + Error writing to underlying device: + Napaka pri pisanju na napravo: + + + Error opening underlying device: + Napaka pri odpiranju naprave: + + + Error reading data from underlying device: + Napak pri branju iz naprave: + + + Internal zlib error when decompressing: + Notranja zlib napaka pri dekompresiranju: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + Ta različica zlib ne podpira gzip formata. + + + Internal zlib error: + Notranja zlib napaka: + + + + SearchWidget + + Case Sensitive + + + + Search + Išči + + + Clear + + + + Search... + + + + Limit search to selected group + + + + + Service + + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + + + + Do you want to update the information in %1 - %2? + + + + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + + + + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + + + + No shared encryption-keys found in KeePassHttp Settings. + + + + The active database does not contain an entry of KeePassHttp Settings. + + + + Removing stored permissions... + + + + Abort + + + + Successfully removed permissions from %1 %2. + + + + The active database does not contain an entry with permissions. + + + + KeePassXC: New key association request + + + + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + + + + KeePassXC: Overwrite existing key? + + + + KeePassXC: Update Entry + + + + KeePassXC: Database locked! + + + + KeePassXC: Removed keys from database + + + + KeePassXC: No keys found + + + + KeePassXC: Settings not available! + + + + KeePassXC: Removed permissions + + + + KeePassXC: No entry with permissions found! + + + + + SettingsWidget + + Application Settings + Nastavitve aplikacije + + + General + Splošno + + + Security + Varnost + + + Access error for config file %1 + + + + + SettingsWidgetGeneral + + Remember last databases + Zapomni si zadnje podatkovne baze + + + Automatically save on exit + Samodejno shrani ob izhodu + + + Automatically save after every change + Samodejno shrani po vsaki spremembi + + + Minimize when copying to clipboard + Minimiziraj pri kopiranju v odložišče + + + Use group icon on entry creation + Za nove vnose uporabi ikono skupine + + + Global Auto-Type shortcut + Globalna bližnjica za samodejno tipkanje + + + Language + Jezik + + + Show a system tray icon + Pokaži ikono v sistemski vrstici + + + Hide window to system tray when minimized + Minimiziraj v sistemsko vrstico + + + Load previous databases on startup + + + + Automatically reload the database when modified externally + + + + Hide window to system tray instead of app exit + + + + Minimize window at application startup + + + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Samodejno tipkanje + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + + + + SettingsWidgetSecurity + + Clear clipboard after + Pobriši odložišče po + + + sec + sekundah + + + Lock databases after inactivity of + Zakleni podatkovne baze po neaktivnosti + + + Show passwords in cleartext by default + Gesla privzeto v čistopisu + + + Lock databases after minimizing the window + + + + Don't require password repeat when it is visible + + + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + sekundah + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + + + + UnlockDatabaseWidget + + Unlock database + Odkleni podatkovno bazo + + + + WelcomeWidget + + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Nedavne podatkovne baze + + + + main + + path to a custom config file + pot do konfiguracijske datoteke po meri + + + key file of the database + datoteka s ključi podatkovne baze + + + KeePassXC - cross-platform password manager + + + + read password of the database from stdin + + + + filenames of the password databases to open (*.kdbx) + + + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + \ No newline at end of file diff --git a/share/translations/keepassx_sv.ts b/share/translations/keepassx_sv.ts index 70dcd1bfd7..7953bf0faf 100644 --- a/share/translations/keepassx_sv.ts +++ b/share/translations/keepassx_sv.ts @@ -1,33 +1,143 @@ - + AboutDialog - About KeePassX - Om KeePassX + About KeePassXC + Om KeePassXC - KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - Keepassx distribueras enligt villkoren i GNU General Public License (GPL) version 2 eller (om du vill) version 3. + About + Om + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 + + + + + Revision: %1 + - Revision - Revision + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + - Using: - Använder: + Enabled extensions: + - AutoType + AccessControlDialog + + Remember this decision + + + + Allow + + - Auto-Type - KeePassX - Auto-skriv - KeePassX + Deny + + + + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + + + KeePassXC HTTP Confirm Access + + + + + AutoType Couldn't find an entry that matches the window title: Kunde inte hitta en post som matchar fönstertiteln: + + Auto-Type - KeePassXC + + AutoTypeAssociationsModel @@ -46,14 +156,14 @@ AutoTypeSelectDialog - - Auto-Type - KeePassX - Auto-skriv - KeePassX - Select entry to Auto-Type: Välj post att auto-skriva + + Auto-Type - KeePassXC + + ChangeMasterKeyWidget @@ -69,10 +179,6 @@ Repeat password: Repetera lösenord: - - Key file - Nyckel-fil - Browse Bläddra @@ -93,10 +199,6 @@ Create Key File... Skapa nyckel-fil... - - Error - Fel - Unable to create Key File : Kunde inte skapa nyckel-fil @@ -105,10 +207,6 @@ Select a key file Välj nyckel-fil - - Question - Fråga - Do you really want to use an empty string as password? Vill du verkligen vill använda en tom sträng som lösenord? @@ -117,16 +215,173 @@ Different passwords supplied. Olika lösenord angivna - - Failed to set key file - Kunde inte sätta nyckel-fil - Failed to set %1 as the Key file: %2 Kunde inte sätta %1 som nyckel-fil: %2 + + &Key file + + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Fel + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Fel + + + Unable to calculate master key + Kunde inte räkna nu master-nyckeln + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -146,10 +401,6 @@ Browse Bläddra - - Error - Fel - Unable to open the database. Kunde inte öppna databas. @@ -170,6 +421,14 @@ Select key file Välj nyckel-fil + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -226,10 +485,6 @@ Du kan nu spara den. Default username: Standard användarnamn: - - Use recycle bin: - Använd papperskorg: - MiB MiB @@ -246,6 +501,22 @@ Du kan nu spara den. Max. history size: Maximal historik storlek: + + Use recycle bin + + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -265,10 +536,6 @@ Du kan nu spara den. Open database Öppna databas - - Warning - Varning - File not found! Filen kunde inte hittas! @@ -299,10 +566,6 @@ Save changes? "%1" har ändrats. Spara ändringarna? - - Error - Fel - Writing the database failed. Kunde inte skriva till databasen. @@ -319,12 +582,6 @@ Spara ändringarna? locked låst - - The database you are trying to open is locked by another instance of KeePassX. -Do you want to open it anyway? Alternatively the database is opened read-only. - Databasen som du försöker öppna är låst av en annan instans av KeePassX. -Vill du öppna den ändå? Databasen kommer då att öppnas skrivskyddad. - Lock database Lås databasen @@ -368,13 +625,42 @@ Kasta ändringarna och stäng endå? Kunde inte skriva till CSV-filen - The database you are trying to save as is locked by another instance of KeePassX. + Unable to open the database. + Kunde inte öppna databas. + + + Merge database + + + + The database you are trying to save as is locked by another instance of KeePassXC. Do you want to save it anyway? - Databasen du försöker spara som är låst av en annan instans av KeePassX. -Vill du spara endå? + - Unable to open the database. + Passwords + Lösenord + + + Database already opened + + + + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + + + + Open read-only + + + + File opened in read only mode. + + + + Open CSV file @@ -416,14 +702,6 @@ Vill du spara endå? Do you really want to delete the group "%1" for good? Vill du verkligen ta bort gruppen "%1" för gott? - - Current group - Nuvarande grupp - - - Error - Fel - Unable to calculate master key Kunde inte räkna nu master-nyckeln @@ -436,6 +714,66 @@ Vill du spara endå? Do you really want to move entry "%1" to the recycle bin? + + Searching... + + + + No current database. + + + + No source database, nothing to do. + + + + Search Results (%1) + + + + No Results + + + + Execute command? + + + + Do you really want to execute the following command?<br><br>%1<br> + + + + Remember my choice + + + + Autoreload Request + + + + The database file has changed. Do you want to load the changes? + + + + Merge Request + + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + + + + Could not open the new database file while attempting to autoreload this database. + + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -475,10 +813,6 @@ Vill du spara endå? Edit entry Ändra post - - Error - Fel - Different passwords supplied. Olika lösenord angivna @@ -521,6 +855,22 @@ Vill du spara endå? 1 year 1 år + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -532,10 +882,6 @@ Vill du spara endå? Add Lägg till - - Edit - Ändra - Remove Ta bort @@ -552,6 +898,18 @@ Vill du spara endå? Open Öppna + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -559,14 +917,6 @@ Vill du spara endå? Enable Auto-Type for this entry Slå på auto-skriv för denna post - - Inherit default Auto-Type sequence from the group - Ärv standard auto-skriv sekvens för grupp - - - Use custom Auto-Type sequence: - Använd egen auto-skriv sekvens: - + + @@ -580,12 +930,24 @@ Vill du spara endå? Fönster titel: - Use default sequence - Använd standard sekvens + Inherit default Auto-Type sequence from the &group + + + + &Use custom Auto-Type sequence: + + + + Use default se&quence + + + + Set custo&m sequence: + - Set custom sequence: - Egen sekvens: + Window Associations + @@ -625,10 +987,6 @@ Vill du spara endå? Repeat: Repetera: - - Gen. - Gen. - URL: URL: @@ -700,28 +1058,20 @@ Vill du spara endå? Sök - Auto-type + Auto-Type Auto-skriv - Use default auto-type sequence of parent group - Använd standard auto-skriv sekvensen från föräldergruppen + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Ange standard auto-skriv sekvens + Set default Auto-Type se&quence + EditWidgetIcons - - Use default icon - Använd standard ikon - - - Use custom icon - Använd egen ikon - Add custom icon Lägg till egen ikon @@ -743,19 +1093,35 @@ Vill du spara endå? Välj bild - Can't delete icon! - Kan inte ta bort ikon! + Error + Fel + + + Download favicon + - - Can't delete icon. Still used by %n item(s). - Kan inte ta bort ikonen. Den används fortfarande av %n postKan inte ta bort ikonen. Den används fortfarande av %n poster + + Unable to fetch favicon. + - Error + Can't read icon + + + + &Use default icon + + + + Use custo&m icon + + + + Confirm Delete - Can't read icon: + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? @@ -778,6 +1144,13 @@ Vill du spara endå? UUID: + + Entry + + - Clone + + + EntryAttributesModel @@ -822,6 +1195,11 @@ Vill du spara endå? URL URL + + Ref: + Reference abbreviation + + Group @@ -830,16 +1208,74 @@ Vill du spara endå? Papperskorg + + HttpPasswordGeneratorWidget + + Length: + Längd: + + + Character Types + Teckentyper + + + Upper Case Letters + Versaler + + + A-Z + + + + Lower Case Letters + Gemener + + + a-z + + + + Numbers + Siffror + + + 0-9 + + + + Special Characters + Specialtecken + + + /*_& ... + + + + Exclude look-alike characters + Uteslut liknande tecken + + + Ensure that the password contains characters from every group + Säkerställ att lösenordet innehåller tecken från varje grupp + + + + KMessageWidget + + &Close + + + + Close message + + + KeePass1OpenWidget Import KeePass1 database Importera KeePass1 databas - - Error - Fel - Unable to open the database. Kunde inte öppna databas. @@ -873,7 +1309,7 @@ Vill du spara endå? Wrong key or database file is corrupt. - + Fel lösenord eller korrupt databas-fil @@ -904,6 +1340,10 @@ This is a one-way migration. You won't be able to open the imported databas Du kan importera den genom att klicka på Databas > Importera KeePass 1 databas. Detta är en envägsmigration. Du kan inte spara en databas som KeePass1 databas. Det som används i KeePassX 0.4. + + Unable to issue challenge-response. + + Main @@ -912,483 +1352,1039 @@ Detta är en envägsmigration. Du kan inte spara en databas som KeePass1 databas Allvarligt fel vid testning av kryptografiska funktioner. - KeePassX - Error - KeePassX - Fel + KeePassXC - Error + + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + MainWindow - Database - Databas + Open database + Öppna databas - Recent databases - Senast använda databaser + Database settings + Databasinställningar - Help - Hjälp + Copy username to clipboard + Kopiera användarnamn - Entries - Poster + Copy password to clipboard + Kopiera lösenord - Copy attribute to clipboard - Kopiera attribut + Settings + Inställningar - Groups - Grupper + Show toolbar + Visa verktygsfält - View - Vy + read-only + läs bara - Quit - Avsluta + Toggle window + Visa/dölj fönster - About - Om + KeePass 2 Database + KeePass 2 databas - Open database - Öppna databas + All files + Alla filer - Save database - Spara databas + Save repaired database + Spara lagad databas - Close database - Stäng databas + Writing the database failed. + Misslyckades med att skriva till databasen. - New database - Ny databas + &Recent databases + - Add new entry - Lägg till ny post + He&lp + - View/Edit entry - Visa/ändra post + E&ntries + - Delete entry - Ta bort post + Copy att&ribute to clipboard + - Add new group - Lägg till ny grupp + &Groups + - Edit group - Ändra grupp + &View + - Delete group - Ta bort grupp + &Quit + - Save database as - Spara databas som + &About + - Change master key - Ändra huvud lösenord + &Open database + - Database settings - Databasinställningar + &Save database + - Import KeePass 1 database - Importera KeePass1 databas + &Close database + - Clone entry - Klona post + &New database + - Find - Sök + Merge from KeePassX database + - Copy username to clipboard - Kopiera användarnamn + &Add new entry + + + + &View/Edit entry + + + + &Delete entry + + + + &Add new group + + + + &Edit group + + + + &Delete group + + + + Sa&ve database as + + + + Change &master key + + + + &Database settings + + + + &Clone entry + + + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + + + &Find + + + + Copy &username + + + + Cop&y password + + + + &Settings + + + + &Perform Auto-Type + + + + &Open URL + + + + &Lock databases + + + + &Title + + + + &URL + + + + &Notes + + + + &Export to CSV file + + + + Re&pair database + + + + Password Generator + + + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + Importera KeePass1 databas + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + + + + OptionDialog + + Dialog + + + + General + Allmän + + + Sh&ow a notification when credentials are requested + + + + Sort matching entries by &username + + + + Re&move all stored permissions from entries in active database + + + + Advanced + Avancerat + + + Always allow &access to entries + + + + Always allow &updating entries + + + + Searc&h in all opened databases for matching entries + + + + HTTP Port: + + + + Default port: 19455 + + + + Re&quest to unlock the database if it is locked + + + + Sort &matching entries by title + + + + KeePassXC will listen to this port on 127.0.0.1 + + + + Cannot bind to privileged ports + + + + Cannot bind to privileged ports below 1024! +Using default port 19455. + + + + R&emove all shared encryption keys from active database + + + + &Return advanced string fields which start with "KPH: " + + + + Automatically creating or updating string fields is not supported. + + + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + + + + PasswordGeneratorWidget + + Password: + Lösenord: + + + Character Types + Teckentyper + + + Upper Case Letters + Versaler + + + Lower Case Letters + Gemener + + + Numbers + Siffror + + + Special Characters + Specialtecken + + + Exclude look-alike characters + Uteslut liknande tecken + + + Accept + Acceptera + + + %p% + + + + strength + + + + entropy + + + + &Length: + + + + Pick characters from every group + + + + Generate + + + + Close + + + + Apply + + + + Entropy: %1 bit + + + + Password Quality: %1 + + + + Poor + + + + Weak + + + + Good + + + + Excellent + + + + Password + Lösenord + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + + + + QObject + + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Grupp + + + Title + Titel + + + Username + Användarnamn + + + Password + Lösenord + + + URL + URL + + + Notes + Anteckningar + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + + + + + QtIOCompressor + + Internal zlib error when compressing: + Internt zlib fel vid komprimering: + + + Error writing to underlying device: + Fel vid skrivning till underliggande enhet: + + + Error opening underlying device: + Fel vid öppning av underliggande enhet: + + + Error reading data from underlying device: + Fel vid läsning från underliggande enhet: + + + Internal zlib error when decompressing: + Internt zlib fel vid extrahering: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + Gzip formatet stöds inte av denna version av zlib. + + + Internal zlib error: + Internt zlib fel: + + + + SearchWidget + + Case Sensitive + + + + Search + Sök + + + Clear + + + + Search... + + + + Limit search to selected group + + + + + Service + + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + + + + Do you want to update the information in %1 - %2? + + + + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + + + + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + + + + No shared encryption-keys found in KeePassHttp Settings. + + + + The active database does not contain an entry of KeePassHttp Settings. + + + + Removing stored permissions... + + + + Abort + + + + Successfully removed permissions from %1 %2. + + + + The active database does not contain an entry with permissions. + - Copy password to clipboard - Kopiera lösenord + KeePassXC: New key association request + - Settings - Inställningar + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + - Perform Auto-Type - Utför auto-skriv + KeePassXC: Overwrite existing key? + - Open URL - Öppna URL + KeePassXC: Update Entry + - Lock databases - Lås databaser + KeePassXC: Database locked! + - Title - Titel + KeePassXC: Removed keys from database + - URL - URL + KeePassXC: No keys found + - Notes - Anteckningar + KeePassXC: Settings not available! + - Show toolbar - Visa verktygsfält + KeePassXC: Removed permissions + - read-only - läs bara + KeePassXC: No entry with permissions found! + + + + SettingsWidget - Toggle window - Visa/dölj fönster + Application Settings + Applikationsinställningar - Tools - Verktyg + General + Allmän - Copy username - Kopiera användarnamn + Security + Säkerhet - Copy password - Kopiera lösenord + Access error for config file %1 + + + + SettingsWidgetGeneral - Export to CSV file - Exportera till CSV-fil + Remember last databases + Komihåg senaste databasen - Repair database - Laga databasen + Automatically save on exit + Spara automatiskt när applikationen anslutas - KeePass 2 Database - KeePass 2 databas + Automatically save after every change + Spara automatiskt efter varje ändring - All files - Alla filer + Minimize when copying to clipboard + Minimera vid kopiering - Save repaired database - Spara lagad databas + Use group icon on entry creation + Använd gruppens ikon för nya poster - Error - Fel + Global Auto-Type shortcut + Globalt auto-skriv kortkommando - Writing the database failed. - Misslyckades med att skriva till databasen. + Language + Språk - - - PasswordGeneratorWidget - Password: - Lösenord: + Show a system tray icon + Visa statusfält ikon - Length: - Längd: + Hide window to system tray when minimized + Vid minimering, minimera fönstret till systemfältet - Character Types - Teckentyper + Load previous databases on startup + - Upper Case Letters - Versaler + Automatically reload the database when modified externally + - Lower Case Letters - Gemener + Hide window to system tray instead of app exit + - Numbers - Siffror + Minimize window at application startup + - Special Characters - Specialtecken + Basic Settings + - Exclude look-alike characters - Uteslut liknande tecken + Remember last key files and security dongles + - Ensure that the password contains characters from every group - Säkerställ att lösenordet innehåller tecken från varje grupp + Don't mark database as modified for non-data changes (e.g., expanding groups) + - Accept - Acceptera + Auto-Type + Auto-skriv + + + Use entry title and URL to match windows for global Auto-Type + - - - QCommandLineParser - Displays version information. - Visar versionsinformation. + Always ask before performing Auto-Type + + + + SettingsWidgetSecurity - Displays this help. - Visa denna hjälp. + Clear clipboard after + Rensa urklipp efter - Unknown option '%1'. - Okänt alternativ: '%1' + sec + sek - Unknown options: %1. - Okända alternativ: '%1' + Lock databases after inactivity of + Lås databaser efter inaktivitet i - Missing value after '%1'. - Saknar värde efter '%1' + Show passwords in cleartext by default + Visa lösenord i klartext som standard - Unexpected value after '%1'. - Oväntat värde efter '%1' + Lock databases after minimizing the window + - [options] - [alternativ] + Don't require password repeat when it is visible + - Usage: %1 - Användning: %1 + Timeouts + - Options: - Alternativ: + Convenience + - Arguments: - Argument: + Lock databases when session is locked or lid is closed + - QSaveFile + SetupTotpDialog + + Setup TOTP + + - Existing file %1 is not writable - Den existerande filen %1 är inte skrivbar + Key: + - Writing canceled by application - Skrivning avbruten av applikation + Use custom settings + - Partial write. Partition full? - Delvis skrivet. Är partitionen full? + Note: Change these settings only if you know what you are doing. + - - - QtIOCompressor - Internal zlib error when compressing: - Internt zlib fel vid komprimering: + Time step: + - Error writing to underlying device: - Fel vid skrivning till underliggande enhet: + 8 digits + - Error opening underlying device: - Fel vid öppning av underliggande enhet: + 6 digits + - Error reading data from underlying device: - Fel vid läsning från underliggande enhet: + Code size: + - Internal zlib error when decompressing: - Internt zlib fel vid extrahering: + sec + sek - QtIOCompressor::open + TotpDialog - The gzip format not supported in this version of zlib. - Gzip formatet stöds inte av denna version av zlib. + Timed Password + - Internal zlib error: - Internt zlib fel: + 000000 + - - - SearchWidget - Find: - Sök: + Copy + - Case sensitive - Skiftlägeskänslig + Expires in + - Current group - Nuvarande grupp + seconds + + + + UnlockDatabaseWidget - Root group - Root grupp + Unlock database + Lås upp databas - SettingsWidget + WelcomeWidget - Application Settings - Applikationsinställningar + Welcome to KeePassXC + - General - Allmän + Start storing your passwords securely in a KeePassXC database + - Security - Säkerhet + Create new database + - - - SettingsWidgetGeneral - Remember last databases - Komihåg senaste databasen + Open existing database + - Open previous databases on startup - Öppna senaste databasen när programmet startar + Import from KeePass 1 + - Automatically save on exit - Spara automatiskt när applikationen anslutas + Import from CSV + - Automatically save after every change - Spara automatiskt efter varje ändring + Recent databases + Senast använda databaser + + + main - Minimize when copying to clipboard - Minimera vid kopiering + path to a custom config file + Sökväg till egen konfigurations-fil - Use group icon on entry creation - Använd gruppens ikon för nya poster + key file of the database + nyckel-fil för databas - Global Auto-Type shortcut - Globalt auto-skriv kortkommando + KeePassXC - cross-platform password manager + - Use entry title to match windows for global auto-type - Använda postens titel till matchning med fönster för globalt auto-skriv + read password of the database from stdin + - Language - Språk + filenames of the password databases to open (*.kdbx) + - Show a system tray icon - Visa statusfält ikon + Copy a password to the clipboard + - Hide window to system tray when minimized - Vid minimering, minimera fönstret till systemfältet + Path of the database. + - Remember last key files - Komihåg senaste nyckel-filen + Use a GUI prompt unlocking the database. + - Hide window to system tray instead of App Exit + Name of the entry to clip. - Hide window to system tray on App start + Extract and print the content of a database. - - - SettingsWidgetSecurity - Clear clipboard after - Rensa urklipp efter + Path of the database to extract. + - sec - sek + Name of the command to execute. + - Lock databases after inactivity of - Lås databaser efter inaktivitet i + List database entries. + - Show passwords in cleartext by default - Visa lösenord i klartext som standard + Path of the group to list. Default is / + - Always ask before performing auto-type - Fråga alltid innan auto-skriv utförs + Print the UUIDs of the entries and groups. + - - - UnlockDatabaseWidget - Unlock database - Lås upp databas + Merge two databases. + - - - WelcomeWidget - Welcome! - Välkommen! + Path of the database to merge into. + - - - main - KeePassX - cross-platform password manager - KeePassX - plattformsoberoende lösenordshanterare + Path of the database to merge from. + - filename of the password database to open (*.kdbx) - namn på databas fil att öppna (*.kdbx) + Use the same password for both database files. + - path to a custom config file - Sökväg till egen konfigurations-fil + Show a password. + - key file of the database - nyckel-fil för databas + Name of the entry to show. + \ No newline at end of file diff --git a/share/translations/keepassx_uk.ts b/share/translations/keepassx_uk.ts index 46541a0595..d2ceb1d327 100644 --- a/share/translations/keepassx_uk.ts +++ b/share/translations/keepassx_uk.ts @@ -1,33 +1,143 @@ - + AboutDialog - About KeePassX - Про KeePassX + About KeePassXC + + + + About + Про програму + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + - KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassX розповсюджується на умовах Загальної публічної ліцензії GNU (GPL) версії 2 або (на ваш вибір) версії 3. + Version %1 + + + + + Revision: %1 + + + + Libraries: + - Revision - Ревізія + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + - Using: - Використання: + Enabled extensions: + - AutoType + AccessControlDialog + + Remember this decision + + + + Allow + + + + Deny + + - Auto-Type - KeePassX - Автозаповнення — KeePassX + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + + + + KeePassXC HTTP Confirm Access + + + + AutoType Couldn't find an entry that matches the window title: Не знайдено запис, що відповідає заголовку вікна: + + Auto-Type - KeePassXC + + AutoTypeAssociationsModel @@ -46,14 +156,14 @@ AutoTypeSelectDialog - - Auto-Type - KeePassX - Автозаповнення — KeePassX - Select entry to Auto-Type: Оберіть запис для автозаповнення: + + Auto-Type - KeePassXC + + ChangeMasterKeyWidget @@ -69,10 +179,6 @@ Repeat password: Повторіть пароль: - - Key file - Файл-ключ - Browse Огляд @@ -93,10 +199,6 @@ Create Key File... Створити файл-ключ... - - Error - Помилка - Unable to create Key File : Неможливо створити файл-ключ: @@ -105,10 +207,6 @@ Select a key file Обрати файл-ключ - - Question - Питання - Do you really want to use an empty string as password? Ви дійсно хочете використати порожній рядок в якості пароля? @@ -117,16 +215,173 @@ Different passwords supplied. Паролі не співпадають. - - Failed to set key file - Не вдалося встановити файл-ключ - Failed to set %1 as the Key file: %2 Не вдалося встановити %1 в якості файл-ключа: %2 + + &Key file + + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + Помилка + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + Помилка + + + Unable to calculate master key + Неможливо вирахувати майстер-пароль + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -146,10 +401,6 @@ Browse Огляд - - Error - Помилка - Unable to open the database. Неможливо відкрити сховище. @@ -170,6 +421,14 @@ Select key file Оберіть файл-ключ + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -179,11 +438,11 @@ Error - + Помилка Can't open key file - + Не вдається відкрити файл-ключ Database opened fine. Nothing to do. @@ -191,7 +450,7 @@ Unable to open the database. - + Неможливо відкрити сховище. Success @@ -225,10 +484,6 @@ You can now save it. Default username: Типове ім’я користувача: - - Use recycle bin: - Використати смітник: - MiB MiB @@ -245,6 +500,22 @@ You can now save it. Max. history size: Максимальний розмір історії: + + Use recycle bin + + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -264,10 +535,6 @@ You can now save it. Open database Відкрити сховище - - Warning - Увага - File not found! Файл не знайдено! @@ -298,10 +565,6 @@ Save changes? "%1" змінено. Зберегти зміни? - - Error - Помилка - Writing the database failed. Записати сховище не вдалося. @@ -318,11 +581,6 @@ Save changes? locked заблоковано - - The database you are trying to open is locked by another instance of KeePassX. -Do you want to open it anyway? Alternatively the database is opened read-only. - Сховище, яке ви хочете відкрити, заблоковано іншою запущеною копією KeePassX. Все одно відкрити? Сховище буде відкрито тільки для читання. - Lock database Заблокувати сховище @@ -366,32 +624,61 @@ Discard changes and close anyway? Не вдалось записати CSV файл. - The database you are trying to save as is locked by another instance of KeePassX. -Do you want to save it anyway? - Це сховище заблоковано іншою запущеною копією KeePassX. -Ви впевнені, що хочете зберегти його? + Unable to open the database. + Неможливо відкрити сховище. - Unable to open the database. + Merge database - - - DatabaseWidget - Change master key - Змінити майстер-пароль + The database you are trying to save as is locked by another instance of KeePassXC. +Do you want to save it anyway? + - Delete entry? - Видалити запис? + Passwords + - Do you really want to delete the entry "%1" for good? - Ви дійсно хочете видалити запис «%1»? + Database already opened + - Delete entries? + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + + + + Open read-only + + + + File opened in read only mode. + + + + Open CSV file + + + + + DatabaseWidget + + Change master key + Змінити майстер-пароль + + + Delete entry? + Видалити запис? + + + Do you really want to delete the entry "%1" for good? + Ви дійсно хочете видалити запис «%1»? + + + Delete entries? Видалити записи? @@ -414,14 +701,6 @@ Do you want to save it anyway? Do you really want to delete the group "%1" for good? Ви дійсно хочете назавжди видалити групу «%1»? - - Current group - Поточна група - - - Error - Помилка - Unable to calculate master key Неможливо вирахувати майстер-пароль @@ -434,6 +713,66 @@ Do you want to save it anyway? Do you really want to move entry "%1" to the recycle bin? + + Searching... + + + + No current database. + + + + No source database, nothing to do. + + + + Search Results (%1) + + + + No Results + + + + Execute command? + + + + Do you really want to execute the following command?<br><br>%1<br> + + + + Remember my choice + + + + Autoreload Request + + + + The database file has changed. Do you want to load the changes? + + + + Merge Request + + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + + + + Could not open the new database file while attempting to autoreload this database. + + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -473,10 +812,6 @@ Do you want to save it anyway? Edit entry Змінити запис - - Error - Помилка - Different passwords supplied. Паролі не співпадають. @@ -519,6 +854,22 @@ Do you want to save it anyway? 1 year 1 рік + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -530,10 +881,6 @@ Do you want to save it anyway? Add Додати - - Edit - Змінити - Remove Видалити @@ -550,6 +897,18 @@ Do you want to save it anyway? Open Відкрити + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -557,14 +916,6 @@ Do you want to save it anyway? Enable Auto-Type for this entry Увімкнути автозаповнення для цього запису - - Inherit default Auto-Type sequence from the group - Успадкувати типову послідовність автозаповнення від групи - - - Use custom Auto-Type sequence: - Використовувати свою послідовність автозаповнення: - + + @@ -578,12 +929,24 @@ Do you want to save it anyway? Заголовок вікна: - Use default sequence - Використовувати типову послідовність + Inherit default Auto-Type sequence from the &group + + + + &Use custom Auto-Type sequence: + + + + Use default se&quence + + + + Set custo&m sequence: + - Set custom sequence: - Встановити свою послідовність: + Window Associations + @@ -623,10 +986,6 @@ Do you want to save it anyway? Repeat: Пароль ще раз: - - Gen. - Генер. - URL: URL: @@ -698,28 +1057,20 @@ Do you want to save it anyway? Пошук - Auto-type + Auto-Type Автозаповнення - Use default auto-type sequence of parent group - Використовувати типову послідовність автозаповнення батьківської групи + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - Типова послідовність автозаповнення + Set default Auto-Type se&quence + EditWidgetIcons - - Use default icon - Використовувати типовий значок - - - Use custom icon - Використовувати свій значок - Add custom icon Додати свій значок @@ -741,19 +1092,35 @@ Do you want to save it anyway? Вибір зображення - Can't delete icon! - Неможливо видалити значок! + Error + Помилка - - Can't delete icon. Still used by %n item(s). - Ви дійсно хочете перемістити %n запис в смітник?Ви дійсно хочете перемістити %n записи в смітник?Ви дійсно хочете перемістити %n записів в смітник? + + Download favicon + - Error + Unable to fetch favicon. + + + + Can't read icon + + + + &Use default icon - Can't read icon: + Use custo&m icon + + + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? @@ -776,6 +1143,13 @@ Do you want to save it anyway? Uuid: + + Entry + + - Clone + + + EntryAttributesModel @@ -820,6 +1194,11 @@ Do you want to save it anyway? URL URL + + Ref: + Reference abbreviation + + Group @@ -828,16 +1207,74 @@ Do you want to save it anyway? Смітник + + HttpPasswordGeneratorWidget + + Length: + Довжина: + + + Character Types + Види символів + + + Upper Case Letters + Великі літери + + + A-Z + + + + Lower Case Letters + Малі літери + + + a-z + + + + Numbers + Цифри + + + 0-9 + + + + Special Characters + Спеціальні символи + + + /*_& ... + + + + Exclude look-alike characters + Виключити неоднозначні символи + + + Ensure that the password contains characters from every group + Переконатися, що пароль містить символи всіх видів + + + + KMessageWidget + + &Close + + + + Close message + + + KeePass1OpenWidget Import KeePass1 database Імпортувати сховище KeePass 1 - - Error - Помилка - Unable to open the database. Неможливо відкрити сховище. @@ -871,7 +1308,7 @@ Do you want to save it anyway? Wrong key or database file is corrupt. - + Неправильний ключ або файл сховища пошкоджено. @@ -902,6 +1339,10 @@ This is a one-way migration. You won't be able to open the imported databas Ви можете імпортувати його, натиснувши Сховище > 'Імпортувати сховище KeePass 1'. Це односторонній спосіб міграції. Ви не зможете відкрити імпортоване сховище в попередній версії KeePassX 0.4. + + Unable to issue challenge-response. + + Main @@ -910,483 +1351,1039 @@ This is a one-way migration. You won't be able to open the imported databas Невиправна помилка в процесі тестування криптографічних функцій. - KeePassX - Error - KeePassX — Помилка + KeePassXC - Error + + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + MainWindow - Database - Сховище + Open database + Відкрити сховище - Recent databases - Недавні сховища + Database settings + Параметри сховища - Help - Довідка + Copy username to clipboard + Копіювати ім’я користувача в буфер обміну - Entries - Записи + Copy password to clipboard + Копіювати пароль в буфер обміну - Copy attribute to clipboard - Копіювати атрибут в буфер обміну + Settings + Налаштування - Groups - Групи + Show toolbar + Показати панель инструментів - View - Вигляд + read-only + тільки для читання - Quit - Вихід + Toggle window + Перемкнути вікно - About - Про програму + KeePass 2 Database + Сховище KeePass 2 - Open database - Відкрити сховище + All files + Всі файли - Save database - Зберегти сховище + Save repaired database + - Close database - Закрити сховище + Writing the database failed. + Записати сховище не вдалося. - New database - Нове сховище + &Recent databases + - Add new entry - Додати новий запис + He&lp + - View/Edit entry - Проглянути/змінити запис + E&ntries + - Delete entry - Видалити запис + Copy att&ribute to clipboard + - Add new group - Додати нову групу + &Groups + - Edit group - Редагувати групу + &View + - Delete group - Видалити групу + &Quit + - Save database as - Зберегти сховище як + &About + - Change master key - Змінити майстер-пароль + &Open database + - Database settings - Параметри сховища + &Save database + - Import KeePass 1 database - Імпортувати сховище KeePass 1 + &Close database + - Clone entry - Клонувати запис + &New database + - Find - Знайти + Merge from KeePassX database + - Copy username to clipboard - Копіювати ім’я користувача в буфер обміну + &Add new entry + - Copy password to clipboard - Копіювати пароль в буфер обміну + &View/Edit entry + - Settings - Налаштування + &Delete entry + - Perform Auto-Type - Здійснити автозаповнення + &Add new group + - Open URL - Відкрити URL + &Edit group + - Lock databases - Заблокувати сховище + &Delete group + - Title - Заголовок + Sa&ve database as + - URL - URL + Change &master key + - Notes - Примітки + &Database settings + - Show toolbar - Показати панель инструментів + &Clone entry + - read-only - тільки для читання + Timed one-time password + - Toggle window - Перемкнути вікно + Setup TOTP + - Tools - Інструменти + Copy &TOTP + - Copy username - Копіювати ім’я користувача + Show TOTP + - Copy password - Копіювати пароль + &Find + - Export to CSV file - Експортувати в файл CSV + Copy &username + - Repair database + Cop&y password - KeePass 2 Database + &Settings - All files + &Perform Auto-Type - Save repaired database + &Open URL - Error + &Lock databases - Writing the database failed. + &Title - - - PasswordGeneratorWidget - Password: - Пароль: + &URL + - Length: - Довжина: + &Notes + - Character Types - Види символів + &Export to CSV file + - Upper Case Letters - Великі літери + Re&pair database + - Lower Case Letters - Малі літери + Password Generator + - Numbers - Цифри + Clear history + - Special Characters - Спеціальні символи + &Database + - Exclude look-alike characters - Виключити неоднозначні символи + Import + - Ensure that the password contains characters from every group - Переконатися, що пароль містить символи всіх видів + &Tools + - Accept - Прийняти + Import KeePass 1 database + Імпортувати сховище KeePass 1 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + - QCommandLineParser + OptionDialog + + Dialog + + - Displays version information. - Показує інформацію про версію. + General + Загальні - Displays this help. - Показує цю довідку. + Sh&ow a notification when credentials are requested + - Unknown option '%1'. - Невідома опція «%1». + Sort matching entries by &username + - Unknown options: %1. - Невідомі опції %1. + Re&move all stored permissions from entries in active database + - Missing value after '%1'. - Пропущено значення після «%1». + Advanced + Розширені - Unexpected value after '%1'. - Непередбачене значення після «%1». + Always allow &access to entries + - [options] - [опції] + Always allow &updating entries + - Usage: %1 - Використання: %1 + Searc&h in all opened databases for matching entries + - Options: - Опції: + HTTP Port: + - Arguments: - Аргументи: + Default port: 19455 + - - - QSaveFile - Existing file %1 is not writable - Існуючий файл %1 непридатний для запису + Re&quest to unlock the database if it is locked + - Writing canceled by application - Запис відмінено застосунком + Sort &matching entries by title + - Partial write. Partition full? - Частковий запис. Разділ переповнений? + KeePassXC will listen to this port on 127.0.0.1 + - - - QtIOCompressor - Internal zlib error when compressing: - Внутрішня помилка zlib при стисненні: + Cannot bind to privileged ports + - Error writing to underlying device: - Помилка запису на основний пристрій: + Cannot bind to privileged ports below 1024! +Using default port 19455. + - Error opening underlying device: - Помилка відкриття основного пристрою: + R&emove all shared encryption keys from active database + - Error reading data from underlying device: - Помилка читання з основного пристрою: + &Return advanced string fields which start with "KPH: " + - Internal zlib error when decompressing: - Внутрішня помилка zlib при розпакуванні: + Automatically creating or updating string fields is not supported. + - - - QtIOCompressor::open - The gzip format not supported in this version of zlib. - Формат gzip не підтримується в цій версії zlib. + This is required for accessing your databases from ChromeIPass or PassIFox + - Internal zlib error: - Внутрішня помилка zlib: + Enable KeePassHTTP server + - - - SearchWidget - Find: - Знайти: + Only returns the best matches for a specific URL instead of all entries for the whole domain. + - Case sensitive - Враховується регістр + &Return only best matching entries + - Current group - Поточна група + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + - Root group - Коренева група + &Match URL schemes + - - - SettingsWidget - Application Settings - Параметри застосунку + Password Generator + - General - Загальні + Only the selected database has to be connected with a client. + - Security - Безпека + The following options can be dangerous! +Change them only if you know what you are doing. + - SettingsWidgetGeneral + PasswordGeneratorWidget - Remember last databases - Пам’ятати останнє сховище + Password: + Пароль: - Open previous databases on startup - Відкривати останнє сховище під час запуску + Character Types + Види символів - Automatically save on exit - Автоматично зберігати при виході + Upper Case Letters + Великі літери - Automatically save after every change - Автоматично зберігати після кожної зміни + Lower Case Letters + Малі літери - Minimize when copying to clipboard - Згортати при копіюванні до буфера обміну + Numbers + Цифри - Use group icon on entry creation - Використовувати для нових записів значок групи + Special Characters + Спеціальні символи - Global Auto-Type shortcut - Глобальні сполучення клавіш для автозаповнення + Exclude look-alike characters + Виключити неоднозначні символи - Use entry title to match windows for global auto-type - Використовувати заголовок запису для вибору вікон для глобального автозаповнення + Accept + Прийняти - Language - Мова + %p% + - Show a system tray icon - Показувати значок в треї + strength + - Hide window to system tray when minimized - При згортанні ховати вікно в область системних повідомлень + entropy + - Remember last key files - Пам’ятати останні файл-ключі + &Length: + - Hide window to system tray instead of App Exit + Pick characters from every group - Hide window to system tray on App start + Generate - - - SettingsWidgetSecurity - Clear clipboard after - Очищати буфер обміну через + Close + - sec - сек + Apply + - Lock databases after inactivity of - Заблокувати сховище, неактивне протягом + Entropy: %1 bit + - Show passwords in cleartext by default - Типово показувати пароль у відкритому вигляді + Password Quality: %1 + - Always ask before performing auto-type - Завжди запитувати перед автозаповненням + Poor + - - - UnlockDatabaseWidget - Unlock database - Розблокувати сховище + Weak + - - - WelcomeWidget - Welcome! - Ласкаво просимо! + Good + - - - main - KeePassX - cross-platform password manager - KeePassX — кросплатформний менеджер паролів + Excellent + - filename of the password database to open (*.kdbx) - назва файла сховища паролів, що відкривається (*.kdbx) + Password + Пароль - path to a custom config file + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + + + + QObject + + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + Група + + + Title + Заголовок + + + Username + Ім’я користувача + + + Password + Пароль + + + URL + URL + + + Notes + Примітки + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + + + + + QtIOCompressor + + Internal zlib error when compressing: + Внутрішня помилка zlib при стисненні: + + + Error writing to underlying device: + Помилка запису на основний пристрій: + + + Error opening underlying device: + Помилка відкриття основного пристрою: + + + Error reading data from underlying device: + Помилка читання з основного пристрою: + + + Internal zlib error when decompressing: + Внутрішня помилка zlib при розпакуванні: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + Формат gzip не підтримується в цій версії zlib. + + + Internal zlib error: + Внутрішня помилка zlib: + + + + SearchWidget + + Case Sensitive + + + + Search + Пошук + + + Clear + + + + Search... + + + + Limit search to selected group + + + + + Service + + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + + + + Do you want to update the information in %1 - %2? + + + + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + + + + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + + + + No shared encryption-keys found in KeePassHttp Settings. + + + + The active database does not contain an entry of KeePassHttp Settings. + + + + Removing stored permissions... + + + + Abort + + + + Successfully removed permissions from %1 %2. + + + + The active database does not contain an entry with permissions. + + + + KeePassXC: New key association request + + + + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + + + + KeePassXC: Overwrite existing key? + + + + KeePassXC: Update Entry + + + + KeePassXC: Database locked! + + + + KeePassXC: Removed keys from database + + + + KeePassXC: No keys found + + + + KeePassXC: Settings not available! + + + + KeePassXC: Removed permissions + + + + KeePassXC: No entry with permissions found! + + + + + SettingsWidget + + Application Settings + Параметри застосунку + + + General + Загальні + + + Security + Безпека + + + Access error for config file %1 + + + + + SettingsWidgetGeneral + + Remember last databases + Пам’ятати останнє сховище + + + Automatically save on exit + Автоматично зберігати при виході + + + Automatically save after every change + Автоматично зберігати після кожної зміни + + + Minimize when copying to clipboard + Згортати при копіюванні до буфера обміну + + + Use group icon on entry creation + Використовувати для нових записів значок групи + + + Global Auto-Type shortcut + Глобальні сполучення клавіш для автозаповнення + + + Language + Мова + + + Show a system tray icon + Показувати значок в треї + + + Hide window to system tray when minimized + При згортанні ховати вікно в область системних повідомлень + + + Load previous databases on startup + + + + Automatically reload the database when modified externally + + + + Hide window to system tray instead of app exit + + + + Minimize window at application startup + + + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + Автозаповнення + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + + + + SettingsWidgetSecurity + + Clear clipboard after + Очищати буфер обміну через + + + sec + сек + + + Lock databases after inactivity of + Заблокувати сховище, неактивне протягом + + + Show passwords in cleartext by default + Типово показувати пароль у відкритому вигляді + + + Lock databases after minimizing the window + + + + Don't require password repeat when it is visible + + + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + сек + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + + + + UnlockDatabaseWidget + + Unlock database + Розблокувати сховище + + + + WelcomeWidget + + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + Недавні сховища + + + + main + + path to a custom config file шлях до власного файла налаштувань key file of the database файл-ключ сховища + + KeePassXC - cross-platform password manager + + + + read password of the database from stdin + + + + filenames of the password databases to open (*.kdbx) + + + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_zh_CN.ts b/share/translations/keepassx_zh_CN.ts index bbb55e651b..8bc3aaac62 100644 --- a/share/translations/keepassx_zh_CN.ts +++ b/share/translations/keepassx_zh_CN.ts @@ -2,26 +2,106 @@ AboutDialog - Revision - 修改 + About KeePassXC + 关于 KeePassXC - Using: - 使用: + About + 关于 - About KeePassXC - 关于 KeePassXC + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + - Extensions: + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 - 扩展: - + - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassXC 使用的是第 2 版 GNU 通用公共授权协议(GPL)(你可以根据需要选用第 3 版). + Revision: %1 + + + + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + + + + Enabled extensions: + @@ -119,10 +199,6 @@ Please select whether you want to allow access. Create Key File... 创建秘钥文件... - - Error - 错误 - Unable to create Key File : 无法创建秘钥文件: @@ -131,10 +207,6 @@ Please select whether you want to allow access. Select a key file 选择一个秘钥文件 - - Question - 问题 - Do you really want to use an empty string as password? 你确定要使用空密码? @@ -143,10 +215,6 @@ Please select whether you want to allow access. Different passwords supplied. 你输入了不同的密码 - - Failed to set key file - 设置秘钥文件失败 - Failed to set %1 as the Key file: %2 @@ -157,6 +225,163 @@ Please select whether you want to allow access. &Key file 秘钥文件 + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + 错误 + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + 错误 + + + Unable to calculate master key + 无法计算主密码 + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -176,10 +401,6 @@ Please select whether you want to allow access. Browse 浏览 - - Error - 错误 - Unable to open the database. 无法打开数据库 @@ -200,6 +421,14 @@ Please select whether you want to allow access. Select key file 选择秘钥文件 + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -276,6 +505,18 @@ You can now save it. Use recycle bin 使用回收站 + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -295,10 +536,6 @@ You can now save it. Open database 打开数据库 - - Warning - 警告 - File not found! 找不到文件! @@ -329,10 +566,6 @@ Save changes? "%1" 已被修改。 要保存吗? - - Error - 错误 - Writing the database failed. 数据库写入失败 @@ -424,6 +657,14 @@ Do you want to open it anyway? Open read-only 已只读方式打开 + + File opened in read only mode. + + + + Open CSV file + + DatabaseWidget @@ -463,10 +704,6 @@ Do you want to open it anyway? Do you really want to delete the group "%1" for good? 你确定永远删除 "%1" 群组吗? - - Error - 错误 - Unable to calculate master key 无法计算主密码 @@ -527,14 +764,18 @@ Do you want to open it anyway? The database file has changed and you have unsaved changes.Do you want to merge your changes? 数据库文件已更改,您有未保存的更改。是否合并您的更改? - - Autoreload Failed - 自动加载失败 - Could not open the new database file while attempting to autoreload this database. 在尝试 autoreload 此数据库不打开新的数据库文件。 + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + EditEntryWidget @@ -574,10 +815,6 @@ Do you want to open it anyway? Edit entry 编辑项目 - - Error - 错误 - Different passwords supplied. 你输入了不同的密码 @@ -620,6 +857,22 @@ Do you want to open it anyway? 1 year 1 年 + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -631,10 +884,6 @@ Do you want to open it anyway? Add 添加 - - Edit - 编辑 - Remove 移除 @@ -651,6 +900,18 @@ Do you want to open it anyway? Open 打开 + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -686,6 +947,10 @@ Do you want to open it anyway? Set custo&m sequence: 设置自定义顺序 + + Window Associations + + EditEntryWidgetHistory @@ -795,16 +1060,16 @@ Do you want to open it anyway? 搜索 - Auto-type + Auto-Type 自动输入 - Use default auto-type sequence of parent group - 使用父群组默认顺序 + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - 设置默认自动输入顺序 + Set default Auto-Type se&quence + @@ -829,10 +1094,6 @@ Do you want to open it anyway? Select Image 选择图片 - - Can't delete icon! - 不能删除图标! - Error 错误 @@ -849,10 +1110,6 @@ Do you want to open it anyway? Can't read icon 无法读取图标 - - Can't delete icon. Still used by %1 items. - %1 项目正在使用,无法删除图标。 - &Use default icon 使用默认图标 @@ -861,6 +1118,14 @@ Do you want to open it anyway? Use custo&m icon 使用自定义图标 + + Confirm Delete + + + + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? + + EditWidgetProperties @@ -932,6 +1197,11 @@ Do you want to open it anyway? URL 网址 + + Ref: + Reference abbreviation + + Group @@ -990,9 +1260,16 @@ Do you want to open it anyway? Ensure that the password contains characters from every group 确保密码包含每种的字符 + + + KMessageWidget - Accept - 接受 + &Close + + + + Close message + @@ -1001,10 +1278,6 @@ Do you want to open it anyway? Import KeePass1 database 导入 KeePass 1 数据库 - - Error - 错误 - Unable to open the database. 无法打开数据库。 @@ -1068,6 +1341,10 @@ This is a one-way migration. You won't be able to open the imported databas 你可以通过点击 数据库 > '导入KeePass 1 数据库’ 来导入。 这是不可逆的修改。导入后的数据库将无法由旧版的KeePassX 0.4版本打开。 + + Unable to issue challenge-response. + + Main @@ -1079,13 +1356,17 @@ This is a one-way migration. You won't be able to open the imported databas KeePassXC - Error KeePassXC - 错误 + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + + MainWindow - - Database - 数据库 - Open database 打开数据库 @@ -1118,10 +1399,6 @@ This is a one-way migration. You won't be able to open the imported databas Toggle window 切换窗口 - - Tools - 工具 - KeePass 2 Database KeePass 2 数据库 @@ -1134,10 +1411,6 @@ This is a one-way migration. You won't be able to open the imported databas Save repaired database 保存修复后的数据库 - - Error - 错误 - Writing the database failed. 数据库写入失败 @@ -1230,14 +1503,26 @@ This is a one-way migration. You won't be able to open the imported databas &Database settings 数据库设置 - - &Import KeePass 1 database - 导入KeePass 1 数据库 - &Clone entry 复制项目 + + Timed one-time password + + + + Setup TOTP + + + + Copy &TOTP + + + + Show TOTP + + &Find 查找 @@ -1290,6 +1575,46 @@ This is a one-way migration. You won't be able to open the imported databas Password Generator 密码生成器 + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + 导入KeePass 1 数据库 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + OptionDialog @@ -1305,11 +1630,6 @@ This is a one-way migration. You won't be able to open the imported databas Sh&ow a notification when credentials are requested - - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned - - Sort matching entries by &username 按匹配用户名排序 @@ -1318,10 +1638,6 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< Re&move all stored permissions from entries in active database - - Password generator - 密码生成器 - Advanced 高级 @@ -1338,10 +1654,6 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< Searc&h in all opened databases for matching entries 在所有打开的数据库中查找匹配项目 - - Only the selected database has to be connected with a client! - 客户端只能连接选中的数据库! - HTTP Port: HTTP端口: @@ -1358,12 +1670,6 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< Sort &matching entries by title 用标题排序匹配的项目 - - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox - 启用KeepassXC HTTP协议 -这需要ChromeIPass或PassIFox访问你的数据库 - KeePassXC will listen to this port on 127.0.0.1 KeePassXC 将监听 127.0.0.1上的此端口 @@ -1378,19 +1684,10 @@ Using default port 19455. 无法绑定低于 1024的特殊端口 ! 使用默认端口 19455。 - - &Return only best matching entries for a URL instead -of all entries for the whole domain - 只返回最佳匹配条目的 URL 而不是整个域的所有条目 - R&emove all shared encryption keys from active database 移除所有激活数据库共享的加密密钥 - - The following options can be dangerous. Change them only if you know what you are doing. - 以下选项不要修改。除非你知道自己在做什么。 - &Return advanced string fields which start with "KPH: " @@ -1399,6 +1696,43 @@ of all entries for the whole domain Automatically creating or updating string fields is not supported. 不支持自动创建或更新字符串字段。 + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + 密码生成器 + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + PasswordGeneratorWidget @@ -1490,12 +1824,101 @@ of all entries for the whole domain Excellent 优秀 + + Password + 密码 + + + Extended ASCII + + + + Passphrase + + + + Wordlist: + + + + Word Count: + + + + Word Separator: + + + + Copy + + QObject - Http - Http + NULL device + + + + error reading from device + + + + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + 群组 + + + Title + 标题 + + + Username + 用户名 + + + Password + 密码 + + + URL + 网址 + + + Notes + 备注 + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1542,14 +1965,18 @@ of all entries for the whole domain Search 搜索 - - Find - 查找 - Clear 清除 + + Search... + + + + Limit search to selected group + + Service @@ -1654,6 +2081,10 @@ give it a unique name to identify and accept it. Security 安全 + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1681,10 +2112,6 @@ give it a unique name to identify and accept it. Global Auto-Type shortcut 自动输入全局快捷键 - - Use entry title to match windows for global auto-type - 使用项目标题来查找自动输入的目标窗口 - Language 语言 @@ -1697,10 +2124,6 @@ give it a unique name to identify and accept it. Hide window to system tray when minimized 将窗口最小化至任务栏 - - Remember last key files - 记住最近的秘钥文件 - Load previous databases on startup 在启动时加载最近的数据库 @@ -1717,6 +2140,30 @@ give it a unique name to identify and accept it. Minimize window at application startup 在应用程序启动时窗口最小化 + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + 自动输入 + + + Use entry title and URL to match windows for global Auto-Type + + + + Always ask before performing Auto-Type + + SettingsWidgetSecurity @@ -1736,10 +2183,6 @@ give it a unique name to identify and accept it. Show passwords in cleartext by default 默认以明码显示密码 - - Always ask before performing auto-type - 在执行自动输入前询问 - Lock databases after minimizing the window 在最小化窗口后锁定数据库 @@ -1748,6 +2191,80 @@ give it a unique name to identify and accept it. Don't require password repeat when it is visible 可见时不需要重复输入密码 + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + + UnlockDatabaseWidget @@ -1759,8 +2276,32 @@ give it a unique name to identify and accept it. WelcomeWidget - Welcome! - 欢迎! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + + + + Import from KeePass 1 + + + + Import from CSV + + + + Recent databases + 最近的数据库 @@ -1785,5 +2326,69 @@ give it a unique name to identify and accept it. filenames of the password databases to open (*.kdbx) 打开密码数据库文件名(*.kdbx) + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/keepassx_zh_TW.ts b/share/translations/keepassx_zh_TW.ts index c8c2f9e1aa..d50444e767 100644 --- a/share/translations/keepassx_zh_TW.ts +++ b/share/translations/keepassx_zh_TW.ts @@ -1,33 +1,144 @@ - + AboutDialog - About KeePassX - 關於 KeePassX + About KeePassXC + 關於 KeePassXC - KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassX 是使用第 2 版 GNU 通用公共授權條款所發佈的 (或者,可根據你的選擇選用第 3 版) + About + 關於 + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + Contributors + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + + Debug Info + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + Copy to clipboard + + + + Version %1 + + + + + Revision: %1 + - Revision - 修改紀錄 + Libraries: + + + + Operating system: %1 +CPU architecture: %2 +Kernel: %3 %4 + - Using: - 使用: + Enabled extensions: + - AutoType + AccessControlDialog + + Remember this decision + 記住此決定 + + + Allow + 允許 + + + Deny + 禁止 + - Auto-Type - KeePassX - KeePassX - 自動輸入 + %1 has requested access to passwords for the following item(s). +Please select whether you want to allow access. + %1 要求存取下列項目的密碼。 +請選擇是否允許存取。 + + KeePassXC HTTP Confirm Access + KeePassXC HTTP 確認存取 + + + + AutoType Couldn't find an entry that matches the window title: 無法找到符合視窗標題的項目 + + Auto-Type - KeePassXC + 自動輸入 - KeePassXC + AutoTypeAssociationsModel @@ -46,14 +157,14 @@ AutoTypeSelectDialog - - Auto-Type - KeePassX - KeePassX - 自動輸入 - Select entry to Auto-Type: 選擇自動輸入的項目 + + Auto-Type - KeePassXC + 自動輸入 - KeePassXC + ChangeMasterKeyWidget @@ -69,10 +180,6 @@ Repeat password: 再次輸入密碼 - - Key file - 金鑰檔案 - Browse 瀏覽 @@ -93,10 +200,6 @@ Create Key File... 建立一個金鑰檔案 - - Error - 錯誤 - Unable to create Key File : 無法建立金鑰檔案: @@ -105,10 +208,6 @@ Select a key file 選擇一個金鑰檔案 - - Question - 問題 - Do you really want to use an empty string as password? 你真的想使用空白密碼嗎? @@ -117,16 +216,173 @@ Different passwords supplied. 提供了不同的密碼 - - Failed to set key file - 無法設定金鑰檔案 - Failed to set %1 as the Key file: %2 無法設定 %1 成為金鑰檔案: %2 + + &Key file + 金鑰檔案 (&K) + + + Cha&llenge Response + + + + Refresh + + + + Empty password + + + + Changing master key failed: no YubiKey inserted. + + + + + CloneDialog + + Clone Options + + + + Append ' - Copy' to title + + + + Replace username and password with references + + + + Copy history + + + + + CsvImportWidget + + Import CSV fields + + + + filename + + + + size, rows, columns + + + + Encoding + + + + Codec + + + + Text is qualified by + + + + Fields are separated by + + + + Comments start with + + + + First record has field names + + + + Number of headers line to discard + + + + Consider '\' an escape character + + + + Preview + + + + Column layout + + + + Not present in CSV file + + + + Empty fieldname + + + + column + + + + Imported from CSV file + + + + Original data: + + + + Error(s) detected in CSV file ! + + + + more messages skipped] + + + + Error + 錯誤 + + + CSV import: writer has errors: + + + + + + CsvImportWizard + + Import CSV file + + + + Error + 錯誤 + + + Unable to calculate master key + 無法計算主金鑰 + + + + CsvParserModel + + byte, + + + + rows, + + + + columns + + DatabaseOpenWidget @@ -146,10 +402,6 @@ Browse 瀏覽 - - Error - 錯誤 - Unable to open the database. 無法打開這個資料庫 @@ -170,6 +422,14 @@ Select key file 選擇金鑰檔案 + + Refresh + + + + Challenge Response: + + DatabaseRepairWidget @@ -226,10 +486,6 @@ You can now save it. Default username: 預設的使用者名稱: - - Use recycle bin: - 使用垃圾桶: - MiB MiB @@ -246,6 +502,22 @@ You can now save it. Max. history size: 最大的歷史大小: + + Use recycle bin + 使用回收桶 + + + AES: 256 Bit (default) + + + + Twofish: 256 Bit + + + + Algorithm: + + DatabaseTabWidget @@ -265,10 +537,6 @@ You can now save it. Open database 打開資料庫 - - Warning - 警告 - File not found! 找不到檔案! @@ -298,10 +566,6 @@ You can now save it. Save changes? "%1" 已被修改。要儲存嗎? - - Error - 錯誤 - Writing the database failed. 寫入資料庫失敗 @@ -318,12 +582,6 @@ Save changes? locked 已鎖住 - - The database you are trying to open is locked by another instance of KeePassX. -Do you want to open it anyway? Alternatively the database is opened read-only. - 你嘗試要打開的資料庫已經被另一個正在執行的 KeePassX 鎖定 -你要打開它嗎?或者,打開唯讀的資料庫 - Lock database 鎖定資料庫 @@ -367,13 +625,45 @@ Discard changes and close anyway? 寫入 CSV 檔案失敗 - The database you are trying to save as is locked by another instance of KeePassX. + Unable to open the database. + 無法開啟這個資料庫 + + + Merge database + 合併資料庫 + + + The database you are trying to save as is locked by another instance of KeePassXC. Do you want to save it anyway? - 你嘗試要打開的資料庫已經被另一個正在執行的 KeePassX 鎖定 -還要儲存嗎? + 欲保存的資料庫已被其他 KeePassXC 程式鎖定。 +確定仍要繼續儲存? - Unable to open the database. + Passwords + 密碼 + + + Database already opened + 資料庫已經開啟 + + + The database you are trying to open is locked by another instance of KeePassXC. + +Do you want to open it anyway? + 欲開啟的資料庫已被其他 KeePassXC 程式鎖定。 + +確定仍要繼續開啟? + + + Open read-only + 以唯讀模式開啟 + + + File opened in read only mode. + + + + Open CSV file @@ -415,31 +705,83 @@ Do you want to save it anyway? Do you really want to delete the group "%1" for good? 你真的想永遠刪除 "%1 " 群組嗎? - - Current group - 目前的群組 - - - Error - 錯誤 - Unable to calculate master key 無法計算主金鑰 Move entry to recycle bin? - + 移動項目到回收桶? Do you really want to move entry "%1" to the recycle bin? - + 你真的想將 "%1" 移到回收桶? - - - EditEntryWidget - Entry + Searching... + 搜尋中…… + + + No current database. + 無目前資料庫。 + + + No source database, nothing to do. + 無來源資料庫,無事可做。 + + + Search Results (%1) + 搜尋結果 (%1) + + + No Results + 無結果 + + + Execute command? + 執行命令? + + + Do you really want to execute the following command?<br><br>%1<br> + 你真的想執行下列命令嗎?<br><br>%1<br> + + + Remember my choice + 記住我的選擇 + + + Autoreload Request + 自動重新讀取請求 + + + The database file has changed. Do you want to load the changes? + 資料庫檔案已變更。要讀取變更嗎? + + + Merge Request + 合併請求 + + + The database file has changed and you have unsaved changes.Do you want to merge your changes? + 資料庫檔案已變更,且你有尚未儲存的變更。要合併你的變更嗎? + + + Could not open the new database file while attempting to autoreload this database. + 自動重新讀取此資料庫時無法開啟新資料褲檔案。 + + + Empty recycle bin? + + + + Are you sure you want to permanently delete everything from your recycle bin? + + + + + EditEntryWidget + + Entry 項目 @@ -474,10 +816,6 @@ Do you want to save it anyway? Edit entry 編輯項目 - - Error - 錯誤 - Different passwords supplied. 提供了不同的密碼 @@ -520,6 +858,22 @@ Do you want to save it anyway? 1 year 1 年 + + Confirm Remove + + + + Are you sure you want to remove this attribute? + + + + [PROTECTED] Press reveal to view or edit + + + + Are you sure you want to remove this attachment? + + EditEntryWidgetAdvanced @@ -531,10 +885,6 @@ Do you want to save it anyway? Add 加入 - - Edit - 編輯 - Remove 移除 @@ -551,6 +901,18 @@ Do you want to save it anyway? Open 打開 + + Edit Name + + + + Protect + + + + Reveal + + EditEntryWidgetAutoType @@ -558,14 +920,6 @@ Do you want to save it anyway? Enable Auto-Type for this entry 打開此項目的自動輸入 - - Inherit default Auto-Type sequence from the group - 從父群組繼承預設的自動輸入序列 - - - Use custom Auto-Type sequence: - 使用自訂的自動輸入序列 - + + @@ -579,12 +933,24 @@ Do you want to save it anyway? 視窗標題: - Use default sequence - 使用預設序列 + Inherit default Auto-Type sequence from the &group + 從群組中繼承預設的自動輸入序列 (&G) + + + &Use custom Auto-Type sequence: + 使用自訂的自動輸入序列:(&U) + + + Use default se&quence + 使用預設序列 (&Q) + + + Set custo&m sequence: + 設定預設的序列:(&M) - Set custom sequence: - 設定自訂的序列 + Window Associations + @@ -624,10 +990,6 @@ Do you want to save it anyway? Repeat: 重複: - - Gen. - 產生 - URL: 網址: @@ -699,28 +1061,20 @@ Do you want to save it anyway? 搜尋 - Auto-type + Auto-Type 自動輸入 - Use default auto-type sequence of parent group - 使用預設的父群組自動輸入序列 + &Use default Auto-Type sequence of parent group + - Set default auto-type sequence - 設定預設自動輸入序列 + Set default Auto-Type se&quence + EditWidgetIcons - - Use default icon - 使用預設的圖示 - - - Use custom icon - 使用自訂的圖示 - Add custom icon 加入自訂的圖示 @@ -742,19 +1096,35 @@ Do you want to save it anyway? 選擇圖片 - Can't delete icon! - 不能刪除圖示! + Error + 錯誤 - - Can't delete icon. Still used by %n item(s). - 不能刪除圖示。仍在被 %n 個使用 + + Download favicon + 下載圖示 - Error + Unable to fetch favicon. + 無法擷取圖示。 + + + Can't read icon + 無法讀取圖示 + + + &Use default icon + 使用預設圖示 (&U) + + + Use custo&m icon + 使用自訂圖示 (&M) + + + Confirm Delete - Can't read icon: + This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it? @@ -777,6 +1147,13 @@ Do you want to save it anyway? Uuid (通用唯一識別碼) + + Entry + + - Clone + - 複製 + + EntryAttributesModel @@ -821,6 +1198,11 @@ Do you want to save it anyway? URL 網址 + + Ref: + Reference abbreviation + + Group @@ -829,16 +1211,74 @@ Do you want to save it anyway? 回收桶 + + HttpPasswordGeneratorWidget + + Length: + 長度: + + + Character Types + 字元類型 + + + Upper Case Letters + 大寫英文字母 + + + A-Z + A-Z + + + Lower Case Letters + 小寫英文字母 + + + a-z + a-z + + + Numbers + 數字 + + + 0-9 + 0-9 + + + Special Characters + 特殊字元 + + + /*_& ... + /*_& ... + + + Exclude look-alike characters + 去除相似的字元 + + + Ensure that the password contains characters from every group + 確定密碼包含每一組的字元 + + + + KMessageWidget + + &Close + + + + Close message + + + KeePass1OpenWidget Import KeePass1 database 匯入 KeePass 1 資料庫 - - Error - 錯誤 - Unable to open the database. 無法開啟這個資料庫 @@ -872,7 +1312,7 @@ Do you want to save it anyway? Wrong key or database file is corrupt. - + 無法的金鑰或資料庫損壞 @@ -904,6 +1344,10 @@ This is a one-way migration. You won't be able to open the imported databas 你可以點選 資料庫 > 「匯入 KeePass 1 資料庫」。 這是單向遷移。你無法用舊的 KeePassX 0.4 的版本打開被匯入的資料庫。 + + Unable to issue challenge-response. + + Main @@ -912,213 +1356,395 @@ This is a one-way migration. You won't be able to open the imported databas 重大錯誤,在測試加密函數時 - KeePassX - Error - KeePassX - 錯誤 + KeePassXC - Error + KeePassXC - 錯誤 + + + The lock file could not be created. Single-instance mode disabled. + + + + Another instance of KeePassXC is already running. + MainWindow - Database - 資料庫 + Open database + 打開資料庫 - Recent databases - 近期的資料庫 + Database settings + 資料庫設定 - Help - 幫助 + Copy username to clipboard + 將使用者名稱複製到剪貼簿 - Entries - 項目 + Copy password to clipboard + 將密碼複製到剪貼簿 - Copy attribute to clipboard - 將屬性複製到剪貼簿 + Settings + 設定 - Groups - 群組 + Show toolbar + 顯示工具列 - View - 顯示 + read-only + 唯讀 - Quit - 關閉 + Toggle window + 切換視窗 - About - 關於 + KeePass 2 Database + KeePass 2 資料庫 - Open database - 打開資料庫 + All files + 所有的檔案 - Save database - 儲存資料庫 + Save repaired database + 儲存已修復的資料庫 - Close database - 關閉資料庫 + Writing the database failed. + 寫入資料庫失敗 - New database - 新增資料庫 + &Recent databases + 最近的資料庫 (&R) - Add new entry - 加入項目 + He&lp + 幫助 (&L) - View/Edit entry - 瀏覽/編輯項目 + E&ntries + 項目 (&N) - Delete entry - 刪除項目 + Copy att&ribute to clipboard + 複製屬性到剪貼簿 (&R) - Add new group - 增加新的群組 + &Groups + 群組 (&G) - Edit group - 編輯群組 + &View + 檢視 (&V) - Delete group - 刪除群組 + &Quit + 離開 (&Q) - Save database as - 儲存資料庫為 + &About + 關於 (&A) - Change master key - 變更主金鑰 + &Open database + 開啟資料庫 (&O) - Database settings - 資料庫設定 + &Save database + 儲存資料庫 (&S) - Import KeePass 1 database - 匯入 KeePass 1 資料庫 + &Close database + 關閉資料庫 (&C) - Clone entry - 拷貝項目 + &New database + 新的資料庫 (&N) - Find - 尋找 + Merge from KeePassX database + 從 KeePassX 資料庫合併 - Copy username to clipboard - 將使用者名稱複製到剪貼簿 + &Add new entry + 新增項目 (&A) - Copy password to clipboard - 將密碼複製到剪貼簿 + &View/Edit entry + 檢視/編輯項目 (&V) - Settings - 設定 + &Delete entry + 刪除項目 (&D) - Perform Auto-Type - 執行自動輸入 + &Add new group + 新增群組 (&A) - Open URL - 打開網址 + &Edit group + 編輯群組 (&E) - Lock databases - 鎖住資料庫 + &Delete group + 刪除群組 (&D) - Title - 標題 + Sa&ve database as + 將資料庫儲存為 (&V) - URL - 網址 + Change &master key + 變更主金鑰 (&M) - Notes - 附註 + &Database settings + 資料庫設定 (&D) - Show toolbar - 顯示工具列 + &Clone entry + 複製項目 (&C) - read-only - 唯讀 + Timed one-time password + - Toggle window - 切換視窗 + Setup TOTP + - Tools - 工具 + Copy &TOTP + - Copy username - 複製使用者名稱 + Show TOTP + - Copy password - 複製密碼 + &Find + 尋找 (&F) - Export to CSV file - 輸出成 CSV 檔案 + Copy &username + 複製使用者名稱 (&U) - Repair database - 修復資料庫 + Cop&y password + 複製密碼 (&Y) - KeePass 2 Database - KeePass 2 資料庫 + &Settings + 設定 (&S) - All files - 所有的檔案 + &Perform Auto-Type + 執行自動輸入 (&P) - Save repaired database - 儲存已修復的資料庫 + &Open URL + 開啟網址 (&O) - Error - 錯誤 + &Lock databases + 鎖定資料庫 (&L) - Writing the database failed. - 寫入資料庫失敗 + &Title + 標題 (&T) - - - PasswordGeneratorWidget - Password: - 密碼: + &URL + 網址 (&U) - Length: - 長度: + &Notes + 附註 (&N) - Character Types + &Export to CSV file + 匯出到 CSV 檔案 (&E) + + + Re&pair database + 修復資料庫 (&P) + + + Password Generator + 密碼產生器 + + + Clear history + + + + &Database + + + + Import + + + + &Tools + + + + Import KeePass 1 database + 匯入 KeePass 1 資料庫 + + + Import CSV file + + + + Empty recycle bin + + + + Access error for config file %1 + + + + Quit KeePassXC + + + + Please touch the button on your YubiKey! + + + + + OptionDialog + + Dialog + 對話方塊 + + + General + 一般 + + + Sh&ow a notification when credentials are requested + 要求憑證時顯示通知 (&O) + + + Sort matching entries by &username + 依使用者名稱排序符合項目 (&U) + + + Re&move all stored permissions from entries in active database + 從目前的資料庫項目中移除所有權限 (&M) + + + Advanced + 進階的 + + + Always allow &access to entries + 總是允許存取項目 (&A) + + + Always allow &updating entries + 總是允許更新項目 (&U) + + + Searc&h in all opened databases for matching entries + 在所有開啟的資料庫內搜尋相符的項目 (&H) + + + HTTP Port: + HTTP Port: + + + Default port: 19455 + 預設 port: 19455 + + + Re&quest to unlock the database if it is locked + 若資料庫已鎖定,則請求解鎖 (&Q) + + + Sort &matching entries by title + 依名稱排序符合項目 (&M) + + + KeePassXC will listen to this port on 127.0.0.1 + KeePassXC 會在 127.0.0.1 上監聽此 port + + + Cannot bind to privileged ports + 無法綁定到特殊權限 port + + + Cannot bind to privileged ports below 1024! +Using default port 19455. + 無法綁定到 1024 以下的特殊權限 port! +使用預設 port 19455。 + + + R&emove all shared encryption keys from active database + 從目前的資料庫移除所有共用的加密金鑰 (&E) + + + &Return advanced string fields which start with "KPH: " + 回傳 "KPH: " 起首的進階文字欄位 (&R) + + + Automatically creating or updating string fields is not supported. + 不支援自動建立或更新文字欄位 + + + This is required for accessing your databases from ChromeIPass or PassIFox + + + + Enable KeePassHTTP server + + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + + + + &Return only best matching entries + + + + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + + + + &Match URL schemes + + + + Password Generator + 密碼產生器 + + + Only the selected database has to be connected with a client. + + + + The following options can be dangerous! +Change them only if you know what you are doing. + + + + + PasswordGeneratorWidget + + Password: + 密碼: + + + Character Types 字元類型 @@ -1141,71 +1767,161 @@ This is a one-way migration. You won't be able to open the imported databas Exclude look-alike characters 去除相似的字元 - - Ensure that the password contains characters from every group - 確定密碼包含每一組的字元 - Accept 接受 - - - QCommandLineParser - Displays version information. - 顯示版本資訊 + %p% + %p% + + + strength + 強度 + + + entropy + + + + &Length: + 長度 (&L): + + + Pick characters from every group + 從每一組中選擇字元 - Displays this help. - 顯示這個幫助訊息 + Generate + 產生 + + + Close + 關閉 + + + Apply + 套用 + + + Entropy: %1 bit + 熵:%1 bit + + + Password Quality: %1 + 密碼素質:%1 + + + Poor + 極弱 + + + Weak + 較弱 - Unknown option '%1'. - 不知的選項 '%1' + Good + 較好 - Unknown options: %1. - 不知的選項 '%1' + Excellent + 極好 - Missing value after '%1'. - 在 "%1" 後缺少值 + Password + 密碼 - Unexpected value after '%1'. - "%1" 後有不預期的值 + Extended ASCII + - [options] - [選項] + Passphrase + - Usage: %1 - 使用方式:%1 + Wordlist: + - Options: - 選項: + Word Count: + - Arguments: - 參數 + Word Separator: + + + + Copy + - QSaveFile + QObject - Existing file %1 is not writable - 現有的檔案 %1 不可寫入 + NULL device + - Writing canceled by application - 應用程式取消寫入 + error reading from device + - Partial write. Partition full? - 部分寫入。分區滿了嗎? + file empty ! + + + + + malformed string + + + + missing closing quote + + + + INTERNAL - unget lower bound exceeded + + + + Group + 群組 + + + Title + 標題 + + + Username + 使用者名稱 + + + Password + 密碼 + + + URL + 網址 + + + Notes + 附註 + + + Browser Integration + + + + YubiKey[%1] Challenge Response - Slot %2 - %3 + + + + Press + + + + Passive + @@ -1245,20 +1961,115 @@ This is a one-way migration. You won't be able to open the imported databas SearchWidget - Find: - 尋找: + Case Sensitive + 區分大小寫 - Case sensitive - 區分大小寫 + Search + 搜尋 - Current group - 目前的群組 + Clear + 清除 - Root group - 根群組 + Search... + + + + Limit search to selected group + + + + + Service + + A shared encryption-key with the name "%1" already exists. +Do you want to overwrite it? + 已存在名為 "%1" 的共用加密金鑰。 +你想覆蓋嗎? + + + Do you want to update the information in %1 - %2? + 你想更新 %1 到 %2 的資訊嗎? + + + The active database is locked! +Please unlock the selected database or choose another one which is unlocked. + 目前的資料庫已鎖定! +請解鎖所選的資料庫或選擇其他已解鎖的資料庫。 + + + Successfully removed %1 encryption-%2 from KeePassX/Http Settings. + 成功從 KeePassX/Http Settings 移除 %1 encryption-%2。 + + + No shared encryption-keys found in KeePassHttp Settings. + KeePassHttp Settings 中找不到共享加密金鑰。 + + + The active database does not contain an entry of KeePassHttp Settings. + 目前的資料庫沒有 KeePassHttp Settings 項目。 + + + Removing stored permissions... + 正在移除所有已儲存的權限…… + + + Abort + 中止 + + + Successfully removed permissions from %1 %2. + 成功從 %1 %2 移除權限。 + + + The active database does not contain an entry with permissions. + 目前的資料庫中無包含權限的項目。 + + + KeePassXC: New key association request + KeePassXC:新的金鑰關聯請求 + + + You have received an association request for the above key. +If you would like to allow it access to your KeePassXC database +give it a unique name to identify and accept it. + 你已接收到上述金鑰的關聯請求。 +如果你允許透過此金鑰存取你的 KeePassXC 資料庫 +請命名專屬的名稱並按下接受。 + + + KeePassXC: Overwrite existing key? + KeePassXC:覆蓋現有的金鑰嗎? + + + KeePassXC: Update Entry + KeePassXC:更新項目 + + + KeePassXC: Database locked! + KeePassXC:資料庫已鎖定! + + + KeePassXC: Removed keys from database + KeePassXC:從資料庫中刪除金鑰 + + + KeePassXC: No keys found + KeePassXC:沒有找到金鑰 + + + KeePassXC: Settings not available! + KeePassXC:設定不可用! + + + KeePassXC: Removed permissions + KeePassXC:已移除權限 + + + KeePassXC: No entry with permissions found! + KeePassXC:無含有權限的項目! @@ -1275,6 +2086,10 @@ This is a one-way migration. You won't be able to open the imported databas Security 安全性 + + Access error for config file %1 + + SettingsWidgetGeneral @@ -1282,10 +2097,6 @@ This is a one-way migration. You won't be able to open the imported databas Remember last databases 記住最近的資料庫 - - Open previous databases on startup - 在啟動時開啟最近的資料庫 - Automatically save on exit 離開時,自動儲存 @@ -1306,10 +2117,6 @@ This is a one-way migration. You won't be able to open the imported databas Global Auto-Type shortcut 全域自動輸入快捷鍵 - - Use entry title to match windows for global auto-type - 使用項目標題來找尋自動輸入的目標視窗 - Language 語言 @@ -1323,15 +2130,43 @@ This is a one-way migration. You won't be able to open the imported databas 將視窗最小化至工作列 - Remember last key files - 記住最近的金鑰檔案 + Load previous databases on startup + 啟動時載入之前的資料庫 + + + Automatically reload the database when modified externally + 當有外部修改時自動重新載入資料庫 + + + Hide window to system tray instead of app exit + 將視窗最小化至工作列而非關閉程式 + + + Minimize window at application startup + 程式啟動時視窗最小化 + + + Basic Settings + + + + Remember last key files and security dongles + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + Auto-Type + 自動輸入 - Hide window to system tray instead of App Exit + Use entry title and URL to match windows for global Auto-Type - Hide window to system tray on App start + Always ask before performing Auto-Type @@ -1354,8 +2189,86 @@ This is a one-way migration. You won't be able to open the imported databas 預設以明碼顯示密碼 - Always ask before performing auto-type - 在執行自動輸入前通常要詢問 + Lock databases after minimizing the window + 最小化視窗後鎖定資料庫 + + + Don't require password repeat when it is visible + 顯示密碼時不需要重複輸入密碼 + + + Timeouts + + + + Convenience + + + + Lock databases when session is locked or lid is closed + + + + + SetupTotpDialog + + Setup TOTP + + + + Key: + + + + Use custom settings + + + + Note: Change these settings only if you know what you are doing. + + + + Time step: + + + + 8 digits + + + + 6 digits + + + + Code size: + + + + sec + + + + + TotpDialog + + Timed Password + + + + 000000 + + + + Copy + + + + Expires in + + + + seconds + @@ -1368,20 +2281,36 @@ This is a one-way migration. You won't be able to open the imported databas WelcomeWidget - Welcome! - 歡迎! + Welcome to KeePassXC + + + + Start storing your passwords securely in a KeePassXC database + + + + Create new database + + + + Open existing database + - - - main - KeePassX - cross-platform password manager - KeePassX - 跨平台密碼管理軟體 + Import from KeePass 1 + - filename of the password database to open (*.kdbx) - 要開啟的密碼資料庫檔案名稱 (*.kdbx) + Import from CSV + + + Recent databases + 近期的資料庫 + + + + main path to a custom config file 自定設定檔的路徑 @@ -1390,5 +2319,81 @@ This is a one-way migration. You won't be able to open the imported databas key file of the database 資料庫的金鑰 + + KeePassXC - cross-platform password manager + KeePassXC - 跨平台的密碼管理工具 + + + read password of the database from stdin + 從 stdin 讀取資料庫密碼 + + + filenames of the password databases to open (*.kdbx) + 欲開啟的密碼資料庫檔名 (*.kdbx) + + + Copy a password to the clipboard + + + + Path of the database. + + + + Use a GUI prompt unlocking the database. + + + + Name of the entry to clip. + + + + Extract and print the content of a database. + + + + Path of the database to extract. + + + + Name of the command to execute. + + + + List database entries. + + + + Path of the group to list. Default is / + + + + Print the UUIDs of the entries and groups. + + + + Merge two databases. + + + + Path of the database to merge into. + + + + Path of the database to merge from. + + + + Use the same password for both database files. + + + + Show a password. + + + + Name of the entry to show. + + \ No newline at end of file diff --git a/share/translations/update.sh b/share/translations/update.sh index 7e8069e0d0..eaa1179d43 100755 --- a/share/translations/update.sh +++ b/share/translations/update.sh @@ -14,4 +14,4 @@ tx push -s echo echo Pulling translations from Transifex -tx pull -a --minimum-perc=80 +tx pull -af --minimum-perc=40 diff --git a/share/wordlists/eff_large.wordlist b/share/wordlists/eff_large.wordlist new file mode 100644 index 0000000000..caf71f5263 --- /dev/null +++ b/share/wordlists/eff_large.wordlist @@ -0,0 +1,7776 @@ +abacus +abdomen +abdominal +abide +abiding +ability +ablaze +able +abnormal +abrasion +abrasive +abreast +abridge +abroad +abruptly +absence +absentee +absently +absinthe +absolute +absolve +abstain +abstract +absurd +accent +acclaim +acclimate +accompany +account +accuracy +accurate +accustom +acetone +achiness +aching +acid +acorn +acquaint +acquire +acre +acrobat +acronym +acting +action +activate +activator +active +activism +activist +activity +actress +acts +acutely +acuteness +aeration +aerobics +aerosol +aerospace +afar +affair +affected +affecting +affection +affidavit +affiliate +affirm +affix +afflicted +affluent +afford +affront +aflame +afloat +aflutter +afoot +afraid +afterglow +afterlife +aftermath +aftermost +afternoon +aged +ageless +agency +agenda +agent +aggregate +aghast +agile +agility +aging +agnostic +agonize +agonizing +agony +agreeable +agreeably +agreed +agreeing +agreement +aground +ahead +ahoy +aide +aids +aim +ajar +alabaster +alarm +albatross +album +alfalfa +algebra +algorithm +alias +alibi +alienable +alienate +aliens +alike +alive +alkaline +alkalize +almanac +almighty +almost +aloe +aloft +aloha +alone +alongside +aloof +alphabet +alright +although +altitude +alto +aluminum +alumni +always +amaretto +amaze +amazingly +amber +ambiance +ambiguity +ambiguous +ambition +ambitious +ambulance +ambush +amendable +amendment +amends +amenity +amiable +amicably +amid +amigo +amino +amiss +ammonia +ammonium +amnesty +amniotic +among +amount +amperage +ample +amplifier +amplify +amply +amuck +amulet +amusable +amused +amusement +amuser +amusing +anaconda +anaerobic +anagram +anatomist +anatomy +anchor +anchovy +ancient +android +anemia +anemic +aneurism +anew +angelfish +angelic +anger +angled +angler +angles +angling +angrily +angriness +anguished +angular +animal +animate +animating +animation +animator +anime +animosity +ankle +annex +annotate +announcer +annoying +annually +annuity +anointer +another +answering +antacid +antarctic +anteater +antelope +antennae +anthem +anthill +anthology +antibody +antics +antidote +antihero +antiquely +antiques +antiquity +antirust +antitoxic +antitrust +antiviral +antivirus +antler +antonym +antsy +anvil +anybody +anyhow +anymore +anyone +anyplace +anything +anytime +anyway +anywhere +aorta +apache +apostle +appealing +appear +appease +appeasing +appendage +appendix +appetite +appetizer +applaud +applause +apple +appliance +applicant +applied +apply +appointee +appraisal +appraiser +apprehend +approach +approval +approve +apricot +april +apron +aptitude +aptly +aqua +aqueduct +arbitrary +arbitrate +ardently +area +arena +arguable +arguably +argue +arise +armadillo +armband +armchair +armed +armful +armhole +arming +armless +armoire +armored +armory +armrest +army +aroma +arose +around +arousal +arrange +array +arrest +arrival +arrive +arrogance +arrogant +arson +art +ascend +ascension +ascent +ascertain +ashamed +ashen +ashes +ashy +aside +askew +asleep +asparagus +aspect +aspirate +aspire +aspirin +astonish +astound +astride +astrology +astronaut +astronomy +astute +atlantic +atlas +atom +atonable +atop +atrium +atrocious +atrophy +attach +attain +attempt +attendant +attendee +attention +attentive +attest +attic +attire +attitude +attractor +attribute +atypical +auction +audacious +audacity +audible +audibly +audience +audio +audition +augmented +august +authentic +author +autism +autistic +autograph +automaker +automated +automatic +autopilot +available +avalanche +avatar +avenge +avenging +avenue +average +aversion +avert +aviation +aviator +avid +avoid +await +awaken +award +aware +awhile +awkward +awning +awoke +awry +axis +babble +babbling +babied +baboon +backache +backboard +backboned +backdrop +backed +backer +backfield +backfire +backhand +backing +backlands +backlash +backless +backlight +backlit +backlog +backpack +backpedal +backrest +backroom +backshift +backside +backslid +backspace +backspin +backstab +backstage +backtalk +backtrack +backup +backward +backwash +backwater +backyard +bacon +bacteria +bacterium +badass +badge +badland +badly +badness +baffle +baffling +bagel +bagful +baggage +bagged +baggie +bagginess +bagging +baggy +bagpipe +baguette +baked +bakery +bakeshop +baking +balance +balancing +balcony +balmy +balsamic +bamboo +banana +banish +banister +banjo +bankable +bankbook +banked +banker +banking +banknote +bankroll +banner +bannister +banshee +banter +barbecue +barbed +barbell +barber +barcode +barge +bargraph +barista +baritone +barley +barmaid +barman +barn +barometer +barrack +barracuda +barrel +barrette +barricade +barrier +barstool +bartender +barterer +bash +basically +basics +basil +basin +basis +basket +batboy +batch +bath +baton +bats +battalion +battered +battering +battery +batting +battle +bauble +bazooka +blabber +bladder +blade +blah +blame +blaming +blanching +blandness +blank +blaspheme +blasphemy +blast +blatancy +blatantly +blazer +blazing +bleach +bleak +bleep +blemish +blend +bless +blighted +blimp +bling +blinked +blinker +blinking +blinks +blip +blissful +blitz +blizzard +bloated +bloating +blob +blog +bloomers +blooming +blooper +blot +blouse +blubber +bluff +bluish +blunderer +blunt +blurb +blurred +blurry +blurt +blush +blustery +boaster +boastful +boasting +boat +bobbed +bobbing +bobble +bobcat +bobsled +bobtail +bodacious +body +bogged +boggle +bogus +boil +bok +bolster +bolt +bonanza +bonded +bonding +bondless +boned +bonehead +boneless +bonelike +boney +bonfire +bonnet +bonsai +bonus +bony +boogeyman +boogieman +book +boondocks +booted +booth +bootie +booting +bootlace +bootleg +boots +boozy +borax +boring +borough +borrower +borrowing +boss +botanical +botanist +botany +botch +both +bottle +bottling +bottom +bounce +bouncing +bouncy +bounding +boundless +bountiful +bovine +boxcar +boxer +boxing +boxlike +boxy +breach +breath +breeches +breeching +breeder +breeding +breeze +breezy +brethren +brewery +brewing +briar +bribe +brick +bride +bridged +brigade +bright +brilliant +brim +bring +brink +brisket +briskly +briskness +bristle +brittle +broadband +broadcast +broaden +broadly +broadness +broadside +broadways +broiler +broiling +broken +broker +bronchial +bronco +bronze +bronzing +brook +broom +brought +browbeat +brownnose +browse +browsing +bruising +brunch +brunette +brunt +brush +brussels +brute +brutishly +bubble +bubbling +bubbly +buccaneer +bucked +bucket +buckle +buckshot +buckskin +bucktooth +buckwheat +buddhism +buddhist +budding +buddy +budget +buffalo +buffed +buffer +buffing +buffoon +buggy +bulb +bulge +bulginess +bulgur +bulk +bulldog +bulldozer +bullfight +bullfrog +bullhorn +bullion +bullish +bullpen +bullring +bullseye +bullwhip +bully +bunch +bundle +bungee +bunion +bunkbed +bunkhouse +bunkmate +bunny +bunt +busboy +bush +busily +busload +bust +busybody +buzz +cabana +cabbage +cabbie +cabdriver +cable +caboose +cache +cackle +cacti +cactus +caddie +caddy +cadet +cadillac +cadmium +cage +cahoots +cake +calamari +calamity +calcium +calculate +calculus +caliber +calibrate +calm +caloric +calorie +calzone +camcorder +cameo +camera +camisole +camper +campfire +camping +campsite +campus +canal +canary +cancel +candied +candle +candy +cane +canine +canister +cannabis +canned +canning +cannon +cannot +canola +canon +canopener +canopy +canteen +canyon +capable +capably +capacity +cape +capillary +capital +capitol +capped +capricorn +capsize +capsule +caption +captivate +captive +captivity +capture +caramel +carat +caravan +carbon +cardboard +carded +cardiac +cardigan +cardinal +cardstock +carefully +caregiver +careless +caress +caretaker +cargo +caring +carless +carload +carmaker +carnage +carnation +carnival +carnivore +carol +carpenter +carpentry +carpool +carport +carried +carrot +carrousel +carry +cartel +cartload +carton +cartoon +cartridge +cartwheel +carve +carving +carwash +cascade +case +cash +casing +casino +casket +cassette +casually +casualty +catacomb +catalog +catalyst +catalyze +catapult +cataract +catatonic +catcall +catchable +catcher +catching +catchy +caterer +catering +catfight +catfish +cathedral +cathouse +catlike +catnap +catnip +catsup +cattail +cattishly +cattle +catty +catwalk +caucasian +caucus +causal +causation +cause +causing +cauterize +caution +cautious +cavalier +cavalry +caviar +cavity +cedar +celery +celestial +celibacy +celibate +celtic +cement +census +ceramics +ceremony +certainly +certainty +certified +certify +cesarean +cesspool +chafe +chaffing +chain +chair +chalice +challenge +chamber +chamomile +champion +chance +change +channel +chant +chaos +chaperone +chaplain +chapped +chaps +chapter +character +charbroil +charcoal +charger +charging +chariot +charity +charm +charred +charter +charting +chase +chasing +chaste +chastise +chastity +chatroom +chatter +chatting +chatty +cheating +cheddar +cheek +cheer +cheese +cheesy +chef +chemicals +chemist +chemo +cherisher +cherub +chess +chest +chevron +chevy +chewable +chewer +chewing +chewy +chief +chihuahua +childcare +childhood +childish +childless +childlike +chili +chill +chimp +chip +chirping +chirpy +chitchat +chivalry +chive +chloride +chlorine +choice +chokehold +choking +chomp +chooser +choosing +choosy +chop +chosen +chowder +chowtime +chrome +chubby +chuck +chug +chummy +chump +chunk +churn +chute +cider +cilantro +cinch +cinema +cinnamon +circle +circling +circular +circulate +circus +citable +citadel +citation +citizen +citric +citrus +city +civic +civil +clad +claim +clambake +clammy +clamor +clamp +clamshell +clang +clanking +clapped +clapper +clapping +clarify +clarinet +clarity +clash +clasp +class +clatter +clause +clavicle +claw +clay +clean +clear +cleat +cleaver +cleft +clench +clergyman +clerical +clerk +clever +clicker +client +climate +climatic +cling +clinic +clinking +clip +clique +cloak +clobber +clock +clone +cloning +closable +closure +clothes +clothing +cloud +clover +clubbed +clubbing +clubhouse +clump +clumsily +clumsy +clunky +clustered +clutch +clutter +coach +coagulant +coastal +coaster +coasting +coastland +coastline +coat +coauthor +cobalt +cobbler +cobweb +cocoa +coconut +cod +coeditor +coerce +coexist +coffee +cofounder +cognition +cognitive +cogwheel +coherence +coherent +cohesive +coil +coke +cola +cold +coleslaw +coliseum +collage +collapse +collar +collected +collector +collide +collie +collision +colonial +colonist +colonize +colony +colossal +colt +coma +come +comfort +comfy +comic +coming +comma +commence +commend +comment +commerce +commode +commodity +commodore +common +commotion +commute +commuting +compacted +compacter +compactly +compactor +companion +company +compare +compel +compile +comply +component +composed +composer +composite +compost +composure +compound +compress +comprised +computer +computing +comrade +concave +conceal +conceded +concept +concerned +concert +conch +concierge +concise +conclude +concrete +concur +condense +condiment +condition +condone +conducive +conductor +conduit +cone +confess +confetti +confidant +confident +confider +confiding +configure +confined +confining +confirm +conflict +conform +confound +confront +confused +confusing +confusion +congenial +congested +congrats +congress +conical +conjoined +conjure +conjuror +connected +connector +consensus +consent +console +consoling +consonant +constable +constant +constrain +constrict +construct +consult +consumer +consuming +contact +container +contempt +contend +contented +contently +contents +contest +context +contort +contour +contrite +control +contusion +convene +convent +copartner +cope +copied +copier +copilot +coping +copious +copper +copy +coral +cork +cornball +cornbread +corncob +cornea +corned +corner +cornfield +cornflake +cornhusk +cornmeal +cornstalk +corny +coronary +coroner +corporal +corporate +corral +correct +corridor +corrode +corroding +corrosive +corsage +corset +cortex +cosigner +cosmetics +cosmic +cosmos +cosponsor +cost +cottage +cotton +couch +cough +could +countable +countdown +counting +countless +country +county +courier +covenant +cover +coveted +coveting +coyness +cozily +coziness +cozy +crabbing +crabgrass +crablike +crabmeat +cradle +cradling +crafter +craftily +craftsman +craftwork +crafty +cramp +cranberry +crane +cranial +cranium +crank +crate +crave +craving +crawfish +crawlers +crawling +crayfish +crayon +crazed +crazily +craziness +crazy +creamed +creamer +creamlike +crease +creasing +creatable +create +creation +creative +creature +credible +credibly +credit +creed +creme +creole +crepe +crept +crescent +crested +cresting +crestless +crevice +crewless +crewman +crewmate +crib +cricket +cried +crier +crimp +crimson +cringe +cringing +crinkle +crinkly +crisped +crisping +crisply +crispness +crispy +criteria +critter +croak +crock +crook +croon +crop +cross +crouch +crouton +crowbar +crowd +crown +crucial +crudely +crudeness +cruelly +cruelness +cruelty +crumb +crummiest +crummy +crumpet +crumpled +cruncher +crunching +crunchy +crusader +crushable +crushed +crusher +crushing +crust +crux +crying +cryptic +crystal +cubbyhole +cube +cubical +cubicle +cucumber +cuddle +cuddly +cufflink +culinary +culminate +culpable +culprit +cultivate +cultural +culture +cupbearer +cupcake +cupid +cupped +cupping +curable +curator +curdle +cure +curfew +curing +curled +curler +curliness +curling +curly +curry +curse +cursive +cursor +curtain +curtly +curtsy +curvature +curve +curvy +cushy +cusp +cussed +custard +custodian +custody +customary +customer +customize +customs +cut +cycle +cyclic +cycling +cyclist +cylinder +cymbal +cytoplasm +cytoplast +dab +dad +daffodil +dagger +daily +daintily +dainty +dairy +daisy +dallying +dance +dancing +dandelion +dander +dandruff +dandy +danger +dangle +dangling +daredevil +dares +daringly +darkened +darkening +darkish +darkness +darkroom +darling +darn +dart +darwinism +dash +dastardly +data +datebook +dating +daughter +daunting +dawdler +dawn +daybed +daybreak +daycare +daydream +daylight +daylong +dayroom +daytime +dazzler +dazzling +deacon +deafening +deafness +dealer +dealing +dealmaker +dealt +dean +debatable +debate +debating +debit +debrief +debtless +debtor +debug +debunk +decade +decaf +decal +decathlon +decay +deceased +deceit +deceiver +deceiving +december +decency +decent +deception +deceptive +decibel +decidable +decimal +decimeter +decipher +deck +declared +decline +decode +decompose +decorated +decorator +decoy +decrease +decree +dedicate +dedicator +deduce +deduct +deed +deem +deepen +deeply +deepness +deface +defacing +defame +default +defeat +defection +defective +defendant +defender +defense +defensive +deferral +deferred +defiance +defiant +defile +defiling +define +definite +deflate +deflation +deflator +deflected +deflector +defog +deforest +defraud +defrost +deftly +defuse +defy +degraded +degrading +degrease +degree +dehydrate +deity +dejected +delay +delegate +delegator +delete +deletion +delicacy +delicate +delicious +delighted +delirious +delirium +deliverer +delivery +delouse +delta +deluge +delusion +deluxe +demanding +demeaning +demeanor +demise +democracy +democrat +demote +demotion +demystify +denatured +deniable +denial +denim +denote +dense +density +dental +dentist +denture +deny +deodorant +deodorize +departed +departure +depict +deplete +depletion +deplored +deploy +deport +depose +depraved +depravity +deprecate +depress +deprive +depth +deputize +deputy +derail +deranged +derby +derived +desecrate +deserve +deserving +designate +designed +designer +designing +deskbound +desktop +deskwork +desolate +despair +despise +despite +destiny +destitute +destruct +detached +detail +detection +detective +detector +detention +detergent +detest +detonate +detonator +detoxify +detract +deuce +devalue +deviancy +deviant +deviate +deviation +deviator +device +devious +devotedly +devotee +devotion +devourer +devouring +devoutly +dexterity +dexterous +diabetes +diabetic +diabolic +diagnoses +diagnosis +diagram +dial +diameter +diaper +diaphragm +diary +dice +dicing +dictate +dictation +dictator +difficult +diffused +diffuser +diffusion +diffusive +dig +dilation +diligence +diligent +dill +dilute +dime +diminish +dimly +dimmed +dimmer +dimness +dimple +diner +dingbat +dinghy +dinginess +dingo +dingy +dining +dinner +diocese +dioxide +diploma +dipped +dipper +dipping +directed +direction +directive +directly +directory +direness +dirtiness +disabled +disagree +disallow +disarm +disarray +disaster +disband +disbelief +disburse +discard +discern +discharge +disclose +discolor +discount +discourse +discover +discuss +disdain +disengage +disfigure +disgrace +dish +disinfect +disjoin +disk +dislike +disliking +dislocate +dislodge +disloyal +dismantle +dismay +dismiss +dismount +disobey +disorder +disown +disparate +disparity +dispatch +dispense +dispersal +dispersed +disperser +displace +display +displease +disposal +dispose +disprove +dispute +disregard +disrupt +dissuade +distance +distant +distaste +distill +distinct +distort +distract +distress +district +distrust +ditch +ditto +ditzy +dividable +divided +dividend +dividers +dividing +divinely +diving +divinity +divisible +divisibly +division +divisive +divorcee +dizziness +dizzy +doable +docile +dock +doctrine +document +dodge +dodgy +doily +doing +dole +dollar +dollhouse +dollop +dolly +dolphin +domain +domelike +domestic +dominion +dominoes +donated +donation +donator +donor +donut +doodle +doorbell +doorframe +doorknob +doorman +doormat +doornail +doorpost +doorstep +doorstop +doorway +doozy +dork +dormitory +dorsal +dosage +dose +dotted +doubling +douche +dove +down +dowry +doze +drab +dragging +dragonfly +dragonish +dragster +drainable +drainage +drained +drainer +drainpipe +dramatic +dramatize +drank +drapery +drastic +draw +dreaded +dreadful +dreadlock +dreamboat +dreamily +dreamland +dreamless +dreamlike +dreamt +dreamy +drearily +dreary +drench +dress +drew +dribble +dried +drier +drift +driller +drilling +drinkable +drinking +dripping +drippy +drivable +driven +driver +driveway +driving +drizzle +drizzly +drone +drool +droop +drop-down +dropbox +dropkick +droplet +dropout +dropper +drove +drown +drowsily +drudge +drum +dry +dubbed +dubiously +duchess +duckbill +ducking +duckling +ducktail +ducky +duct +dude +duffel +dugout +duh +duke +duller +dullness +duly +dumping +dumpling +dumpster +duo +dupe +duplex +duplicate +duplicity +durable +durably +duration +duress +during +dusk +dust +dutiful +duty +duvet +dwarf +dweeb +dwelled +dweller +dwelling +dwindle +dwindling +dynamic +dynamite +dynasty +dyslexia +dyslexic +each +eagle +earache +eardrum +earflap +earful +earlobe +early +earmark +earmuff +earphone +earpiece +earplugs +earring +earshot +earthen +earthlike +earthling +earthly +earthworm +earthy +earwig +easeful +easel +easiest +easily +easiness +easing +eastbound +eastcoast +easter +eastward +eatable +eaten +eatery +eating +eats +ebay +ebony +ebook +ecard +eccentric +echo +eclair +eclipse +ecologist +ecology +economic +economist +economy +ecosphere +ecosystem +edge +edginess +edging +edgy +edition +editor +educated +education +educator +eel +effective +effects +efficient +effort +eggbeater +egging +eggnog +eggplant +eggshell +egomaniac +egotism +egotistic +either +eject +elaborate +elastic +elated +elbow +eldercare +elderly +eldest +electable +election +elective +elephant +elevate +elevating +elevation +elevator +eleven +elf +eligible +eligibly +eliminate +elite +elitism +elixir +elk +ellipse +elliptic +elm +elongated +elope +eloquence +eloquent +elsewhere +elude +elusive +elves +email +embargo +embark +embassy +embattled +embellish +ember +embezzle +emblaze +emblem +embody +embolism +emboss +embroider +emcee +emerald +emergency +emission +emit +emote +emoticon +emotion +empathic +empathy +emperor +emphases +emphasis +emphasize +emphatic +empirical +employed +employee +employer +emporium +empower +emptier +emptiness +empty +emu +enable +enactment +enamel +enchanted +enchilada +encircle +enclose +enclosure +encode +encore +encounter +encourage +encroach +encrust +encrypt +endanger +endeared +endearing +ended +ending +endless +endnote +endocrine +endorphin +endorse +endowment +endpoint +endurable +endurance +enduring +energetic +energize +energy +enforced +enforcer +engaged +engaging +engine +engorge +engraved +engraver +engraving +engross +engulf +enhance +enigmatic +enjoyable +enjoyably +enjoyer +enjoying +enjoyment +enlarged +enlarging +enlighten +enlisted +enquirer +enrage +enrich +enroll +enslave +ensnare +ensure +entail +entangled +entering +entertain +enticing +entire +entitle +entity +entomb +entourage +entrap +entree +entrench +entrust +entryway +entwine +enunciate +envelope +enviable +enviably +envious +envision +envoy +envy +enzyme +epic +epidemic +epidermal +epidermis +epidural +epilepsy +epileptic +epilogue +epiphany +episode +equal +equate +equation +equator +equinox +equipment +equity +equivocal +eradicate +erasable +erased +eraser +erasure +ergonomic +errand +errant +erratic +error +erupt +escalate +escalator +escapable +escapade +escapist +escargot +eskimo +esophagus +espionage +espresso +esquire +essay +essence +essential +establish +estate +esteemed +estimate +estimator +estranged +estrogen +etching +eternal +eternity +ethanol +ether +ethically +ethics +euphemism +evacuate +evacuee +evade +evaluate +evaluator +evaporate +evasion +evasive +even +everglade +evergreen +everybody +everyday +everyone +evict +evidence +evident +evil +evoke +evolution +evolve +exact +exalted +example +excavate +excavator +exceeding +exception +excess +exchange +excitable +exciting +exclaim +exclude +excluding +exclusion +exclusive +excretion +excretory +excursion +excusable +excusably +excuse +exemplary +exemplify +exemption +exerciser +exert +exes +exfoliate +exhale +exhaust +exhume +exile +existing +exit +exodus +exonerate +exorcism +exorcist +expand +expanse +expansion +expansive +expectant +expedited +expediter +expel +expend +expenses +expensive +expert +expire +expiring +explain +expletive +explicit +explode +exploit +explore +exploring +exponent +exporter +exposable +expose +exposure +express +expulsion +exquisite +extended +extending +extent +extenuate +exterior +external +extinct +extortion +extradite +extras +extrovert +extrude +extruding +exuberant +fable +fabric +fabulous +facebook +facecloth +facedown +faceless +facelift +faceplate +faceted +facial +facility +facing +facsimile +faction +factoid +factor +factsheet +factual +faculty +fade +fading +failing +falcon +fall +false +falsify +fame +familiar +family +famine +famished +fanatic +fancied +fanciness +fancy +fanfare +fang +fanning +fantasize +fantastic +fantasy +fascism +fastball +faster +fasting +fastness +faucet +favorable +favorably +favored +favoring +favorite +fax +feast +federal +fedora +feeble +feed +feel +feisty +feline +felt-tip +feminine +feminism +feminist +feminize +femur +fence +fencing +fender +ferment +fernlike +ferocious +ferocity +ferret +ferris +ferry +fervor +fester +festival +festive +festivity +fetal +fetch +fever +fiber +fiction +fiddle +fiddling +fidelity +fidgeting +fidgety +fifteen +fifth +fiftieth +fifty +figment +figure +figurine +filing +filled +filler +filling +film +filter +filth +filtrate +finale +finalist +finalize +finally +finance +financial +finch +fineness +finer +finicky +finished +finisher +finishing +finite +finless +finlike +fiscally +fit +five +flaccid +flagman +flagpole +flagship +flagstick +flagstone +flail +flakily +flaky +flame +flammable +flanked +flanking +flannels +flap +flaring +flashback +flashbulb +flashcard +flashily +flashing +flashy +flask +flatbed +flatfoot +flatly +flatness +flatten +flattered +flatterer +flattery +flattop +flatware +flatworm +flavored +flavorful +flavoring +flaxseed +fled +fleshed +fleshy +flick +flier +flight +flinch +fling +flint +flip +flirt +float +flock +flogging +flop +floral +florist +floss +flounder +flyable +flyaway +flyer +flying +flyover +flypaper +foam +foe +fog +foil +folic +folk +follicle +follow +fondling +fondly +fondness +fondue +font +food +fool +footage +football +footbath +footboard +footer +footgear +foothill +foothold +footing +footless +footman +footnote +footpad +footpath +footprint +footrest +footsie +footsore +footwear +footwork +fossil +foster +founder +founding +fountain +fox +foyer +fraction +fracture +fragile +fragility +fragment +fragrance +fragrant +frail +frame +framing +frantic +fraternal +frayed +fraying +frays +freckled +freckles +freebase +freebee +freebie +freedom +freefall +freehand +freeing +freeload +freely +freemason +freeness +freestyle +freeware +freeway +freewill +freezable +freezing +freight +french +frenzied +frenzy +frequency +frequent +fresh +fretful +fretted +friction +friday +fridge +fried +friend +frighten +frightful +frigidity +frigidly +frill +fringe +frisbee +frisk +fritter +frivolous +frolic +from +front +frostbite +frosted +frostily +frosting +frostlike +frosty +froth +frown +frozen +fructose +frugality +frugally +fruit +frustrate +frying +gab +gaffe +gag +gainfully +gaining +gains +gala +gallantly +galleria +gallery +galley +gallon +gallows +gallstone +galore +galvanize +gambling +game +gaming +gamma +gander +gangly +gangrene +gangway +gap +garage +garbage +garden +gargle +garland +garlic +garment +garnet +garnish +garter +gas +gatherer +gathering +gating +gauging +gauntlet +gauze +gave +gawk +gazing +gear +gecko +geek +geiger +gem +gender +generic +generous +genetics +genre +gentile +gentleman +gently +gents +geography +geologic +geologist +geology +geometric +geometry +geranium +gerbil +geriatric +germicide +germinate +germless +germproof +gestate +gestation +gesture +getaway +getting +getup +giant +gibberish +giblet +giddily +giddiness +giddy +gift +gigabyte +gigahertz +gigantic +giggle +giggling +giggly +gigolo +gilled +gills +gimmick +girdle +giveaway +given +giver +giving +gizmo +gizzard +glacial +glacier +glade +gladiator +gladly +glamorous +glamour +glance +glancing +glandular +glare +glaring +glass +glaucoma +glazing +gleaming +gleeful +glider +gliding +glimmer +glimpse +glisten +glitch +glitter +glitzy +gloater +gloating +gloomily +gloomy +glorified +glorifier +glorify +glorious +glory +gloss +glove +glowing +glowworm +glucose +glue +gluten +glutinous +glutton +gnarly +gnat +goal +goatskin +goes +goggles +going +goldfish +goldmine +goldsmith +golf +goliath +gonad +gondola +gone +gong +good +gooey +goofball +goofiness +goofy +google +goon +gopher +gore +gorged +gorgeous +gory +gosling +gossip +gothic +gotten +gout +gown +grab +graceful +graceless +gracious +gradation +graded +grader +gradient +grading +gradually +graduate +graffiti +grafted +grafting +grain +granddad +grandkid +grandly +grandma +grandpa +grandson +granite +granny +granola +grant +granular +grape +graph +grapple +grappling +grasp +grass +gratified +gratify +grating +gratitude +gratuity +gravel +graveness +graves +graveyard +gravitate +gravity +gravy +gray +grazing +greasily +greedily +greedless +greedy +green +greeter +greeting +grew +greyhound +grid +grief +grievance +grieving +grievous +grill +grimace +grimacing +grime +griminess +grimy +grinch +grinning +grip +gristle +grit +groggily +groggy +groin +groom +groove +grooving +groovy +grope +ground +grouped +grout +grove +grower +growing +growl +grub +grudge +grudging +grueling +gruffly +grumble +grumbling +grumbly +grumpily +grunge +grunt +guacamole +guidable +guidance +guide +guiding +guileless +guise +gulf +gullible +gully +gulp +gumball +gumdrop +gumminess +gumming +gummy +gurgle +gurgling +guru +gush +gusto +gusty +gutless +guts +gutter +guy +guzzler +gyration +habitable +habitant +habitat +habitual +hacked +hacker +hacking +hacksaw +had +haggler +haiku +half +halogen +halt +halved +halves +hamburger +hamlet +hammock +hamper +hamster +hamstring +handbag +handball +handbook +handbrake +handcart +handclap +handclasp +handcraft +handcuff +handed +handful +handgrip +handgun +handheld +handiness +handiwork +handlebar +handled +handler +handling +handmade +handoff +handpick +handprint +handrail +handsaw +handset +handsfree +handshake +handstand +handwash +handwork +handwoven +handwrite +handyman +hangnail +hangout +hangover +hangup +hankering +hankie +hanky +haphazard +happening +happier +happiest +happily +happiness +happy +harbor +hardcopy +hardcore +hardcover +harddisk +hardened +hardener +hardening +hardhat +hardhead +hardiness +hardly +hardness +hardship +hardware +hardwired +hardwood +hardy +harmful +harmless +harmonica +harmonics +harmonize +harmony +harness +harpist +harsh +harvest +hash +hassle +haste +hastily +hastiness +hasty +hatbox +hatchback +hatchery +hatchet +hatching +hatchling +hate +hatless +hatred +haunt +haven +hazard +hazelnut +hazily +haziness +hazing +hazy +headache +headband +headboard +headcount +headdress +headed +header +headfirst +headgear +heading +headlamp +headless +headlock +headphone +headpiece +headrest +headroom +headscarf +headset +headsman +headstand +headstone +headway +headwear +heap +heat +heave +heavily +heaviness +heaving +hedge +hedging +heftiness +hefty +helium +helmet +helper +helpful +helping +helpless +helpline +hemlock +hemstitch +hence +henchman +henna +herald +herbal +herbicide +herbs +heritage +hermit +heroics +heroism +herring +herself +hertz +hesitancy +hesitant +hesitate +hexagon +hexagram +hubcap +huddle +huddling +huff +hug +hula +hulk +hull +human +humble +humbling +humbly +humid +humiliate +humility +humming +hummus +humongous +humorist +humorless +humorous +humpback +humped +humvee +hunchback +hundredth +hunger +hungrily +hungry +hunk +hunter +hunting +huntress +huntsman +hurdle +hurled +hurler +hurling +hurray +hurricane +hurried +hurry +hurt +husband +hush +husked +huskiness +hut +hybrid +hydrant +hydrated +hydration +hydrogen +hydroxide +hyperlink +hypertext +hyphen +hypnoses +hypnosis +hypnotic +hypnotism +hypnotist +hypnotize +hypocrisy +hypocrite +ibuprofen +ice +iciness +icing +icky +icon +icy +idealism +idealist +idealize +ideally +idealness +identical +identify +identity +ideology +idiocy +idiom +idly +igloo +ignition +ignore +iguana +illicitly +illusion +illusive +image +imaginary +imagines +imaging +imbecile +imitate +imitation +immature +immerse +immersion +imminent +immobile +immodest +immorally +immortal +immovable +immovably +immunity +immunize +impaired +impale +impart +impatient +impeach +impeding +impending +imperfect +imperial +impish +implant +implement +implicate +implicit +implode +implosion +implosive +imply +impolite +important +importer +impose +imposing +impotence +impotency +impotent +impound +imprecise +imprint +imprison +impromptu +improper +improve +improving +improvise +imprudent +impulse +impulsive +impure +impurity +iodine +iodize +ion +ipad +iphone +ipod +irate +irk +iron +irregular +irrigate +irritable +irritably +irritant +irritate +islamic +islamist +isolated +isolating +isolation +isotope +issue +issuing +italicize +italics +item +itinerary +itunes +ivory +ivy +jab +jackal +jacket +jackknife +jackpot +jailbird +jailbreak +jailer +jailhouse +jalapeno +jam +janitor +january +jargon +jarring +jasmine +jaundice +jaunt +java +jawed +jawless +jawline +jaws +jaybird +jaywalker +jazz +jeep +jeeringly +jellied +jelly +jersey +jester +jet +jiffy +jigsaw +jimmy +jingle +jingling +jinx +jitters +jittery +job +jockey +jockstrap +jogger +jogging +john +joining +jokester +jokingly +jolliness +jolly +jolt +jot +jovial +joyfully +joylessly +joyous +joyride +joystick +jubilance +jubilant +judge +judgingly +judicial +judiciary +judo +juggle +juggling +jugular +juice +juiciness +juicy +jujitsu +jukebox +july +jumble +jumbo +jump +junction +juncture +june +junior +juniper +junkie +junkman +junkyard +jurist +juror +jury +justice +justifier +justify +justly +justness +juvenile +kabob +kangaroo +karaoke +karate +karma +kebab +keenly +keenness +keep +keg +kelp +kennel +kept +kerchief +kerosene +kettle +kick +kiln +kilobyte +kilogram +kilometer +kilowatt +kilt +kimono +kindle +kindling +kindly +kindness +kindred +kinetic +kinfolk +king +kinship +kinsman +kinswoman +kissable +kisser +kissing +kitchen +kite +kitten +kitty +kiwi +kleenex +knapsack +knee +knelt +knickers +knoll +koala +kooky +kosher +krypton +kudos +kung +labored +laborer +laboring +laborious +labrador +ladder +ladies +ladle +ladybug +ladylike +lagged +lagging +lagoon +lair +lake +lance +landed +landfall +landfill +landing +landlady +landless +landline +landlord +landmark +landmass +landmine +landowner +landscape +landside +landslide +language +lankiness +lanky +lantern +lapdog +lapel +lapped +lapping +laptop +lard +large +lark +lash +lasso +last +latch +late +lather +latitude +latrine +latter +latticed +launch +launder +laundry +laurel +lavender +lavish +laxative +lazily +laziness +lazy +lecturer +left +legacy +legal +legend +legged +leggings +legible +legibly +legislate +lego +legroom +legume +legwarmer +legwork +lemon +lend +length +lens +lent +leotard +lesser +letdown +lethargic +lethargy +letter +lettuce +level +leverage +levers +levitate +levitator +liability +liable +liberty +librarian +library +licking +licorice +lid +life +lifter +lifting +liftoff +ligament +likely +likeness +likewise +liking +lilac +lilly +lily +limb +limeade +limelight +limes +limit +limping +limpness +line +lingo +linguini +linguist +lining +linked +linoleum +linseed +lint +lion +lip +liquefy +liqueur +liquid +lisp +list +litigate +litigator +litmus +litter +little +livable +lived +lively +liver +livestock +lividly +living +lizard +lubricant +lubricate +lucid +luckily +luckiness +luckless +lucrative +ludicrous +lugged +lukewarm +lullaby +lumber +luminance +luminous +lumpiness +lumping +lumpish +lunacy +lunar +lunchbox +luncheon +lunchroom +lunchtime +lung +lurch +lure +luridness +lurk +lushly +lushness +luster +lustfully +lustily +lustiness +lustrous +lusty +luxurious +luxury +lying +lyrically +lyricism +lyricist +lyrics +macarena +macaroni +macaw +mace +machine +machinist +magazine +magenta +maggot +magical +magician +magma +magnesium +magnetic +magnetism +magnetize +magnifier +magnify +magnitude +magnolia +mahogany +maimed +majestic +majesty +majorette +majority +makeover +maker +makeshift +making +malformed +malt +mama +mammal +mammary +mammogram +manager +managing +manatee +mandarin +mandate +mandatory +mandolin +manger +mangle +mango +mangy +manhandle +manhole +manhood +manhunt +manicotti +manicure +manifesto +manila +mankind +manlike +manliness +manly +manmade +manned +mannish +manor +manpower +mantis +mantra +manual +many +map +marathon +marauding +marbled +marbles +marbling +march +mardi +margarine +margarita +margin +marigold +marina +marine +marital +maritime +marlin +marmalade +maroon +married +marrow +marry +marshland +marshy +marsupial +marvelous +marxism +mascot +masculine +mashed +mashing +massager +masses +massive +mastiff +matador +matchbook +matchbox +matcher +matching +matchless +material +maternal +maternity +math +mating +matriarch +matrimony +matrix +matron +matted +matter +maturely +maturing +maturity +mauve +maverick +maximize +maximum +maybe +mayday +mayflower +moaner +moaning +mobile +mobility +mobilize +mobster +mocha +mocker +mockup +modified +modify +modular +modulator +module +moisten +moistness +moisture +molar +molasses +mold +molecular +molecule +molehill +mollusk +mom +monastery +monday +monetary +monetize +moneybags +moneyless +moneywise +mongoose +mongrel +monitor +monkhood +monogamy +monogram +monologue +monopoly +monorail +monotone +monotype +monoxide +monsieur +monsoon +monstrous +monthly +monument +moocher +moodiness +moody +mooing +moonbeam +mooned +moonlight +moonlike +moonlit +moonrise +moonscape +moonshine +moonstone +moonwalk +mop +morale +morality +morally +morbidity +morbidly +morphine +morphing +morse +mortality +mortally +mortician +mortified +mortify +mortuary +mosaic +mossy +most +mothball +mothproof +motion +motivate +motivator +motive +motocross +motor +motto +mountable +mountain +mounted +mounting +mourner +mournful +mouse +mousiness +moustache +mousy +mouth +movable +move +movie +moving +mower +mowing +much +muck +mud +mug +mulberry +mulch +mule +mulled +mullets +multiple +multiply +multitask +multitude +mumble +mumbling +mumbo +mummified +mummify +mummy +mumps +munchkin +mundane +municipal +muppet +mural +murkiness +murky +murmuring +muscular +museum +mushily +mushiness +mushroom +mushy +music +musket +muskiness +musky +mustang +mustard +muster +mustiness +musty +mutable +mutate +mutation +mute +mutilated +mutilator +mutiny +mutt +mutual +muzzle +myself +myspace +mystified +mystify +myth +nacho +nag +nail +name +naming +nanny +nanometer +nape +napkin +napped +napping +nappy +narrow +nastily +nastiness +national +native +nativity +natural +nature +naturist +nautical +navigate +navigator +navy +nearby +nearest +nearly +nearness +neatly +neatness +nebula +nebulizer +nectar +negate +negation +negative +neglector +negligee +negligent +negotiate +nemeses +nemesis +neon +nephew +nerd +nervous +nervy +nest +net +neurology +neuron +neurosis +neurotic +neuter +neutron +never +next +nibble +nickname +nicotine +niece +nifty +nimble +nimbly +nineteen +ninetieth +ninja +nintendo +ninth +nuclear +nuclei +nucleus +nugget +nullify +number +numbing +numbly +numbness +numeral +numerate +numerator +numeric +numerous +nuptials +nursery +nursing +nurture +nutcase +nutlike +nutmeg +nutrient +nutshell +nuttiness +nutty +nuzzle +nylon +oaf +oak +oasis +oat +obedience +obedient +obituary +object +obligate +obliged +oblivion +oblivious +oblong +obnoxious +oboe +obscure +obscurity +observant +observer +observing +obsessed +obsession +obsessive +obsolete +obstacle +obstinate +obstruct +obtain +obtrusive +obtuse +obvious +occultist +occupancy +occupant +occupier +occupy +ocean +ocelot +octagon +octane +october +octopus +ogle +oil +oink +ointment +okay +old +olive +olympics +omega +omen +ominous +omission +omit +omnivore +onboard +oncoming +ongoing +onion +online +onlooker +only +onscreen +onset +onshore +onslaught +onstage +onto +onward +onyx +oops +ooze +oozy +opacity +opal +open +operable +operate +operating +operation +operative +operator +opium +opossum +opponent +oppose +opposing +opposite +oppressed +oppressor +opt +opulently +osmosis +other +otter +ouch +ought +ounce +outage +outback +outbid +outboard +outbound +outbreak +outburst +outcast +outclass +outcome +outdated +outdoors +outer +outfield +outfit +outflank +outgoing +outgrow +outhouse +outing +outlast +outlet +outline +outlook +outlying +outmatch +outmost +outnumber +outplayed +outpost +outpour +output +outrage +outrank +outreach +outright +outscore +outsell +outshine +outshoot +outsider +outskirts +outsmart +outsource +outspoken +outtakes +outthink +outward +outweigh +outwit +oval +ovary +oven +overact +overall +overarch +overbid +overbill +overbite +overblown +overboard +overbook +overbuilt +overcast +overcoat +overcome +overcook +overcrowd +overdraft +overdrawn +overdress +overdrive +overdue +overeager +overeater +overexert +overfed +overfeed +overfill +overflow +overfull +overgrown +overhand +overhang +overhaul +overhead +overhear +overheat +overhung +overjoyed +overkill +overlabor +overlaid +overlap +overlay +overload +overlook +overlord +overlying +overnight +overpass +overpay +overplant +overplay +overpower +overprice +overrate +overreach +overreact +override +overripe +overrule +overrun +overshoot +overshot +oversight +oversized +oversleep +oversold +overspend +overstate +overstay +overstep +overstock +overstuff +oversweet +overtake +overthrow +overtime +overtly +overtone +overture +overturn +overuse +overvalue +overview +overwrite +owl +oxford +oxidant +oxidation +oxidize +oxidizing +oxygen +oxymoron +oyster +ozone +paced +pacemaker +pacific +pacifier +pacifism +pacifist +pacify +padded +padding +paddle +paddling +padlock +pagan +pager +paging +pajamas +palace +palatable +palm +palpable +palpitate +paltry +pampered +pamperer +pampers +pamphlet +panama +pancake +pancreas +panda +pandemic +pang +panhandle +panic +panning +panorama +panoramic +panther +pantomime +pantry +pants +pantyhose +paparazzi +papaya +paper +paprika +papyrus +parabola +parachute +parade +paradox +paragraph +parakeet +paralegal +paralyses +paralysis +paralyze +paramedic +parameter +paramount +parasail +parasite +parasitic +parcel +parched +parchment +pardon +parish +parka +parking +parkway +parlor +parmesan +parole +parrot +parsley +parsnip +partake +parted +parting +partition +partly +partner +partridge +party +passable +passably +passage +passcode +passenger +passerby +passing +passion +passive +passivism +passover +passport +password +pasta +pasted +pastel +pastime +pastor +pastrami +pasture +pasty +patchwork +patchy +paternal +paternity +path +patience +patient +patio +patriarch +patriot +patrol +patronage +patronize +pauper +pavement +paver +pavestone +pavilion +paving +pawing +payable +payback +paycheck +payday +payee +payer +paying +payment +payphone +payroll +pebble +pebbly +pecan +pectin +peculiar +peddling +pediatric +pedicure +pedigree +pedometer +pegboard +pelican +pellet +pelt +pelvis +penalize +penalty +pencil +pendant +pending +penholder +penknife +pennant +penniless +penny +penpal +pension +pentagon +pentagram +pep +perceive +percent +perch +percolate +perennial +perfected +perfectly +perfume +periscope +perish +perjurer +perjury +perkiness +perky +perm +peroxide +perpetual +perplexed +persecute +persevere +persuaded +persuader +pesky +peso +pessimism +pessimist +pester +pesticide +petal +petite +petition +petri +petroleum +petted +petticoat +pettiness +petty +petunia +phantom +phobia +phoenix +phonebook +phoney +phonics +phoniness +phony +phosphate +photo +phrase +phrasing +placard +placate +placidly +plank +planner +plant +plasma +plaster +plastic +plated +platform +plating +platinum +platonic +platter +platypus +plausible +plausibly +playable +playback +player +playful +playgroup +playhouse +playing +playlist +playmaker +playmate +playoff +playpen +playroom +playset +plaything +playtime +plaza +pleading +pleat +pledge +plentiful +plenty +plethora +plexiglas +pliable +plod +plop +plot +plow +ploy +pluck +plug +plunder +plunging +plural +plus +plutonium +plywood +poach +pod +poem +poet +pogo +pointed +pointer +pointing +pointless +pointy +poise +poison +poker +poking +polar +police +policy +polio +polish +politely +polka +polo +polyester +polygon +polygraph +polymer +poncho +pond +pony +popcorn +pope +poplar +popper +poppy +popsicle +populace +popular +populate +porcupine +pork +porous +porridge +portable +portal +portfolio +porthole +portion +portly +portside +poser +posh +posing +possible +possibly +possum +postage +postal +postbox +postcard +posted +poster +posting +postnasal +posture +postwar +pouch +pounce +pouncing +pound +pouring +pout +powdered +powdering +powdery +power +powwow +pox +praising +prance +prancing +pranker +prankish +prankster +prayer +praying +preacher +preaching +preachy +preamble +precinct +precise +precision +precook +precut +predator +predefine +predict +preface +prefix +preflight +preformed +pregame +pregnancy +pregnant +preheated +prelaunch +prelaw +prelude +premiere +premises +premium +prenatal +preoccupy +preorder +prepaid +prepay +preplan +preppy +preschool +prescribe +preseason +preset +preshow +president +presoak +press +presume +presuming +preteen +pretended +pretender +pretense +pretext +pretty +pretzel +prevail +prevalent +prevent +preview +previous +prewar +prewashed +prideful +pried +primal +primarily +primary +primate +primer +primp +princess +print +prior +prism +prison +prissy +pristine +privacy +private +privatize +prize +proactive +probable +probably +probation +probe +probing +probiotic +problem +procedure +process +proclaim +procreate +procurer +prodigal +prodigy +produce +product +profane +profanity +professed +professor +profile +profound +profusely +progeny +prognosis +program +progress +projector +prologue +prolonged +promenade +prominent +promoter +promotion +prompter +promptly +prone +prong +pronounce +pronto +proofing +proofread +proofs +propeller +properly +property +proponent +proposal +propose +props +prorate +protector +protegee +proton +prototype +protozoan +protract +protrude +proud +provable +proved +proven +provided +provider +providing +province +proving +provoke +provoking +provolone +prowess +prowler +prowling +proximity +proxy +prozac +prude +prudishly +prune +pruning +pry +psychic +public +publisher +pucker +pueblo +pug +pull +pulmonary +pulp +pulsate +pulse +pulverize +puma +pumice +pummel +punch +punctual +punctuate +punctured +pungent +punisher +punk +pupil +puppet +puppy +purchase +pureblood +purebred +purely +pureness +purgatory +purge +purging +purifier +purify +purist +puritan +purity +purple +purplish +purposely +purr +purse +pursuable +pursuant +pursuit +purveyor +pushcart +pushchair +pusher +pushiness +pushing +pushover +pushpin +pushup +pushy +putdown +putt +puzzle +puzzling +pyramid +pyromania +python +quack +quadrant +quail +quaintly +quake +quaking +qualified +qualifier +qualify +quality +qualm +quantum +quarrel +quarry +quartered +quarterly +quarters +quartet +quench +query +quicken +quickly +quickness +quicksand +quickstep +quiet +quill +quilt +quintet +quintuple +quirk +quit +quiver +quizzical +quotable +quotation +quote +rabid +race +racing +racism +rack +racoon +radar +radial +radiance +radiantly +radiated +radiation +radiator +radio +radish +raffle +raft +rage +ragged +raging +ragweed +raider +railcar +railing +railroad +railway +raisin +rake +raking +rally +ramble +rambling +ramp +ramrod +ranch +rancidity +random +ranged +ranger +ranging +ranked +ranking +ransack +ranting +rants +rare +rarity +rascal +rash +rasping +ravage +raven +ravine +raving +ravioli +ravishing +reabsorb +reach +reacquire +reaction +reactive +reactor +reaffirm +ream +reanalyze +reappear +reapply +reappoint +reapprove +rearrange +rearview +reason +reassign +reassure +reattach +reawake +rebalance +rebate +rebel +rebirth +reboot +reborn +rebound +rebuff +rebuild +rebuilt +reburial +rebuttal +recall +recant +recapture +recast +recede +recent +recess +recharger +recipient +recital +recite +reckless +reclaim +recliner +reclining +recluse +reclusive +recognize +recoil +recollect +recolor +reconcile +reconfirm +reconvene +recopy +record +recount +recoup +recovery +recreate +rectal +rectangle +rectified +rectify +recycled +recycler +recycling +reemerge +reenact +reenter +reentry +reexamine +referable +referee +reference +refill +refinance +refined +refinery +refining +refinish +reflected +reflector +reflex +reflux +refocus +refold +reforest +reformat +reformed +reformer +reformist +refract +refrain +refreeze +refresh +refried +refueling +refund +refurbish +refurnish +refusal +refuse +refusing +refutable +refute +regain +regalia +regally +reggae +regime +region +register +registrar +registry +regress +regretful +regroup +regular +regulate +regulator +rehab +reheat +rehire +rehydrate +reimburse +reissue +reiterate +rejoice +rejoicing +rejoin +rekindle +relapse +relapsing +relatable +related +relation +relative +relax +relay +relearn +release +relenting +reliable +reliably +reliance +reliant +relic +relieve +relieving +relight +relish +relive +reload +relocate +relock +reluctant +rely +remake +remark +remarry +rematch +remedial +remedy +remember +reminder +remindful +remission +remix +remnant +remodeler +remold +remorse +remote +removable +removal +removed +remover +removing +rename +renderer +rendering +rendition +renegade +renewable +renewably +renewal +renewed +renounce +renovate +renovator +rentable +rental +rented +renter +reoccupy +reoccur +reopen +reorder +repackage +repacking +repaint +repair +repave +repaying +repayment +repeal +repeated +repeater +repent +rephrase +replace +replay +replica +reply +reporter +repose +repossess +repost +repressed +reprimand +reprint +reprise +reproach +reprocess +reproduce +reprogram +reps +reptile +reptilian +repugnant +repulsion +repulsive +repurpose +reputable +reputably +request +require +requisite +reroute +rerun +resale +resample +rescuer +reseal +research +reselect +reseller +resemble +resend +resent +reset +reshape +reshoot +reshuffle +residence +residency +resident +residual +residue +resigned +resilient +resistant +resisting +resize +resolute +resolved +resonant +resonate +resort +resource +respect +resubmit +result +resume +resupply +resurface +resurrect +retail +retainer +retaining +retake +retaliate +retention +rethink +retinal +retired +retiree +retiring +retold +retool +retorted +retouch +retrace +retract +retrain +retread +retreat +retrial +retrieval +retriever +retry +return +retying +retype +reunion +reunite +reusable +reuse +reveal +reveler +revenge +revenue +reverb +revered +reverence +reverend +reversal +reverse +reversing +reversion +revert +revisable +revise +revision +revisit +revivable +revival +reviver +reviving +revocable +revoke +revolt +revolver +revolving +reward +rewash +rewind +rewire +reword +rework +rewrap +rewrite +rhyme +ribbon +ribcage +rice +riches +richly +richness +rickety +ricotta +riddance +ridden +ride +riding +rifling +rift +rigging +rigid +rigor +rimless +rimmed +rind +rink +rinse +rinsing +riot +ripcord +ripeness +ripening +ripping +ripple +rippling +riptide +rise +rising +risk +risotto +ritalin +ritzy +rival +riverbank +riverbed +riverboat +riverside +riveter +riveting +roamer +roaming +roast +robbing +robe +robin +robotics +robust +rockband +rocker +rocket +rockfish +rockiness +rocking +rocklike +rockslide +rockstar +rocky +rogue +roman +romp +rope +roping +roster +rosy +rotten +rotting +rotunda +roulette +rounding +roundish +roundness +roundup +roundworm +routine +routing +rover +roving +royal +rubbed +rubber +rubbing +rubble +rubdown +ruby +ruckus +rudder +rug +ruined +rule +rumble +rumbling +rummage +rumor +runaround +rundown +runner +running +runny +runt +runway +rupture +rural +ruse +rush +rust +rut +sabbath +sabotage +sacrament +sacred +sacrifice +sadden +saddlebag +saddled +saddling +sadly +sadness +safari +safeguard +safehouse +safely +safeness +saffron +saga +sage +sagging +saggy +said +saint +sake +salad +salami +salaried +salary +saline +salon +saloon +salsa +salt +salutary +salute +salvage +salvaging +salvation +same +sample +sampling +sanction +sanctity +sanctuary +sandal +sandbag +sandbank +sandbar +sandblast +sandbox +sanded +sandfish +sanding +sandlot +sandpaper +sandpit +sandstone +sandstorm +sandworm +sandy +sanitary +sanitizer +sank +santa +sapling +sappiness +sappy +sarcasm +sarcastic +sardine +sash +sasquatch +sassy +satchel +satiable +satin +satirical +satisfied +satisfy +saturate +saturday +sauciness +saucy +sauna +savage +savanna +saved +savings +savior +savor +saxophone +say +scabbed +scabby +scalded +scalding +scale +scaling +scallion +scallop +scalping +scam +scandal +scanner +scanning +scant +scapegoat +scarce +scarcity +scarecrow +scared +scarf +scarily +scariness +scarring +scary +scavenger +scenic +schedule +schematic +scheme +scheming +schilling +schnapps +scholar +science +scientist +scion +scoff +scolding +scone +scoop +scooter +scope +scorch +scorebook +scorecard +scored +scoreless +scorer +scoring +scorn +scorpion +scotch +scoundrel +scoured +scouring +scouting +scouts +scowling +scrabble +scraggly +scrambled +scrambler +scrap +scratch +scrawny +screen +scribble +scribe +scribing +scrimmage +script +scroll +scrooge +scrounger +scrubbed +scrubber +scruffy +scrunch +scrutiny +scuba +scuff +sculptor +sculpture +scurvy +scuttle +secluded +secluding +seclusion +second +secrecy +secret +sectional +sector +secular +securely +security +sedan +sedate +sedation +sedative +sediment +seduce +seducing +segment +seismic +seizing +seldom +selected +selection +selective +selector +self +seltzer +semantic +semester +semicolon +semifinal +seminar +semisoft +semisweet +senate +senator +send +senior +senorita +sensation +sensitive +sensitize +sensually +sensuous +sepia +september +septic +septum +sequel +sequence +sequester +series +sermon +serotonin +serpent +serrated +serve +service +serving +sesame +sessions +setback +setting +settle +settling +setup +sevenfold +seventeen +seventh +seventy +severity +shabby +shack +shaded +shadily +shadiness +shading +shadow +shady +shaft +shakable +shakily +shakiness +shaking +shaky +shale +shallot +shallow +shame +shampoo +shamrock +shank +shanty +shape +shaping +share +sharpener +sharper +sharpie +sharply +sharpness +shawl +sheath +shed +sheep +sheet +shelf +shell +shelter +shelve +shelving +sherry +shield +shifter +shifting +shiftless +shifty +shimmer +shimmy +shindig +shine +shingle +shininess +shining +shiny +ship +shirt +shivering +shock +shone +shoplift +shopper +shopping +shoptalk +shore +shortage +shortcake +shortcut +shorten +shorter +shorthand +shortlist +shortly +shortness +shorts +shortwave +shorty +shout +shove +showbiz +showcase +showdown +shower +showgirl +showing +showman +shown +showoff +showpiece +showplace +showroom +showy +shrank +shrapnel +shredder +shredding +shrewdly +shriek +shrill +shrimp +shrine +shrink +shrivel +shrouded +shrubbery +shrubs +shrug +shrunk +shucking +shudder +shuffle +shuffling +shun +shush +shut +shy +siamese +siberian +sibling +siding +sierra +siesta +sift +sighing +silenced +silencer +silent +silica +silicon +silk +silliness +silly +silo +silt +silver +similarly +simile +simmering +simple +simplify +simply +sincere +sincerity +singer +singing +single +singular +sinister +sinless +sinner +sinuous +sip +siren +sister +sitcom +sitter +sitting +situated +situation +sixfold +sixteen +sixth +sixties +sixtieth +sixtyfold +sizable +sizably +size +sizing +sizzle +sizzling +skater +skating +skedaddle +skeletal +skeleton +skeptic +sketch +skewed +skewer +skid +skied +skier +skies +skiing +skilled +skillet +skillful +skimmed +skimmer +skimming +skimpily +skincare +skinhead +skinless +skinning +skinny +skintight +skipper +skipping +skirmish +skirt +skittle +skydiver +skylight +skyline +skype +skyrocket +skyward +slab +slacked +slacker +slacking +slackness +slacks +slain +slam +slander +slang +slapping +slapstick +slashed +slashing +slate +slather +slaw +sled +sleek +sleep +sleet +sleeve +slept +sliceable +sliced +slicer +slicing +slick +slider +slideshow +sliding +slighted +slighting +slightly +slimness +slimy +slinging +slingshot +slinky +slip +slit +sliver +slobbery +slogan +sloped +sloping +sloppily +sloppy +slot +slouching +slouchy +sludge +slug +slum +slurp +slush +sly +small +smartly +smartness +smasher +smashing +smashup +smell +smelting +smile +smilingly +smirk +smite +smith +smitten +smock +smog +smoked +smokeless +smokiness +smoking +smoky +smolder +smooth +smother +smudge +smudgy +smuggler +smuggling +smugly +smugness +snack +snagged +snaking +snap +snare +snarl +snazzy +sneak +sneer +sneeze +sneezing +snide +sniff +snippet +snipping +snitch +snooper +snooze +snore +snoring +snorkel +snort +snout +snowbird +snowboard +snowbound +snowcap +snowdrift +snowdrop +snowfall +snowfield +snowflake +snowiness +snowless +snowman +snowplow +snowshoe +snowstorm +snowsuit +snowy +snub +snuff +snuggle +snugly +snugness +speak +spearfish +spearhead +spearman +spearmint +species +specimen +specked +speckled +specks +spectacle +spectator +spectrum +speculate +speech +speed +spellbind +speller +spelling +spendable +spender +spending +spent +spew +sphere +spherical +sphinx +spider +spied +spiffy +spill +spilt +spinach +spinal +spindle +spinner +spinning +spinout +spinster +spiny +spiral +spirited +spiritism +spirits +spiritual +splashed +splashing +splashy +splatter +spleen +splendid +splendor +splice +splicing +splinter +splotchy +splurge +spoilage +spoiled +spoiler +spoiling +spoils +spoken +spokesman +sponge +spongy +sponsor +spoof +spookily +spooky +spool +spoon +spore +sporting +sports +sporty +spotless +spotlight +spotted +spotter +spotting +spotty +spousal +spouse +spout +sprain +sprang +sprawl +spray +spree +sprig +spring +sprinkled +sprinkler +sprint +sprite +sprout +spruce +sprung +spry +spud +spur +sputter +spyglass +squabble +squad +squall +squander +squash +squatted +squatter +squatting +squeak +squealer +squealing +squeamish +squeegee +squeeze +squeezing +squid +squiggle +squiggly +squint +squire +squirt +squishier +squishy +stability +stabilize +stable +stack +stadium +staff +stage +staging +stagnant +stagnate +stainable +stained +staining +stainless +stalemate +staleness +stalling +stallion +stamina +stammer +stamp +stand +stank +staple +stapling +starboard +starch +stardom +stardust +starfish +stargazer +staring +stark +starless +starlet +starlight +starlit +starring +starry +starship +starter +starting +startle +startling +startup +starved +starving +stash +state +static +statistic +statue +stature +status +statute +statutory +staunch +stays +steadfast +steadier +steadily +steadying +steam +steed +steep +steerable +steering +steersman +stegosaur +stellar +stem +stench +stencil +step +stereo +sterile +sterility +sterilize +sterling +sternness +sternum +stew +stick +stiffen +stiffly +stiffness +stifle +stifling +stillness +stilt +stimulant +stimulate +stimuli +stimulus +stinger +stingily +stinging +stingray +stingy +stinking +stinky +stipend +stipulate +stir +stitch +stock +stoic +stoke +stole +stomp +stonewall +stoneware +stonework +stoning +stony +stood +stooge +stool +stoop +stoplight +stoppable +stoppage +stopped +stopper +stopping +stopwatch +storable +storage +storeroom +storewide +storm +stout +stove +stowaway +stowing +straddle +straggler +strained +strainer +straining +strangely +stranger +strangle +strategic +strategy +stratus +straw +stray +streak +stream +street +strength +strenuous +strep +stress +stretch +strewn +stricken +strict +stride +strife +strike +striking +strive +striving +strobe +strode +stroller +strongbox +strongly +strongman +struck +structure +strudel +struggle +strum +strung +strut +stubbed +stubble +stubbly +stubborn +stucco +stuck +student +studied +studio +study +stuffed +stuffing +stuffy +stumble +stumbling +stump +stung +stunned +stunner +stunning +stunt +stupor +sturdily +sturdy +styling +stylishly +stylist +stylized +stylus +suave +subarctic +subatomic +subdivide +subdued +subduing +subfloor +subgroup +subheader +subject +sublease +sublet +sublevel +sublime +submarine +submerge +submersed +submitter +subpanel +subpar +subplot +subprime +subscribe +subscript +subsector +subside +subsiding +subsidize +subsidy +subsoil +subsonic +substance +subsystem +subtext +subtitle +subtly +subtotal +subtract +subtype +suburb +subway +subwoofer +subzero +succulent +such +suction +sudden +sudoku +suds +sufferer +suffering +suffice +suffix +suffocate +suffrage +sugar +suggest +suing +suitable +suitably +suitcase +suitor +sulfate +sulfide +sulfite +sulfur +sulk +sullen +sulphate +sulphuric +sultry +superbowl +superglue +superhero +superior +superjet +superman +supermom +supernova +supervise +supper +supplier +supply +support +supremacy +supreme +surcharge +surely +sureness +surface +surfacing +surfboard +surfer +surgery +surgical +surging +surname +surpass +surplus +surprise +surreal +surrender +surrogate +surround +survey +survival +survive +surviving +survivor +sushi +suspect +suspend +suspense +sustained +sustainer +swab +swaddling +swagger +swampland +swan +swapping +swarm +sway +swear +sweat +sweep +swell +swept +swerve +swifter +swiftly +swiftness +swimmable +swimmer +swimming +swimsuit +swimwear +swinger +swinging +swipe +swirl +switch +swivel +swizzle +swooned +swoop +swoosh +swore +sworn +swung +sycamore +sympathy +symphonic +symphony +symptom +synapse +syndrome +synergy +synopses +synopsis +synthesis +synthetic +syrup +system +t-shirt +tabasco +tabby +tableful +tables +tablet +tableware +tabloid +tackiness +tacking +tackle +tackling +tacky +taco +tactful +tactical +tactics +tactile +tactless +tadpole +taekwondo +tag +tainted +take +taking +talcum +talisman +tall +talon +tamale +tameness +tamer +tamper +tank +tanned +tannery +tanning +tantrum +tapeless +tapered +tapering +tapestry +tapioca +tapping +taps +tarantula +target +tarmac +tarnish +tarot +tartar +tartly +tartness +task +tassel +taste +tastiness +tasting +tasty +tattered +tattle +tattling +tattoo +taunt +tavern +thank +that +thaw +theater +theatrics +thee +theft +theme +theology +theorize +thermal +thermos +thesaurus +these +thesis +thespian +thicken +thicket +thickness +thieving +thievish +thigh +thimble +thing +think +thinly +thinner +thinness +thinning +thirstily +thirsting +thirsty +thirteen +thirty +thong +thorn +those +thousand +thrash +thread +threaten +threefold +thrift +thrill +thrive +thriving +throat +throbbing +throng +throttle +throwaway +throwback +thrower +throwing +thud +thumb +thumping +thursday +thus +thwarting +thyself +tiara +tibia +tidal +tidbit +tidiness +tidings +tidy +tiger +tighten +tightly +tightness +tightrope +tightwad +tigress +tile +tiling +till +tilt +timid +timing +timothy +tinderbox +tinfoil +tingle +tingling +tingly +tinker +tinkling +tinsel +tinsmith +tint +tinwork +tiny +tipoff +tipped +tipper +tipping +tiptoeing +tiptop +tiring +tissue +trace +tracing +track +traction +tractor +trade +trading +tradition +traffic +tragedy +trailing +trailside +train +traitor +trance +tranquil +transfer +transform +translate +transpire +transport +transpose +trapdoor +trapeze +trapezoid +trapped +trapper +trapping +traps +trash +travel +traverse +travesty +tray +treachery +treading +treadmill +treason +treat +treble +tree +trekker +tremble +trembling +tremor +trench +trend +trespass +triage +trial +triangle +tribesman +tribunal +tribune +tributary +tribute +triceps +trickery +trickily +tricking +trickle +trickster +tricky +tricolor +tricycle +trident +tried +trifle +trifocals +trillion +trilogy +trimester +trimmer +trimming +trimness +trinity +trio +tripod +tripping +triumph +trivial +trodden +trolling +trombone +trophy +tropical +tropics +trouble +troubling +trough +trousers +trout +trowel +truce +truck +truffle +trump +trunks +trustable +trustee +trustful +trusting +trustless +truth +try +tubby +tubeless +tubular +tucking +tuesday +tug +tuition +tulip +tumble +tumbling +tummy +turban +turbine +turbofan +turbojet +turbulent +turf +turkey +turmoil +turret +turtle +tusk +tutor +tutu +tux +tweak +tweed +tweet +tweezers +twelve +twentieth +twenty +twerp +twice +twiddle +twiddling +twig +twilight +twine +twins +twirl +twistable +twisted +twister +twisting +twisty +twitch +twitter +tycoon +tying +tyke +udder +ultimate +ultimatum +ultra +umbilical +umbrella +umpire +unabashed +unable +unadorned +unadvised +unafraid +unaired +unaligned +unaltered +unarmored +unashamed +unaudited +unawake +unaware +unbaked +unbalance +unbeaten +unbend +unbent +unbiased +unbitten +unblended +unblessed +unblock +unbolted +unbounded +unboxed +unbraided +unbridle +unbroken +unbuckled +unbundle +unburned +unbutton +uncanny +uncapped +uncaring +uncertain +unchain +unchanged +uncharted +uncheck +uncivil +unclad +unclaimed +unclamped +unclasp +uncle +unclip +uncloak +unclog +unclothed +uncoated +uncoiled +uncolored +uncombed +uncommon +uncooked +uncork +uncorrupt +uncounted +uncouple +uncouth +uncover +uncross +uncrown +uncrushed +uncured +uncurious +uncurled +uncut +undamaged +undated +undaunted +undead +undecided +undefined +underage +underarm +undercoat +undercook +undercut +underdog +underdone +underfed +underfeed +underfoot +undergo +undergrad +underhand +underline +underling +undermine +undermost +underpaid +underpass +underpay +underrate +undertake +undertone +undertook +undertow +underuse +underwear +underwent +underwire +undesired +undiluted +undivided +undocked +undoing +undone +undrafted +undress +undrilled +undusted +undying +unearned +unearth +unease +uneasily +uneasy +uneatable +uneaten +unedited +unelected +unending +unengaged +unenvied +unequal +unethical +uneven +unexpired +unexposed +unfailing +unfair +unfasten +unfazed +unfeeling +unfiled +unfilled +unfitted +unfitting +unfixable +unfixed +unflawed +unfocused +unfold +unfounded +unframed +unfreeze +unfrosted +unfrozen +unfunded +unglazed +ungloved +unglue +ungodly +ungraded +ungreased +unguarded +unguided +unhappily +unhappy +unharmed +unhealthy +unheard +unhearing +unheated +unhelpful +unhidden +unhinge +unhitched +unholy +unhook +unicorn +unicycle +unified +unifier +uniformed +uniformly +unify +unimpeded +uninjured +uninstall +uninsured +uninvited +union +uniquely +unisexual +unison +unissued +unit +universal +universe +unjustly +unkempt +unkind +unknotted +unknowing +unknown +unlaced +unlatch +unlawful +unleaded +unlearned +unleash +unless +unleveled +unlighted +unlikable +unlimited +unlined +unlinked +unlisted +unlit +unlivable +unloaded +unloader +unlocked +unlocking +unlovable +unloved +unlovely +unloving +unluckily +unlucky +unmade +unmanaged +unmanned +unmapped +unmarked +unmasked +unmasking +unmatched +unmindful +unmixable +unmixed +unmolded +unmoral +unmovable +unmoved +unmoving +unnamable +unnamed +unnatural +unneeded +unnerve +unnerving +unnoticed +unopened +unopposed +unpack +unpadded +unpaid +unpainted +unpaired +unpaved +unpeeled +unpicked +unpiloted +unpinned +unplanned +unplanted +unpleased +unpledged +unplowed +unplug +unpopular +unproven +unquote +unranked +unrated +unraveled +unreached +unread +unreal +unreeling +unrefined +unrelated +unrented +unrest +unretired +unrevised +unrigged +unripe +unrivaled +unroasted +unrobed +unroll +unruffled +unruly +unrushed +unsaddle +unsafe +unsaid +unsalted +unsaved +unsavory +unscathed +unscented +unscrew +unsealed +unseated +unsecured +unseeing +unseemly +unseen +unselect +unselfish +unsent +unsettled +unshackle +unshaken +unshaved +unshaven +unsheathe +unshipped +unsightly +unsigned +unskilled +unsliced +unsmooth +unsnap +unsocial +unsoiled +unsold +unsolved +unsorted +unspoiled +unspoken +unstable +unstaffed +unstamped +unsteady +unsterile +unstirred +unstitch +unstopped +unstuck +unstuffed +unstylish +unsubtle +unsubtly +unsuited +unsure +unsworn +untagged +untainted +untaken +untamed +untangled +untapped +untaxed +unthawed +unthread +untidy +untie +until +untimed +untimely +untitled +untoasted +untold +untouched +untracked +untrained +untreated +untried +untrimmed +untrue +untruth +unturned +untwist +untying +unusable +unused +unusual +unvalued +unvaried +unvarying +unveiled +unveiling +unvented +unviable +unvisited +unvocal +unwanted +unwarlike +unwary +unwashed +unwatched +unweave +unwed +unwelcome +unwell +unwieldy +unwilling +unwind +unwired +unwitting +unwomanly +unworldly +unworn +unworried +unworthy +unwound +unwoven +unwrapped +unwritten +unzip +upbeat +upchuck +upcoming +upcountry +update +upfront +upgrade +upheaval +upheld +uphill +uphold +uplifted +uplifting +upload +upon +upper +upright +uprising +upriver +uproar +uproot +upscale +upside +upstage +upstairs +upstart +upstate +upstream +upstroke +upswing +uptake +uptight +uptown +upturned +upward +upwind +uranium +urban +urchin +urethane +urgency +urgent +urging +urologist +urology +usable +usage +useable +used +uselessly +user +usher +usual +utensil +utility +utilize +utmost +utopia +utter +vacancy +vacant +vacate +vacation +vagabond +vagrancy +vagrantly +vaguely +vagueness +valiant +valid +valium +valley +valuables +value +vanilla +vanish +vanity +vanquish +vantage +vaporizer +variable +variably +varied +variety +various +varmint +varnish +varsity +varying +vascular +vaseline +vastly +vastness +veal +vegan +veggie +vehicular +velcro +velocity +velvet +vendetta +vending +vendor +veneering +vengeful +venomous +ventricle +venture +venue +venus +verbalize +verbally +verbose +verdict +verify +verse +version +versus +vertebrae +vertical +vertigo +very +vessel +vest +veteran +veto +vexingly +viability +viable +vibes +vice +vicinity +victory +video +viewable +viewer +viewing +viewless +viewpoint +vigorous +village +villain +vindicate +vineyard +vintage +violate +violation +violator +violet +violin +viper +viral +virtual +virtuous +virus +visa +viscosity +viscous +viselike +visible +visibly +vision +visiting +visitor +visor +vista +vitality +vitalize +vitally +vitamins +vivacious +vividly +vividness +vixen +vocalist +vocalize +vocally +vocation +voice +voicing +void +volatile +volley +voltage +volumes +voter +voting +voucher +vowed +vowel +voyage +wackiness +wad +wafer +waffle +waged +wager +wages +waggle +wagon +wake +waking +walk +walmart +walnut +walrus +waltz +wand +wannabe +wanted +wanting +wasabi +washable +washbasin +washboard +washbowl +washcloth +washday +washed +washer +washhouse +washing +washout +washroom +washstand +washtub +wasp +wasting +watch +water +waviness +waving +wavy +whacking +whacky +wham +wharf +wheat +whenever +whiff +whimsical +whinny +whiny +whisking +whoever +whole +whomever +whoopee +whooping +whoops +why +wick +widely +widen +widget +widow +width +wieldable +wielder +wife +wifi +wikipedia +wildcard +wildcat +wilder +wildfire +wildfowl +wildland +wildlife +wildly +wildness +willed +willfully +willing +willow +willpower +wilt +wimp +wince +wincing +wind +wing +winking +winner +winnings +winter +wipe +wired +wireless +wiring +wiry +wisdom +wise +wish +wisplike +wispy +wistful +wizard +wobble +wobbling +wobbly +wok +wolf +wolverine +womanhood +womankind +womanless +womanlike +womanly +womb +woof +wooing +wool +woozy +word +work +worried +worrier +worrisome +worry +worsening +worshiper +worst +wound +woven +wow +wrangle +wrath +wreath +wreckage +wrecker +wrecking +wrench +wriggle +wriggly +wrinkle +wrinkly +wrist +writing +written +wrongdoer +wronged +wrongful +wrongly +wrongness +wrought +xbox +xerox +yahoo +yam +yanking +yapping +yard +yarn +yeah +yearbook +yearling +yearly +yearning +yeast +yelling +yelp +yen +yesterday +yiddish +yield +yin +yippee +yo-yo +yodel +yoga +yogurt +yonder +yoyo +yummy +zap +zealous +zebra +zen +zeppelin +zero +zestfully +zesty +zigzagged +zipfile +zipping +zippy +zips +zit +zodiac +zombie +zone +zoning +zookeeper +zoologist +zoology +zoom diff --git a/snapcraft.yaml b/snapcraft.yaml index c0d5919f58..c05ad2aab2 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -1,17 +1,17 @@ name: keepassxc -version: 2.1.3 +version: 2.2.0 grade: stable summary: community driven port of the windows application “Keepass Password Safe” description: | - KeePassXC is an application for people with extremly high demands on secure + KeePassXC is an application for people with extremely high demands on secure personal data management. It has a light interface, is cross platform and - published under the terms of the GNU General Public License. + is published under the terms of the GNU General Public License. confinement: strict apps: keepassxc: command: desktop-launch keepassxc - plugs: [unity7, opengl, gsettings, home, network, network-bind] + plugs: [unity7, x11, opengl, gsettings, home, network, network-bind, removable-media] parts: keepassxc: @@ -22,6 +22,7 @@ parts: - -DWITH_TESTS=OFF - -DWITH_XC_AUTOTYPE=ON - -DWITH_XC_HTTP=ON + - -DWITH_XC_YUBIKEY=ON build-packages: - g++ - libgcrypt20-dev @@ -30,4 +31,20 @@ parts: - qttools5-dev - qttools5-dev-tools - zlib1g-dev + - libxi-dev + - libxtst-dev + - libyubikey-dev + - libykpers-1-dev after: [desktop-qt5] + desktop-qt5: + # Redefine stage packages to work with Ubuntu 17.04 + stage-packages: + - libxkbcommon0 + - ttf-ubuntu-font-family + - dmz-cursor-theme + - light-themes + - shared-mime-info + - libqt5gui5 + - libgdk-pixbuf2.0-0 + - libqt5svg5 # for loading icon themes which are svg + - locales-all diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9935985ccf..7916855766 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ # Copyright (C) 2010 Felix Geyer +# Copyright (C) 2017 KeePassXC Team # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -31,6 +32,7 @@ configure_file(version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/version.h @ONLY) set(keepassx_SOURCES core/AutoTypeAssociations.cpp core/Config.cpp + core/CsvParser.cpp core/Database.cpp core/DatabaseIcons.cpp core/Endian.cpp @@ -45,13 +47,20 @@ set(keepassx_SOURCES core/ListDeleter.h core/Metadata.cpp core/PasswordGenerator.cpp + core/PassphraseGenerator.cpp core/SignalMultiplexer.cpp + core/ScreenLockListener.cpp + core/ScreenLockListener.h + core/ScreenLockListenerPrivate.h + core/ScreenLockListenerPrivate.cpp core/TimeDelta.cpp core/TimeInfo.cpp core/ToDbExporter.cpp core/Tools.cpp core/Translator.cpp core/Uuid.cpp + cli/PasswordInput.cpp + cli/PasswordInput.h crypto/Crypto.cpp crypto/CryptoHash.cpp crypto/Random.cpp @@ -70,8 +79,10 @@ set(keepassx_SOURCES format/KeePass2XmlWriter.cpp gui/AboutDialog.cpp gui/Application.cpp + gui/CategoryListWidget.cpp gui/ChangeMasterKeyWidget.cpp gui/Clipboard.cpp + gui/CloneDialog.cpp gui/DatabaseOpenWidget.cpp gui/DatabaseRepairWidget.cpp gui/DatabaseSettingsWidget.cpp @@ -86,18 +97,24 @@ set(keepassx_SOURCES gui/FileDialog.cpp gui/IconModels.cpp gui/KeePass1OpenWidget.cpp + gui/KMessageWidget.cpp gui/LineEdit.cpp gui/MainWindow.cpp gui/MessageBox.cpp + gui/MessageWidget.cpp gui/PasswordEdit.cpp gui/PasswordGeneratorWidget.cpp - gui/PasswordComboBox.cpp gui/SettingsWidget.cpp gui/SearchWidget.cpp gui/SortFilterHideProxyModel.cpp + gui/SetupTotpDialog.cpp + gui/TotpDialog.cpp gui/UnlockDatabaseWidget.cpp gui/UnlockDatabaseDialog.cpp gui/WelcomeWidget.cpp + gui/csvImport/CsvImportWidget.cpp + gui/csvImport/CsvImportWizard.cpp + gui/csvImport/CsvParserModel.cpp gui/entry/AutoTypeAssociationsModel.cpp gui/entry/EditEntryWidget.cpp gui/entry/EditEntryWidget_p.h @@ -111,50 +128,55 @@ set(keepassx_SOURCES gui/group/GroupView.cpp keys/CompositeKey.cpp keys/CompositeKey_p.h + keys/drivers/YubiKey.h keys/FileKey.cpp keys/Key.h keys/PasswordKey.cpp + keys/YkChallengeResponseKey.cpp streams/HashedBlockStream.cpp streams/LayeredStream.cpp streams/qtiocompressor.cpp streams/StoreDataStream.cpp streams/SymmetricCipherStream.cpp + totp/base32.h + totp/base32.cpp + totp/totp.h + totp/totp.cpp ) +if(APPLE) + set(keepassx_SOURCES ${keepassx_SOURCES} + core/ScreenLockListenerMac.h + core/ScreenLockListenerMac.cpp + ) +endif() +if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(keepassx_SOURCES ${keepassx_SOURCES} + core/ScreenLockListenerDBus.h + core/ScreenLockListenerDBus.cpp + ) +endif() +if(MINGW) + set(keepassx_SOURCES ${keepassx_SOURCES} + core/ScreenLockListenerWin.h + core/ScreenLockListenerWin.cpp + ) +endif() set(keepassx_SOURCES_MAINEXE main.cpp ) -set(keepassx_FORMS - gui/AboutDialog.ui - gui/ChangeMasterKeyWidget.ui - gui/DatabaseOpenWidget.ui - gui/DatabaseSettingsWidget.ui - gui/EditWidget.ui - gui/EditWidgetIcons.ui - gui/EditWidgetProperties.ui - gui/MainWindow.ui - gui/PasswordGeneratorWidget.ui - gui/SearchWidget.ui - gui/SettingsWidgetGeneral.ui - gui/SettingsWidgetSecurity.ui - gui/WelcomeWidget.ui - gui/entry/EditEntryWidgetAdvanced.ui - gui/entry/EditEntryWidgetAutoType.ui - gui/entry/EditEntryWidgetHistory.ui - gui/entry/EditEntryWidgetMain.ui - gui/group/EditGroupWidgetMain.ui -) - -add_feature_info(KeePassHTTP WITH_XC_HTTP "KeePassHTTP support for ChromeIPass and PassIFox") -add_feature_info(Autotype WITH_XC_AUTOTYPE "Auto-type passwords in Input fields") +add_feature_info(AutoType WITH_XC_AUTOTYPE "Automatic password typing") +add_feature_info(KeePassHTTP WITH_XC_HTTP "Browser integration compatible with ChromeIPass and PassIFox") +add_feature_info(YubiKey WITH_XC_YUBIKEY "YubiKey HMAC-SHA1 challenge-response") add_subdirectory(http) if(WITH_XC_HTTP) - set(keepasshttp_LIB keepasshttp) + set(keepasshttp_LIB keepasshttp qhttp Qt5::Network) endif() add_subdirectory(autotype) +add_subdirectory(cli) set(autotype_SOURCES core/Tools.cpp @@ -175,7 +197,11 @@ if(MINGW) ${CMAKE_SOURCE_DIR}/share/windows/icon.rc) endif() -qt5_wrap_ui(keepassx_SOURCES ${keepassx_FORMS}) +if(WITH_XC_YUBIKEY) + list(APPEND keepassx_SOURCES keys/drivers/YubiKey.cpp) +else() + list(APPEND keepassx_SOURCES keys/drivers/YubiKeyStub.cpp) +endif() add_library(zxcvbn STATIC zxcvbn/zxcvbn.cpp) target_link_libraries(zxcvbn) @@ -191,25 +217,27 @@ set_target_properties(keepassx_core PROPERTIES COMPILE_DEFINITIONS KEEPASSX_BUIL target_link_libraries(keepassx_core ${keepasshttp_LIB} ${autotype_LIB} + ${YUBIKEY_LIBRARIES} zxcvbn - qhttp Qt5::Core + Qt5::Network Qt5::Concurrent Qt5::Widgets - Qt5::Network ${GCRYPT_LIBRARIES} ${GPGERROR_LIBRARIES} ${ZLIB_LIBRARIES}) + +if(APPLE) + target_link_libraries(keepassx_core "-framework Foundation") +endif() if (UNIX AND NOT APPLE) target_link_libraries(keepassx_core Qt5::DBus) endif() - if(MINGW) - string(REPLACE "." ";" VERSION_LIST ${KEEPASSXC_VERSION}) - list(GET VERSION_LIST 0 KEEPASSXC_VERSION_MAJOR) - list(GET VERSION_LIST 1 KEEPASSXC_VERSION_MINOR) - list(GET VERSION_LIST 2 KEEPASSXC_VERSION_PATCH) + target_link_libraries(keepassx_core Wtsapi32.lib) +endif() +if(MINGW) include(GenerateProductVersion) generate_product_version( WIN32_ProductVersionFiles @@ -221,14 +249,15 @@ if(MINGW) ) endif() -add_executable(${PROGNAME} WIN32 MACOSX_BUNDLE ${keepassx_SOURCES_MAINEXE} ${WIN32_ProductVersionFiles}) +add_executable(${PROGNAME} WIN32 ${keepassx_SOURCES_MAINEXE} ${WIN32_ProductVersionFiles}) target_link_libraries(${PROGNAME} keepassx_core) set_target_properties(${PROGNAME} PROPERTIES ENABLE_EXPORTS ON) -if(APPLE) +if(APPLE AND WITH_APP_BUNDLE) configure_file(${CMAKE_SOURCE_DIR}/share/macosx/Info.plist.cmake ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) set_target_properties(${PROGNAME} PROPERTIES + MACOSX_BUNDLE ON MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) endif() @@ -236,7 +265,7 @@ install(TARGETS ${PROGNAME} BUNDLE DESTINATION . COMPONENT Runtime RUNTIME DESTINATION ${BIN_INSTALL_DIR} COMPONENT Runtime) -if(APPLE) +if(APPLE AND WITH_APP_BUNDLE) if(QT_MAC_USE_COCOA AND EXISTS "${QT_LIBRARY_DIR}/Resources/qt_menu.nib") install(DIRECTORY "${QT_LIBRARY_DIR}/Resources/qt_menu.nib" DESTINATION "${DATA_INSTALL_DIR}") @@ -247,7 +276,7 @@ if(APPLE) set(CPACK_DMG_VOLUME_NAME "${PROGNAME}") set(CPACK_SYSTEM_NAME "OSX") set(CPACK_STRIP_FILES ON) - set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSXC_VERSION_NUM}") + set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSXC_VERSION}") include(CPack) if(NOT DEFINED QT_BINARY_DIR) @@ -261,7 +290,12 @@ if(APPLE) endif() if(MINGW) - string(REPLACE "AMD" "Win" OUTPUT_FILE_POSTFIX "${CMAKE_HOST_SYSTEM_PROCESSOR}") + if(${CMAKE_SIZEOF_VOID_P} EQUAL "8") + set(OUTPUT_FILE_POSTFIX "Win64") + else() + set(OUTPUT_FILE_POSTFIX "Win32") + endif() + set(CPACK_GENERATOR "ZIP;NSIS") set(CPACK_STRIP_FILES ON) set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSXC_VERSION}-${OUTPUT_FILE_POSTFIX}") @@ -270,6 +304,7 @@ if(MINGW) set(CPACK_PACKAGE_VENDOR "${PROGNAME} Team") string(REGEX REPLACE "/" "\\\\\\\\" CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/share/windows/installer-header.bmp") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.GPL-2") + set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) set(CPACK_NSIS_MUI_ICON "${CMAKE_SOURCE_DIR}/share/windows/keepassxc.ico") set(CPACK_NSIS_MUI_UNIICON "${CPACK_NSIS_MUI_ICON}") set(CPACK_NSIS_INSTALLED_ICON_NAME "\\\\${PROGNAME}.exe") @@ -278,6 +313,7 @@ if(MINGW) set(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut '$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${PROGNAME}.lnk' '$INSTDIR\\\\${PROGNAME}.exe'") set(CPACK_NSIS_DELETE_ICONS_EXTRA "Delete '$SMPROGRAMS\\\\$START_MENU\\\\${PROGNAME}.lnk'") set(CPACK_NSIS_URL_INFO_ABOUT "https://keepassxc.org") + set(CPACK_NSIS_DISPLAY_NAME ${PROGNAME}) set(CPACK_NSIS_PACKAGE_NAME "${PROGNAME} v${KEEPASSXC_VERSION}") set(CPACK_NSIS_MUI_FINISHPAGE_RUN "../${PROGNAME}.exe") include(CPack) diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index 0c942e7282..927d6822bd 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -142,6 +143,9 @@ void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow, const QS sequence = customSequence; } + sequence.replace("{{}", "{LEFTBRACE}"); + sequence.replace("{}}", "{RIGHTBRACE}"); + QList actions; ListDeleter actionsDeleter(&actions); @@ -317,8 +321,6 @@ bool AutoType::parseActions(const QString& sequence, const Entry* entry, QList AutoType::createActionFromTemplate(const QString& tmpl, c else if (tmplName.compare("enter",Qt::CaseInsensitive)==0) { list.append(new AutoTypeKey(Qt::Key_Enter)); } + else if (tmplName.compare("space",Qt::CaseInsensitive)==0) { + list.append(new AutoTypeKey(Qt::Key_Space)); + } else if (tmplName.compare("up",Qt::CaseInsensitive)==0) { list.append(new AutoTypeKey(Qt::Key_Up)); } @@ -483,10 +488,10 @@ QList AutoType::createActionFromTemplate(const QString& tmpl, c else if (tmplName.compare(")",Qt::CaseInsensitive)==0) { list.append(new AutoTypeChar(')')); } - else if (tmplName.compare("{",Qt::CaseInsensitive)==0) { + else if (tmplName.compare("leftbrace",Qt::CaseInsensitive)==0) { list.append(new AutoTypeChar('{')); } - else if (tmplName.compare("}",Qt::CaseInsensitive)==0) { + else if (tmplName.compare("rightbrace",Qt::CaseInsensitive)==0) { list.append(new AutoTypeChar('}')); } else { @@ -514,6 +519,14 @@ QList AutoType::createActionFromTemplate(const QString& tmpl, c else if (tmplName.compare("clearfield",Qt::CaseInsensitive)==0) { list.append(new AutoTypeClearField()); } + else if (tmplName.compare("totp", Qt::CaseInsensitive) == 0) { + QString totp = entry->totp(); + if (!totp.isEmpty()) { + for (const QChar& ch : totp) { + list.append(new AutoTypeChar(ch)); + } + } + } if (!list.isEmpty()) { return list; @@ -562,8 +575,9 @@ QString AutoType::autoTypeSequence(const Entry* entry, const QString& windowTitl } } - if (!match && config()->get("AutoTypeEntryTitleMatch").toBool() && !entry->title().isEmpty() - && windowTitle.contains(entry->title(), Qt::CaseInsensitive)) { + if (!match && config()->get("AutoTypeEntryTitleMatch").toBool() + && (windowMatchesTitle(windowTitle, entry->resolvePlaceholder(entry->title())) + || windowMatchesUrl(windowTitle, entry->resolvePlaceholder(entry->url())))) { sequence = entry->defaultAutoTypeSequence(); match = true; } @@ -594,11 +608,11 @@ QString AutoType::autoTypeSequence(const Entry* entry, const QString& windowTitl group = group->parentGroup(); } while (group && (!enableSet || sequence.isEmpty())); - if (sequence.isEmpty() && (!entry->username().isEmpty() || !entry->password().isEmpty())) { - if (entry->username().isEmpty()) { + if (sequence.isEmpty() && (!entry->resolvePlaceholder(entry->username()).isEmpty() || !entry->resolvePlaceholder(entry->password()).isEmpty())) { + if (entry->resolvePlaceholder(entry->username()).isEmpty()) { sequence = "{PASSWORD}{ENTER}"; } - else if (entry->password().isEmpty()) { + else if (entry->resolvePlaceholder(entry->password()).isEmpty()) { sequence = "{USERNAME}{ENTER}"; } else { @@ -619,3 +633,22 @@ bool AutoType::windowMatches(const QString& windowTitle, const QString& windowPa return WildcardMatcher(windowTitle).match(windowPattern); } } + +bool AutoType::windowMatchesTitle(const QString& windowTitle, const QString& resolvedTitle) +{ + return !resolvedTitle.isEmpty() && windowTitle.contains(resolvedTitle, Qt::CaseInsensitive); +} + +bool AutoType::windowMatchesUrl(const QString& windowTitle, const QString& resolvedUrl) +{ + if (!resolvedUrl.isEmpty() && windowTitle.contains(resolvedUrl, Qt::CaseInsensitive)) { + return true; + } + + QUrl url(resolvedUrl); + if (url.isValid() && !url.host().isEmpty()) { + return windowTitle.contains(url.host(), Qt::CaseInsensitive); + } + + return false; +} diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h index 9799af4f3f..6f4a815f81 100644 --- a/src/autotype/AutoType.h +++ b/src/autotype/AutoType.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -48,13 +49,13 @@ class AutoType : public QObject static AutoType* instance(); static void createTestInstance(); -public Q_SLOTS: +public slots: void performGlobalAutoType(const QList& dbList); -Q_SIGNALS: +signals: void globalShortcutTriggered(); -private Q_SLOTS: +private slots: void performAutoTypeFromGlobal(Entry* entry, const QString& sequence); void resetInAutoType(); void unloadPlugin(); @@ -66,6 +67,8 @@ private Q_SLOTS: bool parseActions(const QString& sequence, const Entry* entry, QList& actions); QList createActionFromTemplate(const QString& tmpl, const Entry* entry); QString autoTypeSequence(const Entry* entry, const QString& windowTitle = QString()); + bool windowMatchesTitle(const QString& windowTitle, const QString& resolvedTitle); + bool windowMatchesUrl(const QString& windowTitle, const QString& resolvedUrl); bool windowMatches(const QString& windowTitle, const QString& windowPattern); bool m_inAutoType; diff --git a/src/autotype/AutoTypeAction.cpp b/src/autotype/AutoTypeAction.cpp index 090ca8234b..64dae79623 100644 --- a/src/autotype/AutoTypeAction.cpp +++ b/src/autotype/AutoTypeAction.cpp @@ -90,6 +90,4 @@ void AutoTypeExecutor::execDelay(AutoTypeDelay* action) void AutoTypeExecutor::execClearField(AutoTypeClearField* action) { Q_UNUSED(action); - - // TODO: implement } diff --git a/src/autotype/AutoTypeSelectDialog.cpp b/src/autotype/AutoTypeSelectDialog.cpp index 6bb155b81f..240dd723bc 100644 --- a/src/autotype/AutoTypeSelectDialog.cpp +++ b/src/autotype/AutoTypeSelectDialog.cpp @@ -91,7 +91,7 @@ void AutoTypeSelectDialog::emitEntryActivated(const QModelIndex& index) Entry* entry = m_view->entryFromIndex(index); accept(); - Q_EMIT entryActivated(entry, m_sequences[entry]); + emit entryActivated(entry, m_sequences[entry]); } void AutoTypeSelectDialog::entryRemoved() diff --git a/src/autotype/AutoTypeSelectDialog.h b/src/autotype/AutoTypeSelectDialog.h index 7b3909a191..3d9c684ed1 100644 --- a/src/autotype/AutoTypeSelectDialog.h +++ b/src/autotype/AutoTypeSelectDialog.h @@ -33,13 +33,13 @@ class AutoTypeSelectDialog : public QDialog explicit AutoTypeSelectDialog(QWidget* parent = nullptr); void setEntries(const QList& entries, const QHash& sequences); -Q_SIGNALS: +signals: void entryActivated(Entry* entry, const QString& sequence); -public Q_SLOTS: +public slots: void done(int r) override; -private Q_SLOTS: +private slots: void emitEntryActivated(const QModelIndex& index); void entryRemoved(); diff --git a/src/autotype/AutoTypeSelectView.h b/src/autotype/AutoTypeSelectView.h index 749f6a9f31..a781757b8e 100644 --- a/src/autotype/AutoTypeSelectView.h +++ b/src/autotype/AutoTypeSelectView.h @@ -32,7 +32,7 @@ class AutoTypeSelectView : public EntryView protected: void mouseMoveEvent(QMouseEvent* event) override; -private Q_SLOTS: +private slots: void selectFirstEntry(); }; diff --git a/src/autotype/mac/AppKit.h b/src/autotype/mac/AppKit.h index 114038d637..f1eced5bb6 100644 --- a/src/autotype/mac/AppKit.h +++ b/src/autotype/mac/AppKit.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Lennart Glauer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/autotype/mac/AppKitImpl.h b/src/autotype/mac/AppKitImpl.h index 1b57d7b147..f370096fc1 100644 --- a/src/autotype/mac/AppKitImpl.h +++ b/src/autotype/mac/AppKitImpl.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Lennart Glauer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/autotype/mac/AppKitImpl.mm b/src/autotype/mac/AppKitImpl.mm index ad600cb959..457044389a 100644 --- a/src/autotype/mac/AppKitImpl.mm +++ b/src/autotype/mac/AppKitImpl.mm @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Lennart Glauer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/autotype/mac/AutoTypeMac.cpp b/src/autotype/mac/AutoTypeMac.cpp index e55c336cb2..7056c7310e 100644 --- a/src/autotype/mac/AutoTypeMac.cpp +++ b/src/autotype/mac/AutoTypeMac.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Lennart Glauer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -120,7 +121,7 @@ bool AutoTypePlatformMac::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifi qWarning("Invalid key code"); return false; } - uint16 nativeModifiers = qtToNativeModifiers(modifiers); + CGEventFlags nativeModifiers = qtToNativeModifiers(modifiers, false); if (::RegisterEventHotKey(nativeKeyCode, nativeModifiers, m_hotkeyId, GetApplicationEventTarget(), 0, &m_hotkeyRef) != noErr) { qWarning("Register hotkey failed"); return false; @@ -201,7 +202,7 @@ void AutoTypePlatformMac::sendChar(const QChar& ch, bool isKeyDown) // Send key code to active window // see: Quartz Event Services // -void AutoTypePlatformMac::sendKey(Qt::Key key, bool isKeyDown) +void AutoTypePlatformMac::sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers = 0) { uint16 keyCode = qtToNativeKeyCode(key); if (keyCode == INVALID_KEYCODE) { @@ -209,7 +210,9 @@ void AutoTypePlatformMac::sendKey(Qt::Key key, bool isKeyDown) } CGEventRef keyEvent = ::CGEventCreateKeyboardEvent(nullptr, keyCode, isKeyDown); + CGEventFlags nativeModifiers = qtToNativeModifiers(modifiers, true); if (keyEvent != nullptr) { + ::CGEventSetFlags(keyEvent, nativeModifiers); ::CGEventPost(kCGSessionEventTap, keyEvent); ::CFRelease(keyEvent); } @@ -317,6 +320,10 @@ uint16 AutoTypePlatformMac::qtToNativeKeyCode(Qt::Key key) case Qt::Key_Period: return kVK_ANSI_Period; + case Qt::Key_Shift: + return kVK_Shift; + case Qt::Key_Control: + return kVK_Command; case Qt::Key_Backspace: return kVK_Delete; case Qt::Key_Tab: @@ -395,21 +402,34 @@ uint16 AutoTypePlatformMac::qtToNativeKeyCode(Qt::Key key) // Translate qt key modifiers to mac os modifiers // see: https://doc.qt.io/qt-5/osx-issues.html#special-keys // -uint16 AutoTypePlatformMac::qtToNativeModifiers(Qt::KeyboardModifiers modifiers) +CGEventFlags AutoTypePlatformMac::qtToNativeModifiers(Qt::KeyboardModifiers modifiers, bool native) { - uint16 nativeModifiers = 0; + CGEventFlags nativeModifiers = CGEventFlags(0); + + CGEventFlags shiftMod = CGEventFlags(shiftKey); + CGEventFlags cmdMod = CGEventFlags(cmdKey); + CGEventFlags optionMod = CGEventFlags(optionKey); + CGEventFlags controlMod = CGEventFlags(controlKey); + + if (native) { + shiftMod = kCGEventFlagMaskShift; + cmdMod = kCGEventFlagMaskCommand; + optionMod = kCGEventFlagMaskAlternate; + controlMod = kCGEventFlagMaskControl; + } + if (modifiers & Qt::ShiftModifier) { - nativeModifiers |= shiftKey; + nativeModifiers = CGEventFlags(nativeModifiers | shiftMod); } if (modifiers & Qt::ControlModifier) { - nativeModifiers |= cmdKey; + nativeModifiers = CGEventFlags(nativeModifiers | cmdMod); } if (modifiers & Qt::AltModifier) { - nativeModifiers |= optionKey; + nativeModifiers = CGEventFlags(nativeModifiers | optionMod); } if (modifiers & Qt::MetaModifier) { - nativeModifiers |= controlKey; + nativeModifiers = CGEventFlags(nativeModifiers | controlMod); } return nativeModifiers; @@ -460,7 +480,7 @@ OSStatus AutoTypePlatformMac::hotkeyHandler(EventHandlerCallRef nextHandler, Eve if (::GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, nullptr, sizeof(hotkeyId), nullptr, &hotkeyId) == noErr && hotkeyId.id == HOTKEY_ID) { - Q_EMIT self->globalShortcutTriggered(); + emit self->globalShortcutTriggered(); } return noErr; @@ -488,3 +508,25 @@ void AutoTypeExecutorMac::execKey(AutoTypeKey* action) m_platform->sendKey(action->key, false); usleep(25 * 1000); } + +void AutoTypeExecutorMac::execClearField(AutoTypeClearField* action = nullptr) +{ + Q_UNUSED(action); + + m_platform->sendKey(Qt::Key_Control, true, Qt::ControlModifier); + m_platform->sendKey(Qt::Key_Up, true, Qt::ControlModifier); + m_platform->sendKey(Qt::Key_Up, false, Qt::ControlModifier); + m_platform->sendKey(Qt::Key_Control, false); + usleep(25 * 1000); + m_platform->sendKey(Qt::Key_Shift, true, Qt::ShiftModifier); + m_platform->sendKey(Qt::Key_Control, true, Qt::ShiftModifier | Qt::ControlModifier); + m_platform->sendKey(Qt::Key_Down, true, Qt::ShiftModifier | Qt::ControlModifier); + m_platform->sendKey(Qt::Key_Down, false, Qt::ShiftModifier | Qt::ControlModifier); + m_platform->sendKey(Qt::Key_Control, false, Qt::ShiftModifier); + m_platform->sendKey(Qt::Key_Shift, false); + usleep(25 * 1000); + m_platform->sendKey(Qt::Key_Backspace, true); + m_platform->sendKey(Qt::Key_Backspace, false); + + usleep(25 * 1000); +} diff --git a/src/autotype/mac/AutoTypeMac.h b/src/autotype/mac/AutoTypeMac.h index 475a4b99bd..c554fa6e4e 100644 --- a/src/autotype/mac/AutoTypeMac.h +++ b/src/autotype/mac/AutoTypeMac.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Lennart Glauer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,9 +50,9 @@ class AutoTypePlatformMac : public QObject, public AutoTypePlatformInterface bool raiseOwnWindow() override; void sendChar(const QChar& ch, bool isKeyDown); - void sendKey(Qt::Key key, bool isKeyDown); + void sendKey(Qt::Key key, bool isKeyDown, Qt::KeyboardModifiers modifiers); -Q_SIGNALS: +signals: void globalShortcutTriggered(); private: @@ -60,7 +61,7 @@ class AutoTypePlatformMac : public QObject, public AutoTypePlatformInterface EventHotKeyID m_hotkeyId; static uint16 qtToNativeKeyCode(Qt::Key key); - static uint16 qtToNativeModifiers(Qt::KeyboardModifiers modifiers); + static CGEventFlags qtToNativeModifiers(Qt::KeyboardModifiers modifiers, bool native); static int windowLayer(CFDictionaryRef window); static QString windowTitle(CFDictionaryRef window); static OSStatus hotkeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData); @@ -73,6 +74,7 @@ class AutoTypeExecutorMac : public AutoTypeExecutor void execChar(AutoTypeChar* action) override; void execKey(AutoTypeKey* action) override; + void execClearField(AutoTypeClearField* action) override; private: AutoTypePlatformMac* const m_platform; diff --git a/src/autotype/mac/CMakeLists.txt b/src/autotype/mac/CMakeLists.txt index 076dd50383..ac93de0e7b 100644 --- a/src/autotype/mac/CMakeLists.txt +++ b/src/autotype/mac/CMakeLists.txt @@ -12,9 +12,15 @@ target_link_libraries(keepassx-autotype-cocoa ${PROGNAME} Qt5::Core Qt5::Widgets if(NOT DEFINED QT_BINARY_DIR) set(QT_BINARY_DIR "/usr/local/opt/qt5/bin" CACHE PATH "QT binary folder") endif() -add_custom_command(TARGET keepassx-autotype-cocoa - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libkeepassx-autotype-cocoa.so ${PLUGIN_INSTALL_DIR} - COMMAND ${QT_BINARY_DIR}/macdeployqt ${PROGNAME}.app -executable=${PLUGIN_INSTALL_DIR}/libkeepassx-autotype-cocoa.so -no-plugins - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src -COMMENT "Deploying autotype plugin") +if(WITH_APP_BUNDLE) + add_custom_command(TARGET keepassx-autotype-cocoa + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/libkeepassx-autotype-cocoa.so ${PLUGIN_INSTALL_DIR} + COMMAND ${QT_BINARY_DIR}/macdeployqt ${PROGNAME}.app -executable=${PLUGIN_INSTALL_DIR}/libkeepassx-autotype-cocoa.so -no-plugins + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src + COMMENT "Deploying autotype plugin") +else() + install(TARGETS keepassx-autotype-cocoa + BUNDLE DESTINATION . COMPONENT Runtime + LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime) +endif() diff --git a/src/autotype/test/AutoTypeTest.h b/src/autotype/test/AutoTypeTest.h index 4feaab9422..d9a86c3de5 100644 --- a/src/autotype/test/AutoTypeTest.h +++ b/src/autotype/test/AutoTypeTest.h @@ -60,7 +60,7 @@ class AutoTypePlatformTest : public QObject, void addActionChar(AutoTypeChar* action); void addActionKey(AutoTypeKey* action); -Q_SIGNALS: +signals: void globalShortcutTriggered(); private: diff --git a/src/autotype/windows/AutoTypeWindows.cpp b/src/autotype/windows/AutoTypeWindows.cpp index 481caa83fb..2dfc7a2698 100644 --- a/src/autotype/windows/AutoTypeWindows.cpp +++ b/src/autotype/windows/AutoTypeWindows.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Lennart Glauer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -96,7 +97,7 @@ int AutoTypePlatformWin::platformEventFilter(void* event) MSG *msg = static_cast(event); if (msg->message == WM_HOTKEY && msg->wParam == HOTKEY_ID) { - Q_EMIT globalShortcutTriggered(); + emit globalShortcutTriggered(); return 1; } @@ -189,6 +190,10 @@ DWORD AutoTypePlatformWin::qtToNativeKeyCode(Qt::Key key) case Qt::Key_Enter: case Qt::Key_Return: return VK_RETURN; // 0x0D + case Qt::Key_Shift: + return VK_SHIFT; // 0x10 + case Qt::Key_Control: + return VK_CONTROL; // 0x11 case Qt::Key_Pause: return VK_PAUSE; // 0x13 case Qt::Key_CapsLock: @@ -527,3 +532,24 @@ void AutoTypeExecutorWin::execKey(AutoTypeKey* action) ::Sleep(25); } +void AutoTypeExecutorWin::execClearField(AutoTypeClearField* action = nullptr) +{ + Q_UNUSED(action); + + m_platform->sendKey(Qt::Key_Control, true); + m_platform->sendKey(Qt::Key_Home, true); + m_platform->sendKey(Qt::Key_Home, false); + m_platform->sendKey(Qt::Key_Control, false); + ::Sleep(25); + m_platform->sendKey(Qt::Key_Control, true); + m_platform->sendKey(Qt::Key_Shift, true); + m_platform->sendKey(Qt::Key_End, true); + m_platform->sendKey(Qt::Key_End, false); + m_platform->sendKey(Qt::Key_Shift, false); + m_platform->sendKey(Qt::Key_Control, false); + ::Sleep(25); + m_platform->sendKey(Qt::Key_Backspace, true); + m_platform->sendKey(Qt::Key_Backspace, false); + + ::Sleep(25); +} diff --git a/src/autotype/windows/AutoTypeWindows.h b/src/autotype/windows/AutoTypeWindows.h index 7a8c4bcabc..88b9a9fd2f 100644 --- a/src/autotype/windows/AutoTypeWindows.h +++ b/src/autotype/windows/AutoTypeWindows.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Lennart Glauer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,7 +46,7 @@ class AutoTypePlatformWin : public QObject, public AutoTypePlatformInterface void sendChar(const QChar& ch, bool isKeyDown); void sendKey(Qt::Key key, bool isKeyDown); -Q_SIGNALS: +signals: void globalShortcutTriggered(); private: @@ -64,6 +65,7 @@ class AutoTypeExecutorWin : public AutoTypeExecutor void execChar(AutoTypeChar* action) override; void execKey(AutoTypeKey* action) override; + void execClearField(AutoTypeClearField* action) override; private: AutoTypePlatformWin* const m_platform; diff --git a/src/autotype/xcb/AutoTypeXCB.cpp b/src/autotype/xcb/AutoTypeXCB.cpp index f419875dc8..436cd5b59f 100644 --- a/src/autotype/xcb/AutoTypeXCB.cpp +++ b/src/autotype/xcb/AutoTypeXCB.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2012 Felix Geyer * Copyright (C) 2000-2008 Tom Sato + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -214,7 +215,7 @@ int AutoTypePlatformX11::platformEventFilter(void* event) && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized()) && m_loaded) { if (type == XCB_KEY_PRESS) { - Q_EMIT globalShortcutTriggered(); + emit globalShortcutTriggered(); } return 1; @@ -435,6 +436,8 @@ KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key) return XK_Tab; case Qt::Key_Enter: return XK_Return; + case Qt::Key_Space: + return XK_space; case Qt::Key_Up: return XK_Up; case Qt::Key_Down: @@ -471,6 +474,12 @@ KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key) return XK_Print; case Qt::Key_ScrollLock: return XK_Scroll_Lock; + case Qt::Key_Shift: + return XK_Shift_L; + case Qt::Key_Control: + return XK_Control_L; + case Qt::Key_Alt: + return XK_Alt_L; default: if (key >= Qt::Key_F1 && key <= Qt::Key_F16) { return XK_F1 + (key - Qt::Key_F1); @@ -721,6 +730,12 @@ bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned i * are set ON, many events will be sent. */ void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym) +{ + SendKey(keysym,true); + SendKey(keysym,false); +} + +void AutoTypePlatformX11::SendKey(KeySym keysym, bool isKeyDown) { Window cur_focus; int revert_to; @@ -800,8 +815,11 @@ void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym) /* press and release key */ event.keycode = keycode; - SendEvent(&event, KeyPress); - SendEvent(&event, KeyRelease); + if (isKeyDown) { + SendEvent(&event, KeyPress); + } else { + SendEvent(&event, KeyRelease); + } /* release the modifiers */ SendModifier(&event, press_mask, KeyRelease); @@ -831,13 +849,40 @@ AutoTypeExecutorX11::AutoTypeExecutorX11(AutoTypePlatformX11* platform) void AutoTypeExecutorX11::execChar(AutoTypeChar* action) { m_platform->SendKeyPressedEvent(m_platform->charToKeySym(action->character)); + Tools::wait(25); } void AutoTypeExecutorX11::execKey(AutoTypeKey* action) { m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(action->key)); + Tools::wait(25); } +void AutoTypeExecutorX11::execClearField(AutoTypeClearField* action = nullptr) +{ + Q_UNUSED(action); + + timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 25 * 1000 * 1000; + + m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Control), true); + m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(Qt::Key_Home)); + m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Control), false); + nanosleep(&ts, nullptr); + + m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Control), true); + m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Shift), true); + m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(Qt::Key_End)); + m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Shift), false); + m_platform->SendKey(m_platform->keyToKeySym(Qt::Key_Control), false); + nanosleep(&ts, nullptr); + + m_platform->SendKeyPressedEvent(m_platform->keyToKeySym(Qt::Key_Backspace)); + nanosleep(&ts, nullptr); +} + + int AutoTypePlatformX11::initialTimeout() { return 500; diff --git a/src/autotype/xcb/AutoTypeXCB.h b/src/autotype/xcb/AutoTypeXCB.h index 26d1e8102d..34e539cf9e 100644 --- a/src/autotype/xcb/AutoTypeXCB.h +++ b/src/autotype/xcb/AutoTypeXCB.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2012 Felix Geyer * Copyright (C) 2000-2008 Tom Sato + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,8 +59,9 @@ class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface KeySym keyToKeySym(Qt::Key key); void SendKeyPressedEvent(KeySym keysym); + void SendKey(KeySym keysym, bool isKeyDown); -Q_SIGNALS: +signals: void globalShortcutTriggered(); private: @@ -126,6 +128,7 @@ class AutoTypeExecutorX11 : public AutoTypeExecutor void execChar(AutoTypeChar* action) override; void execKey(AutoTypeKey* action) override; + void execClearField(AutoTypeClearField* action) override; private: AutoTypePlatformX11* const m_platform; diff --git a/utils/CMakeLists.txt b/src/cli/CMakeLists.txt similarity index 55% rename from utils/CMakeLists.txt rename to src/cli/CMakeLists.txt index 83f00b4bc7..86edb9c018 100644 --- a/utils/CMakeLists.txt +++ b/src/cli/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (C) 2010 Felix Geyer +# Copyright (C) 2017 KeePassXC Team # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,24 +13,33 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -include_directories(../src) +set(cli_SOURCES + Clip.cpp + Clip.h + EntropyMeter.cpp + EntropyMeter.h + Extract.cpp + Extract.h + List.cpp + List.h + Merge.cpp + Merge.h + Show.cpp + Show.h) -add_executable(kdbx-extract kdbx-extract.cpp) -target_link_libraries(kdbx-extract - keepassx_core - Qt5::Core - ${GCRYPT_LIBRARIES} - ${GPGERROR_LIBRARIES} - ${ZLIB_LIBRARIES}) +add_library(cli STATIC ${cli_SOURCES}) +target_link_libraries(cli Qt5::Core Qt5::Widgets) -add_executable(kdbx-merge kdbx-merge.cpp) -target_link_libraries(kdbx-merge +add_executable(keepassxc-cli keepassxc-cli.cpp) +target_link_libraries(keepassxc-cli + cli keepassx_core Qt5::Core ${GCRYPT_LIBRARIES} ${GPGERROR_LIBRARIES} - ${ZLIB_LIBRARIES}) - + ${ZLIB_LIBRARIES} + zxcvbn) -add_executable(entropy-meter entropy-meter.cpp) -target_link_libraries(entropy-meter zxcvbn) +install(TARGETS keepassxc-cli + BUNDLE DESTINATION . COMPONENT Runtime + RUNTIME DESTINATION ${CLI_INSTALL_DIR} COMPONENT Runtime) diff --git a/src/cli/Clip.cpp b/src/cli/Clip.cpp new file mode 100644 index 0000000000..70d97c0e2c --- /dev/null +++ b/src/cli/Clip.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "Clip.h" + +#include +#include +#include +#include +#include + +#include "gui/UnlockDatabaseDialog.h" +#include "core/Database.h" +#include "core/Entry.h" +#include "core/Group.h" +#include "gui/Clipboard.h" + +int Clip::execute(int argc, char** argv) +{ + + QStringList arguments; + for (int i = 0; i < argc; ++i) { + arguments << QString(argv[i]); + } + QTextStream out(stdout); + + QCommandLineParser parser; + parser.setApplicationDescription(QCoreApplication::translate("main", "Copy a password to the clipboard")); + parser.addPositionalArgument("database", QCoreApplication::translate("main", "Path of the database.")); + QCommandLineOption guiPrompt( + QStringList() << "g" + << "gui-prompt", + QCoreApplication::translate("main", "Use a GUI prompt unlocking the database.")); + parser.addOption(guiPrompt); + parser.addPositionalArgument("entry", QCoreApplication::translate("main", "Name of the entry to clip.")); + parser.process(arguments); + + const QStringList args = parser.positionalArguments(); + if (args.size() != 2) { + QCoreApplication app(argc, argv); + parser.showHelp(EXIT_FAILURE); + } + + Database* db = nullptr; + QApplication app(argc, argv); + if (parser.isSet("gui-prompt")) { + db = UnlockDatabaseDialog::openDatabasePrompt(args.at(0)); + } else { + db = Database::unlockFromStdin(args.at(0)); + } + + if (!db) { + return EXIT_FAILURE; + } + + QString entryId = args.at(1); + Entry* entry = db->rootGroup()->findEntry(entryId); + if (!entry) { + qCritical("Entry %s not found.", qPrintable(entryId)); + return EXIT_FAILURE; + } + + Clipboard::instance()->setText(entry->password()); + return EXIT_SUCCESS; +} diff --git a/src/cli/Clip.h b/src/cli/Clip.h new file mode 100644 index 0000000000..cb72e42996 --- /dev/null +++ b/src/cli/Clip.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_CLIP_H +#define KEEPASSXC_CLIP_H + +class Clip +{ +public: + static int execute(int argc, char** argv); +}; + +#endif // KEEPASSXC_CLIP_H diff --git a/utils/entropy-meter.cpp b/src/cli/EntropyMeter.cpp similarity index 84% rename from utils/entropy-meter.cpp rename to src/cli/EntropyMeter.cpp index 74f6bc11a3..a62cd3077f 100644 --- a/utils/entropy-meter.cpp +++ b/src/cli/EntropyMeter.cpp @@ -1,10 +1,21 @@ /* -Part of this code come from zxcvbn-c example. -Copyright (c) 2015, Tony Evans -Copyright (c) 2016, KeePassXC Team + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ -See zxcvbn/zxcvbn.cpp for complete COPYRIGHT Notice -*/ +#include "EntropyMeter.h" #include #include @@ -76,7 +87,7 @@ static void calculate(const char *pwd, int advanced) } } -int main(int argc, char **argv) +int EntropyMeter::execute(int argc, char **argv) { printf("KeePassXC Entropy Meter, based on zxcvbn-c.\nEnter your password below or pass it as argv\n"); printf(" Usage: entropy-meter [-a] [pwd1 pwd2 ...]\n> "); diff --git a/src/cli/EntropyMeter.h b/src/cli/EntropyMeter.h new file mode 100644 index 0000000000..d160115bf0 --- /dev/null +++ b/src/cli/EntropyMeter.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_ENTROPYMETER_H +#define KEEPASSXC_ENTROPYMETER_H + +class EntropyMeter +{ +public: + static int execute(int argc, char** argv); +}; + +#endif // KEEPASSXC_ENTROPYMETER_H diff --git a/utils/kdbx-extract.cpp b/src/cli/Extract.cpp similarity index 70% rename from utils/kdbx-extract.cpp rename to src/cli/Extract.cpp index 255f5d003a..b9433801cd 100644 --- a/utils/kdbx-extract.cpp +++ b/src/cli/Extract.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,8 +15,11 @@ * along with this program. If not, see . */ +#include #include +#include "Extract.h" + #include #include #include @@ -24,46 +27,41 @@ #include #include "core/Database.h" -#include "crypto/Crypto.h" #include "format/KeePass2Reader.h" #include "keys/CompositeKey.h" -#include "keys/FileKey.h" -#include "keys/PasswordKey.h" +#include "cli/PasswordInput.h" -int main(int argc, char **argv) +int Extract::execute(int argc, char** argv) { QCoreApplication app(argc, argv); + QTextStream out(stdout); QCommandLineParser parser; - parser.setApplicationDescription(QCoreApplication::translate("main", - "Extract and print a KeePassXC database file.")); - parser.addPositionalArgument("database", QCoreApplication::translate("main", "path of the database to extract.")); - parser.addHelpOption(); + parser.setApplicationDescription( + QCoreApplication::translate("main", "Extract and print the content of a database.")); + parser.addPositionalArgument("database", QCoreApplication::translate("main", "Path of the database to extract.")); parser.process(app); const QStringList args = parser.positionalArguments(); if (args.size() != 1) { - parser.showHelp(); - return 1; + parser.showHelp(EXIT_FAILURE); } - if (!Crypto::init()) { - qFatal("Fatal error while testing the cryptographic functions:\n%s", qPrintable(Crypto::errorString())); - } + out << "Insert the database password\n> "; + out.flush(); - static QTextStream inputTextStream(stdin, QIODevice::ReadOnly); - QString line = inputTextStream.readLine(); + QString line = PasswordInput::getPassword(); CompositeKey key = CompositeKey::readFromLine(line); QString databaseFilename = args.at(0); QFile dbFile(databaseFilename); if (!dbFile.exists()) { qCritical("File %s does not exist.", qPrintable(databaseFilename)); - return 1; + return EXIT_FAILURE; } if (!dbFile.open(QIODevice::ReadOnly)) { qCritical("Unable to open file %s.", qPrintable(databaseFilename)); - return 1; + return EXIT_FAILURE; } KeePass2Reader reader; @@ -76,15 +74,13 @@ int main(int argc, char **argv) if (reader.hasError()) { if (xmlData.isEmpty()) { qCritical("Error while reading the database:\n%s", qPrintable(reader.errorString())); - return 1; - } - else { + } else { qWarning("Error while parsing the database:\n%s\n", qPrintable(reader.errorString())); } + return EXIT_FAILURE; } - QTextStream out(stdout); out << xmlData.constData() << "\n"; - return 0; + return EXIT_SUCCESS; } diff --git a/src/cli/Extract.h b/src/cli/Extract.h new file mode 100644 index 0000000000..e1b0672ecd --- /dev/null +++ b/src/cli/Extract.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_EXTRACT_H +#define KEEPASSXC_EXTRACT_H + +class Extract +{ +public: + static int execute(int argc, char** argv); +}; + +#endif // KEEPASSXC_EXTRACT_H diff --git a/src/cli/List.cpp b/src/cli/List.cpp new file mode 100644 index 0000000000..de6bd5ef53 --- /dev/null +++ b/src/cli/List.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "List.h" + +#include +#include +#include +#include +#include + +#include "gui/UnlockDatabaseDialog.h" +#include "core/Database.h" +#include "core/Entry.h" +#include "core/Group.h" +#include "keys/CompositeKey.h" + + +int List::execute(int argc, char** argv) +{ + QStringList arguments; + for (int i = 0; i < argc; ++i) { + arguments << QString(argv[i]); + } + QTextStream out(stdout); + + QCommandLineParser parser; + parser.setApplicationDescription(QCoreApplication::translate("main", "List database entries.")); + parser.addPositionalArgument("database", QCoreApplication::translate("main", "Path of the database.")); + parser.addPositionalArgument("group", + QCoreApplication::translate("main", "Path of the group to list. Default is /"), + QString("[group]")); + QCommandLineOption printUuidsOption( + QStringList() << "u" + << "print-uuids", + QCoreApplication::translate("main", "Print the UUIDs of the entries and groups.")); + parser.addOption(printUuidsOption); + QCommandLineOption guiPrompt( + QStringList() << "g" + << "gui-prompt", + QCoreApplication::translate("main", "Use a GUI prompt unlocking the database.")); + parser.addOption(guiPrompt); + parser.process(arguments); + + const QStringList args = parser.positionalArguments(); + if (args.size() != 1 && args.size() != 2) { + QCoreApplication app(argc, argv); + parser.showHelp(EXIT_FAILURE); + } + + Database* db = nullptr; + if (parser.isSet("gui-prompt")) { + QApplication app(argc, argv); + db = UnlockDatabaseDialog::openDatabasePrompt(args.at(0)); + } else { + QCoreApplication app(argc, argv); + db = Database::unlockFromStdin(args.at(0)); + } + + if (db == nullptr) { + return EXIT_FAILURE; + } + + Group* group = db->rootGroup(); + if (args.size() == 2) { + QString groupPath = args.at(1); + group = db->rootGroup()->findGroupByPath(groupPath); + if (group == nullptr) { + qCritical("Cannot find group %s.", qPrintable(groupPath)); + return EXIT_FAILURE; + } + } + + out << group->print(parser.isSet("print-uuids")); + out.flush(); + return EXIT_SUCCESS; +} diff --git a/src/cli/List.h b/src/cli/List.h new file mode 100644 index 0000000000..18528bd78e --- /dev/null +++ b/src/cli/List.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_LIST_H +#define KEEPASSXC_LIST_H + +class List +{ +public: + static int execute(int argc, char** argv); +}; + +#endif // KEEPASSXC_LIST_H diff --git a/src/cli/Merge.cpp b/src/cli/Merge.cpp new file mode 100644 index 0000000000..a179d69be1 --- /dev/null +++ b/src/cli/Merge.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include "Merge.h" + +#include +#include +#include +#include +#include + +#include "core/Database.h" +#include "gui/UnlockDatabaseDialog.h" + +int Merge::execute(int argc, char** argv) +{ + + QStringList arguments; + for (int i = 0; i < argc; ++i) { + arguments << QString(argv[i]); + } + QTextStream out(stdout); + + QCommandLineParser parser; + parser.setApplicationDescription(QCoreApplication::translate("main", "Merge two databases.")); + parser.addPositionalArgument("database1", + QCoreApplication::translate("main", "Path of the database to merge into.")); + parser.addPositionalArgument("database2", + QCoreApplication::translate("main", "Path of the database to merge from.")); + + QCommandLineOption samePasswordOption( + QStringList() << "s" + << "same-password", + QCoreApplication::translate("main", "Use the same password for both database files.")); + + QCommandLineOption guiPrompt( + QStringList() << "g" + << "gui-prompt", + QCoreApplication::translate("main", "Use a GUI prompt unlocking the database.")); + parser.addOption(guiPrompt); + + parser.addOption(samePasswordOption); + parser.process(arguments); + + const QStringList args = parser.positionalArguments(); + if (args.size() != 2) { + QCoreApplication app(argc, argv); + parser.showHelp(EXIT_FAILURE); + } + + Database* db1; + Database* db2; + + if (parser.isSet("gui-prompt")) { + QApplication app(argc, argv); + db1 = UnlockDatabaseDialog::openDatabasePrompt(args.at(0)); + if (!parser.isSet("same-password")) { + db2 = UnlockDatabaseDialog::openDatabasePrompt(args.at(1)); + } else { + db2 = Database::openDatabaseFile(args.at(1), *(db1->key().clone())); + } + } else { + QCoreApplication app(argc, argv); + db1 = Database::unlockFromStdin(args.at(0)); + if (!parser.isSet("same-password")) { + db2 = Database::unlockFromStdin(args.at(1)); + } else { + db2 = Database::openDatabaseFile(args.at(1), *(db1->key().clone())); + } + } + if (db1 == nullptr) { + return EXIT_FAILURE; + } + if (db2 == nullptr) { + return EXIT_FAILURE; + } + + db1->merge(db2); + QString errorMessage = db1->saveToFile(args.at(0)); + if (!errorMessage.isEmpty()) { + qCritical("Unable to save database to file : %s", qPrintable(errorMessage)); + return EXIT_FAILURE; + } + + out << "Successfully merged the database files.\n"; + return EXIT_SUCCESS; + +} diff --git a/src/cli/Merge.h b/src/cli/Merge.h new file mode 100644 index 0000000000..95da7af81a --- /dev/null +++ b/src/cli/Merge.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_MERGE_H +#define KEEPASSXC_MERGE_H + +class Merge +{ +public: + static int execute(int argc, char** argv); +}; + +#endif // KEEPASSXC_MERGE_H diff --git a/src/cli/PasswordInput.cpp b/src/cli/PasswordInput.cpp new file mode 100644 index 0000000000..16913e9566 --- /dev/null +++ b/src/cli/PasswordInput.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "PasswordInput.h" + +#ifdef Q_OS_WIN +#include +#else +#include +#include +#endif + +#include + + +PasswordInput::PasswordInput() +{ +} + +void PasswordInput::setStdinEcho(bool enable = true) +{ +#ifdef Q_OS_WIN + HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); + DWORD mode; + GetConsoleMode(hIn, &mode); + + if (enable) { + mode |= ENABLE_ECHO_INPUT; + } else { + mode &= ~ENABLE_ECHO_INPUT; + } + + SetConsoleMode(hIn, mode); + +#else + struct termios t; + tcgetattr(STDIN_FILENO, &t); + + if (enable) { + t.c_lflag |= ECHO; + } else { + t.c_lflag &= ~ECHO; + } + + tcsetattr(STDIN_FILENO, TCSANOW, &t); +#endif +} + +QString PasswordInput::getPassword() +{ + static QTextStream inputTextStream(stdin, QIODevice::ReadOnly); + static QTextStream outputTextStream(stdout, QIODevice::WriteOnly); + + setStdinEcho(false); + QString line = inputTextStream.readLine(); + setStdinEcho(true); + + // The new line was also not echoed, but we do want to echo it. + outputTextStream << "\n"; + outputTextStream.flush(); + + return line; +} diff --git a/src/cli/PasswordInput.h b/src/cli/PasswordInput.h new file mode 100644 index 0000000000..b760618645 --- /dev/null +++ b/src/cli/PasswordInput.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_PASSWORDINPUT_H +#define KEEPASSXC_PASSWORDINPUT_H + +#include + +class PasswordInput +{ +public: + PasswordInput(); + static void setStdinEcho(bool enable); + static QString getPassword(); +}; + +#endif // KEEPASSXC_PASSWORDINPUT_H diff --git a/src/cli/Show.cpp b/src/cli/Show.cpp new file mode 100644 index 0000000000..c212a9d613 --- /dev/null +++ b/src/cli/Show.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "Show.h" + +#include +#include +#include +#include + +#include "core/Database.h" +#include "core/Entry.h" +#include "core/Group.h" +#include "keys/CompositeKey.h" +#include "cli/PasswordInput.h" + +int Show::execute(int argc, char** argv) +{ + QCoreApplication app(argc, argv); + QTextStream out(stdout); + + QCommandLineParser parser; + parser.setApplicationDescription(QCoreApplication::translate("main", "Show a password.")); + parser.addPositionalArgument("database", QCoreApplication::translate("main", "Path of the database.")); + parser.addPositionalArgument("entry", QCoreApplication::translate("main", "Name of the entry to show.")); + parser.process(app); + + const QStringList args = parser.positionalArguments(); + if (args.size() != 2) { + parser.showHelp(EXIT_FAILURE); + } + + out << "Insert the database password\n> "; + out.flush(); + + QString line = PasswordInput::getPassword(); + CompositeKey key = CompositeKey::readFromLine(line); + + Database* db = Database::openDatabaseFile(args.at(0), key); + if (db == nullptr) { + return EXIT_FAILURE; + } + + QString entryId = args.at(1); + Entry* entry = db->rootGroup()->findEntry(entryId); + if (!entry) { + qCritical("Entry %s not found.", qPrintable(entryId)); + return EXIT_FAILURE; + } + + out << entry->password() << "\n"; + return EXIT_SUCCESS; +} diff --git a/src/cli/Show.h b/src/cli/Show.h new file mode 100644 index 0000000000..630b18f80e --- /dev/null +++ b/src/cli/Show.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSXC_SHOW_H +#define KEEPASSXC_SHOW_H + +class Show +{ +public: + static int execute(int argc, char** argv); +}; + +#endif // KEEPASSXC_SHOW_H diff --git a/src/cli/keepassxc-cli.cpp b/src/cli/keepassxc-cli.cpp new file mode 100644 index 0000000000..18bb224ec3 --- /dev/null +++ b/src/cli/keepassxc-cli.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "config-keepassx.h" +#include "core/Tools.h" +#include "crypto/Crypto.h" + +#if defined(WITH_ASAN) && defined(WITH_LSAN) +#include +#endif + +int main(int argc, char** argv) +{ +#ifdef QT_NO_DEBUG + Tools::disableCoreDumps(); +#endif + + if (!Crypto::init()) { + qFatal("Fatal error while testing the cryptographic functions:\n%s", qPrintable(Crypto::errorString())); + return EXIT_FAILURE; + } + + QStringList arguments; + for (int i = 0; i < argc; ++i) { + arguments << QString(argv[i]); + } + QCommandLineParser parser; + + QString description("KeePassXC command line interface."); + description = description.append(QString("\n\nAvailable commands:")); + description = description.append(QString("\n clip\t\tCopy a password to the clipboard.")); + description = description.append(QString("\n extract\tExtract and print the content of a database.")); + description = description.append(QString("\n entropy-meter\tCalculate password entropy.")); + description = description.append(QString("\n list\t\tList database entries.")); + description = description.append(QString("\n merge\t\tMerge two databases.")); + description = description.append(QString("\n show\t\tShow a password.")); + parser.setApplicationDescription(QCoreApplication::translate("main", qPrintable(description))); + + parser.addPositionalArgument("command", QCoreApplication::translate("main", "Name of the command to execute.")); + + parser.addHelpOption(); + parser.addVersionOption(); + // TODO : use the setOptionsAfterPositionalArgumentsMode (Qt 5.6) function + // when available. Until then, options passed to sub-commands won't be + // recognized by this parser. + parser.parse(arguments); + + if (parser.positionalArguments().size() < 1) { + QCoreApplication app(argc, argv); + app.setApplicationVersion(KEEPASSX_VERSION); + if (parser.isSet("version")) { + // Switch to parser.showVersion() when available (QT 5.4). + QTextStream out(stdout); + out << KEEPASSX_VERSION << "\n"; + out.flush(); + return EXIT_SUCCESS; + } + parser.showHelp(); + } + + QString commandName = parser.positionalArguments().at(0); + + int exitCode = EXIT_FAILURE; + + if (commandName == "clip") { + // Removing the first cli argument before dispatching. + ++argv; + --argc; + argv[0] = const_cast("keepassxc-cli clip"); + exitCode = Clip::execute(argc, argv); + } else if (commandName == "entropy-meter") { + ++argv; + --argc; + argv[0] = const_cast("keepassxc-cli entropy-meter"); + exitCode = EntropyMeter::execute(argc, argv); + } else if (commandName == "extract") { + ++argv; + --argc; + argv[0] = const_cast("keepassxc-cli extract"); + exitCode = Extract::execute(argc, argv); + } else if (commandName == "list") { + ++argv; + --argc; + argv[0] = const_cast("keepassxc-cli list"); + exitCode = List::execute(argc, argv); + } else if (commandName == "merge") { + ++argv; + --argc; + argv[0] = const_cast("keepassxc-cli merge"); + exitCode = Merge::execute(argc, argv); + } else if (commandName == "show") { + ++argv; + --argc; + argv[0] = const_cast("keepassxc-cli show"); + exitCode = Show::execute(argc, argv); + } else { + qCritical("Invalid command %s.", qPrintable(commandName)); + QCoreApplication app(argc, argv); + app.setApplicationVersion(KEEPASSX_VERSION); + // showHelp exits the application immediately, so we need to set the + // exit code here. + parser.showHelp(EXIT_FAILURE); + } + +#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(); + __lsan_disable(); +#endif + + return exitCode; +} diff --git a/src/core/AutoTypeAssociations.cpp b/src/core/AutoTypeAssociations.cpp index 75d21fe3f8..5ec4eb3b33 100644 --- a/src/core/AutoTypeAssociations.cpp +++ b/src/core/AutoTypeAssociations.cpp @@ -39,29 +39,29 @@ void AutoTypeAssociations::copyDataFrom(const AutoTypeAssociations* other) return; } - Q_EMIT aboutToReset(); + emit aboutToReset(); m_associations = other->m_associations; - Q_EMIT reset(); - Q_EMIT modified(); + emit reset(); + emit modified(); } void AutoTypeAssociations::add(const AutoTypeAssociations::Association& association) { int index = m_associations.size(); - Q_EMIT aboutToAdd(index); + emit aboutToAdd(index); m_associations.append(association); - Q_EMIT added(index); - Q_EMIT modified(); + emit added(index); + emit modified(); } void AutoTypeAssociations::remove(int index) { Q_ASSERT(index >= 0 && index < m_associations.size()); - Q_EMIT aboutToRemove(index); + emit aboutToRemove(index); m_associations.removeAt(index); - Q_EMIT removed(index); - Q_EMIT modified(); + emit removed(index); + emit modified(); } void AutoTypeAssociations::removeEmpty() @@ -81,8 +81,8 @@ void AutoTypeAssociations::update(int index, const AutoTypeAssociations::Associa if (m_associations.at(index) != association) { m_associations[index] = association; - Q_EMIT dataChanged(index); - Q_EMIT modified(); + emit dataChanged(index); + emit modified(); } } diff --git a/src/core/AutoTypeAssociations.h b/src/core/AutoTypeAssociations.h index 491a5db1cc..61ef3fd4a0 100644 --- a/src/core/AutoTypeAssociations.h +++ b/src/core/AutoTypeAssociations.h @@ -48,7 +48,7 @@ class AutoTypeAssociations : public QObject private: QList m_associations; -Q_SIGNALS: +signals: void modified(); void dataChanged(int index); void aboutToAdd(int index); diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 03b5e4755b..5afbfccebf 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +36,16 @@ QVariant Config::get(const QString& key, const QVariant& defaultValue) return m_settings->value(key, defaultValue); } +bool Config::hasAccessError() +{ + return m_settings->status() & QSettings::AccessError; +} + +QString Config::getFileName() +{ + return m_settings->fileName(); +} + void Config::set(const QString& key, const QVariant& value) { m_settings->setValue(key, value); @@ -49,35 +60,43 @@ Config::Config(const QString& fileName, QObject* parent) Config::Config(QObject* parent) : QObject(parent) { - QString userPath; - QString homePath = QDir::homePath(); - -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) - // we can't use QStandardPaths on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME - QByteArray env = qgetenv("XDG_CONFIG_HOME"); - if (env.isEmpty()) { - userPath = homePath; - userPath += "/.config"; + // Check if portable config is present. If not, find it in user's directory + QString portablePath = QCoreApplication::applicationDirPath() + "/keepassxc.ini"; + if (QFile::exists(portablePath)) { + init(portablePath); + } else { + QString userPath; + QString homePath = QDir::homePath(); + + #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) + // we can't use QStandardPaths on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME + QByteArray env = qgetenv("XDG_CONFIG_HOME"); + if (env.isEmpty()) { + userPath = homePath; + userPath += "/.config"; + } else if (env[0] == '/') { + userPath = QFile::decodeName(env); + } else { + userPath = homePath; + userPath += '/'; + userPath += QFile::decodeName(env); + } + + userPath += "/keepassxc/"; + #else + userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); + // storageLocation() appends the application name ("/keepassxc") to the end + userPath += "/"; + #endif + + #ifdef QT_DEBUG + userPath += "keepassxc_debug.ini"; + #else + userPath += "keepassxc.ini"; + #endif + + init(userPath); } - else if (env[0] == '/') { - userPath = QFile::decodeName(env); - } - else { - userPath = homePath; - userPath += '/'; - userPath += QFile::decodeName(env); - } - - userPath += "/keepassxc/"; -#else - userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); - // storageLocation() appends the application name ("/keepassxc") to the end - userPath += "/"; -#endif - - userPath += "keepassxc.ini"; - - init(userPath); } Config::~Config() @@ -95,14 +114,18 @@ void Config::init(const QString& fileName) m_defaults.insert("AutoReloadOnChange", true); m_defaults.insert("AutoSaveOnExit", false); m_defaults.insert("ShowToolbar", true); + m_defaults.insert("SearchLimitGroup", false); m_defaults.insert("MinimizeOnCopy", false); m_defaults.insert("UseGroupIconOnEntryCreation", false); m_defaults.insert("AutoTypeEntryTitleMatch", true); + m_defaults.insert("UseGroupIconOnEntryCreation", true); + m_defaults.insert("IgnoreGroupExpansion", false); m_defaults.insert("security/clearclipboard", true); m_defaults.insert("security/clearclipboardtimeout", 10); m_defaults.insert("security/lockdatabaseidle", false); - m_defaults.insert("security/lockdatabaseidlesec", 10); + m_defaults.insert("security/lockdatabaseidlesec", 240); m_defaults.insert("security/lockdatabaseminimize", false); + m_defaults.insert("security/lockdatabasescreenlock", true); m_defaults.insert("security/passwordsrepeat", false); m_defaults.insert("security/passwordscleartext", false); m_defaults.insert("security/autotypeask", true); diff --git a/src/core/Config.h b/src/core/Config.h index 09aa02fb17..2ee3f4dce0 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,7 +32,9 @@ class Config : public QObject ~Config(); QVariant get(const QString& key); QVariant get(const QString& key, const QVariant& defaultValue); + QString getFileName(); void set(const QString& key, const QVariant& value); + bool hasAccessError(); static Config* instance(); static void createConfigFromFile(const QString& file); diff --git a/src/core/CsvParser.cpp b/src/core/CsvParser.cpp new file mode 100644 index 0000000000..70493804ec --- /dev/null +++ b/src/core/CsvParser.cpp @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2016 Enrico Mariotti + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CsvParser.h" + +#include +#include + +#include "core/Tools.h" + +CsvParser::CsvParser() + : m_ch(0) + , m_comment('#') + , m_currCol(1) + , m_currRow(1) + , m_isBackslashSyntax(false) + , m_isEof(false) + , m_isFileLoaded(false) + , m_isGood(true) + , m_lastPos(-1) + , m_maxCols(0) + , m_qualifier('"') + , m_separator(',') + , m_statusMsg("") +{ + m_csv.setBuffer(&m_array); + m_ts.setDevice(&m_csv); + m_csv.open(QIODevice::ReadOnly); + m_ts.setCodec("UTF-8"); +} + +CsvParser::~CsvParser() { + m_csv.close(); +} + +bool CsvParser::isFileLoaded() { + return m_isFileLoaded; +} + +bool CsvParser::reparse() { + reset(); + return parseFile(); +} + + +bool CsvParser::parse(QFile *device) { + clear(); + if (nullptr == device) { + appendStatusMsg(QObject::tr("NULL device"), true); + return false; + } + if (!readFile(device)) + return false; + return parseFile(); +} + +bool CsvParser::readFile(QFile *device) { + if (device->isOpen()) + device->close(); + + device->open(QIODevice::ReadOnly); + if (!Tools::readAllFromDevice(device, m_array)) { + appendStatusMsg(QObject::tr("error reading from device"), true); + m_isFileLoaded = false; + } + else { + device->close(); + + m_array.replace("\r\n", "\n"); + m_array.replace("\r", "\n"); + if (0 == m_array.size()) + appendStatusMsg(QObject::tr("file empty !\n")); + m_isFileLoaded = true; + } + return m_isFileLoaded; +} + +void CsvParser::reset() { + m_ch = 0; + m_currCol = 1; + m_currRow = 1; + m_isEof = false; + m_isGood = true; + m_lastPos = -1; + m_maxCols = 0; + m_statusMsg = ""; + m_ts.seek(0); + m_table.clear(); + //the following are users' concern :) + //m_comment = '#'; + //m_backslashSyntax = false; + //m_comment = '#'; + //m_qualifier = '"'; + //m_separator = ','; +} + +void CsvParser::clear() { + reset(); + m_isFileLoaded = false; + m_array.clear(); +} + +bool CsvParser::parseFile() { + parseRecord(); + while (!m_isEof) { + if (!skipEndline()) + appendStatusMsg(QObject::tr("malformed string"), true); + m_currRow++; + m_currCol = 1; + parseRecord(); + } + fillColumns(); + return m_isGood; +} + +void CsvParser::parseRecord() { + CsvRow row; + if (isComment()) { + skipLine(); + return; + } + do { + parseField(row); + getChar(m_ch); + } while (isSeparator(m_ch) && !m_isEof); + + if (!m_isEof) + ungetChar(); + if (isEmptyRow(row)) { + row.clear(); + return; + } + m_table.push_back(row); + if (m_maxCols < row.size()) + m_maxCols = row.size(); + m_currCol++; +} + +void CsvParser::parseField(CsvRow& row) { + QString field; + peek(m_ch); + if (!isTerminator(m_ch)) { + if (isQualifier(m_ch)) + parseQuoted(field); + else + parseSimple(field); + } + row.push_back(field); +} + +void CsvParser::parseSimple(QString &s) { + QChar c; + getChar(c); + while ((isText(c)) && (!m_isEof)) { + s.append(c); + getChar(c); + } + if (!m_isEof) + ungetChar(); +} + +void CsvParser::parseQuoted(QString &s) { + //read and discard initial qualifier (e.g. quote) + getChar(m_ch); + parseEscaped(s); + //getChar(m_ch); + if (!isQualifier(m_ch)) + appendStatusMsg(QObject::tr("missing closing quote"), true); +} + +void CsvParser::parseEscaped(QString &s) { + parseEscapedText(s); + while (processEscapeMark(s, m_ch)) + parseEscapedText(s); + if (!m_isEof) + ungetChar(); +} + +void CsvParser::parseEscapedText(QString &s) { + getChar(m_ch); + while ((!isQualifier(m_ch)) && !m_isEof) { + s.append(m_ch); + getChar(m_ch); + } +} + +bool CsvParser::processEscapeMark(QString &s, QChar c) { + QChar buf; + peek(buf); + QChar c2; + if (true == m_isBackslashSyntax) { + //escape-character syntax, e.g. \" + if (c != '\\') { + return false; + } + //consume (and append) second qualifier + getChar(c2); + if (m_isEof) { + c2='\\'; + s.append('\\'); + return false; + } else { + s.append(c2); + return true; + } + } else { + //double quote syntax, e.g. "" + if (!isQualifier(c)) + return false; + peek(c2); + if (!m_isEof) { //not EOF, can read one char + if (isQualifier(c2)) { + s.append(c2); + getChar(c2); + return true; + } + } + return false; + } +} + +void CsvParser::fillColumns() { + //fill shorter rows with empty placeholder columns + for (int i = 0; i < m_table.size(); ++i) { + int gap = m_maxCols-m_table.at(i).size(); + if (gap > 0) { + CsvRow r = m_table.at(i); + for (int j = 0; j < gap; ++j) { + r.append(QString("")); + } + m_table.replace(i, r); + } + } +} + +void CsvParser::skipLine() { + m_ts.readLine(); + m_ts.seek(m_ts.pos() - 1); +} + +bool CsvParser::skipEndline() { + getChar(m_ch); + return (m_ch == '\n'); +} + + +void CsvParser::getChar(QChar& c) { + m_isEof = m_ts.atEnd(); + if (!m_isEof) { + m_lastPos = m_ts.pos(); + m_ts >> c; + } +} + +void CsvParser::ungetChar() { + if (!m_ts.seek(m_lastPos)) + appendStatusMsg(QObject::tr("INTERNAL - unget lower bound exceeded"), true); +} + +void CsvParser::peek(QChar& c) { + getChar(c); + if (!m_isEof) + ungetChar(); +} + +bool CsvParser::isQualifier(const QChar &c) const { + if (true == m_isBackslashSyntax && (c != m_qualifier)) + return (c == '\\'); + else + return (c == m_qualifier); +} + +bool CsvParser::isComment() { + bool result = false; + QChar c2; + qint64 pos = m_ts.pos(); + + do getChar(c2); + while ((isSpace(c2) || isTab(c2)) && (!m_isEof)); + + if (c2 == m_comment) + result = true; + m_ts.seek(pos); + return result; +} + +bool CsvParser::isText(QChar c) const { + return !( (isCRLF(c)) || (isSeparator(c)) ); +} + +bool CsvParser::isEmptyRow(CsvRow row) const { + CsvRow::const_iterator it = row.constBegin(); + for (; it != row.constEnd(); ++it) + if ( ((*it) != "\n") && ((*it) != "") ) + return false; + return true; +} + +bool CsvParser::isCRLF(const QChar &c) const { + return (c == '\n'); +} + +bool CsvParser::isSpace(const QChar &c) const { + return (c == ' '); +} + +bool CsvParser::isTab(const QChar &c) const { + return (c == '\t'); +} + +bool CsvParser::isSeparator(const QChar &c) const { + return (c == m_separator); +} + +bool CsvParser::isTerminator(const QChar &c) const { + return (isSeparator(c) || (c == '\n') || (c == '\r')); +} + +void CsvParser::setBackslashSyntax(bool set) { + m_isBackslashSyntax = set; +} + +void CsvParser::setComment(const QChar &c) { + m_comment = c.unicode(); +} + +void CsvParser::setCodec(const QString &s) { + m_ts.setCodec(QTextCodec::codecForName(s.toLocal8Bit())); +} + +void CsvParser::setFieldSeparator(const QChar &c) { + m_separator = c.unicode(); +} + +void CsvParser::setTextQualifier(const QChar &c) { + m_qualifier = c.unicode(); +} + +int CsvParser::getFileSize() const { + return m_csv.size(); +} + +const CsvTable CsvParser::getCsvTable() const { + return m_table; +} + +QString CsvParser::getStatus() const { + return m_statusMsg; +} + +int CsvParser::getCsvCols() const { + if ((m_table.size() > 0) && (m_table.at(0).size() > 0)) + return m_table.at(0).size(); + else return 0; +} + +int CsvParser::getCsvRows() const { + return m_table.size(); +} + + +void CsvParser::appendStatusMsg(QString s, bool isCritical) { + m_statusMsg += s + .append(": (row,col) " + QString::number(m_currRow)) + .append(",") + .append(QString::number(m_currCol)) + .append("\n"); + m_isGood = not isCritical; +} diff --git a/src/core/CsvParser.h b/src/core/CsvParser.h new file mode 100644 index 0000000000..3ab31bf676 --- /dev/null +++ b/src/core/CsvParser.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2016 Enrico Mariotti + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_CSVPARSER_H +#define KEEPASSX_CSVPARSER_H + +#include +#include +#include +#include + +typedef QStringList CsvRow; +typedef QList CsvTable; + +class CsvParser { + +public: + CsvParser(); + ~CsvParser(); + //read data from device and parse it + bool parse(QFile *device); + bool isFileLoaded(); + //reparse the same buffer (device is not opened again) + bool reparse(); + void setCodec(const QString &s); + void setComment(const QChar &c); + void setFieldSeparator(const QChar &c); + void setTextQualifier(const QChar &c); + void setBackslashSyntax(bool set); + int getFileSize() const; + int getCsvRows() const; + int getCsvCols() const; + QString getStatus() const; + const CsvTable getCsvTable() const; + +protected: + CsvTable m_table; + +private: + QByteArray m_array; + QBuffer m_csv; + QChar m_ch; + QChar m_comment; + unsigned int m_currCol; + unsigned int m_currRow; + bool m_isBackslashSyntax; + bool m_isEof; + bool m_isFileLoaded; + bool m_isGood; + qint64 m_lastPos; + int m_maxCols; + QChar m_qualifier; + QChar m_separator; + QString m_statusMsg; + QTextStream m_ts; + + void getChar(QChar &c); + void ungetChar(); + void peek(QChar &c); + void fillColumns(); + bool isTerminator(const QChar &c) const; + bool isSeparator(const QChar &c) const; + bool isQualifier(const QChar &c) const; + bool processEscapeMark(QString &s, QChar c); + bool isText(QChar c) const; + bool isComment(); + bool isCRLF(const QChar &c) const; + bool isSpace(const QChar &c) const; + bool isTab(const QChar &c) const; + bool isEmptyRow(CsvRow row) const; + bool parseFile(); + void parseRecord(); + void parseField(CsvRow &row); + void parseSimple(QString &s); + void parseQuoted(QString &s); + void parseEscaped(QString &s); + void parseEscapedText(QString &s); + bool readFile(QFile *device); + void reset(); + void clear(); + bool skipEndline(); + void skipLine(); + void appendStatusMsg(QString s, bool isCritical = false); +}; + +#endif //CSVPARSER_H + diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 3368203818..d1c0fea4d2 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,13 +19,18 @@ #include "Database.h" #include +#include +#include #include #include +#include "cli/PasswordInput.h" #include "core/Group.h" #include "core/Metadata.h" #include "crypto/Random.h" #include "format/KeePass2.h" +#include "format/KeePass2Reader.h" +#include "format/KeePass2Writer.h" QHash Database::m_uuidMap; @@ -176,6 +182,17 @@ QByteArray Database::transformedMasterKey() const return m_data.transformedMasterKey; } +QByteArray Database::challengeResponseKey() const +{ + return m_data.challengeResponseKey; +} + +bool Database::challengeMasterSeed(const QByteArray& masterSeed) +{ + m_data.masterSeed = masterSeed; + return m_data.key.challenge(masterSeed, m_data.challengeResponseKey); +} + void Database::setCipher(const Uuid& cipher) { Q_ASSERT(!cipher.isNull()); @@ -208,14 +225,12 @@ bool Database::setTransformRounds(quint64 rounds) return true; } -bool Database::setKey(const CompositeKey& key, const QByteArray& transformSeed, - bool updateChangedTime) +bool Database::setKey(const CompositeKey& key, const QByteArray& transformSeed, bool updateChangedTime) { bool ok; QString errorString; - QByteArray transformedMasterKey = - key.transform(transformSeed, transformRounds(), &ok, &errorString); + QByteArray transformedMasterKey = key.transform(transformSeed, transformRounds(), &ok, &errorString); if (!ok) { return false; } @@ -227,7 +242,7 @@ bool Database::setKey(const CompositeKey& key, const QByteArray& transformSeed, if (updateChangedTime) { m_metadata->setMasterKeyChanged(QDateTime::currentDateTimeUtc()); } - Q_EMIT modifiedImmediate(); + emit modifiedImmediate(); return true; } @@ -246,6 +261,20 @@ bool Database::verifyKey(const CompositeKey& key) const { Q_ASSERT(hasKey()); + if (!m_data.challengeResponseKey.isEmpty()) { + QByteArray result; + + if (!key.challenge(m_data.masterSeed, result)) { + // challenge failed, (YubiKey?) removed? + return false; + } + + if (m_data.challengeResponseKey != result) { + // wrong response from challenged device(s) + return false; + } + } + return (m_data.key.rawKey() == key.rawKey()); } @@ -263,29 +292,43 @@ void Database::recycleEntry(Entry* entry) createRecycleBin(); } entry->setGroup(metadata()->recycleBin()); - } - else { + } else { delete entry; } } void Database::recycleGroup(Group* group) { - if (m_metadata->recycleBinEnabled()) { + if (m_metadata->recycleBinEnabled()) { if (!m_metadata->recycleBin()) { createRecycleBin(); } group->setParent(metadata()->recycleBin()); - } - else { + } else { delete group; - } + } +} + +void Database::emptyRecycleBin() +{ + if (m_metadata->recycleBinEnabled() && m_metadata->recycleBin()) { + // destroying direct entries of the recycle bin + QList subEntries = m_metadata->recycleBin()->entries(); + for (Entry* entry : subEntries) { + delete entry; + } + // destroying direct subgroups of the recycle bin + QList subGroups = m_metadata->recycleBin()->children(); + for (Group* group : subGroups) { + delete group; + } + } } void Database::merge(const Database* other) { m_rootGroup->merge(other->rootGroup()); - Q_EMIT modified(); + emit modified(); } void Database::setEmitModified(bool value) @@ -325,8 +368,67 @@ void Database::startModifiedTimer() m_timer->start(150); } -const CompositeKey & Database::key() const +const CompositeKey& Database::key() const { return m_data.key; } +Database* Database::openDatabaseFile(QString fileName, CompositeKey key) +{ + + QFile dbFile(fileName); + if (!dbFile.exists()) { + qCritical("File %s does not exist.", qPrintable(fileName)); + return nullptr; + } + if (!dbFile.open(QIODevice::ReadOnly)) { + qCritical("Unable to open file %s.", qPrintable(fileName)); + return nullptr; + } + + KeePass2Reader reader; + Database* db = reader.readDatabase(&dbFile, key); + + if (reader.hasError()) { + qCritical("Error while parsing the database: %s", qPrintable(reader.errorString())); + return nullptr; + } + + return db; +} + +Database* Database::unlockFromStdin(QString databaseFilename) +{ + QTextStream outputTextStream(stdout); + + outputTextStream << QString("Insert password to unlock " + databaseFilename + "\n> "); + outputTextStream.flush(); + + QString line = PasswordInput::getPassword(); + CompositeKey key = CompositeKey::readFromLine(line); + return Database::openDatabaseFile(databaseFilename, key); +} + +QString Database::saveToFile(QString filePath) +{ + KeePass2Writer writer; + QSaveFile saveFile(filePath); + if (saveFile.open(QIODevice::WriteOnly)) { + + // write the database to the file + writer.writeDatabase(&saveFile, this); + + if (writer.hasError()) { + return writer.errorString(); + } + + if (saveFile.commit()) { + // successfully saved database file + return QString(); + } else { + return saveFile.errorString(); + } + } else { + return saveFile.errorString(); + } +} diff --git a/src/core/Database.h b/src/core/Database.h index 3cd5ed1b17..a799e0b3bf 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,6 +60,8 @@ class Database : public QObject QByteArray transformedMasterKey; CompositeKey key; bool hasKey; + QByteArray masterSeed; + QByteArray challengeResponseKey; }; Database(); @@ -88,7 +91,9 @@ class Database : public QObject QByteArray transformSeed() const; quint64 transformRounds() const; QByteArray transformedMasterKey() const; - const CompositeKey & key() const; + const CompositeKey& key() const; + QByteArray challengeResponseKey() const; + bool challengeMasterSeed(const QByteArray& masterSeed); void setCipher(const Uuid& cipher); void setCompressionAlgo(Database::CompressionAlgorithm algo); @@ -104,9 +109,11 @@ class Database : public QObject bool verifyKey(const CompositeKey& key) const; void recycleEntry(Entry* entry); void recycleGroup(Group* group); + void emptyRecycleBin(); void setEmitModified(bool value); void copyAttributesFrom(const Database* other); void merge(const Database* other); + QString saveToFile(QString filePath); /** * Returns a unique id that is only valid as long as the Database exists. @@ -114,8 +121,10 @@ class Database : public QObject Uuid uuid(); static Database* databaseByUuid(const Uuid& uuid); + static Database* openDatabaseFile(QString fileName, CompositeKey key); + static Database* unlockFromStdin(QString databaseFilename); -Q_SIGNALS: +signals: void groupDataChanged(Group* group); void groupAboutToAdd(Group* group, int index); void groupAdded(); @@ -127,7 +136,7 @@ class Database : public QObject void modified(); void modifiedImmediate(); -private Q_SLOTS: +private slots: void startModifiedTimer(); private: diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 46e2670ac8..a8cc6d3b79 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -14,13 +15,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - #include "Entry.h" #include "core/Database.h" #include "core/DatabaseIcons.h" #include "core/Group.h" #include "core/Metadata.h" +#include "totp/totp.h" const int Entry::DefaultIconNumber = 0; @@ -35,6 +36,8 @@ Entry::Entry() m_data.iconNumber = DefaultIconNumber; m_data.autoTypeEnabled = true; m_data.autoTypeObfuscation = 0; + m_data.totpStep = QTotp::defaultStep; + m_data.totpDigits = QTotp::defaultDigits; connect(m_attributes, SIGNAL(modified()), this, SIGNAL(modified())); connect(m_attributes, SIGNAL(defaultKeyModified()), SLOT(emitDataChanged())); @@ -62,7 +65,7 @@ template inline bool Entry::set(T& property, const T& value) { if (property != value) { property = value; - Q_EMIT modified(); + emit modified(); return true; } else { @@ -254,6 +257,17 @@ bool Entry::isExpired() const return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc(); } +bool Entry::hasReferences() const +{ + const QList keyList = EntryAttributes::DefaultAttributes; + for (const QString& key : keyList) { + if (m_attributes->isReference(key)) { + return true; + } + } + return false; +} + EntryAttributes* Entry::attributes() { return m_attributes; @@ -274,6 +288,77 @@ const EntryAttachments* Entry::attachments() const return m_attachments; } +bool Entry::hasTotp() const +{ + return m_attributes->hasKey("TOTP Seed") || m_attributes->hasKey("otp"); +} + +QString Entry::totp() const +{ + if (hasTotp()) { + QString seed = totpSeed(); + quint64 time = QDateTime::currentDateTime().toTime_t(); + QString output = QTotp::generateTotp(seed.toLatin1(), time, m_data.totpDigits, m_data.totpStep); + + return QString(output); + } else { + return QString(""); + } +} + +void Entry::setTotp(const QString& seed, quint8& step, quint8& digits) +{ + if (step == 0) { + step = QTotp::defaultStep; + } + + if (digits == 0) { + digits = QTotp::defaultDigits; + } + + if (m_attributes->hasKey("otp")) { + m_attributes->set("otp", QString("key=%1&step=%2&size=%3").arg(seed).arg(step).arg(digits), true); + } else { + m_attributes->set("TOTP Seed", seed, true); + m_attributes->set("TOTP Settings", QString("%1;%2").arg(step).arg(digits)); + } +} + +QString Entry::totpSeed() const +{ + QString secret = ""; + + if (m_attributes->hasKey("otp")) { + secret = m_attributes->value("otp"); + } else if (m_attributes->hasKey("TOTP Seed")) { + secret = m_attributes->value("TOTP Seed"); + } + + m_data.totpDigits = QTotp::defaultDigits; + m_data.totpStep = QTotp::defaultStep; + + if (m_attributes->hasKey("TOTP Settings")) { + QRegExp rx("(\\d+);(\\d)", Qt::CaseInsensitive, QRegExp::RegExp); + int pos = rx.indexIn(m_attributes->value("TOTP Settings")); + if (pos > -1) { + m_data.totpStep = rx.cap(1).toUInt(); + m_data.totpDigits = rx.cap(2).toUInt(); + } + } + + return QTotp::parseOtpString(secret, m_data.totpDigits, m_data.totpStep); +} + +quint8 Entry::totpStep() const +{ + return m_data.totpStep; +} + +quint8 Entry::totpDigits() const +{ + return m_data.totpDigits; +} + void Entry::setUuid(const Uuid& uuid) { Q_ASSERT(!uuid.isNull()); @@ -288,7 +373,7 @@ void Entry::setIcon(int iconNumber) m_data.iconNumber = iconNumber; m_data.customIcon = Uuid(); - Q_EMIT modified(); + emit modified(); emitDataChanged(); } } @@ -301,7 +386,7 @@ void Entry::setIcon(const Uuid& uuid) m_data.customIcon = uuid; m_data.iconNumber = 0; - Q_EMIT modified(); + emit modified(); emitDataChanged(); } } @@ -381,7 +466,7 @@ void Entry::setExpires(const bool& value) { if (m_data.timeInfo.expires() != value) { m_data.timeInfo.setExpires(value); - Q_EMIT modified(); + emit modified(); } } @@ -389,7 +474,7 @@ void Entry::setExpiryTime(const QDateTime& dateTime) { if (m_data.timeInfo.expiryTime() != dateTime) { m_data.timeInfo.setExpiryTime(dateTime); - Q_EMIT modified(); + emit modified(); } } @@ -408,7 +493,7 @@ void Entry::addHistoryItem(Entry* entry) Q_ASSERT(!entry->parent()); m_history.append(entry); - Q_EMIT modified(); + emit modified(); } void Entry::removeHistoryItems(const QList& historyEntries) @@ -426,7 +511,7 @@ void Entry::removeHistoryItems(const QList& historyEntries) delete entry; } - Q_EMIT modified(); + emit modified(); } void Entry::truncateHistory() @@ -494,6 +579,18 @@ Entry* Entry::clone(CloneFlags flags) const entry->m_data = m_data; entry->m_attributes->copyDataFrom(m_attributes); entry->m_attachments->copyDataFrom(m_attachments); + + if (flags & CloneUserAsRef) { + // Build the username refrence + QString username = "{REF:U@I:" + m_uuid.toHex() + "}"; + entry->m_attributes->set(EntryAttributes::UserNameKey, username.toUpper(), m_attributes->isProtected(EntryAttributes::UserNameKey)); + } + + if (flags & ClonePassAsRef) { + QString password = "{REF:P@I:" + m_uuid.toHex() + "}"; + entry->m_attributes->set(EntryAttributes::PasswordKey, password.toUpper(), m_attributes->isProtected(EntryAttributes::PasswordKey)); + } + entry->m_autoTypeAssociations->copyDataFrom(this->m_autoTypeAssociations); if (flags & CloneIncludeHistory) { for (Entry* historyItem : m_history) { @@ -610,7 +707,7 @@ void Entry::setGroup(Group* group) void Entry::emitDataChanged() { - Q_EMIT dataChanged(this); + emit dataChanged(this); } const Database* Entry::database() const @@ -626,7 +723,8 @@ const Database* Entry::database() const QString Entry::resolveMultiplePlaceholders(const QString& str) const { QString result = str; - QRegExp tmplRegEx("({.*})", Qt::CaseInsensitive, QRegExp::RegExp2); + QRegExp tmplRegEx("(\\{.*\\})", Qt::CaseInsensitive, QRegExp::RegExp2); + tmplRegEx.setMinimal(true); QStringList tmplList; int pos = 0; @@ -646,17 +744,43 @@ QString Entry::resolvePlaceholder(const QString& str) const const QList keyList = attributes()->keys(); for (const QString& key : keyList) { Qt::CaseSensitivity cs = Qt::CaseInsensitive; + QString k = key; + if (!EntryAttributes::isDefaultAttribute(key)) { cs = Qt::CaseSensitive; + k.prepend("{S:"); + } else { + k.prepend("{"); } - QString k = key; - k.prepend("{").append("}"); + + k.append("}"); if (result.compare(k,cs)==0) { result.replace(result,attributes()->value(key)); break; } } + // resolving references in format: {REF:@I:} + // using format from http://keepass.info/help/base/fieldrefs.html at the time of writing, + // but supporting lookups of standard fields and references by UUID only + + QRegExp* tmpRegExp = m_attributes->referenceRegExp(); + if (tmpRegExp->indexIn(result) != -1) { + // cap(0) contains the whole reference + // cap(1) contains which field is wanted + // cap(2) contains the uuid of the referenced entry + Entry* tmpRefEntry = m_group->database()->resolveEntry(Uuid(QByteArray::fromHex(tmpRegExp->cap(2).toLatin1()))); + if (tmpRefEntry) { + // entry found, get the relevant field + QString tmpRefField = tmpRegExp->cap(1).toLower(); + if (tmpRefField == "t") result.replace(tmpRegExp->cap(0), tmpRefEntry->title(), Qt::CaseInsensitive); + else if (tmpRefField == "u") result.replace(tmpRegExp->cap(0), tmpRefEntry->username(), Qt::CaseInsensitive); + else if (tmpRefField == "p") result.replace(tmpRegExp->cap(0), tmpRefEntry->password(), Qt::CaseInsensitive); + else if (tmpRefField == "a") result.replace(tmpRegExp->cap(0), tmpRefEntry->url(), Qt::CaseInsensitive); + else if (tmpRefField == "n") result.replace(tmpRegExp->cap(0), tmpRefEntry->notes(), Qt::CaseInsensitive); + } + } + return result; } diff --git a/src/core/Entry.h b/src/core/Entry.h index ae60b596cb..91a0012a12 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,6 +48,8 @@ struct EntryData int autoTypeObfuscation; QString defaultAutoTypeSequence; TimeInfo timeInfo; + mutable quint8 totpDigits; + mutable quint8 totpStep; }; class Entry : public QObject @@ -78,7 +81,14 @@ class Entry : public QObject QString username() const; QString password() const; QString notes() const; + QString totp() const; + QString totpSeed() const; + quint8 totpDigits() const; + quint8 totpStep() const; + + bool hasTotp() const; bool isExpired() const; + bool hasReferences() const; EntryAttributes* attributes(); const EntryAttributes* attributes() const; EntryAttachments* attachments(); @@ -104,6 +114,7 @@ class Entry : public QObject void setNotes(const QString& notes); void setExpires(const bool& value); void setExpiryTime(const QDateTime& dateTime); + void setTotp(const QString& seed, quint8& step, quint8& digits); QList historyItems(); const QList& historyItems() const; @@ -113,10 +124,12 @@ class Entry : public QObject enum CloneFlag { CloneNoFlags = 0, - CloneNewUuid = 1, // generate a random uuid for the clone - CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time - CloneIncludeHistory = 4, // clone the history items - CloneRenameTitle = 8 // add "-Clone" after the original title + CloneNewUuid = 1, // generate a random uuid for the clone + CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time + CloneIncludeHistory = 4, // clone the history items + CloneRenameTitle = 8, // add "-Clone" after the original title + CloneUserAsRef = 16, // Add the user as a refrence to the origional entry + ClonePassAsRef = 32, // Add the password as a refrence to the origional entry }; Q_DECLARE_FLAGS(CloneFlags, CloneFlag) @@ -144,7 +157,7 @@ class Entry : public QObject void setUpdateTimeinfo(bool value); -Q_SIGNALS: +signals: /** * Emitted when a default attribute has been changed. */ @@ -152,7 +165,7 @@ class Entry : public QObject void modified(); -private Q_SLOTS: +private slots: void emitDataChanged(); void updateTimeinfo(); void updateModifiedSinceBegin(); diff --git a/src/core/EntryAttachments.cpp b/src/core/EntryAttachments.cpp index 7bd080bfac..a53a3c997f 100644 --- a/src/core/EntryAttachments.cpp +++ b/src/core/EntryAttachments.cpp @@ -48,7 +48,7 @@ void EntryAttachments::set(const QString& key, const QByteArray& value) bool addAttachment = !m_attachments.contains(key); if (addAttachment) { - Q_EMIT aboutToBeAdded(key); + emit aboutToBeAdded(key); } if (addAttachment || m_attachments.value(key) != value) { @@ -57,14 +57,14 @@ void EntryAttachments::set(const QString& key, const QByteArray& value) } if (addAttachment) { - Q_EMIT added(key); + emit added(key); } else { - Q_EMIT keyModified(key); + emit keyModified(key); } if (emitModified) { - Q_EMIT modified(); + emit modified(); } } @@ -75,12 +75,12 @@ void EntryAttachments::remove(const QString& key) return; } - Q_EMIT aboutToBeRemoved(key); + emit aboutToBeRemoved(key); m_attachments.remove(key); - Q_EMIT removed(key); - Q_EMIT modified(); + emit removed(key); + emit modified(); } void EntryAttachments::clear() @@ -89,23 +89,23 @@ void EntryAttachments::clear() return; } - Q_EMIT aboutToBeReset(); + emit aboutToBeReset(); m_attachments.clear(); - Q_EMIT reset(); - Q_EMIT modified(); + emit reset(); + emit modified(); } void EntryAttachments::copyDataFrom(const EntryAttachments* other) { if (*this != *other) { - Q_EMIT aboutToBeReset(); + emit aboutToBeReset(); m_attachments = other->m_attachments; - Q_EMIT reset(); - Q_EMIT modified(); + emit reset(); + emit modified(); } } diff --git a/src/core/EntryAttachments.h b/src/core/EntryAttachments.h index 903ca10bb8..04c22cb34c 100644 --- a/src/core/EntryAttachments.h +++ b/src/core/EntryAttachments.h @@ -38,7 +38,7 @@ class EntryAttachments : public QObject bool operator==(const EntryAttachments& other) const; bool operator!=(const EntryAttachments& other) const; -Q_SIGNALS: +signals: void modified(); void keyModified(const QString& key); void aboutToBeAdded(const QString& key); diff --git a/src/core/EntryAttributes.cpp b/src/core/EntryAttributes.cpp index b633cae328..a5143aa04f 100644 --- a/src/core/EntryAttributes.cpp +++ b/src/core/EntryAttributes.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +29,7 @@ const QString EntryAttributes::RememberCmdExecAttr = "_EXEC_CMD"; EntryAttributes::EntryAttributes(QObject* parent) : QObject(parent) + , m_referenceRegExp("\\{REF:([TUPAN])@I:([^}]+)\\}", Qt::CaseInsensitive, QRegExp::RegExp2) { clear(); } @@ -69,6 +71,25 @@ bool EntryAttributes::isProtected(const QString& key) const return m_protectedAttributes.contains(key); } +bool EntryAttributes::isReference(const QString& key) const +{ + if (!m_attributes.contains(key)) { + Q_ASSERT(false); + return false; + } + + QString data = value(key); + if (m_referenceRegExp.indexIn(data) != -1) { + return true; + } + return false; +} + +QRegExp* EntryAttributes::referenceRegExp() +{ + return &m_referenceRegExp; +} + void EntryAttributes::set(const QString& key, const QString& value, bool protect) { bool emitModified = false; @@ -78,7 +99,7 @@ void EntryAttributes::set(const QString& key, const QString& value, bool protect bool defaultAttribute = isDefaultAttribute(key); if (addAttribute && !defaultAttribute) { - Q_EMIT aboutToBeAdded(key); + emit aboutToBeAdded(key); } if (addAttribute || changeValue) { @@ -97,17 +118,17 @@ void EntryAttributes::set(const QString& key, const QString& value, bool protect } if (emitModified) { - Q_EMIT modified(); + emit modified(); } if (defaultAttribute && changeValue) { - Q_EMIT defaultKeyModified(); + emit defaultKeyModified(); } else if (addAttribute) { - Q_EMIT added(key); + emit added(key); } else if (emitModified) { - Q_EMIT customKeyModified(key); + emit customKeyModified(key); } } @@ -120,13 +141,13 @@ void EntryAttributes::remove(const QString& key) return; } - Q_EMIT aboutToBeRemoved(key); + emit aboutToBeRemoved(key); m_attributes.remove(key); m_protectedAttributes.remove(key); - Q_EMIT removed(key); - Q_EMIT modified(); + emit removed(key); + emit modified(); } void EntryAttributes::rename(const QString& oldKey, const QString& newKey) @@ -147,7 +168,7 @@ void EntryAttributes::rename(const QString& oldKey, const QString& newKey) QString data = value(oldKey); bool protect = isProtected(oldKey); - Q_EMIT aboutToRename(oldKey, newKey); + emit aboutToRename(oldKey, newKey); m_attributes.remove(oldKey); m_attributes.insert(newKey, data); @@ -156,8 +177,8 @@ void EntryAttributes::rename(const QString& oldKey, const QString& newKey) m_protectedAttributes.insert(newKey); } - Q_EMIT modified(); - Q_EMIT renamed(oldKey, newKey); + emit modified(); + emit renamed(oldKey, newKey); } void EntryAttributes::copyCustomKeysFrom(const EntryAttributes* other) @@ -166,7 +187,7 @@ void EntryAttributes::copyCustomKeysFrom(const EntryAttributes* other) return; } - Q_EMIT aboutToBeReset(); + emit aboutToBeReset(); // remove all non-default keys const QList keyList = keys(); @@ -187,8 +208,8 @@ void EntryAttributes::copyCustomKeysFrom(const EntryAttributes* other) } } - Q_EMIT reset(); - Q_EMIT modified(); + emit reset(); + emit modified(); } bool EntryAttributes::areCustomKeysDifferent(const EntryAttributes* other) @@ -215,13 +236,13 @@ bool EntryAttributes::areCustomKeysDifferent(const EntryAttributes* other) void EntryAttributes::copyDataFrom(const EntryAttributes* other) { if (*this != *other) { - Q_EMIT aboutToBeReset(); + emit aboutToBeReset(); m_attributes = other->m_attributes; m_protectedAttributes = other->m_protectedAttributes; - Q_EMIT reset(); - Q_EMIT modified(); + emit reset(); + emit modified(); } } @@ -239,7 +260,7 @@ bool EntryAttributes::operator!=(const EntryAttributes& other) const void EntryAttributes::clear() { - Q_EMIT aboutToBeReset(); + emit aboutToBeReset(); m_attributes.clear(); m_protectedAttributes.clear(); @@ -248,8 +269,8 @@ void EntryAttributes::clear() m_attributes.insert(key, ""); } - Q_EMIT reset(); - Q_EMIT modified(); + emit reset(); + emit modified(); } int EntryAttributes::attributesSize() diff --git a/src/core/EntryAttributes.h b/src/core/EntryAttributes.h index 211b6d483a..40fc5dec43 100644 --- a/src/core/EntryAttributes.h +++ b/src/core/EntryAttributes.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +36,8 @@ class EntryAttributes : public QObject QString value(const QString& key) const; bool contains(const QString& key) const; bool isProtected(const QString& key) const; + bool isReference(const QString& key) const; + QRegExp* referenceRegExp(); void set(const QString& key, const QString& value, bool protect = false); void remove(const QString& key); void rename(const QString& oldKey, const QString& newKey); @@ -55,7 +58,7 @@ class EntryAttributes : public QObject static const QString RememberCmdExecAttr; static bool isDefaultAttribute(const QString& key); -Q_SIGNALS: +signals: void modified(); void defaultKeyModified(); void customKeyModified(const QString& key); @@ -71,6 +74,7 @@ class EntryAttributes : public QObject private: QMap m_attributes; QSet m_protectedAttributes; + QRegExp m_referenceRegExp; }; #endif // KEEPASSX_ENTRYATTRIBUTES_H diff --git a/src/core/EntrySearcher.cpp b/src/core/EntrySearcher.cpp index 01e152e2ab..deaefa1aa9 100644 --- a/src/core/EntrySearcher.cpp +++ b/src/core/EntrySearcher.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Florian Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -68,10 +69,10 @@ QList EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, bool EntrySearcher::wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity) { - return entry->title().contains(word, caseSensitivity) || - entry->username().contains(word, caseSensitivity) || - entry->url().contains(word, caseSensitivity) || - entry->notes().contains(word, caseSensitivity); + return entry->resolvePlaceholder(entry->title()).contains(word, caseSensitivity) || + entry->resolvePlaceholder(entry->username()).contains(word, caseSensitivity) || + entry->resolvePlaceholder(entry->url()).contains(word, caseSensitivity) || + entry->resolvePlaceholder(entry->notes()).contains(word, caseSensitivity); } bool EntrySearcher::matchGroup(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity) diff --git a/src/core/EntrySearcher.h b/src/core/EntrySearcher.h index 4e8d4eabe7..da51eebc71 100644 --- a/src/core/EntrySearcher.h +++ b/src/core/EntrySearcher.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Florian Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/core/FilePath.cpp b/src/core/FilePath.cpp index 0506e3ab73..132fdc0071 100644 --- a/src/core/FilePath.cpp +++ b/src/core/FilePath.cpp @@ -49,7 +49,7 @@ QString FilePath::pluginPath(const QString& name) // for TestAutoType pluginPaths << QCoreApplication::applicationDirPath() + "/../src/autotype/test"; -#if defined(Q_OS_MAC) +#if defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE) pluginPaths << QCoreApplication::applicationDirPath() + "/../PlugIns"; #endif @@ -101,7 +101,7 @@ QIcon FilePath::trayIconLocked() QIcon FilePath::trayIconUnlocked() { - return applicationIcon(); + return icon("apps", "keepassxc-unlocked"); } QIcon FilePath::icon(const QString& category, const QString& name, bool fromTheme) @@ -195,7 +195,7 @@ FilePath::FilePath() else if (testSetDir(QString(KEEPASSX_SOURCE_DIR) + "/share")) { } #endif -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) +#if defined(Q_OS_UNIX) && !(defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE)) else if (isDataDirAbsolute && testSetDir(KEEPASSX_DATA_DIR)) { } else if (!isDataDirAbsolute && testSetDir(QString("%1/../%2").arg(appDirPath, KEEPASSX_DATA_DIR))) { @@ -203,7 +203,7 @@ FilePath::FilePath() else if (!isDataDirAbsolute && testSetDir(QString("%1/%2").arg(KEEPASSX_PREFIX_DIR, KEEPASSX_DATA_DIR))) { } #endif -#ifdef Q_OS_MAC +#if defined(Q_OS_MAC) && defined(WITH_APP_BUNDLE) else if (testSetDir(appDirPath + "/../Resources")) { } #endif diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 8c96bb0743..edbed947e9 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,8 +19,8 @@ #include "Group.h" #include "core/Config.h" -#include "core/Global.h" #include "core/DatabaseIcons.h" +#include "core/Global.h" #include "core/Metadata.h" const int Group::DefaultIconNumber = 48; @@ -74,7 +75,7 @@ template inline bool Group::set(P& property, const V& value) if (property != value) { property = value; updateTimeinfo(); - Q_EMIT modified(); + emit modified(); return true; } else { @@ -202,7 +203,7 @@ QString Group::effectiveAutoTypeSequence() const } while (group && sequence.isEmpty()); if (sequence.isEmpty()) { - sequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}"; + sequence = "{USERNAME}{TAB}{PASSWORD}{ENTER}"; } return sequence; @@ -249,7 +250,7 @@ void Group::setUuid(const Uuid& uuid) void Group::setName(const QString& name) { if (set(m_data.name, name)) { - Q_EMIT dataChanged(this); + emit dataChanged(this); } } @@ -267,8 +268,8 @@ void Group::setIcon(int iconNumber) m_data.customIcon = Uuid(); updateTimeinfo(); - Q_EMIT modified(); - Q_EMIT dataChanged(this); + emit modified(); + emit dataChanged(this); } } @@ -281,8 +282,8 @@ void Group::setIcon(const Uuid& uuid) m_data.iconNumber = 0; updateTimeinfo(); - Q_EMIT modified(); - Q_EMIT dataChanged(this); + emit modified(); + emit dataChanged(this); } } @@ -296,7 +297,10 @@ void Group::setExpanded(bool expanded) if (m_data.isExpanded != expanded) { m_data.isExpanded = expanded; updateTimeinfo(); - Q_EMIT modified(); + if (config()->get("IgnoreGroupExpansion").toBool()) { + return; + } + emit modified(); } } @@ -325,7 +329,7 @@ void Group::setExpires(bool value) if (m_data.timeInfo.expires() != value) { m_data.timeInfo.setExpires(value); updateTimeinfo(); - Q_EMIT modified(); + emit modified(); } } @@ -334,7 +338,7 @@ void Group::setExpiryTime(const QDateTime& dateTime) if (m_data.timeInfo.expiryTime() != dateTime) { m_data.timeInfo.setExpiryTime(dateTime); updateTimeinfo(); - Q_EMIT modified(); + emit modified(); } } @@ -391,12 +395,12 @@ void Group::setParent(Group* parent, int index) recSetDatabase(parent->m_db); } QObject::setParent(parent); - Q_EMIT aboutToAdd(this, index); + emit aboutToAdd(this, index); Q_ASSERT(index <= parent->m_children.size()); parent->m_children.insert(index, this); } else { - Q_EMIT aboutToMove(this, parent, index); + emit aboutToMove(this, parent, index); m_parent->m_children.removeAll(this); m_parent = parent; QObject::setParent(parent); @@ -408,13 +412,13 @@ void Group::setParent(Group* parent, int index) m_data.timeInfo.setLocationChanged(QDateTime::currentDateTimeUtc()); } - Q_EMIT modified(); + emit modified(); if (!moveWithinDatabase) { - Q_EMIT added(); + emit added(); } else { - Q_EMIT moved(); + emit moved(); } } @@ -480,7 +484,34 @@ QList Group::entriesRecursive(bool includeHistoryItems) const return entryList; } -Entry* Group::findEntry(const Uuid& uuid) +Entry* Group::findEntry(QString entryId) +{ + Q_ASSERT(!entryId.isNull()); + + if (Uuid::isUuid(entryId)) { + Uuid entryUuid = Uuid::fromHex(entryId); + for (Entry* entry : entriesRecursive(false)) { + if (entry->uuid() == entryUuid) { + return entry; + } + } + } + + Entry* entry = findEntryByPath(entryId); + if (entry) { + return entry; + } + + for (Entry* entry : entriesRecursive(false)) { + if (entry->title() == entryId) { + return entry; + } + } + + return nullptr; +} + +Entry* Group::findEntryByUuid(const Uuid& uuid) { Q_ASSERT(!uuid.isNull()); for (Entry* entry : asConst(m_entries)) { @@ -492,6 +523,93 @@ Entry* Group::findEntry(const Uuid& uuid) return nullptr; } +Entry* Group::findEntryByPath(QString entryPath, QString basePath) +{ + + Q_ASSERT(!entryPath.isNull()); + + for (Entry* entry : asConst(m_entries)) { + QString currentEntryPath = basePath + entry->title(); + if (entryPath == currentEntryPath || entryPath == QString("/" + currentEntryPath)) { + return entry; + } + } + + for (Group* group : asConst(m_children)) { + Entry* entry = group->findEntryByPath(entryPath, basePath + group->name() + QString("/")); + if (entry != nullptr) { + return entry; + } + } + + return nullptr; +} + +Group* Group::findGroupByPath(QString groupPath, QString basePath) +{ + + Q_ASSERT(!groupPath.isNull()); + + QStringList possiblePaths; + possiblePaths << groupPath; + if (!groupPath.startsWith("/")) { + possiblePaths << QString("/" + groupPath); + } + if (!groupPath.endsWith("/")) { + possiblePaths << QString(groupPath + "/"); + } + if (!groupPath.endsWith("/") && !groupPath.endsWith("/")) { + possiblePaths << QString("/" + groupPath + "/"); + } + + if (possiblePaths.contains(basePath)) { + return this; + } + + for (Group* innerGroup : children()) { + QString innerBasePath = basePath + innerGroup->name() + "/"; + Group* group = innerGroup->findGroupByPath(groupPath, innerBasePath); + if (group != nullptr) { + return group; + } + } + + return nullptr; + +} + +QString Group::print(bool printUuids, QString baseName, int depth) +{ + + QString response; + QString indentation = QString(" ").repeated(depth); + + if (entries().isEmpty() && children().isEmpty()) { + response += indentation + "[empty]\n"; + return response; + } + + for (Entry* entry : entries()) { + response += indentation + entry->title(); + if (printUuids) { + response += " " + entry->uuid().toHex(); + } + response += "\n"; + } + + for (Group* innerGroup : children()) { + QString newBaseName = baseName + innerGroup->name() + "/"; + response += indentation + newBaseName; + if (printUuids) { + response += " " + innerGroup->uuid().toHex(); + } + response += "\n"; + response += innerGroup->print(printUuids, newBaseName, depth + 1); + } + + return response; +} + QList Group::groupsRecursive(bool includeSelf) const { QList groupList; @@ -548,10 +666,10 @@ void Group::merge(const Group* other) const QList dbEntries = other->entries(); for (Entry* entry : dbEntries) { // entries are searched by uuid - if (!findEntry(entry->uuid())) { + if (!findEntryByUuid(entry->uuid())) { entry->clone(Entry::CloneNoFlags)->setGroup(this); } else { - resolveConflict(findEntry(entry->uuid()), entry); + resolveConflict(findEntryByUuid(entry->uuid()), entry); } } @@ -566,7 +684,7 @@ void Group::merge(const Group* other) } } - Q_EMIT modified(); + emit modified(); } Group* Group::findChildByName(const QString& name) @@ -623,7 +741,7 @@ void Group::addEntry(Entry* entry) Q_ASSERT(entry); Q_ASSERT(!m_entries.contains(entry)); - Q_EMIT entryAboutToAdd(entry); + emit entryAboutToAdd(entry); m_entries << entry; connect(entry, SIGNAL(dataChanged(Entry*)), SIGNAL(entryDataChanged(Entry*))); @@ -631,23 +749,23 @@ void Group::addEntry(Entry* entry) connect(entry, SIGNAL(modified()), m_db, SIGNAL(modifiedImmediate())); } - Q_EMIT modified(); - Q_EMIT entryAdded(entry); + emit modified(); + emit entryAdded(entry); } void Group::removeEntry(Entry* entry) { Q_ASSERT(m_entries.contains(entry)); - Q_EMIT entryAboutToRemove(entry); + emit entryAboutToRemove(entry); entry->disconnect(this); if (m_db) { entry->disconnect(m_db); } m_entries.removeAll(entry); - Q_EMIT modified(); - Q_EMIT entryRemoved(entry); + emit modified(); + emit entryRemoved(entry); } void Group::recSetDatabase(Database* db) @@ -693,10 +811,10 @@ void Group::recSetDatabase(Database* db) void Group::cleanupParent() { if (m_parent) { - Q_EMIT aboutToRemove(this); + emit aboutToRemove(this); m_parent->m_children.removeAll(this); - Q_EMIT modified(); - Q_EMIT removed(); + emit modified(); + emit removed(); } } diff --git a/src/core/Group.h b/src/core/Group.h index 3c054f9767..f8c976eeb5 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -78,8 +79,11 @@ class Group : public QObject static const int DefaultIconNumber; static const int RecycleBinIconNumber; - Entry* findEntry(const Uuid& uuid); Group* findChildByName(const QString& name); + Entry* findEntry(QString entryId); + Entry* findEntryByUuid(const Uuid& uuid); + Entry* findEntryByPath(QString entryPath, QString basePath = QString("")); + Group* findGroupByPath(QString groupPath, QString basePath = QString("/")); void setUuid(const Uuid& uuid); void setName(const QString& name); void setNotes(const QString& notes); @@ -121,8 +125,9 @@ class Group : public QObject Group* clone(Entry::CloneFlags entryFlags = Entry::CloneNewUuid | Entry::CloneResetTimeInfo) const; void copyDataFrom(const Group* other); void merge(const Group* other); + QString print(bool printUuids = false, QString baseName = QString(""), int depth = 0); -Q_SIGNALS: +signals: void dataChanged(Group* group); void aboutToAdd(Group* group, int index); diff --git a/src/core/InactivityTimer.cpp b/src/core/InactivityTimer.cpp index dd162e6951..0cfc8f0d44 100644 --- a/src/core/InactivityTimer.cpp +++ b/src/core/InactivityTimer.cpp @@ -73,7 +73,7 @@ void InactivityTimer::timeout() } if (m_active && !m_timer->isActive()) { - Q_EMIT inactivityDetected(); + emit inactivityDetected(); } m_emitMutx.unlock(); diff --git a/src/core/InactivityTimer.h b/src/core/InactivityTimer.h index ba571a5efd..b9de80fb41 100644 --- a/src/core/InactivityTimer.h +++ b/src/core/InactivityTimer.h @@ -33,13 +33,13 @@ class InactivityTimer : public QObject void activate(); void deactivate(); -Q_SIGNALS: +signals: void inactivityDetected(); protected: bool eventFilter(QObject* watched, QEvent* event); -private Q_SLOTS: +private slots: void timeout(); private: diff --git a/src/core/Metadata.cpp b/src/core/Metadata.cpp index bf68af3ca0..a7207b5925 100644 --- a/src/core/Metadata.cpp +++ b/src/core/Metadata.cpp @@ -55,7 +55,7 @@ template bool Metadata::set(P& property, const V& value) { if (property != value) { property = value; - Q_EMIT modified(); + emit modified(); return true; } else { @@ -69,7 +69,7 @@ template bool Metadata::set(P& property, const V& value, QDat if (m_updateDatetime) { dateTime = QDateTime::currentDateTimeUtc(); } - Q_EMIT modified(); + emit modified(); return true; } else { @@ -308,7 +308,7 @@ void Metadata::setGenerator(const QString& value) void Metadata::setName(const QString& value) { if (set(m_data.name, value, m_data.nameChanged)) { - Q_EMIT nameTextChanged(); + emit nameTextChanged(); } } @@ -391,7 +391,7 @@ void Metadata::addCustomIcon(const Uuid& uuid, const QImage& icon) m_customIconScaledCacheKeys[uuid] = QPixmapCache::Key(); m_customIconsOrder.append(uuid); Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count()); - Q_EMIT modified(); + emit modified(); } void Metadata::addCustomIconScaled(const Uuid& uuid, const QImage& icon) @@ -422,7 +422,7 @@ void Metadata::removeCustomIcon(const Uuid& uuid) m_customIconScaledCacheKeys.remove(uuid); m_customIconsOrder.removeAll(uuid); Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count()); - Q_EMIT modified(); + emit modified(); } void Metadata::copyCustomIcons(const QSet& iconList, const Metadata* otherMetadata) @@ -504,7 +504,7 @@ void Metadata::addCustomField(const QString& key, const QString& value) Q_ASSERT(!m_customFields.contains(key)); m_customFields.insert(key, value); - Q_EMIT modified(); + emit modified(); } void Metadata::removeCustomField(const QString& key) @@ -512,5 +512,5 @@ void Metadata::removeCustomField(const QString& key) Q_ASSERT(m_customFields.contains(key)); m_customFields.remove(key); - Q_EMIT modified(); + emit modified(); } diff --git a/src/core/Metadata.h b/src/core/Metadata.h index c35aed39bc..4f435d7593 100644 --- a/src/core/Metadata.h +++ b/src/core/Metadata.h @@ -146,7 +146,7 @@ class Metadata : public QObject */ void copyAttributesFrom(const Metadata* other); -Q_SIGNALS: +signals: void nameTextChanged(); void modified(); diff --git a/src/core/PassphraseGenerator.cpp b/src/core/PassphraseGenerator.cpp new file mode 100644 index 0000000000..1af6147955 --- /dev/null +++ b/src/core/PassphraseGenerator.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "PassphraseGenerator.h" + +#include +#include +#include + +#include "crypto/Random.h" +#include "core/FilePath.h" + +PassphraseGenerator::PassphraseGenerator() + : m_wordCount(0) + , m_separator(' ') +{ + const QString path = filePath()->dataPath("wordlists/eff_large.wordlist"); + setWordList(path); +} + +double PassphraseGenerator::calculateEntropy(QString passphrase) +{ + Q_UNUSED(passphrase); + + if (m_wordlist.size() == 0) { + return 0; + } + + return log(m_wordlist.size()) / log(2.0) * m_wordCount; +} + +void PassphraseGenerator::setWordCount(int wordCount) +{ + if (wordCount > 0) { + m_wordCount = wordCount; + } else { + // safe default if something goes wrong + m_wordCount = 7; + } + +} + +void PassphraseGenerator::setWordList(QString path) +{ + m_wordlist.clear(); + + QFile file(path); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning("Couldn't load passphrase wordlist."); + return; + } + + QTextStream in(&file); + while (!in.atEnd()) { + m_wordlist.append(in.readLine()); + } + + if (m_wordlist.size() < 4000) { + qWarning("Wordlist too short!"); + return; + } +} + +void PassphraseGenerator::setWordSeparator(QString separator) { + m_separator = separator; +} + +QString PassphraseGenerator::generatePassphrase() const +{ + Q_ASSERT(isValid()); + + // In case there was an error loading the wordlist + if(m_wordlist.length() == 0) { + return QString(); + } + + QStringList words; + for (int i = 0; i < m_wordCount; i++) { + int wordIndex = randomGen()->randomUInt(m_wordlist.length()); + words.append(m_wordlist.at(wordIndex)); + } + + return words.join(m_separator); +} + +bool PassphraseGenerator::isValid() const +{ + if (m_wordCount == 0) { + return false; + } + + if (m_wordlist.size() < 1000) { + return false; + } + + return true; +} diff --git a/src/core/PassphraseGenerator.h b/src/core/PassphraseGenerator.h new file mode 100644 index 0000000000..3be2d58363 --- /dev/null +++ b/src/core/PassphraseGenerator.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_PASSPHRASEGENERATOR_H +#define KEEPASSX_PASSPHRASEGENERATOR_H + +#include +#include +#include + +class PassphraseGenerator +{ +public: + PassphraseGenerator(); + + double calculateEntropy(QString passphrase); + void setWordCount(int wordCount); + void setWordList(QString path); + void setWordSeparator(QString separator); + bool isValid() const; + + QString generatePassphrase() const; + +private: + int m_wordCount; + QString m_separator; + QVector m_wordlist; + + Q_DISABLE_COPY(PassphraseGenerator) +}; + +#endif // KEEPASSX_PASSPHRASEGENERATOR_H \ No newline at end of file diff --git a/src/core/PasswordGenerator.cpp b/src/core/PasswordGenerator.cpp index aea237a2e5..cdff204a06 100644 --- a/src/core/PasswordGenerator.cpp +++ b/src/core/PasswordGenerator.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -97,11 +98,11 @@ QString PasswordGenerator::generatePassword() const int PasswordGenerator::getbits() const { - QVector groups = passwordGroups(); + const QVector groups = passwordGroups(); int bits = 0; QVector passwordChars; - Q_FOREACH (const PasswordGroup& group, groups) { + for (const PasswordGroup& group: groups) { bits += group.size(); } @@ -195,6 +196,24 @@ QVector PasswordGenerator::passwordGroups() const passwordGroups.append(group); } + if (m_classes & EASCII) { + PasswordGroup group; + + // [U+0080, U+009F] are C1 control characters, + // U+00A0 is non-breaking space + for (int i = 161; i <= 172; i++) { + group.append(i); + } + // U+00AD is soft hyphen (format character) + for (int i = 174; i <= 255; i++) { + if ((m_flags & ExcludeLookAlike) && (i == 249)) { // "﹒" + continue; + } + group.append(i); + } + + passwordGroups.append(group); + } return passwordGroups; } @@ -215,6 +234,9 @@ int PasswordGenerator::numCharClasses() const if (m_classes & SpecialCharacters) { numClasses++; } + if (m_classes & EASCII) { + numClasses++; + } return numClasses; } diff --git a/src/core/PasswordGenerator.h b/src/core/PasswordGenerator.h index b471593244..5a5c7a3f63 100644 --- a/src/core/PasswordGenerator.h +++ b/src/core/PasswordGenerator.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,7 +33,8 @@ class PasswordGenerator LowerLetters = 0x1, UpperLetters = 0x2, Numbers = 0x4, - SpecialCharacters = 0x8 + SpecialCharacters = 0x8, + EASCII = 0x10 }; Q_DECLARE_FLAGS(CharClasses, CharClass) diff --git a/src/core/ScreenLockListener.cpp b/src/core/ScreenLockListener.cpp new file mode 100644 index 0000000000..eb78cd6082 --- /dev/null +++ b/src/core/ScreenLockListener.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ScreenLockListener.h" +#include "ScreenLockListenerPrivate.h" + +ScreenLockListener::ScreenLockListener(QWidget* parent): + QObject(parent){ + m_listener = ScreenLockListenerPrivate::instance(parent); + connect(m_listener,SIGNAL(screenLocked()), this,SIGNAL(screenLocked())); +} + +ScreenLockListener::~ScreenLockListener(){ +} diff --git a/src/core/ScreenLockListener.h b/src/core/ScreenLockListener.h new file mode 100644 index 0000000000..b4eb81e04f --- /dev/null +++ b/src/core/ScreenLockListener.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCREENLOCKLISTENER_H +#define SCREENLOCKLISTENER_H +#include + +class ScreenLockListenerPrivate; + +class ScreenLockListener : public QObject { + Q_OBJECT + +public: + ScreenLockListener(QWidget* parent = nullptr); + ~ScreenLockListener(); + +signals: + void screenLocked(); + +private: + ScreenLockListenerPrivate* m_listener; +}; + +#endif // SCREENLOCKLISTENER_H diff --git a/src/core/ScreenLockListenerDBus.cpp b/src/core/ScreenLockListenerDBus.cpp new file mode 100644 index 0000000000..1976b47ea3 --- /dev/null +++ b/src/core/ScreenLockListenerDBus.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ScreenLockListenerDBus.h" + +#include +#include +#include + +ScreenLockListenerDBus::ScreenLockListenerDBus(QWidget *parent): + ScreenLockListenerPrivate(parent) +{ + QDBusConnection sessionBus = QDBusConnection::sessionBus(); + QDBusConnection systemBus = QDBusConnection::systemBus(); + + sessionBus.connect( + "org.freedesktop.ScreenSaver", // service + "/org/freedesktop/ScreenSaver", // path + "org.freedesktop.ScreenSaver", // interface + "ActiveChanged", // signal name + this, //receiver + SLOT(freedesktopScreenSaver(bool))); + + sessionBus.connect( + "org.gnome.SessionManager", // service + "/org/gnome/SessionManager/Presence", // path + "org.gnome.SessionManager.Presence", // interface + "StatusChanged", // signal name + this, //receiver + SLOT(gnomeSessionStatusChanged(uint))); + + systemBus.connect( + "org.freedesktop.login1", // service + "/org/freedesktop/login1", // path + "org.freedesktop.login1.Manager", // interface + "PrepareForSleep", // signal name + this, //receiver + SLOT(logindPrepareForSleep(bool))); + + sessionBus.connect( + "com.canonical.Unity", // service + "/com/canonical/Unity/Session", // path + "com.canonical.Unity.Session", // interface + "Locked", // signal name + this, //receiver + SLOT(unityLocked())); +} + +void ScreenLockListenerDBus::gnomeSessionStatusChanged(uint status) +{ + if (status != 0) { + emit screenLocked(); + } +} + +void ScreenLockListenerDBus::logindPrepareForSleep(bool beforeSleep) +{ + if (beforeSleep) { + emit screenLocked(); + } +} + +void ScreenLockListenerDBus::unityLocked() +{ + emit screenLocked(); +} + +void ScreenLockListenerDBus::freedesktopScreenSaver(bool status) +{ + if (status) { + emit screenLocked(); + } +} \ No newline at end of file diff --git a/src/core/ScreenLockListenerDBus.h b/src/core/ScreenLockListenerDBus.h new file mode 100644 index 0000000000..72f308f721 --- /dev/null +++ b/src/core/ScreenLockListenerDBus.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCREENLOCKLISTENERDBUS_H +#define SCREENLOCKLISTENERDBUS_H +#include +#include +#include "ScreenLockListenerPrivate.h" + +class ScreenLockListenerDBus : public ScreenLockListenerPrivate +{ + Q_OBJECT +public: + explicit ScreenLockListenerDBus(QWidget *parent = 0); + +private slots: + void gnomeSessionStatusChanged(uint status); + void logindPrepareForSleep(bool beforeSleep); + void unityLocked(); + void freedesktopScreenSaver(bool status); +}; + +#endif // SCREENLOCKLISTENERDBUS_H diff --git a/src/core/ScreenLockListenerMac.cpp b/src/core/ScreenLockListenerMac.cpp new file mode 100644 index 0000000000..dce05de3f9 --- /dev/null +++ b/src/core/ScreenLockListenerMac.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ScreenLockListenerMac.h" + +#include +#include + +ScreenLockListenerMac* ScreenLockListenerMac::instance() +{ + static QMutex mutex; + QMutexLocker lock(&mutex); + + static ScreenLockListenerMac* m_ptr = nullptr; + if (m_ptr == nullptr) { + m_ptr = new ScreenLockListenerMac(); + } + return m_ptr; +} + +void ScreenLockListenerMac::notificationCenterCallBack(CFNotificationCenterRef, void*, + CFStringRef, const void*, + CFDictionaryRef) +{ + instance()->onSignalReception(); +} + +ScreenLockListenerMac::ScreenLockListenerMac(QWidget* parent) + : ScreenLockListenerPrivate(parent) +{ + CFNotificationCenterRef distCenter; + CFStringRef screenIsLockedSignal = CFSTR("com.apple.screenIsLocked"); + distCenter = CFNotificationCenterGetDistributedCenter(); + if (nullptr == distCenter) { + return; + } + + CFNotificationCenterAddObserver(distCenter, + this, + &ScreenLockListenerMac::notificationCenterCallBack, + screenIsLockedSignal, + nullptr, + CFNotificationSuspensionBehaviorDeliverImmediately); +} + +void ScreenLockListenerMac::onSignalReception() +{ + emit screenLocked(); +} diff --git a/src/core/ScreenLockListenerMac.h b/src/core/ScreenLockListenerMac.h new file mode 100644 index 0000000000..cd36ce9e64 --- /dev/null +++ b/src/core/ScreenLockListenerMac.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCREENLOCKLISTENERMAC_H +#define SCREENLOCKLISTENERMAC_H +#include +#include + +#include + +#include "ScreenLockListenerPrivate.h" + +class ScreenLockListenerMac: public ScreenLockListenerPrivate { + Q_OBJECT + +public: + static ScreenLockListenerMac* instance(); + static void notificationCenterCallBack(CFNotificationCenterRef center, void* observer, + CFStringRef name, const void* object, + CFDictionaryRef userInfo); + +private: + ScreenLockListenerMac(QWidget* parent = nullptr); + void onSignalReception(); + +}; + +#endif // SCREENLOCKLISTENERMAC_H diff --git a/src/core/ScreenLockListenerPrivate.cpp b/src/core/ScreenLockListenerPrivate.cpp new file mode 100644 index 0000000000..36ee301f28 --- /dev/null +++ b/src/core/ScreenLockListenerPrivate.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ScreenLockListenerPrivate.h" +#if defined(Q_OS_OSX) +#include "ScreenLockListenerMac.h" +#endif +#if defined(Q_OS_LINUX) +#include "ScreenLockListenerDBus.h" +#endif +#if defined(Q_OS_WIN) +#include "ScreenLockListenerWin.h" +#endif + +ScreenLockListenerPrivate::ScreenLockListenerPrivate(QWidget* parent) + : QObject(parent) +{ +} + +ScreenLockListenerPrivate* ScreenLockListenerPrivate::instance(QWidget* parent) +{ +#if defined(Q_OS_OSX) + Q_UNUSED(parent); + return ScreenLockListenerMac::instance(); +#elif defined(Q_OS_LINUX) + return new ScreenLockListenerDBus(parent); +#elif defined(Q_OS_WIN) + return new ScreenLockListenerWin(parent); +#endif +} diff --git a/src/core/ScreenLockListenerPrivate.h b/src/core/ScreenLockListenerPrivate.h new file mode 100644 index 0000000000..8ecad17d87 --- /dev/null +++ b/src/core/ScreenLockListenerPrivate.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCREENLOCKLISTENERPRIVATE_H +#define SCREENLOCKLISTENERPRIVATE_H +#include +#include + +class ScreenLockListenerPrivate : public QObject +{ + Q_OBJECT +public: + static ScreenLockListenerPrivate* instance(QWidget* parent = 0); + +protected: + ScreenLockListenerPrivate(QWidget* parent = 0); + +signals: + void screenLocked(); +}; + +#endif // SCREENLOCKLISTENERPRIVATE_H diff --git a/src/core/ScreenLockListenerWin.cpp b/src/core/ScreenLockListenerWin.cpp new file mode 100644 index 0000000000..80fa328949 --- /dev/null +++ b/src/core/ScreenLockListenerWin.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ScreenLockListenerWin.h" +#include +#include +#include + +/* + * See https://msdn.microsoft.com/en-us/library/windows/desktop/aa373196(v=vs.85).aspx + * See https://msdn.microsoft.com/en-us/library/aa383841(v=vs.85).aspx + * See https://blogs.msdn.microsoft.com/oldnewthing/20060104-50/?p=32783 + */ +ScreenLockListenerWin::ScreenLockListenerWin(QWidget* parent) + : ScreenLockListenerPrivate(parent) + , QAbstractNativeEventFilter() +{ + Q_ASSERT(parent != nullptr); + // On windows, we need to register for platform specific messages and + // install a message handler for them + QCoreApplication::instance()->installNativeEventFilter(this); + + // This call requests a notification from windows when a laptop is closed + HPOWERNOTIFY hPnotify = RegisterPowerSettingNotification( + reinterpret_cast(parent->winId()), + &GUID_LIDSWITCH_STATE_CHANGE, DEVICE_NOTIFY_WINDOW_HANDLE); + m_powerNotificationHandle = reinterpret_cast(hPnotify); + + // This call requests a notification for session changes + if (!WTSRegisterSessionNotification( + reinterpret_cast(parent->winId()), + NOTIFY_FOR_THIS_SESSION)) { + } +} + +ScreenLockListenerWin::~ScreenLockListenerWin() +{ + HWND h= reinterpret_cast(static_cast(parent())->winId()); + WTSUnRegisterSessionNotification(h); + + if (m_powerNotificationHandle) { + UnregisterPowerSettingNotification(reinterpret_cast(m_powerNotificationHandle)); + } +} + +bool ScreenLockListenerWin::nativeEventFilter(const QByteArray& eventType, void* message, long*) +{ + if (eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG") { + MSG* m = static_cast(message); + if (m->message == WM_POWERBROADCAST) { + if (m->wParam == PBT_POWERSETTINGCHANGE) { + const POWERBROADCAST_SETTING* setting = reinterpret_cast(m->lParam); + if (setting != nullptr && setting->PowerSetting == GUID_LIDSWITCH_STATE_CHANGE) { + const DWORD* state = reinterpret_cast(&setting->Data); + if (*state == 0) { + emit screenLocked(); + return true; + } + } + } else if (m->wParam == PBT_APMSUSPEND) { + emit screenLocked(); + return true; + } + } + if (m->message == WM_WTSSESSION_CHANGE) { + if (m->wParam == WTS_CONSOLE_DISCONNECT) { + emit screenLocked(); + return true; + } + if (m->wParam == WTS_SESSION_LOCK) { + emit screenLocked(); + return true; + } + } + } + return false; +} diff --git a/src/core/ScreenLockListenerWin.h b/src/core/ScreenLockListenerWin.h new file mode 100644 index 0000000000..6a8380efed --- /dev/null +++ b/src/core/ScreenLockListenerWin.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef SCREENLOCKLISTENERWIN_H +#define SCREENLOCKLISTENERWIN_H +#include +#include +#include + +#include "ScreenLockListenerPrivate.h" + +class ScreenLockListenerWin : public ScreenLockListenerPrivate, public QAbstractNativeEventFilter +{ + Q_OBJECT +public: + explicit ScreenLockListenerWin(QWidget* parent = 0); + ~ScreenLockListenerWin(); + virtual bool nativeEventFilter(const QByteArray &eventType, void* message, long*) override; + +private: + void* m_powerNotificationHandle ; +}; + +#endif // SCREENLOCKLISTENERWIN_H diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index bc63bf1395..b9e4be8e04 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -1,5 +1,7 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 Lennart Glauer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,7 +28,8 @@ #include #ifdef Q_OS_WIN -#include // for Sleep(), SetDllDirectoryA() and SetSearchPathMode() +#include // for Sleep(), SetDllDirectoryA(), SetSearchPathMode(), ... +#include // for SetSecurityInfo() #endif #ifdef Q_OS_UNIX @@ -226,6 +229,10 @@ void disableCoreDumps() success = success && (ptrace(PT_DENY_ATTACH, 0, 0, 0) == 0); #endif +#ifdef Q_OS_WIN + success = success && createWindowsDACL(); +#endif + if (!success) { qWarning("Unable to disable core dumps."); } @@ -240,4 +247,114 @@ void setupSearchPaths() #endif } +// +// This function grants the user associated with the process token minimal access rights and +// denies everything else on Windows. This includes PROCESS_QUERY_INFORMATION and +// PROCESS_VM_READ access rights that are required for MiniDumpWriteDump() or ReadProcessMemory(). +// We do this using a discretionary access control list (DACL). Effectively this prevents +// crash dumps and disallows other processes from accessing our memory. This works as long +// as you do not have admin privileges, since then you are able to grant yourself the +// SeDebugPrivilege or SeTakeOwnershipPrivilege and circumvent the DACL. +// +bool createWindowsDACL() +{ + bool bSuccess = false; + +#ifdef Q_OS_WIN + // Process token and user + HANDLE hToken = nullptr; + PTOKEN_USER pTokenUser = nullptr; + DWORD cbBufferSize = 0; + + // Access control list + PACL pACL = nullptr; + DWORD cbACL = 0; + + // Open the access token associated with the calling process + if (!OpenProcessToken( + GetCurrentProcess(), + TOKEN_QUERY, + &hToken + )) { + goto Cleanup; + } + + // Retrieve the token information in a TOKEN_USER structure + GetTokenInformation( + hToken, + TokenUser, + nullptr, + 0, + &cbBufferSize + ); + + pTokenUser = static_cast(HeapAlloc(GetProcessHeap(), 0, cbBufferSize)); + if (pTokenUser == nullptr) { + goto Cleanup; + } + + if (!GetTokenInformation( + hToken, + TokenUser, + pTokenUser, + cbBufferSize, + &cbBufferSize + )) { + goto Cleanup; + } + + if (!IsValidSid(pTokenUser->User.Sid)) { + goto Cleanup; + } + + // Calculate the amount of memory that must be allocated for the DACL + cbACL = sizeof(ACL) + + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid); + + // Create and initialize an ACL + pACL = static_cast(HeapAlloc(GetProcessHeap(), 0, cbACL)); + if (pACL == nullptr) { + goto Cleanup; + } + + if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) { + goto Cleanup; + } + + // Add allowed access control entries, everything else is denied + if (!AddAccessAllowedAce( + pACL, + ACL_REVISION, + SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process + pTokenUser->User.Sid // pointer to the trustee's SID + )) { + goto Cleanup; + } + + // Set discretionary access control list + bSuccess = ERROR_SUCCESS == SetSecurityInfo( + GetCurrentProcess(), // object handle + SE_KERNEL_OBJECT, // type of object + DACL_SECURITY_INFORMATION, // change only the objects DACL + nullptr, nullptr, // do not change owner or group + pACL, // DACL specified + nullptr // do not change SACL + ); + +Cleanup: + + if (pACL != nullptr) { + HeapFree(GetProcessHeap(), 0, pACL); + } + if (pTokenUser != nullptr) { + HeapFree(GetProcessHeap(), 0, pTokenUser); + } + if (hToken != nullptr) { + CloseHandle(hToken); + } +#endif + + return bSuccess; +} + } // namespace Tools diff --git a/src/core/Tools.h b/src/core/Tools.h index 65df1ea4e0..b6fa49c027 100644 --- a/src/core/Tools.h +++ b/src/core/Tools.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +42,7 @@ void sleep(int ms); void wait(int ms); void disableCoreDumps(); void setupSearchPaths(); +bool createWindowsDACL(); template RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value) diff --git a/src/core/Uuid.cpp b/src/core/Uuid.cpp index 1b046c5a34..1b531159f8 100644 --- a/src/core/Uuid.cpp +++ b/src/core/Uuid.cpp @@ -22,6 +22,8 @@ #include "crypto/Random.h" const int Uuid::Length = 16; +const QRegExp Uuid::HexRegExp = QRegExp(QString("^[0-9A-F]{%1}$").arg(QString::number(Uuid::Length * 2)), + Qt::CaseInsensitive); Uuid::Uuid() : m_data(Length, 0) @@ -115,3 +117,8 @@ QDataStream& operator>>(QDataStream& stream, Uuid& uuid) return stream; } + +bool Uuid::isUuid(const QString& uuid) +{ + return Uuid::HexRegExp.exactMatch(uuid); +} diff --git a/src/core/Uuid.h b/src/core/Uuid.h index 4164399d64..ecb20e0c36 100644 --- a/src/core/Uuid.h +++ b/src/core/Uuid.h @@ -20,6 +20,7 @@ #include #include +#include class Uuid { @@ -36,8 +37,10 @@ class Uuid bool operator==(const Uuid& other) const; bool operator!=(const Uuid& other) const; static const int Length; + static const QRegExp HexRegExp; static Uuid fromBase64(const QString& str); static Uuid fromHex(const QString& str); + static bool isUuid(const QString& str); private: QByteArray m_data; diff --git a/src/crypto/SymmetricCipher.cpp b/src/crypto/SymmetricCipher.cpp index 12ec264f56..98d4819697 100644 --- a/src/crypto/SymmetricCipher.cpp +++ b/src/crypto/SymmetricCipher.cpp @@ -83,3 +83,23 @@ QString SymmetricCipher::errorString() const { return m_backend->errorString(); } + +SymmetricCipher::Algorithm SymmetricCipher::cipherToAlgorithm(Uuid cipher) +{ + if (cipher == KeePass2::CIPHER_AES) { + return SymmetricCipher::Aes256; + } + else { + return SymmetricCipher::Twofish; + } +} + +Uuid SymmetricCipher::algorithmToCipher(SymmetricCipher::Algorithm algo) +{ + switch (algo) { + case SymmetricCipher::Aes256: + return KeePass2::CIPHER_AES; + default: + return KeePass2::CIPHER_TWOFISH; + } +} diff --git a/src/crypto/SymmetricCipher.h b/src/crypto/SymmetricCipher.h index 4fc06b7deb..0070ed7de6 100644 --- a/src/crypto/SymmetricCipher.h +++ b/src/crypto/SymmetricCipher.h @@ -23,6 +23,7 @@ #include #include "crypto/SymmetricCipherBackend.h" +#include "format/KeePass2.h" class SymmetricCipher { @@ -71,6 +72,9 @@ class SymmetricCipher int blockSize() const; QString errorString() const; + static SymmetricCipher::Algorithm cipherToAlgorithm(Uuid cipher); + static Uuid algorithmToCipher(SymmetricCipher::Algorithm algo); + private: static SymmetricCipherBackend* createBackend(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, SymmetricCipher::Direction direction); diff --git a/src/format/KeePass2.h b/src/format/KeePass2.h index b49ae4f6af..91ee48293e 100644 --- a/src/format/KeePass2.h +++ b/src/format/KeePass2.h @@ -33,6 +33,7 @@ namespace KeePass2 const QSysInfo::Endian BYTEORDER = QSysInfo::LittleEndian; const Uuid CIPHER_AES = Uuid(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff")); + const Uuid CIPHER_TWOFISH = Uuid(QByteArray::fromHex("ad68f29f576f4bb9a36ad47af965346c")); const QByteArray INNER_STREAM_SALSA20_IV("\xE8\x30\x09\x4B\x97\x20\x5D\x2A"); diff --git a/src/format/KeePass2Reader.cpp b/src/format/KeePass2Reader.cpp index 1371aaa6a4..b0d7807249 100644 --- a/src/format/KeePass2Reader.cpp +++ b/src/format/KeePass2Reader.cpp @@ -113,12 +113,18 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke return nullptr; } + if (m_db->challengeMasterSeed(m_masterSeed) == false) { + raiseError(tr("Unable to issue challenge-response.")); + return nullptr; + } + CryptoHash hash(CryptoHash::Sha256); hash.addData(m_masterSeed); + hash.addData(m_db->challengeResponseKey()); hash.addData(m_db->transformedMasterKey()); QByteArray finalKey = hash.result(); - SymmetricCipherStream cipherStream(m_device, SymmetricCipher::Aes256, + SymmetricCipherStream cipherStream(m_device, SymmetricCipher::cipherToAlgorithm(m_db->cipher()), SymmetricCipher::Cbc, SymmetricCipher::Decrypt); if (!cipherStream.init(finalKey, m_encryptionIV)) { raiseError(cipherStream.errorString()); @@ -192,7 +198,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke QByteArray headerHash = CryptoHash::hash(headerStream.storedData(), CryptoHash::Sha256); if (headerHash != xmlReader.headerHash()) { raiseError("Header doesn't match hash"); - return Q_NULLPTR; + return nullptr; } } @@ -330,7 +336,7 @@ void KeePass2Reader::setCipher(const QByteArray& data) else { Uuid uuid(data); - if (uuid != KeePass2::CIPHER_AES) { + if (uuid != KeePass2::CIPHER_AES && uuid != KeePass2::CIPHER_TWOFISH) { raiseError("Unsupported cipher"); } else { diff --git a/src/format/KeePass2Writer.cpp b/src/format/KeePass2Writer.cpp index dfbbf35325..d63151c844 100644 --- a/src/format/KeePass2Writer.cpp +++ b/src/format/KeePass2Writer.cpp @@ -51,8 +51,14 @@ void KeePass2Writer::writeDatabase(QIODevice* device, Database* db) QByteArray startBytes = randomGen()->randomArray(32); QByteArray endOfHeader = "\r\n\r\n"; + if (db->challengeMasterSeed(masterSeed) == false) { + raiseError("Unable to issue challenge-response."); + return; + } + CryptoHash hash(CryptoHash::Sha256); hash.addData(masterSeed); + hash.addData(db->challengeResponseKey()); Q_ASSERT(!db->transformedMasterKey().isEmpty()); hash.addData(db->transformedMasterKey()); QByteArray finalKey = hash.result(); @@ -87,8 +93,8 @@ void KeePass2Writer::writeDatabase(QIODevice* device, Database* db) QByteArray headerHash = CryptoHash::hash(header.data(), CryptoHash::Sha256); CHECK_RETURN(writeData(header.data())); - SymmetricCipherStream cipherStream(device, SymmetricCipher::Aes256, SymmetricCipher::Cbc, - SymmetricCipher::Encrypt); + SymmetricCipherStream cipherStream(device, SymmetricCipher::cipherToAlgorithm(db->cipher()), + SymmetricCipher::Cbc, SymmetricCipher::Encrypt); cipherStream.init(finalKey, encryptionIV); if (!cipherStream.open(QIODevice::WriteOnly)) { raiseError(cipherStream.errorString()); diff --git a/src/format/KeePass2XmlReader.cpp b/src/format/KeePass2XmlReader.cpp index dca387b196..e4ceb17622 100644 --- a/src/format/KeePass2XmlReader.cpp +++ b/src/format/KeePass2XmlReader.cpp @@ -1037,6 +1037,9 @@ bool KeePass2XmlReader::readBool() else if (str.compare("False", Qt::CaseInsensitive) == 0) { return false; } + else if (str.length() == 0) { + return false; + } else { raiseError("Invalid bool value"); return false; diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index a4f180b05d..0e0f2960ad 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,15 +24,21 @@ #include "core/FilePath.h" #include "crypto/Crypto.h" +#include +#include + AboutDialog::AboutDialog(QWidget* parent) - : QDialog(parent) - , m_ui(new Ui::AboutDialog()) + : QDialog(parent), + m_ui(new Ui::AboutDialog()) { m_ui->setupUi(this); - m_ui->nameLabel->setText(m_ui->nameLabel->text() + " " + KEEPASSX_VERSION); + resize(minimumSize()); + setWindowFlags(Qt::Sheet); + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + + m_ui->nameLabel->setText(m_ui->nameLabel->text().replace("${VERSION}", KEEPASSX_VERSION)); QFont nameLabelFont = m_ui->nameLabel->font(); - nameLabelFont.setBold(true); nameLabelFont.setPointSize(nameLabelFont.pointSize() + 4); m_ui->nameLabel->setFont(nameLabelFont); @@ -45,37 +52,56 @@ AboutDialog::AboutDialog(QWidget* parent) commitHash = DIST_HASH; } + QString debugInfo = "KeePassXC - "; + debugInfo.append(tr("Version %1\n").arg(KEEPASSX_VERSION)); if (!commitHash.isEmpty()) { - QString labelText = tr("Revision").append(": ").append(commitHash); - m_ui->label_git->setText(labelText); + debugInfo.append(tr("Revision: %1").arg(commitHash).append("\n\n")); } - QString libs = QString("%1\n- Qt %2\n- %3") - .arg(m_ui->label_libs->text()) - .arg(QString::fromLocal8Bit(qVersion())) - .arg(Crypto::backendVersion()); - m_ui->label_libs->setText(libs); + debugInfo.append(QString("%1\n- Qt %2\n- %3\n\n") + .arg(tr("Libraries:")) + .arg(QString::fromLocal8Bit(qVersion())) + .arg(Crypto::backendVersion())); + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + debugInfo.append(tr("Operating system: %1\nCPU architecture: %2\nKernel: %3 %4") + .arg(QSysInfo::prettyProductName()) + .arg(QSysInfo::currentCpuArchitecture()) + .arg(QSysInfo::kernelType()) + .arg(QSysInfo::kernelVersion())); + + debugInfo.append("\n\n"); +#endif QString extensions; #ifdef WITH_XC_HTTP - extensions += "- KeePassHTTP\n"; + extensions += "\n- KeePassHTTP"; #endif #ifdef WITH_XC_AUTOTYPE - extensions += "- Autotype\n"; + extensions += "\n- Auto-Type"; #endif #ifdef WITH_XC_YUBIKEY - extensions += "- Yubikey\n"; + extensions += "\n- YubiKey"; #endif if (extensions.isEmpty()) - extensions = "None"; + extensions = " None"; - m_ui->label_features->setText(m_ui->label_features->text() + extensions); + debugInfo.append(tr("Enabled extensions:").append(extensions)); + + m_ui->debugInfo->setPlainText(debugInfo); setAttribute(Qt::WA_DeleteOnClose); connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close())); + connect(m_ui->copyToClipboard, SIGNAL(clicked()), SLOT(copyToClipboard())); } AboutDialog::~AboutDialog() { } + +void AboutDialog::copyToClipboard() +{ + QClipboard* clipboard = QApplication::clipboard(); + clipboard->setText(m_ui->debugInfo->toPlainText()); +} diff --git a/src/gui/AboutDialog.h b/src/gui/AboutDialog.h index 08db6c887d..9d0c1c3559 100644 --- a/src/gui/AboutDialog.h +++ b/src/gui/AboutDialog.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +34,9 @@ class AboutDialog : public QDialog explicit AboutDialog(QWidget* parent = nullptr); ~AboutDialog(); +protected slots: + void copyToClipboard(); + private: QScopedPointer m_ui; }; diff --git a/src/gui/AboutDialog.ui b/src/gui/AboutDialog.ui index 28f4dd0c42..5bea301aa4 100644 --- a/src/gui/AboutDialog.ui +++ b/src/gui/AboutDialog.ui @@ -6,20 +6,35 @@ 0 0 - 455 - 266 + 450 + 450 + + + 0 + 0 + + + + + 450 + 450 + + About KeePassXC - - - QLayout::SetFixedSize - + - + + 15 + + + 20 + + @@ -27,9 +42,21 @@ 0 + + + 48 + 48 + + + + + 48 + 48 + + - + @@ -37,74 +64,236 @@ 0 + + + 75 + true + + - KeePassXC + <span style="font-size: 24pt"> KeePassXC v${VERSION}</span> + + + 0 + + + 11 - - - - 0 - 0 - - - - <a href="https://keepassxc.org/">https://keepassxc.org/</a> - - - true - - - - - - - - 0 - 0 - - - - KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3. - - - true - - - - - - - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Using: - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse - - - - - - - Extensions: - - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + 0 + + + About + + + + + + + 0 + 0 + + + + <html><head/><body><p>Website: <a href="https://keepassxc.org/"><span style="text-decoration: underline; color:#0000ff;">https://keepassxc.org</span></a></p></body></html> + + + true + + + + + + + <html><head/><body><p>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues"><span style="text-decoration: underline; color:#0000ff;">https://github.com</span></a></p></body></html> + + + true + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 5 + + + + + + + + + 0 + 0 + + + + <html><head/><body><p>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</p></body></html> + + + true + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 0 + 5 + + + + + + + + + 0 + 0 + + + + <html><head><style>li {font-size: 10pt}</style></head><body><p><span style=" font-size:10pt;">Project Maintainers:</span></p><ul><li>droidmonkey</li><li>phoerious</li><li>TheZ3ro</li><li>louib</li><li>Weslly</li><li>debfx (KeePassX)</li></ul></body></html> + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + Contributors + + + + + + <html><body> + <p style="font-size:x-large; font-weight:600;">Code:</p> + <ul> + <li style="font-size:10pt">debfx (KeePassX)</li> + <li style="font-size:10pt">BlueIce (KeePassX)</li> + <li style="font-size:10pt">droidmonkey</li> + <li style="font-size:10pt">phoerious</li> + <li style="font-size:10pt">TheZ3ro</li> + <li style="font-size:10pt">louib</li> + <li style="font-size:10pt">weslly</li> + <li style="font-size:10pt">keithbennett (KeePassHTTP)</li> + <li style="font-size:10pt">Typz (KeePassHTTP)</li> + <li style="font-size:10pt">denk-mal (KeePassHTTP)</li> + <li style="font-size:10pt">kylemanna (YubiKey)</li> + <li style="font-size:10pt">seatedscribe (CSV Importer)</li> + <li style="font-size:10pt">pgalves (Inline Messages)</li> + </ul> + <p style="font-size:x-large; font-weight:600;">Translations:</p> + <ul> + <li style="font-size:10pt"><span style="font-weight:600;">Chinese:</span> Biggulu, ligyxy, BestSteve</li> + <li style="font-size:10pt"><span style="font-weight:600;">Czech:</span> pavelb, JosefVitu</li> + <li style="font-size:10pt"><span style="font-weight:600;">Dutch:</span> Vistaus, KnooL, apie</li> + <li style="font-size:10pt"><span style="font-weight:600;">Finnish:</span> MawKKe</li> + <li style="font-size:10pt"><span style="font-weight:600;">French:</span> Scrat15, frgnca, gilbsgilbs, gtalbot, iannick, kyodev, logut</li> + <li style="font-size:10pt"><span style="font-weight:600;">German:</span> Calyrx, DavidHamburg, antsas, codejunky, jensrutschmann, montilo, omnisome4, origin_de, pcrcoding, phoerious, rgloor, vlenzer</li> + <li style="font-size:10pt"><span style="font-weight:600;">Greek:</span> nplatis</li> + <li style="font-size:10pt"><span style="font-weight:600;">Italian:</span> TheZ3ro, FranzMari, Mte90, tosky</li> + <li style="font-size:10pt"><span style="font-weight:600;">Kazakh:</span> sotrud_nik</li> + <li style="font-size:10pt"><span style="font-weight:600;">Lithuanian:</span> Moo</li> + <li style="font-size:10pt"><span style="font-weight:600;">Polish:</span> konradmb, mrerexx</li> + <li style="font-size:10pt"><span style="font-weight:600;">Portuguese: </span>vitor895, weslly, American_Jesus, mihai.ile</li> + <li style="font-size:10pt"><span style="font-weight:600;">Russian:</span> vsvyatski, KekcuHa, wkill95</li> + <li style="font-size:10pt"><span style="font-weight:600;">Spanish:</span> EdwardNavarro, antifaz, piegope, pquin, vsvyatski</li> + <li style="font-size:10pt"><span style="font-weight:600;">Swedish:</span> henziger</li> + </ul> + </body></html> + + + + + + + <html><head/><body><p align="center"><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">See Contributions on GitHub</span></a></p></body></html> + + + true + + + + + + + + Debug Info + + + + + + + 0 + 0 + + + + <html><head/><body><p>Include the following information whenever you report a bug:</p></body></html> + + + + + + + + 0 + 0 + + + + true + + + + + + + Copy to clipboard + + + + + diff --git a/src/gui/Application.cpp b/src/gui/Application.cpp index 26d9d2283d..7c369cf1c5 100644 --- a/src/gui/Application.cpp +++ b/src/gui/Application.cpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2012 Tobias Tangemann * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +23,9 @@ #include #include #include +#include +#include +#include #include "autotype/AutoType.h" @@ -76,6 +80,8 @@ Application::Application(int& argc, char** argv) #ifdef Q_OS_UNIX , m_unixSignalNotifier(nullptr) #endif + , alreadyRunning(false) + , lock(nullptr) { #if defined(Q_OS_UNIX) && !defined(Q_OS_OSX) installNativeEventFilter(new XcbEventFilter()); @@ -85,6 +91,63 @@ Application::Application(int& argc, char** argv) #if defined(Q_OS_UNIX) registerUnixSignals(); #endif + + QString userName = qgetenv("USER"); + if (userName.isEmpty()) { + userName = qgetenv("USERNAME"); + } + QString identifier = "keepassxc"; + if (!userName.isEmpty()) { + identifier.append("-"); + identifier.append(userName); + } + QString socketName = identifier + ".socket"; + QString lockName = identifier + ".lock"; + + // According to documentation we should use RuntimeLocation on *nixes, but even Qt doesn't respect + // this and creates sockets in TempLocation, so let's be consistent. + lock = new QLockFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + lockName); + lock->setStaleLockTime(0); + lock->tryLock(); + switch (lock->error()) { + case QLockFile::NoError: + server.setSocketOptions(QLocalServer::UserAccessOption); + server.listen(socketName); + connect(&server, SIGNAL(newConnection()), this, SIGNAL(anotherInstanceStarted())); + break; + case QLockFile::LockFailedError: { + alreadyRunning = true; + // notify the other instance + // try several times, in case the other instance is still starting up + QLocalSocket client; + for (int i = 0; i < 3; i++) { + client.connectToServer(socketName); + if (client.waitForConnected(150)) { + client.abort(); + break; + } + } + break; + } + default: + qWarning() << QCoreApplication::translate("Main", + "The lock file could not be created. Single-instance mode disabled.") + .toUtf8().constData(); + } +} + +Application::~Application() +{ + server.close(); + if (lock) { + lock->unlock(); + delete lock; + } +} + +QWidget* Application::mainWindow() const +{ + return m_mainWindow; } void Application::setMainWindow(QWidget* mainWindow) @@ -96,7 +159,7 @@ bool Application::event(QEvent* event) { // Handle Apple QFileOpenEvent from finder (double click on .kdbx file) if (event->type() == QEvent::FileOpen) { - Q_EMIT openFile(static_cast(event)->file()); + emit openFile(static_cast(event)->file()); return true; } #ifdef Q_OS_MAC @@ -148,7 +211,7 @@ void Application::handleUnixSignal(int sig) case SIGTERM: { char buf = 0; - ::write(unixSignalSocket[0], &buf, sizeof(buf)); + Q_UNUSED(::write(unixSignalSocket[0], &buf, sizeof(buf))); return; } case SIGHUP: @@ -160,9 +223,15 @@ void Application::quitBySignal() { m_unixSignalNotifier->setEnabled(false); char buf; - ::read(unixSignalSocket[1], &buf, sizeof(buf)); + Q_UNUSED(::read(unixSignalSocket[1], &buf, sizeof(buf))); if (nullptr != m_mainWindow) static_cast(m_mainWindow)->appExit(); } #endif + +bool Application::isAlreadyRunning() const +{ + return alreadyRunning; +} + diff --git a/src/gui/Application.h b/src/gui/Application.h index 9bfe4d549e..5cb10e7590 100644 --- a/src/gui/Application.h +++ b/src/gui/Application.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2012 Tobias Tangemann * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +21,8 @@ #define KEEPASSX_APPLICATION_H #include +#include +class QLockFile; class QSocketNotifier; @@ -29,14 +32,18 @@ class Application : public QApplication public: Application(int& argc, char** argv); + QWidget* mainWindow() const; + ~Application(); void setMainWindow(QWidget* mainWindow); bool event(QEvent* event) override; + bool isAlreadyRunning() const; -Q_SIGNALS: +signals: void openFile(const QString& filename); + void anotherInstanceStarted(); -private Q_SLOTS: +private slots: #if defined(Q_OS_UNIX) void quitBySignal(); #endif @@ -53,6 +60,9 @@ private Q_SLOTS: static void handleUnixSignal(int sig); static int unixSignalSocket[2]; #endif + bool alreadyRunning; + QLockFile* lock; + QLocalServer server; }; #endif // KEEPASSX_APPLICATION_H diff --git a/src/gui/CategoryListWidget.cpp b/src/gui/CategoryListWidget.cpp new file mode 100644 index 0000000000..c93ac46e76 --- /dev/null +++ b/src/gui/CategoryListWidget.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CategoryListWidget.h" +#include "ui_CategoryListWidget.h" + +#include +#include +#include +#include +#include + +CategoryListWidget::CategoryListWidget(QWidget* parent) + : QWidget(parent), + m_itemDelegate(nullptr), + m_ui(new Ui::CategoryListWidget()) +{ + m_ui->setupUi(this); + m_itemDelegate = new CategoryListWidgetDelegate(m_ui->categoryList); + m_ui->categoryList->setItemDelegate(m_itemDelegate); + + connect(m_ui->categoryList, SIGNAL(currentRowChanged(int)), SLOT(emitCategoryChanged(int))); + + connect(m_ui->scrollUp, SIGNAL(clicked()), SLOT(scrollCategoriesUp())); + connect(m_ui->scrollDown, SIGNAL(clicked()), SLOT(scrollCategoriesDown())); + connect(m_ui->categoryList->verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(updateCategoryScrollButtons())); + connect(m_ui->categoryList->verticalScrollBar(), SIGNAL(rangeChanged(int, int)), SLOT(updateCategoryScrollButtons())); +} + +CategoryListWidget::~CategoryListWidget() +{ +} + +QSize CategoryListWidget::sizeHint() const +{ + QSize sizeHint = QWidget::sizeHint(); + + int width = m_ui->categoryList->width(); + + int min = minimumSizeHint().width(); + if (width < min) { + width = min; + } + sizeHint.setWidth(width); + + return sizeHint; +} + +QSize CategoryListWidget::minimumSizeHint() const +{ + return QSize(m_itemDelegate->minWidth() + m_ui->categoryList->frameWidth() * 2, + m_ui->categoryList->sizeHintForRow(0) * 2); +} + +int CategoryListWidget::addCategory(const QString& labelText, const QIcon& icon) +{ + QListWidgetItem* item = new QListWidgetItem(m_ui->categoryList); + item->setText(labelText); + item->setIcon(icon); + m_ui->categoryList->addItem(item); + return m_ui->categoryList->count() - 1; +} + +void CategoryListWidget::removeCategory(int index) +{ + m_ui->categoryList->removeItemWidget(m_ui->categoryList->item(index)); +} + +int CategoryListWidget::currentCategory() +{ + return m_ui->categoryList->currentRow(); +} + +void CategoryListWidget::setCurrentCategory(int index) +{ + m_ui->categoryList->setCurrentRow(index); +} + +void CategoryListWidget::setCategoryHidden(int index, bool hidden) +{ + m_ui->categoryList->item(index)->setHidden(hidden); +} + +bool CategoryListWidget::isCategoryHidden(int index) +{ + return m_ui->categoryList->item(index)->isHidden(); +} + +void CategoryListWidget::showEvent(QShowEvent* event) +{ + QWidget::showEvent(event); + updateCategoryScrollButtons(); +} + +void CategoryListWidget::resizeEvent(QResizeEvent* event) +{ + auto newDelegate = new CategoryListWidgetDelegate(m_ui->categoryList); + m_ui->categoryList->setItemDelegate(newDelegate); + m_itemDelegate->deleteLater(); + m_itemDelegate = newDelegate; + + QWidget::resizeEvent(event); +} + +void CategoryListWidget::updateCategoryScrollButtons() +{ + m_ui->scrollUp->setEnabled(m_ui->categoryList->verticalScrollBar()->value() != 0); + m_ui->scrollDown->setEnabled(m_ui->categoryList->verticalScrollBar()->value() + != m_ui->categoryList->verticalScrollBar()->maximum()); + + m_ui->scrollUp->setVisible(m_ui->categoryList->verticalScrollBar()->maximum() > 0); + m_ui->scrollDown->setVisible(m_ui->scrollUp->isVisible()); +} + +void CategoryListWidget::scrollCategoriesUp() +{ + m_ui->categoryList->verticalScrollBar()->setValue( + m_ui->categoryList->verticalScrollBar()->value() - m_ui->categoryList->verticalScrollBar()->pageStep() + ); +} + +void CategoryListWidget::scrollCategoriesDown() +{ + m_ui->categoryList->verticalScrollBar()->setValue( + m_ui->categoryList->verticalScrollBar()->value() + m_ui->categoryList->verticalScrollBar()->pageStep() + ); +} + +void CategoryListWidget::emitCategoryChanged(int index) +{ + emit categoryChanged(index); +} + + +/* =============================================================================================== */ + + +CategoryListWidgetDelegate::CategoryListWidgetDelegate(QListWidget* parent) + : QStyledItemDelegate(parent), + m_listWidget(parent), + m_size(minWidth(), 96) +{ + if (m_listWidget && m_listWidget->width() > m_size.width()) { + m_size.setWidth(m_listWidget->width()); + } +} + +#ifdef Q_OS_WIN +#include +class WindowsCorrectedStyle : public QProxyStyle +{ +public: + void drawPrimitive(PrimitiveElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const override + { + painter->save(); + + if (PE_PanelItemViewItem == element) { + // Qt on Windows draws selection backgrounds only for the actual text/icon + // bounding box, not over the full width of a list item. + // We therefore need to translate and stretch the painter before we can + // tell Qt to draw its native styles. + // Since we are scaling horizontally, we also need to move the right and left + // edge pixels outside the drawing area to avoid thick border lines. + QRect itemRect = subElementRect(QStyle::SE_ItemViewItemFocusRect, option, widget).adjusted(1, 0, 1, 0); + painter->scale(static_cast(option->rect.width()) / itemRect.width(), 1.0); + painter->translate(option->rect.left() - itemRect.left() + 1, 0); + } + QProxyStyle::drawPrimitive(element, option, painter, widget); + + painter->restore(); + } +}; +#endif + +void CategoryListWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const +{ + QStyleOptionViewItem opt = option; + initStyleOption(&opt, index); + + painter->save(); + + QIcon icon = opt.icon; + QSize iconSize = opt.icon.actualSize(QSize(ICON_SIZE, ICON_SIZE)); + opt.icon = QIcon(); + opt.decorationAlignment = Qt::AlignHCenter | Qt::AlignVCenter; + opt.decorationPosition = QStyleOptionViewItem::Top; + +#ifdef Q_OS_WIN + QScopedPointer style(new WindowsCorrectedStyle()); +#else + QStyle* style = opt.widget ? opt.widget->style() : QApplication::style(); +#endif + + style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget); + + QRect fontRect = painter->fontMetrics().boundingRect( + QRect(0, 0, minWidth(), m_size.height()), Qt::AlignHCenter | Qt::AlignBottom | Qt::TextWordWrap, opt.text); + + int paddingTop = fontRect.height() < 30 ? 15 : 10; + int left = opt.rect.left() + opt.rect.width() / 2 - iconSize.width() / 2; + painter->drawPixmap(left, opt.rect.top() + paddingTop, icon.pixmap(iconSize)); + + painter->restore(); +} + +int CategoryListWidgetDelegate::minWidth() const +{ + int c = m_listWidget->count(); + int maxWidth = 0; + + for (int i = 0; i < c; ++i) { + QFontMetrics fm(m_listWidget->font()); + QRect fontRect = fm.boundingRect( + QRect(0, 0, 0, 0), Qt::TextWordWrap | Qt::ElideNone, m_listWidget->item(i)->text()); + + if (fontRect.width() > maxWidth) { + maxWidth = fontRect.width(); + } + } + + // add some padding + maxWidth += 10; + + return maxWidth < m_size.height() ? m_size.height() : maxWidth; +} + +QSize CategoryListWidgetDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + Q_UNUSED(option); + Q_UNUSED(index); + + int w = minWidth(); + if (m_listWidget->width() > w) { + w = m_listWidget->width(); + } + + return QSize(w, m_size.height()); +} diff --git a/src/gui/CategoryListWidget.h b/src/gui/CategoryListWidget.h new file mode 100644 index 0000000000..3cf82fd1bb --- /dev/null +++ b/src/gui/CategoryListWidget.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +class CategoryListWidgetDelegate; +class QListWidget; + +namespace Ui { + class CategoryListWidget; +} + +class CategoryListWidget : public QWidget +{ + Q_OBJECT + +public: + CategoryListWidget(QWidget* parent = 0); + ~CategoryListWidget(); + + int currentCategory(); + void setCurrentCategory(int index); + int addCategory(const QString& labelText, const QIcon& icon); + void setCategoryHidden(int index, bool hidden); + bool isCategoryHidden(int index); + void removeCategory(int index); + +signals: + void categoryChanged(int index); + +protected: + void showEvent(QShowEvent* event) override; + void resizeEvent(QResizeEvent * event) override; + QSize sizeHint() const override; + QSize minimumSizeHint() const override; + +protected slots: + void updateCategoryScrollButtons(); + void scrollCategoriesDown(); + void scrollCategoriesUp(); + void emitCategoryChanged(int index); + +private: + QPointer m_itemDelegate; + const QScopedPointer m_ui; + + Q_DISABLE_COPY(CategoryListWidget) +}; + + +/* =============================================================================================== */ + + +class CategoryListWidgetDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + explicit CategoryListWidgetDelegate(QListWidget* parent = nullptr); + int minWidth() const; + +protected: + void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; + +private: + + const int ICON_SIZE = 32; + + QPointer m_listWidget; + QSize m_size; + + Q_DISABLE_COPY(CategoryListWidgetDelegate) +}; diff --git a/src/gui/CategoryListWidget.ui b/src/gui/CategoryListWidget.ui new file mode 100644 index 0000000000..f16165cdba --- /dev/null +++ b/src/gui/CategoryListWidget.ui @@ -0,0 +1,122 @@ + + + CategoryListWidget + + + + 0 + 0 + 182 + 418 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 15 + + + + + + + Qt::UpArrow + + + + + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QListView::Static + + + QListView::TopToBottom + + + false + + + QListView::IconMode + + + true + + + true + + + + + + + + 0 + 0 + + + + + 16777215 + 15 + + + + + + + Qt::DownArrow + + + + + + + categoryList + scrollUp + scrollDown + + + + diff --git a/src/gui/ChangeMasterKeyWidget.cpp b/src/gui/ChangeMasterKeyWidget.cpp index 05b9cd2ccc..ef4b61ef28 100644 --- a/src/gui/ChangeMasterKeyWidget.cpp +++ b/src/gui/ChangeMasterKeyWidget.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,8 +22,16 @@ #include "core/FilePath.h" #include "keys/FileKey.h" #include "keys/PasswordKey.h" +#include "keys/YkChallengeResponseKey.h" #include "gui/FileDialog.h" #include "gui/MessageBox.h" +#include "crypto/Random.h" +#include "MainWindow.h" + +#include "config-keepassx.h" + +#include +#include ChangeMasterKeyWidget::ChangeMasterKeyWidget(QWidget* parent) : DialogyWidget(parent) @@ -30,13 +39,37 @@ ChangeMasterKeyWidget::ChangeMasterKeyWidget(QWidget* parent) { m_ui->setupUi(this); - connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(generateKey())); - connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject())); + m_ui->messageWidget->setHidden(true); + m_ui->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show")); - connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), m_ui->enterPasswordEdit, SLOT(setShowPassword(bool))); m_ui->repeatPasswordEdit->enableVerifyMode(m_ui->enterPasswordEdit); + + connect(m_ui->passwordGroup, SIGNAL(clicked(bool)), SLOT(setOkEnabled())); + connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), m_ui->enterPasswordEdit, SLOT(setShowPassword(bool))); + + connect(m_ui->keyFileGroup, SIGNAL(clicked(bool)), SLOT(setOkEnabled())); connect(m_ui->createKeyFileButton, SIGNAL(clicked()), SLOT(createKeyFile())); connect(m_ui->browseKeyFileButton, SIGNAL(clicked()), SLOT(browseKeyFile())); + connect(m_ui->keyFileCombo, SIGNAL(editTextChanged(QString)), SLOT(setOkEnabled())); + + connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(generateKey())); + connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject())); + +#ifdef WITH_XC_YUBIKEY + m_ui->yubikeyProgress->setVisible(false); + QSizePolicy sp = m_ui->yubikeyProgress->sizePolicy(); + sp.setRetainSizeWhenHidden(true); + m_ui->yubikeyProgress->setSizePolicy(sp); + + connect(m_ui->challengeResponseGroup, SIGNAL(clicked(bool)), SLOT(challengeResponseGroupToggled(bool))); + connect(m_ui->challengeResponseGroup, SIGNAL(clicked(bool)), SLOT(setOkEnabled())); + connect(m_ui->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey())); + + connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection); + connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection); +#else + m_ui->challengeResponseGroup->setVisible(false); +#endif } ChangeMasterKeyWidget::~ChangeMasterKeyWidget() @@ -52,7 +85,7 @@ void ChangeMasterKeyWidget::createKeyFile() QString errorMsg; bool created = FileKey::create(fileName, &errorMsg); if (!created) { - MessageBox::warning(this, tr("Error"), tr("Unable to create Key File : ") + errorMsg); + m_ui->messageWidget->showMessage(tr("Unable to create Key File : ").append(errorMsg), MessageWidget::Error); } else { m_ui->keyFileCombo->setEditText(fileName); @@ -79,7 +112,11 @@ void ChangeMasterKeyWidget::clearForms() m_ui->repeatPasswordEdit->setText(""); m_ui->keyFileGroup->setChecked(false); m_ui->togglePasswordButton->setChecked(false); - // TODO: clear m_ui->keyFileCombo + +#ifdef WITH_XC_YUBIKEY + m_ui->challengeResponseGroup->setChecked(false); + m_ui->comboChallengeResponse->clear(); +#endif m_ui->enterPasswordEdit->setFocus(); } @@ -101,16 +138,16 @@ void ChangeMasterKeyWidget::generateKey() if (m_ui->passwordGroup->isChecked()) { if (m_ui->enterPasswordEdit->text() == m_ui->repeatPasswordEdit->text()) { if (m_ui->enterPasswordEdit->text().isEmpty()) { - if (MessageBox::question(this, tr("Question"), - tr("Do you really want to use an empty string as password?"), - QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) { + if (MessageBox::warning(this, tr("Empty password"), + tr("Do you really want to use an empty string as password?"), + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) { return; } } m_key.addKey(PasswordKey(m_ui->enterPasswordEdit->text())); } else { - MessageBox::warning(this, tr("Error"), tr("Different passwords supplied.")); + m_ui->messageWidget->showMessage(tr("Different passwords supplied."), MessageWidget::Error); m_ui->enterPasswordEdit->setText(""); m_ui->repeatPasswordEdit->setText(""); return; @@ -119,22 +156,87 @@ void ChangeMasterKeyWidget::generateKey() if (m_ui->keyFileGroup->isChecked()) { FileKey fileKey; QString errorMsg; - if (!fileKey.load(m_ui->keyFileCombo->currentText(), &errorMsg)) { - MessageBox::critical(this, tr("Failed to set key file"), - tr("Failed to set %1 as the Key file:\n%2") - .arg(m_ui->keyFileCombo->currentText(), errorMsg)); + QString fileKeyName = m_ui->keyFileCombo->currentText(); + if (!fileKey.load(fileKeyName, &errorMsg)) { + m_ui->messageWidget->showMessage( + tr("Failed to set %1 as the Key file:\n%2").arg(fileKeyName, errorMsg), MessageWidget::Error); return; } m_key.addKey(fileKey); } - Q_EMIT editFinished(true); +#ifdef WITH_XC_YUBIKEY + if (m_ui->challengeResponseGroup->isChecked()) { + int selectionIndex = m_ui->comboChallengeResponse->currentIndex(); + int comboPayload = m_ui->comboChallengeResponse->itemData(selectionIndex).toInt(); + + if (0 == comboPayload) { + m_ui->messageWidget->showMessage(tr("Changing master key failed: no YubiKey inserted."), + MessageWidget::Error); + return; + } + + // read blocking mode from LSB and slot index number from second LSB + bool blocking = comboPayload & 1; + int slot = comboPayload >> 1; + auto key = QSharedPointer(new YkChallengeResponseKey(slot, blocking)); + m_key.addChallengeResponseKey(key); + } +#endif + + m_ui->messageWidget->hideMessage(); + emit editFinished(true); } void ChangeMasterKeyWidget::reject() { - Q_EMIT editFinished(false); + emit editFinished(false); +} + +void ChangeMasterKeyWidget::challengeResponseGroupToggled(bool checked) +{ + if (checked) + pollYubikey(); +} + +void ChangeMasterKeyWidget::pollYubikey() +{ + m_ui->buttonRedetectYubikey->setEnabled(false); + m_ui->comboChallengeResponse->setEnabled(false); + m_ui->comboChallengeResponse->clear(); + m_ui->yubikeyProgress->setVisible(true); + setOkEnabled(); + + // YubiKey init is slow, detect asynchronously to not block the UI + QtConcurrent::run(YubiKey::instance(), &YubiKey::detect); +} + +void ChangeMasterKeyWidget::yubikeyDetected(int slot, bool blocking) +{ + YkChallengeResponseKey yk(slot, blocking); + // add detected YubiKey to combo box and encode blocking mode in LSB, slot number in second LSB + m_ui->comboChallengeResponse->addItem(yk.getName(), QVariant((slot << 1) | blocking)); + m_ui->comboChallengeResponse->setEnabled(m_ui->challengeResponseGroup->isChecked()); + m_ui->buttonRedetectYubikey->setEnabled(m_ui->challengeResponseGroup->isChecked()); + m_ui->yubikeyProgress->setVisible(false); + setOkEnabled(); +} + +void ChangeMasterKeyWidget::noYubikeyFound() +{ + m_ui->buttonRedetectYubikey->setEnabled(m_ui->challengeResponseGroup->isChecked()); + m_ui->yubikeyProgress->setVisible(false); + setOkEnabled(); +} + +void ChangeMasterKeyWidget::setOkEnabled() +{ + bool ok = m_ui->passwordGroup->isChecked() || + (m_ui->challengeResponseGroup->isChecked() && !m_ui->comboChallengeResponse->currentText().isEmpty()) || + (m_ui->keyFileGroup->isChecked() && !m_ui->keyFileCombo->currentText().isEmpty()); + + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); } void ChangeMasterKeyWidget::setCancelEnabled(bool enabled) diff --git a/src/gui/ChangeMasterKeyWidget.h b/src/gui/ChangeMasterKeyWidget.h index fc4a1b9cbe..2825d8d554 100644 --- a/src/gui/ChangeMasterKeyWidget.h +++ b/src/gui/ChangeMasterKeyWidget.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,16 +39,23 @@ class ChangeMasterKeyWidget : public DialogyWidget void clearForms(); CompositeKey newMasterKey(); QLabel* headlineLabel(); + +public slots: + void setOkEnabled(); void setCancelEnabled(bool enabled); -Q_SIGNALS: +signals: void editFinished(bool accepted); -private Q_SLOTS: +private slots: void generateKey(); void reject(); void createKeyFile(); void browseKeyFile(); + void yubikeyDetected(int slot, bool blocking); + void noYubikeyFound(); + void challengeResponseGroupToggled(bool checked); + void pollYubikey(); private: const QScopedPointer m_ui; diff --git a/src/gui/ChangeMasterKeyWidget.ui b/src/gui/ChangeMasterKeyWidget.ui index 419cec94cd..693d8ac1d4 100644 --- a/src/gui/ChangeMasterKeyWidget.ui +++ b/src/gui/ChangeMasterKeyWidget.ui @@ -7,10 +7,13 @@ 0 0 818 - 397 + 471 + + + @@ -123,6 +126,67 @@ + + + + true + + + Cha&llenge Response + + + true + + + true + + + + + + 0 + + + + + Refresh + + + + + + + + 0 + 0 + + + + + + + + + 16777215 + 2 + + + + 0 + + + -1 + + + false + + + + + + + + @@ -151,6 +215,12 @@ QLineEdit
gui/PasswordEdit.h
+ + MessageWidget + QWidget +
gui/MessageWidget.h
+ 1 +
passwordGroup diff --git a/src/gui/Clipboard.h b/src/gui/Clipboard.h index dafce70a2e..e0a16d26d9 100644 --- a/src/gui/Clipboard.h +++ b/src/gui/Clipboard.h @@ -31,10 +31,10 @@ class Clipboard : public QObject static Clipboard* instance(); -public Q_SLOTS: +public slots: void clearCopiedText(); -private Q_SLOTS: +private slots: void clearClipboard(); private: diff --git a/src/gui/CloneDialog.cpp b/src/gui/CloneDialog.cpp new file mode 100644 index 0000000000..5985e26a8b --- /dev/null +++ b/src/gui/CloneDialog.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CloneDialog.h" +#include "ui_CloneDialog.h" + +#include "config-keepassx.h" +#include "version.h" +#include "core/Database.h" +#include "core/Entry.h" +#include "core/FilePath.h" +#include "crypto/Crypto.h" +#include "gui/DatabaseWidget.h" + +CloneDialog::CloneDialog(DatabaseWidget* parent, Database* db, Entry* entry) + : QDialog(parent) + , m_ui(new Ui::CloneDialog()) +{ + m_db = db; + m_entry = entry; + m_parent = parent; + + m_ui->setupUi(this); + this->setFixedSize(this->sizeHint()); + + setAttribute(Qt::WA_DeleteOnClose); + + connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close())); + connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(cloneEntry())); +} + +void CloneDialog::cloneEntry() +{ + Entry::CloneFlags flags = Entry::CloneNewUuid | Entry::CloneResetTimeInfo; + + if (m_ui->titleClone->isChecked()) { + flags |= Entry::CloneRenameTitle; + } + + if (m_ui->referencesClone->isChecked()) { + flags |= Entry::CloneUserAsRef; + flags |= Entry::ClonePassAsRef; + } + + if (m_ui->historyClone->isChecked()) { + flags |= Entry::CloneIncludeHistory; + } + + Entry* entry = m_entry->clone(flags); + entry->setGroup(m_entry->group()); + + emit m_parent->refreshSearch(); + close(); +} + +CloneDialog::~CloneDialog() +{ +} diff --git a/src/gui/CloneDialog.h b/src/gui/CloneDialog.h new file mode 100644 index 0000000000..a925bb47aa --- /dev/null +++ b/src/gui/CloneDialog.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_CLONEDIALOG_H +#define KEEPASSX_CLONEDIALOG_H + +#include +#include +#include "core/Entry.h" +#include "core/Database.h" +#include "gui/DatabaseWidget.h" + +namespace Ui { + class CloneDialog; +} + +class CloneDialog : public QDialog +{ + Q_OBJECT + +public: + explicit CloneDialog(DatabaseWidget* parent = nullptr, Database* db = nullptr, Entry* entry = nullptr); + ~CloneDialog(); + +private: + QScopedPointer m_ui; + +private slots: + void cloneEntry(); + +protected: + Database* m_db; + Entry* m_entry; + DatabaseWidget* m_parent; +}; + +#endif // KEEPASSX_CLONEDIALOG_H diff --git a/src/gui/CloneDialog.ui b/src/gui/CloneDialog.ui new file mode 100644 index 0000000000..142b17b999 --- /dev/null +++ b/src/gui/CloneDialog.ui @@ -0,0 +1,72 @@ + + + CloneDialog + + + + 0 + 0 + 347 + 136 + + + + Clone Options + + + + + + + + Append ' - Copy' to title + + + true + + + + + + + Replace username and password with references + + + + + + + Copy history + + + true + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index 21df934c2c..18b4b2b620 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +28,14 @@ #include "format/KeePass2Reader.h" #include "keys/FileKey.h" #include "keys/PasswordKey.h" +#include "crypto/Random.h" +#include "keys/YkChallengeResponseKey.h" + +#include "config-keepassx.h" + +#include +#include + DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) : DialogyWidget(parent) @@ -35,13 +44,13 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) { m_ui->setupUi(this); + m_ui->messageWidget->setHidden(true); + QFont font = m_ui->labelHeadline->font(); font.setBold(true); font.setPointSize(font.pointSize() + 2); m_ui->labelHeadline->setFont(font); - m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - m_ui->buttonTogglePassword->setIcon(filePath()->onOffIcon("actions", "password-show")); connect(m_ui->buttonTogglePassword, SIGNAL(toggled(bool)), m_ui->editPassword, SLOT(setShowPassword(bool))); @@ -52,7 +61,25 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase())); connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject())); - + +#ifdef WITH_XC_YUBIKEY + m_ui->yubikeyProgress->setVisible(false); + QSizePolicy sp = m_ui->yubikeyProgress->sizePolicy(); + sp.setRetainSizeWhenHidden(true); + m_ui->yubikeyProgress->setSizePolicy(sp); + + connect(m_ui->buttonRedetectYubikey, SIGNAL(clicked()), SLOT(pollYubikey())); + connect(m_ui->comboChallengeResponse, SIGNAL(activated(int)), SLOT(activateChallengeResponse())); + + connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection); + connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection); +#else + m_ui->checkChallengeResponse->setVisible(false); + m_ui->buttonRedetectYubikey->setVisible(false); + m_ui->comboChallengeResponse->setVisible(false); + m_ui->yubikeyProgress->setVisible(false); +#endif + #ifdef Q_OS_MACOS // add random padding to layouts to align widgets properly m_ui->dialogButtonsLayout->setContentsMargins(10, 0, 15, 0); @@ -69,6 +96,10 @@ void DatabaseOpenWidget::showEvent(QShowEvent* event) { DialogyWidget::showEvent(event); m_ui->editPassword->setFocus(); + +#ifdef WITH_XC_YUBIKEY + pollYubikey(); +#endif } void DatabaseOpenWidget::load(const QString& filename) @@ -85,7 +116,6 @@ void DatabaseOpenWidget::load(const QString& filename) } } - m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); m_ui->editPassword->setFocus(); } @@ -113,8 +143,8 @@ void DatabaseOpenWidget::openDatabase() QFile file(m_filename); if (!file.open(QIODevice::ReadOnly)) { - MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") - .append(file.errorString())); + m_ui->messageWidget->showMessage( + tr("Unable to open the database.").append("\n").append(file.errorString()), MessageWidget::Error); return; } if (m_db) { @@ -125,11 +155,14 @@ void DatabaseOpenWidget::openDatabase() QApplication::restoreOverrideCursor(); if (m_db) { - Q_EMIT editFinished(true); + if (m_ui->messageWidget->isVisible()) { + m_ui->messageWidget->animatedHide(); + } + emit editFinished(true); } else { - MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") - .append(reader.errorString())); + m_ui->messageWidget->showMessage(tr("Unable to open the database.") + .append("\n").append(reader.errorString()), MessageWidget::Error); m_ui->editPassword->clear(); } } @@ -143,32 +176,56 @@ CompositeKey DatabaseOpenWidget::databaseKey() } QHash lastKeyFiles = config()->get("LastKeyFiles").toHash(); + QHash lastChallengeResponse = config()->get("LastChallengeResponse").toHash(); if (m_ui->checkKeyFile->isChecked()) { FileKey key; QString keyFilename = m_ui->comboKeyFile->currentText(); QString errorMsg; if (!key.load(keyFilename, &errorMsg)) { - MessageBox::warning(this, tr("Error"), tr("Can't open key file").append(":\n").append(errorMsg)); + m_ui->messageWidget->showMessage(tr("Can't open key file").append(":\n") + .append(errorMsg), MessageWidget::Error); return CompositeKey(); } masterKey.addKey(key); lastKeyFiles[m_filename] = keyFilename; - } - else { + } else { lastKeyFiles.remove(m_filename); } + if (m_ui->checkChallengeResponse->isChecked()) { + lastChallengeResponse[m_filename] = true; + } else { + lastChallengeResponse.remove(m_filename); + } + if (config()->get("RememberLastKeyFiles").toBool()) { config()->set("LastKeyFiles", lastKeyFiles); } +#ifdef WITH_XC_YUBIKEY + if (config()->get("RememberLastKeyFiles").toBool()) { + config()->set("LastChallengeResponse", lastChallengeResponse); + } + + if (m_ui->checkChallengeResponse->isChecked()) { + int selectionIndex = m_ui->comboChallengeResponse->currentIndex(); + int comboPayload = m_ui->comboChallengeResponse->itemData(selectionIndex).toInt(); + + // read blocking mode from LSB and slot index number from second LSB + bool blocking = comboPayload & 1; + int slot = comboPayload >> 1; + auto key = QSharedPointer(new YkChallengeResponseKey(slot, blocking)); + masterKey.addChallengeResponseKey(key); + } +#endif + return masterKey; } void DatabaseOpenWidget::reject() { - Q_EMIT editFinished(false); + emit editFinished(false); } void DatabaseOpenWidget::activatePassword() @@ -181,6 +238,11 @@ void DatabaseOpenWidget::activateKeyFile() m_ui->checkKeyFile->setChecked(true); } +void DatabaseOpenWidget::activateChallengeResponse() +{ + m_ui->checkChallengeResponse->setChecked(true); +} + void DatabaseOpenWidget::browseKeyFile() { QString filters = QString("%1 (*);;%2 (*.key)").arg(tr("All files"), tr("Key files")); @@ -190,3 +252,40 @@ void DatabaseOpenWidget::browseKeyFile() m_ui->comboKeyFile->lineEdit()->setText(filename); } } + +void DatabaseOpenWidget::pollYubikey() +{ + m_ui->buttonRedetectYubikey->setEnabled(false); + m_ui->checkChallengeResponse->setEnabled(false); + m_ui->checkChallengeResponse->setChecked(false); + m_ui->comboChallengeResponse->setEnabled(false); + m_ui->comboChallengeResponse->clear(); + m_ui->yubikeyProgress->setVisible(true); + + // YubiKey init is slow, detect asynchronously to not block the UI + QtConcurrent::run(YubiKey::instance(), &YubiKey::detect); +} + +void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking) +{ + YkChallengeResponseKey yk(slot, blocking); + // add detected YubiKey to combo box and encode blocking mode in LSB, slot number in second LSB + m_ui->comboChallengeResponse->addItem(yk.getName(), QVariant((slot << 1) | blocking)); + m_ui->comboChallengeResponse->setEnabled(true); + m_ui->checkChallengeResponse->setEnabled(true); + m_ui->buttonRedetectYubikey->setEnabled(true); + m_ui->yubikeyProgress->setVisible(false); + + if (config()->get("RememberLastKeyFiles").toBool()) { + QHash lastChallengeResponse = config()->get("LastChallengeResponse").toHash(); + if (lastChallengeResponse.contains(m_filename)) { + m_ui->checkChallengeResponse->setChecked(true); + } + } +} + +void DatabaseOpenWidget::noYubikeyFound() +{ + m_ui->buttonRedetectYubikey->setEnabled(true); + m_ui->yubikeyProgress->setVisible(false); +} diff --git a/src/gui/DatabaseOpenWidget.h b/src/gui/DatabaseOpenWidget.h index 34f401a09f..49d3fb83ee 100644 --- a/src/gui/DatabaseOpenWidget.h +++ b/src/gui/DatabaseOpenWidget.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,21 +42,27 @@ class DatabaseOpenWidget : public DialogyWidget void enterKey(const QString& pw, const QString& keyFile); Database* database(); -Q_SIGNALS: +public slots: + void pollYubikey(); + +signals: void editFinished(bool accepted); protected: void showEvent(QShowEvent* event) override; CompositeKey databaseKey(); -protected Q_SLOTS: +protected slots: virtual void openDatabase(); void reject(); -private Q_SLOTS: +private slots: void activatePassword(); void activateKeyFile(); + void activateChallengeResponse(); void browseKeyFile(); + void yubikeyDetected(int slot, bool blocking); + void noYubikeyFound(); protected: const QScopedPointer m_ui; diff --git a/src/gui/DatabaseOpenWidget.ui b/src/gui/DatabaseOpenWidget.ui index 17360f4c4d..dba71d0fac 100644 --- a/src/gui/DatabaseOpenWidget.ui +++ b/src/gui/DatabaseOpenWidget.ui @@ -7,13 +7,16 @@ 0 0 596 - 250 + 302
- + 8 + + + @@ -82,7 +85,7 @@ - + 5 @@ -115,7 +118,7 @@
- + 5 @@ -139,6 +142,87 @@
+ + + + 5 + + + 5 + + + 0 + + + + + true + + + Refresh + + + + + + + false + + + + 0 + 0 + + + + false + + + + + + + + 16777215 + 2 + + + + 0 + + + 0 + + + -1 + + + false + + + + + + + + + 0 + + + 2 + + + + + false + + + Challenge Response: + + + + +
@@ -179,6 +263,12 @@ QLineEdit
gui/PasswordEdit.h
+ + MessageWidget + QWidget +
gui/MessageWidget.h
+ 1 +
checkPassword diff --git a/src/gui/DatabaseRepairWidget.cpp b/src/gui/DatabaseRepairWidget.cpp index e48e0f1f6a..2b0039408a 100644 --- a/src/gui/DatabaseRepairWidget.cpp +++ b/src/gui/DatabaseRepairWidget.cpp @@ -50,7 +50,7 @@ void DatabaseRepairWidget::openDatabase() QString errorMsg; if (!key.load(keyFilename, &errorMsg)) { MessageBox::warning(this, tr("Error"), tr("Can't open key file").append(":\n").append(errorMsg)); - Q_EMIT editFinished(false); + emit editFinished(false); return; } masterKey.addKey(key); @@ -62,7 +62,7 @@ void DatabaseRepairWidget::openDatabase() if (!file.open(QIODevice::ReadOnly)) { MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") .append(file.errorString())); - Q_EMIT editFinished(false); + emit editFinished(false); return; } if (m_db) { @@ -75,21 +75,21 @@ void DatabaseRepairWidget::openDatabase() switch (repairResult) { case KeePass2Repair::NothingTodo: MessageBox::information(this, tr("Error"), tr("Database opened fine. Nothing to do.")); - Q_EMIT editFinished(false); + emit editFinished(false); return; case KeePass2Repair::UnableToOpen: MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") .append(repair.errorString())); - Q_EMIT editFinished(false); + emit editFinished(false); return; case KeePass2Repair::RepairSuccess: m_db = repair.database(); MessageBox::warning(this, tr("Success"), tr("The database has been successfully repaired\nYou can now save it.")); - Q_EMIT editFinished(true); + emit editFinished(true); return; case KeePass2Repair::RepairFailed: MessageBox::warning(this, tr("Error"), tr("Unable to repair the database.")); - Q_EMIT editFinished(false); + emit editFinished(false); return; } } @@ -97,9 +97,9 @@ void DatabaseRepairWidget::openDatabase() void DatabaseRepairWidget::processEditFinished(bool result) { if (result) { - Q_EMIT success(); + emit success(); } else { - Q_EMIT error(); + emit error(); } } diff --git a/src/gui/DatabaseRepairWidget.h b/src/gui/DatabaseRepairWidget.h index 6775d2dc16..67b48ce54e 100644 --- a/src/gui/DatabaseRepairWidget.h +++ b/src/gui/DatabaseRepairWidget.h @@ -27,14 +27,14 @@ class DatabaseRepairWidget : public DatabaseOpenWidget public: explicit DatabaseRepairWidget(QWidget* parent = nullptr); -Q_SIGNALS: +signals: void success(); void error(); protected: void openDatabase() override; -private Q_SLOTS: +private slots: void processEditFinished(bool result); }; diff --git a/src/gui/DatabaseSettingsWidget.cpp b/src/gui/DatabaseSettingsWidget.cpp index b0759bf3a0..7c51edfd48 100644 --- a/src/gui/DatabaseSettingsWidget.cpp +++ b/src/gui/DatabaseSettingsWidget.cpp @@ -21,6 +21,8 @@ #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" +#include "crypto/SymmetricCipher.h" +#include "format/KeePass2.h" #include "keys/CompositeKey.h" DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent) @@ -53,6 +55,7 @@ void DatabaseSettingsWidget::load(Database* db) m_ui->dbDescriptionEdit->setText(meta->description()); m_ui->recycleBinEnabledCheckBox->setChecked(meta->recycleBinEnabled()); m_ui->defaultUsernameEdit->setText(meta->defaultUserName()); + m_ui->AlgorithmComboBox->setCurrentIndex(SymmetricCipher::cipherToAlgorithm(m_db->cipher())); m_ui->transformRoundsSpinBox->setValue(m_db->transformRounds()); if (meta->historyMaxItems() > -1) { m_ui->historyMaxItemsSpinBox->setValue(meta->historyMaxItems()); @@ -82,6 +85,8 @@ void DatabaseSettingsWidget::save() meta->setName(m_ui->dbNameEdit->text()); meta->setDescription(m_ui->dbDescriptionEdit->text()); meta->setDefaultUserName(m_ui->defaultUsernameEdit->text()); + m_db->setCipher(SymmetricCipher::algorithmToCipher(static_cast + (m_ui->AlgorithmComboBox->currentIndex()))); meta->setRecycleBinEnabled(m_ui->recycleBinEnabledCheckBox->isChecked()); if (static_cast(m_ui->transformRoundsSpinBox->value()) != m_db->transformRounds()) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); @@ -119,12 +124,12 @@ void DatabaseSettingsWidget::save() truncateHistories(); } - Q_EMIT editFinished(true); + emit editFinished(true); } void DatabaseSettingsWidget::reject() { - Q_EMIT editFinished(false); + emit editFinished(false); } void DatabaseSettingsWidget::transformRoundsBenchmark() diff --git a/src/gui/DatabaseSettingsWidget.h b/src/gui/DatabaseSettingsWidget.h index 040e0dbe7b..733b32f876 100644 --- a/src/gui/DatabaseSettingsWidget.h +++ b/src/gui/DatabaseSettingsWidget.h @@ -38,10 +38,10 @@ class DatabaseSettingsWidget : public DialogyWidget void load(Database* db); -Q_SIGNALS: +signals: void editFinished(bool accepted); -private Q_SLOTS: +private slots: void save(); void reject(); void transformRoundsBenchmark(); diff --git a/src/gui/DatabaseSettingsWidget.ui b/src/gui/DatabaseSettingsWidget.ui index 1d1351fde9..c38aebc8cc 100644 --- a/src/gui/DatabaseSettingsWidget.ui +++ b/src/gui/DatabaseSettingsWidget.ui @@ -48,7 +48,7 @@ - + @@ -94,21 +94,21 @@ - + Max. history size: - + Transform rounds: - + Max. history items: @@ -118,7 +118,7 @@ - + @@ -135,7 +135,7 @@ - + Default username: @@ -145,7 +145,7 @@ - + @@ -168,14 +168,14 @@ - + Use recycle bin - + true @@ -189,6 +189,27 @@ + + + + + AES: 256 Bit (default) + + + + + Twofish: 256 Bit + + + + + + + + Algorithm: + + + diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 3168fc383b..e13158eacf 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +20,6 @@ #include #include -#include #include #include @@ -54,7 +54,7 @@ const int DatabaseTabWidget::LastDatabasesCount = 5; DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) : QTabWidget(parent) - , m_dbWidgetSateSync(new DatabaseWidgetStateSync(this)) + , m_dbWidgetStateSync(new DatabaseWidgetStateSync(this)) { DragTabBar* tabBar = new DragTabBar(this); setTabBar(tabBar); @@ -62,7 +62,7 @@ DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) connect(this, SIGNAL(tabCloseRequested(int)), SLOT(closeDatabase(int))); connect(this, SIGNAL(currentChanged(int)), SLOT(emitActivateDatabaseChanged())); - connect(this, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), m_dbWidgetSateSync, SLOT(setActive(DatabaseWidget*))); + connect(this, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), m_dbWidgetStateSync, SLOT(setActive(DatabaseWidget*))); connect(autoType(), SIGNAL(globalShortcutTriggered()), SLOT(performGlobalAutoType())); } @@ -120,7 +120,7 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, QFileInfo fileInfo(fileName); QString canonicalFilePath = fileInfo.canonicalFilePath(); if (canonicalFilePath.isEmpty()) { - MessageBox::warning(this, tr("Warning"), tr("File not found!")); + emit messageGlobal(tr("File not found!"), MessageWidget::Error); return; } @@ -140,8 +140,9 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, QFile file(fileName); if (!file.open(QIODevice::ReadWrite)) { if (!file.open(QIODevice::ReadOnly)) { - MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") - .append(file.errorString())); + // can't open + emit messageGlobal( + tr("Unable to open the database.").append("\n").append(file.errorString()), MessageWidget::Error); return; } else { @@ -196,6 +197,10 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, insertDatabase(db, dbStruct); + if (dbStruct.readOnly) { + emit messageTab(tr("File opened in read only mode."), MessageWidget::Warning); + } + updateLastDatabases(dbStruct.filePath); if (!pw.isNull() || !keyFile.isEmpty()) { @@ -204,6 +209,24 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, else { dbStruct.dbWidget->switchToOpenDatabase(dbStruct.filePath); } + emit messageDismissGlobal(); +} + +void DatabaseTabWidget::importCsv() +{ + QString fileName = fileDialog()->getOpenFileName(this, tr("Open CSV file"), QString(), + tr("CSV file") + " (*.csv);;" + tr("All files (*)")); + + if (fileName.isEmpty()) { + return; + } + + Database* db = new Database(); + DatabaseManagerStruct dbStruct; + dbStruct.dbWidget = new DatabaseWidget(db, this); + + insertDatabase(db, dbStruct); + dbStruct.dbWidget->switchToImportCsv(fileName); } void DatabaseTabWidget::mergeDatabase() @@ -308,7 +331,7 @@ void DatabaseTabWidget::deleteDatabase(Database* db) delete db; if (emitDatabaseWithFileClosed) { - Q_EMIT databaseWithFileClosed(filePath); + emit databaseWithFileClosed(filePath); } } @@ -325,40 +348,27 @@ bool DatabaseTabWidget::closeAllDatabases() bool DatabaseTabWidget::saveDatabase(Database* db) { DatabaseManagerStruct& dbStruct = m_dbList[db]; - // temporarily disable autoreload - dbStruct.dbWidget->ignoreNextAutoreload(); if (dbStruct.saveToFilename) { - QSaveFile saveFile(dbStruct.canonicalFilePath); - if (saveFile.open(QIODevice::WriteOnly)) { - // write the database to the file - m_writer.writeDatabase(&saveFile, db); - if (m_writer.hasError()) { - MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n" - + m_writer.errorString()); - return false; - } - if (saveFile.commit()) { - // successfully saved database file - dbStruct.modified = false; - dbStruct.dbWidget->databaseSaved(); - updateTabName(db); - return true; - } - else { - MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n" - + saveFile.errorString()); - return false; - } - } - else { - MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n" - + saveFile.errorString()); + dbStruct.dbWidget->blockAutoReload(true); + QString errorMessage = db->saveToFile(dbStruct.canonicalFilePath); + dbStruct.dbWidget->blockAutoReload(false); + + if (errorMessage.isEmpty()) { + // successfully saved database file + dbStruct.modified = false; + dbStruct.dbWidget->databaseSaved(); + updateTabName(db); + emit messageDismissTab(); + return true; + } else { + emit messageTab(tr("Writing the database failed.").append("\n").append(errorMessage), + MessageWidget::Error); return false; } - } - else { + + } else { return saveDatabaseAs(db); } } @@ -496,8 +506,9 @@ void DatabaseTabWidget::exportToCsv() CsvExporter csvExporter; if (!csvExporter.exportDatabase(fileName, db)) { - MessageBox::critical(this, tr("Error"), tr("Writing the CSV file failed.") + "\n\n" - + csvExporter.errorString()); + emit messageGlobal( + tr("Writing the CSV file failed.").append("\n") + .append(csvExporter.errorString()), MessageWidget::Error); } } @@ -520,6 +531,25 @@ bool DatabaseTabWidget::readOnly(int index) return indexDatabaseManagerStruct(index).readOnly; } +bool DatabaseTabWidget::isModified(int index) +{ + if (index == -1) { + index = currentIndex(); + } + + return indexDatabaseManagerStruct(index).modified; +} + +QString DatabaseTabWidget::databasePath(int index) +{ + if (index == -1) { + index = currentIndex(); + } + + return indexDatabaseManagerStruct(index).filePath; +} + + void DatabaseTabWidget::updateTabName(Database* db) { int index = databaseIndex(db); @@ -557,7 +587,7 @@ void DatabaseTabWidget::updateTabName(Database* db) } setTabText(index, tabName); - Q_EMIT tabNameChanged(); + emit tabNameChanged(); } void DatabaseTabWidget::updateTabNameFromDbSender() @@ -726,6 +756,7 @@ void DatabaseTabWidget::lockDatabases() } else if (result == QMessageBox::Discard) { m_dbList[db].modified = false; + m_dbList[db].dbWidget->databaseSaved(); } else if (result == QMessageBox::Cancel) { continue; @@ -736,7 +767,7 @@ void DatabaseTabWidget::lockDatabases() // database has changed so we can't use the db variable anymore updateTabName(dbWidget->database()); - Q_EMIT databaseLocked(dbWidget); + emit databaseLocked(dbWidget); } } @@ -794,12 +825,12 @@ void DatabaseTabWidget::changeDatabase(Database* newDb, bool unsavedChanges) void DatabaseTabWidget::emitActivateDatabaseChanged() { - Q_EMIT activateDatabaseChanged(currentDatabaseWidget()); + emit activateDatabaseChanged(currentDatabaseWidget()); } void DatabaseTabWidget::emitDatabaseUnlockedFromDbWidgetSender() { - Q_EMIT databaseUnlocked(static_cast(sender())); + emit databaseUnlocked(static_cast(sender())); } void DatabaseTabWidget::connectDatabase(Database* newDb, Database* oldDb) diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index 24bdbde2f2..847eaef05d 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,14 +22,15 @@ #include #include -#include "format/KeePass2Writer.h" #include "gui/DatabaseWidget.h" +#include "gui/MessageWidget.h" class DatabaseWidget; class DatabaseWidgetStateSync; class DatabaseOpenWidget; class QFile; class QLockFile; +class MessageWidget; struct DatabaseManagerStruct { @@ -61,9 +63,10 @@ class DatabaseTabWidget : public QTabWidget static const int LastDatabasesCount; -public Q_SLOTS: +public slots: void newDatabase(); void openDatabase(); + void importCsv(); void mergeDatabase(); void importKeePass1Database(); bool saveDatabase(int index = -1); @@ -75,17 +78,23 @@ public Q_SLOTS: void changeMasterKey(); void changeDatabaseSettings(); bool readOnly(int index = -1); + bool isModified(int index = -1); void performGlobalAutoType(); void lockDatabases(); + QString databasePath(int index = -1); -Q_SIGNALS: +signals: void tabNameChanged(); void databaseWithFileClosed(QString filePath); void activateDatabaseChanged(DatabaseWidget* dbWidget); void databaseLocked(DatabaseWidget* dbWidget); void databaseUnlocked(DatabaseWidget* dbWidget); + void messageGlobal(const QString&, MessageWidget::MessageType type); + void messageTab(const QString&, MessageWidget::MessageType type); + void messageDismissGlobal(); + void messageDismissTab(); -private Q_SLOTS: +private slots: void updateTabName(Database* db); void updateTabNameFromDbSender(); void updateTabNameFromDbWidgetSender(); @@ -108,9 +117,8 @@ private Q_SLOTS: void updateLastDatabases(const QString& filename); void connectDatabase(Database* newDb, Database* oldDb = nullptr); - KeePass2Writer m_writer; QHash m_dbList; - DatabaseWidgetStateSync* m_dbWidgetSateSync; + DatabaseWidgetStateSync* m_dbWidgetStateSync; }; #endif // KEEPASSX_DATABASETABWIDGET_H diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index 8a7b2cf3bd..c65d52f54b 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +42,9 @@ #include "format/KeePass2Reader.h" #include "gui/ChangeMasterKeyWidget.h" #include "gui/Clipboard.h" +#include "gui/CloneDialog.h" +#include "gui/SetupTotpDialog.h" +#include "gui/TotpDialog.h" #include "gui/DatabaseOpenWidget.h" #include "gui/DatabaseSettingsWidget.h" #include "gui/KeePass1OpenWidget.h" @@ -60,7 +64,14 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) , m_newParent(nullptr) { m_mainWidget = new QWidget(this); - QLayout* layout = new QHBoxLayout(m_mainWidget); + + m_messageWidget = new MessageWidget(this); + m_messageWidget->setHidden(true); + + QVBoxLayout* mainLayout = new QVBoxLayout(); + QLayout* layout = new QHBoxLayout(); + mainLayout->addWidget(m_messageWidget); + mainLayout->addLayout(layout); m_splitter = new QSplitter(m_mainWidget); m_splitter->setChildrenCollapsible(false); @@ -83,7 +94,8 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) m_searchingLabel = new QLabel(); m_searchingLabel->setText(tr("Searching...")); m_searchingLabel->setAlignment(Qt::AlignCenter); - m_searchingLabel->setStyleSheet("background-color: rgb(255, 253, 160);" + m_searchingLabel->setStyleSheet("color: rgb(0, 0, 0);" + "background-color: rgb(255, 253, 160);" "border: 2px solid rgb(190, 190, 190);" "border-radius: 5px;"); @@ -105,7 +117,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) m_splitter->setStretchFactor(1, 70); layout->addWidget(m_splitter); - m_mainWidget->setLayout(layout); + m_mainWidget->setLayout(mainLayout); m_editEntryWidget = new EditEntryWidget(); m_editEntryWidget->setObjectName("editEntryWidget"); @@ -114,6 +126,8 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) m_editGroupWidget->setObjectName("editGroupWidget"); m_changeMasterKeyWidget = new ChangeMasterKeyWidget(); m_changeMasterKeyWidget->headlineLabel()->setText(tr("Change master key")); + m_csvImportWizard = new CsvImportWizard(); + m_csvImportWizard->setObjectName("csvImportWizard"); QFont headlineLabelFont = m_changeMasterKeyWidget->headlineLabel()->font(); headlineLabelFont.setBold(true); headlineLabelFont.setPointSize(headlineLabelFont.pointSize() + 2); @@ -137,6 +151,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) addWidget(m_databaseSettingsWidget); addWidget(m_historyEditEntryWidget); addWidget(m_databaseOpenWidget); + addWidget(m_csvImportWizard); addWidget(m_databaseOpenMergeWidget); addWidget(m_keepass1OpenWidget); addWidget(m_unlockDatabaseWidget); @@ -157,20 +172,22 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) connect(m_databaseOpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool))); connect(m_databaseOpenMergeWidget, SIGNAL(editFinished(bool)), SLOT(mergeDatabase(bool))); connect(m_keepass1OpenWidget, SIGNAL(editFinished(bool)), SLOT(openDatabase(bool))); + connect(m_csvImportWizard, SIGNAL(importFinished(bool)), SLOT(csvImportFinished(bool))); connect(m_unlockDatabaseWidget, SIGNAL(editFinished(bool)), SLOT(unlockDatabase(bool))); connect(m_unlockDatabaseDialog, SIGNAL(unlockDone(bool)), SLOT(unlockDatabase(bool))); connect(&m_fileWatcher, SIGNAL(fileChanged(QString)), this, SLOT(onWatchedFileChanged())); connect(&m_fileWatchTimer, SIGNAL(timeout()), this, SLOT(reloadDatabaseFile())); - connect(&m_ignoreWatchTimer, SIGNAL(timeout()), this, SLOT(onWatchedFileChanged())); + connect(&m_fileWatchUnblockTimer, SIGNAL(timeout()), this, SLOT(unblockAutoReload())); connect(this, SIGNAL(currentChanged(int)), this, SLOT(emitCurrentModeChanged())); m_databaseModified = false; m_fileWatchTimer.setSingleShot(true); - m_ignoreWatchTimer.setSingleShot(true); - m_ignoreNextAutoreload = false; + m_fileWatchUnblockTimer.setSingleShot(true); + m_ignoreAutoReload = false; m_searchCaseSensitive = false; + m_searchLimitGroup = config()->get("SearchLimitGroup", false).toBool(); setCurrentWidget(m_mainWidget); } @@ -184,6 +201,9 @@ DatabaseWidget::Mode DatabaseWidget::currentMode() const if (currentWidget() == nullptr) { return DatabaseWidget::None; } + else if (currentWidget() == m_csvImportWizard) { + return DatabaseWidget::ImportMode; + } else if (currentWidget() == m_mainWidget) { return DatabaseWidget::ViewMode; } @@ -255,7 +275,7 @@ void DatabaseWidget::clearAllWidgets() void DatabaseWidget::emitCurrentModeChanged() { - Q_EMIT currentModeChanged(currentMode()); + emit currentModeChanged(currentMode()); } Database* DatabaseWidget::database() @@ -301,7 +321,7 @@ void DatabaseWidget::replaceDatabase(Database* db) Database* oldDb = m_db; m_db = db; m_groupView->changeDatabase(m_db); - Q_EMIT databaseChanged(m_db, m_databaseModified); + emit databaseChanged(m_db, m_databaseModified); delete oldDb; } @@ -313,14 +333,53 @@ void DatabaseWidget::cloneEntry() return; } - Entry* entry = currentEntry->clone(Entry::CloneNewUuid | Entry::CloneResetTimeInfo | Entry::CloneRenameTitle); - entry->setGroup(currentEntry->group()); - if (isInSearchMode()) - search(m_lastSearchText); - m_entryView->setFocus(); - m_entryView->setCurrentEntry(entry); + CloneDialog* cloneDialog = new CloneDialog(this, m_db, currentEntry); + cloneDialog->show(); + return; +} + +void DatabaseWidget::showTotp() +{ + Entry* currentEntry = m_entryView->currentEntry(); + if (!currentEntry) { + Q_ASSERT(false); + return; + } + + TotpDialog* totpDialog = new TotpDialog(this, currentEntry); + totpDialog->open(); +} + +void DatabaseWidget::copyTotp() +{ + Entry* currentEntry = m_entryView->currentEntry(); + if (!currentEntry) { + Q_ASSERT(false); + return; + } + setClipboardTextAndMinimize(currentEntry->totp()); +} + +void DatabaseWidget::setupTotp() +{ + Entry* currentEntry = m_entryView->currentEntry(); + if (!currentEntry) { + Q_ASSERT(false); + return; + } + + SetupTotpDialog* setupTotpDialog = new SetupTotpDialog(this, currentEntry); + if (currentEntry->hasTotp()) { + setupTotpDialog->setSeed(currentEntry->totpSeed()); + setupTotpDialog->setStep(currentEntry->totpStep()); + setupTotpDialog->setDigits(currentEntry->totpDigits()); + } + + setupTotpDialog->open(); + } + void DatabaseWidget::deleteEntries() { const QModelIndexList selected = m_entryView->selectionModel()->selectedRows(); @@ -359,6 +418,7 @@ void DatabaseWidget::deleteEntries() for (Entry* entry : asConst(selectedEntries)) { delete entry; } + refreshSearch(); } } else { @@ -401,7 +461,7 @@ void DatabaseWidget::copyTitle() return; } - setClipboardTextAndMinimize(currentEntry->title()); + setClipboardTextAndMinimize(currentEntry->resolveMultiplePlaceholders(currentEntry->title())); } void DatabaseWidget::copyUsername() @@ -412,7 +472,7 @@ void DatabaseWidget::copyUsername() return; } - setClipboardTextAndMinimize(currentEntry->username()); + setClipboardTextAndMinimize(currentEntry->resolveMultiplePlaceholders(currentEntry->username())); } void DatabaseWidget::copyPassword() @@ -423,7 +483,7 @@ void DatabaseWidget::copyPassword() return; } - setClipboardTextAndMinimize(currentEntry->password()); + setClipboardTextAndMinimize(currentEntry->resolveMultiplePlaceholders(currentEntry->password())); } void DatabaseWidget::copyURL() @@ -434,7 +494,7 @@ void DatabaseWidget::copyURL() return; } - setClipboardTextAndMinimize(currentEntry->url()); + setClipboardTextAndMinimize(currentEntry->resolveMultiplePlaceholders(currentEntry->url())); } void DatabaseWidget::copyNotes() @@ -445,7 +505,7 @@ void DatabaseWidget::copyNotes() return; } - setClipboardTextAndMinimize(currentEntry->notes()); + setClipboardTextAndMinimize(currentEntry->resolveMultiplePlaceholders(currentEntry->notes())); } void DatabaseWidget::copyAttribute(QAction* action) @@ -456,7 +516,7 @@ void DatabaseWidget::copyAttribute(QAction* action) return; } - setClipboardTextAndMinimize(currentEntry->attributes()->value(action->text())); + setClipboardTextAndMinimize(currentEntry->resolveMultiplePlaceholders(currentEntry->attributes()->value(action->text()))); } void DatabaseWidget::setClipboardTextAndMinimize(const QString& text) @@ -618,6 +678,16 @@ void DatabaseWidget::setCurrentWidget(QWidget* widget) adjustSize(); } +void DatabaseWidget::csvImportFinished(bool accepted) +{ + if (!accepted) { + emit closeRequest(); + } + else { + setCurrentWidget(m_mainWidget); + } +} + void DatabaseWidget::switchToView(bool accepted) { if (m_newGroup) { @@ -689,12 +759,12 @@ void DatabaseWidget::updateMasterKey(bool accepted) QApplication::restoreOverrideCursor(); if (!result) { - MessageBox::critical(this, tr("Error"), tr("Unable to calculate master key")); + m_messageWidget->showMessage(tr("Unable to calculate master key"), MessageWidget::Error); return; } } else if (!m_db->hasKey()) { - Q_EMIT closeRequest(); + emit closeRequest(); return; } @@ -706,7 +776,7 @@ void DatabaseWidget::openDatabase(bool accepted) if (accepted) { replaceDatabase(static_cast(sender())->database()); setCurrentWidget(m_mainWidget); - Q_EMIT unlockedDatabase(); + emit unlockedDatabase(); // We won't need those anymore and KeePass1OpenWidget closes // the file in its dtor. @@ -721,7 +791,7 @@ void DatabaseWidget::openDatabase(bool accepted) if (m_databaseOpenWidget->database()) { delete m_databaseOpenWidget->database(); } - Q_EMIT closeRequest(); + emit closeRequest(); } } @@ -729,14 +799,14 @@ void DatabaseWidget::mergeDatabase(bool accepted) { if (accepted) { if (!m_db) { - MessageBox::critical(this, tr("Error"), tr("No current database.")); + m_messageWidget->showMessage(tr("No current database."), MessageWidget::Error); return; } Database* srcDb = static_cast(sender())->database(); if (!srcDb) { - MessageBox::critical(this, tr("Error"), tr("No source database, nothing to do.")); + m_messageWidget->showMessage(tr("No source database, nothing to do."), MessageWidget::Error); return; } @@ -744,13 +814,13 @@ void DatabaseWidget::mergeDatabase(bool accepted) } setCurrentWidget(m_mainWidget); - Q_EMIT databaseMerged(m_db); + emit databaseMerged(m_db); } void DatabaseWidget::unlockDatabase(bool accepted) { if (!accepted) { - Q_EMIT closeRequest(); + emit closeRequest(); return; } @@ -769,7 +839,7 @@ void DatabaseWidget::unlockDatabase(bool accepted) setCurrentWidget(m_mainWidget); m_unlockDatabaseWidget->clearForms(); - Q_EMIT unlockedDatabase(); + emit unlockedDatabase(); if (sender() == m_unlockDatabaseDialog) { QList dbList; @@ -838,12 +908,21 @@ void DatabaseWidget::switchToOpenDatabase(const QString& fileName, const QString m_databaseOpenWidget->enterKey(password, keyFile); } +void DatabaseWidget::switchToImportCsv(const QString& fileName) +{ + updateFilename(fileName); + switchToMasterKeyChange(); + m_csvImportWizard->load(fileName, m_db); + setCurrentWidget(m_csvImportWizard); +} + void DatabaseWidget::switchToOpenMergeDatabase(const QString& fileName) { m_databaseOpenMergeWidget->load(fileName); setCurrentWidget(m_databaseOpenMergeWidget); } + void DatabaseWidget::switchToOpenMergeDatabase(const QString& fileName, const QString& password, const QString& keyFile) { @@ -868,6 +947,12 @@ void DatabaseWidget::databaseSaved() m_databaseModified = false; } +void DatabaseWidget::refreshSearch() { + if (isInSearchMode()) { + search(m_lastSearchText); + } +} + void DatabaseWidget::search(const QString& searchtext) { if (searchtext.isEmpty()) @@ -876,11 +961,13 @@ void DatabaseWidget::search(const QString& searchtext) return; } - Q_EMIT searchModeAboutToActivate(); + emit searchModeAboutToActivate(); Qt::CaseSensitivity caseSensitive = m_searchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; - QList searchResult = EntrySearcher().search(searchtext, currentGroup(), caseSensitive); + Group* searchGroup = m_searchLimitGroup ? currentGroup() : m_db->rootGroup(); + + QList searchResult = EntrySearcher().search(searchtext, searchGroup, caseSensitive); m_entryView->setEntryList(searchResult); m_lastSearchText = searchtext; @@ -895,15 +982,19 @@ void DatabaseWidget::search(const QString& searchtext) m_searchingLabel->setVisible(true); - Q_EMIT searchModeActivated(); + emit searchModeActivated(); } void DatabaseWidget::setSearchCaseSensitive(bool state) { m_searchCaseSensitive = state; + refreshSearch(); +} - if (isInSearchMode()) - search(m_lastSearchText); +void DatabaseWidget::setSearchLimitGroup(bool state) +{ + m_searchLimitGroup = state; + refreshSearch(); } void DatabaseWidget::onGroupChanged(Group* group) @@ -924,12 +1015,12 @@ void DatabaseWidget::endSearch() { if (isInSearchMode()) { - Q_EMIT listModeAboutToActivate(); + emit listModeAboutToActivate(); // Show the normal entry view of the current group m_entryView->setGroup(currentGroup()); - Q_EMIT listModeActivated(); + emit listModeActivated(); } m_searchingLabel->setVisible(false); @@ -940,12 +1031,12 @@ void DatabaseWidget::endSearch() void DatabaseWidget::emitGroupContextMenuRequested(const QPoint& pos) { - Q_EMIT groupContextMenuRequested(m_groupView->viewport()->mapToGlobal(pos)); + emit groupContextMenuRequested(m_groupView->viewport()->mapToGlobal(pos)); } void DatabaseWidget::emitEntryContextMenuRequested(const QPoint& pos) { - Q_EMIT entryContextMenuRequested(m_entryView->viewport()->mapToGlobal(pos)); + emit entryContextMenuRequested(m_entryView->viewport()->mapToGlobal(pos)); } bool DatabaseWidget::dbHasKey() const @@ -984,6 +1075,7 @@ void DatabaseWidget::lock() m_entryBeforeLock = m_entryView->currentEntry()->uuid(); } + endSearch(); clearAllWidgets(); m_unlockDatabaseWidget->load(m_filename); setCurrentWidget(m_unlockDatabaseWidget); @@ -994,7 +1086,7 @@ void DatabaseWidget::lock() void DatabaseWidget::updateFilename(const QString& fileName) { - if (! m_filename.isEmpty()) { + if (!m_filename.isEmpty()) { m_fileWatcher.removePath(m_filename); } @@ -1002,26 +1094,31 @@ void DatabaseWidget::updateFilename(const QString& fileName) m_filename = fileName; } -void DatabaseWidget::ignoreNextAutoreload() +void DatabaseWidget::blockAutoReload(bool block) +{ + if (block) { + m_ignoreAutoReload = true; + m_fileWatchTimer.stop(); + } else { + m_fileWatchUnblockTimer.start(500); + } +} + +void DatabaseWidget::unblockAutoReload() { - m_ignoreNextAutoreload = true; - m_ignoreWatchTimer.start(100); + m_ignoreAutoReload = false; + updateFilename(m_filename); } void DatabaseWidget::onWatchedFileChanged() { - if (m_ignoreNextAutoreload) { - // Reset the watch - m_ignoreNextAutoreload = false; - m_ignoreWatchTimer.stop(); - m_fileWatcher.addPath(m_filename); + if (m_ignoreAutoReload) { + return; } - else { - if (m_fileWatchTimer.isActive()) - return; + if (m_fileWatchTimer.isActive()) + return; - m_fileWatchTimer.start(500); - } + m_fileWatchTimer.start(500); } void DatabaseWidget::reloadDatabaseFile() @@ -1086,8 +1183,9 @@ void DatabaseWidget::reloadDatabaseFile() } } else { - MessageBox::critical(this, tr("Autoreload Failed"), - tr("Could not open the new database file while attempting to autoreload this database.")); + m_messageWidget->showMessage( + tr("Could not open the new database file while attempting to autoreload this database."), + MessageWidget::Error); } // Rewatch the database file @@ -1160,7 +1258,7 @@ bool DatabaseWidget::currentEntryHasUsername() Q_ASSERT(false); return false; } - return !currentEntry->username().isEmpty(); + return !currentEntry->resolveMultiplePlaceholders(currentEntry->username()).isEmpty(); } bool DatabaseWidget::currentEntryHasPassword() @@ -1170,7 +1268,7 @@ bool DatabaseWidget::currentEntryHasPassword() Q_ASSERT(false); return false; } - return !currentEntry->password().isEmpty(); + return !currentEntry->resolveMultiplePlaceholders(currentEntry->password()).isEmpty(); } bool DatabaseWidget::currentEntryHasUrl() @@ -1180,7 +1278,18 @@ bool DatabaseWidget::currentEntryHasUrl() Q_ASSERT(false); return false; } - return !currentEntry->url().isEmpty(); + return !currentEntry->resolveMultiplePlaceholders(currentEntry->url()).isEmpty(); +} + + +bool DatabaseWidget::currentEntryHasTotp() +{ + Entry* currentEntry = m_entryView->currentEntry(); + if (!currentEntry) { + Q_ASSERT(false); + return false; + } + return currentEntry->hasTotp(); } bool DatabaseWidget::currentEntryHasNotes() @@ -1190,7 +1299,7 @@ bool DatabaseWidget::currentEntryHasNotes() Q_ASSERT(false); return false; } - return !currentEntry->notes().isEmpty(); + return !currentEntry->resolveMultiplePlaceholders(currentEntry->notes()).isEmpty(); } GroupView* DatabaseWidget::groupView() { @@ -1213,3 +1322,37 @@ void DatabaseWidget::closeUnlockDialog() { m_unlockDatabaseDialog->close(); } + +void DatabaseWidget::showMessage(const QString& text, MessageWidget::MessageType type) +{ + m_messageWidget->showMessage(text, type); +} + +void DatabaseWidget::hideMessage() +{ + if (m_messageWidget->isVisible()) { + m_messageWidget->animatedHide(); + } +} + +bool DatabaseWidget::isRecycleBinSelected() const +{ + return m_groupView->currentGroup() && m_groupView->currentGroup() == m_db->metadata()->recycleBin(); +} + +void DatabaseWidget::emptyRecycleBin() +{ + if(!isRecycleBinSelected()) { + return; + } + + QMessageBox::StandardButton result = MessageBox::question( + this, tr("Empty recycle bin?"), + tr("Are you sure you want to permanently delete everything from your recycle bin?"), + QMessageBox::Yes | QMessageBox::No); + + if (result == QMessageBox::Yes) { + m_db->emptyRecycleBin(); + refreshSearch(); + } +} diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index ef245cf2d5..734e979e72 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +27,8 @@ #include "core/Uuid.h" #include "gui/entry/EntryModel.h" +#include "gui/MessageWidget.h" +#include "gui/csvImport/CsvImportWizard.h" class ChangeMasterKeyWidget; class DatabaseOpenWidget; @@ -43,9 +46,14 @@ class QMenu; class QSplitter; class QLabel; class UnlockDatabaseWidget; +class MessageWidget; class UnlockDatabaseDialog; class QFileSystemWatcher; +namespace Ui { + class SearchWidget; +} + class DatabaseWidget : public QStackedWidget { Q_OBJECT @@ -54,6 +62,7 @@ class DatabaseWidget : public QStackedWidget enum Mode { None, + ImportMode, ViewMode, EditMode, LockedMode @@ -88,13 +97,16 @@ class DatabaseWidget : public QStackedWidget bool currentEntryHasPassword(); bool currentEntryHasUrl(); bool currentEntryHasNotes(); + bool currentEntryHasTotp(); GroupView* groupView(); EntryView* entryView(); void showUnlockDialog(); void closeUnlockDialog(); - void ignoreNextAutoreload(); + void blockAutoReload(bool block = true); + void refreshSearch(); + bool isRecycleBinSelected() const; -Q_SIGNALS: +signals: void closeRequest(); void currentModeChanged(DatabaseWidget::Mode mode); void groupChanged(); @@ -112,7 +124,7 @@ class DatabaseWidget : public QStackedWidget void entryColumnSizesChanged(); void updateSearch(QString text); -public Q_SLOTS: +public slots: void createEntry(); void cloneEntry(); void deleteEntries(); @@ -123,6 +135,9 @@ public Q_SLOTS: void copyURL(); void copyNotes(); void copyAttribute(QAction* action); + void showTotp(); + void copyTotp(); + void setupTotp(); void performAutoType(); void openUrl(); void openUrlForEntry(Entry* entry); @@ -136,17 +151,25 @@ public Q_SLOTS: void switchToDatabaseSettings(); void switchToOpenDatabase(const QString& fileName); void switchToOpenDatabase(const QString& fileName, const QString& password, const QString& keyFile); + void switchToImportCsv(const QString& fileName); + void csvImportFinished(bool accepted); void switchToOpenMergeDatabase(const QString& fileName); void switchToOpenMergeDatabase(const QString& fileName, const QString& password, const QString& keyFile); void switchToImportKeepass1(const QString& fileName); void databaseModified(); void databaseSaved(); + void emptyRecycleBin(); + // Search related slots void search(const QString& searchtext); void setSearchCaseSensitive(bool state); + void setSearchLimitGroup(bool state); void endSearch(); -private Q_SLOTS: + void showMessage(const QString& text, MessageWidget::MessageType type); + void hideMessage(); + +private slots: void entryActivationSignalReceived(Entry* entry, EntryModel::ModelColumn column); void switchBackToEntryEdit(); void switchToHistoryView(Entry* entry); @@ -164,6 +187,7 @@ private Q_SLOTS: void onWatchedFileChanged(); void reloadDatabaseFile(); void restoreGroupEntryFocus(Uuid groupUuid, Uuid EntryUuid); + void unblockAutoReload(); private: void setClipboardTextAndMinimize(const QString& text); @@ -176,6 +200,7 @@ private Q_SLOTS: EditEntryWidget* m_historyEditEntryWidget; EditGroupWidget* m_editGroupWidget; ChangeMasterKeyWidget* m_changeMasterKeyWidget; + CsvImportWizard* m_csvImportWizard; DatabaseSettingsWidget* m_databaseSettingsWidget; DatabaseOpenWidget* m_databaseOpenWidget; DatabaseOpenWidget* m_databaseOpenMergeWidget; @@ -192,16 +217,18 @@ private Q_SLOTS: QString m_filename; Uuid m_groupBeforeLock; Uuid m_entryBeforeLock; + MessageWidget* m_messageWidget; // Search state QString m_lastSearchText; bool m_searchCaseSensitive; + bool m_searchLimitGroup; // Autoreload QFileSystemWatcher m_fileWatcher; QTimer m_fileWatchTimer; - bool m_ignoreNextAutoreload; - QTimer m_ignoreWatchTimer; + QTimer m_fileWatchUnblockTimer; + bool m_ignoreAutoReload; bool m_databaseModified; }; diff --git a/src/gui/DatabaseWidgetStateSync.cpp b/src/gui/DatabaseWidgetStateSync.cpp index fd5719f5a3..1510d84407 100644 --- a/src/gui/DatabaseWidgetStateSync.cpp +++ b/src/gui/DatabaseWidgetStateSync.cpp @@ -149,3 +149,4 @@ QVariant DatabaseWidgetStateSync::intListToVariant(const QList& list) return result; } + diff --git a/src/gui/DatabaseWidgetStateSync.h b/src/gui/DatabaseWidgetStateSync.h index a4861179e9..96ecd104a5 100644 --- a/src/gui/DatabaseWidgetStateSync.h +++ b/src/gui/DatabaseWidgetStateSync.h @@ -29,12 +29,12 @@ class DatabaseWidgetStateSync : public QObject explicit DatabaseWidgetStateSync(QObject* parent = nullptr); ~DatabaseWidgetStateSync(); -public Q_SLOTS: +public slots: void setActive(DatabaseWidget* dbWidget); void restoreListView(); void restoreSearchView(); -private Q_SLOTS: +private slots: void blockUpdates(); void updateSplitterSizes(); void updateColumnSizes(); diff --git a/src/gui/DragTabBar.h b/src/gui/DragTabBar.h index a6117a047d..38de10dab6 100644 --- a/src/gui/DragTabBar.h +++ b/src/gui/DragTabBar.h @@ -34,7 +34,7 @@ class DragTabBar : public QTabBar void dropEvent(QDropEvent* event) override; void tabLayoutChange() override; -private Q_SLOTS: +private slots: void dragSwitchTab(); private: diff --git a/src/gui/EditWidget.cpp b/src/gui/EditWidget.cpp index b3d9842be9..cf3568d117 100644 --- a/src/gui/EditWidget.cpp +++ b/src/gui/EditWidget.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +18,10 @@ #include "EditWidget.h" #include "ui_EditWidget.h" +#include +#include + +#include "core/FilePath.h" EditWidget::EditWidget(QWidget* parent) : DialogyWidget(parent) @@ -25,12 +30,14 @@ EditWidget::EditWidget(QWidget* parent) m_ui->setupUi(this); setReadOnly(false); + m_ui->messageWidget->setHidden(true); + QFont headerLabelFont = m_ui->headerLabel->font(); headerLabelFont.setBold(true); headerLabelFont.setPointSize(headerLabelFont.pointSize() + 2); headlineLabel()->setFont(headerLabelFont); - connect(m_ui->categoryList, SIGNAL(currentRowChanged(int)), + connect(m_ui->categoryList, SIGNAL(categoryChanged(int)), m_ui->stackedWidget, SLOT(setCurrentIndex(int))); connect(m_ui->buttonBox, SIGNAL(accepted()), SIGNAL(accepted())); @@ -41,23 +48,42 @@ EditWidget::~EditWidget() { } -void EditWidget::add(const QString& labelText, QWidget* widget) +void EditWidget::addPage(const QString& labelText, const QIcon& icon, QWidget* widget) { - m_ui->categoryList->addItem(labelText); - m_ui->stackedWidget->addWidget(widget); + /* + * Instead of just adding a widget we're going to wrap it into a scroll area. It will automatically show + * scrollbars when the widget cannot fit into the page. This approach prevents the main window of the application + * from automatic resizing and it now should be able to fit into a user's monitor even if the monitor is only 768 + * pixels high. + */ + QScrollArea* scrollArea = new QScrollArea(m_ui->stackedWidget); + scrollArea->setFrameShape(QFrame::NoFrame); + scrollArea->setWidget(widget); + scrollArea->setWidgetResizable(true); + m_ui->stackedWidget->addWidget(scrollArea); + m_ui->categoryList->addCategory(labelText, icon); } -void EditWidget::setRowHidden(QWidget* widget, bool hide) +void EditWidget::setPageHidden(QWidget* widget, bool hidden) { - int row = m_ui->stackedWidget->indexOf(widget); - if (row != -1) { - m_ui->categoryList->item(row)->setHidden(hide); + int index = m_ui->stackedWidget->indexOf(widget); + if (index != -1) { + m_ui->categoryList->setCategoryHidden(index, hidden); + } + + if (index == m_ui->stackedWidget->currentIndex()) { + int newIndex = m_ui->stackedWidget->currentIndex() - 1; + if (newIndex < 0) { + newIndex = m_ui->stackedWidget->count() - 1; + } + m_ui->stackedWidget->setCurrentIndex(newIndex); } } -void EditWidget::setCurrentRow(int index) +void EditWidget::setCurrentPage(int index) { - m_ui->categoryList->setCurrentRow(index); + m_ui->categoryList->setCurrentCategory(index); + m_ui->stackedWidget->setCurrentIndex(index); } void EditWidget::setHeadline(const QString& text) @@ -78,7 +104,10 @@ void EditWidget::setReadOnly(bool readOnly) m_ui->buttonBox->setStandardButtons(QDialogButtonBox::Close); } else { - m_ui->buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + m_ui->buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply); + // Find and connect the apply button + QPushButton* applyButton = m_ui->buttonBox->button(QDialogButtonBox::Apply); + connect(applyButton, SIGNAL(clicked()), SIGNAL(apply())); } } @@ -86,3 +115,15 @@ bool EditWidget::readOnly() const { return m_readOnly; } + +void EditWidget::showMessage(const QString& text, MessageWidget::MessageType type) +{ + m_ui->messageWidget->showMessage(text, type); +} + +void EditWidget::hideMessage() +{ + if (m_ui->messageWidget->isVisible()) { + m_ui->messageWidget->animatedHide(); + } +} diff --git a/src/gui/EditWidget.h b/src/gui/EditWidget.h index c5f507ac95..442365b96b 100644 --- a/src/gui/EditWidget.h +++ b/src/gui/EditWidget.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,8 +20,11 @@ #define KEEPASSX_EDITWIDGET_H #include +#include +#include #include "gui/DialogyWidget.h" +#include "gui/MessageWidget.h" class QLabel; @@ -36,18 +40,23 @@ class EditWidget : public DialogyWidget explicit EditWidget(QWidget* parent = nullptr); ~EditWidget(); - void add(const QString& labelText, QWidget* widget); - void setRowHidden(QWidget* widget, bool hide); - void setCurrentRow(int index); + void addPage(const QString& labelText, const QIcon& icon, QWidget* widget); + void setPageHidden(QWidget* widget, bool hidden); + void setCurrentPage(int index); void setHeadline(const QString& text); QLabel* headlineLabel(); void setReadOnly(bool readOnly); bool readOnly() const; -Q_SIGNALS: +signals: + void apply(); void accepted(); void rejected(); +protected slots: + void showMessage(const QString& text, MessageWidget::MessageType type); + void hideMessage(); + private: const QScopedPointer m_ui; bool m_readOnly; diff --git a/src/gui/EditWidget.ui b/src/gui/EditWidget.ui index b9b3be496b..b8ac5f3eb8 100644 --- a/src/gui/EditWidget.ui +++ b/src/gui/EditWidget.ui @@ -11,6 +11,9 @@ + + + @@ -35,9 +38,16 @@ - + - + + + + 0 + 0 + + + @@ -49,14 +59,14 @@ - + 5 - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -65,15 +75,19 @@ + + MessageWidget + QWidget +
gui/MessageWidget.h
+ 1 +
CategoryListWidget - QListWidget -
gui/entry/EditEntryWidget_p.h
+ QWidget +
gui/CategoryListWidget.h
+ 1
- - categoryList - diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index b9c34aa4f2..a68bda05e6 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,10 +29,12 @@ #include "gui/IconModels.h" #include "gui/MessageBox.h" +#ifdef WITH_XC_HTTP #include "http/qhttp/qhttpclient.hpp" #include "http/qhttp/qhttpclientresponse.hpp" using namespace qhttp::client; +#endif IconStruct::IconStruct() : uuid(Uuid()) @@ -45,7 +48,11 @@ EditWidgetIcons::EditWidgetIcons(QWidget* parent) , m_database(nullptr) , m_defaultIconModel(new DefaultIconModel(this)) , m_customIconModel(new CustomIconModel(this)) + #ifdef WITH_XC_HTTP + , m_fallbackToGoogle(true) + , m_redirectCount(0) , m_httpClient(nullptr) + #endif { m_ui->setupUi(this); @@ -138,18 +145,26 @@ void EditWidgetIcons::load(const Uuid& currentUuid, Database* database, const Ic void EditWidgetIcons::setUrl(const QString& url) { +#ifdef WITH_XC_HTTP m_url = url; m_ui->faviconButton->setVisible(!url.isEmpty()); resetFaviconDownload(); +#else + Q_UNUSED(url); + m_ui->faviconButton->setVisible(false); +#endif } void EditWidgetIcons::downloadFavicon() { +#ifdef WITH_XC_HTTP QUrl url = QUrl(m_url); url.setPath("/favicon.ico"); fetchFavicon(url); +#endif } +#ifdef WITH_XC_HTTP void EditWidgetIcons::fetchFavicon(const QUrl& url) { if (nullptr == m_httpClient) { @@ -216,12 +231,11 @@ void EditWidgetIcons::fetchFavicon(const QUrl& url) void EditWidgetIcons::fetchFaviconFromGoogle(const QString& domain) { - if (m_fallbackToGoogle) { + if (m_fallbackToGoogle) { resetFaviconDownload(); m_fallbackToGoogle = false; fetchFavicon(QUrl("http://www.google.com/s2/favicons?domain=" + domain)); - } - else { + } else { resetFaviconDownload(); MessageBox::warning(this, tr("Error"), tr("Unable to fetch favicon.")); } @@ -242,6 +256,7 @@ void EditWidgetIcons::resetFaviconDownload(bool clearRedirect) m_fallbackToGoogle = true; m_ui->faviconButton->setDisabled(false); } +#endif void EditWidgetIcons::addCustomIcon() { @@ -262,7 +277,7 @@ void EditWidgetIcons::addCustomIcon() m_ui->customIconsView->setCurrentIndex(index); } else { - MessageBox::critical(this, tr("Error"), tr("Can't read icon")); + emit messageEditEntry(tr("Can't read icon"), MessageWidget::Error); } } } @@ -274,51 +289,74 @@ void EditWidgetIcons::removeCustomIcon() QModelIndex index = m_ui->customIconsView->currentIndex(); if (index.isValid()) { Uuid iconUuid = m_customIconModel->uuidFromIndex(index); - int iconUsedCount = 0; const QList allEntries = m_database->rootGroup()->entriesRecursive(true); + QList entriesWithSameIcon; QList historyEntriesWithSameIcon; for (Entry* entry : allEntries) { - bool isHistoryEntry = !entry->group(); if (iconUuid == entry->iconUuid()) { - if (isHistoryEntry) { + // Check if this is a history entry (no assigned group) + if (!entry->group()) { historyEntriesWithSameIcon << entry; - } - else if (m_currentUuid != entry->uuid()) { - iconUsedCount++; + } else if (m_currentUuid != entry->uuid()) { + entriesWithSameIcon << entry; } } } const QList allGroups = m_database->rootGroup()->groupsRecursive(true); - for (const Group* group : allGroups) { + QList groupsWithSameIcon; + + for (Group* group : allGroups) { if (iconUuid == group->iconUuid() && m_currentUuid != group->uuid()) { - iconUsedCount++; + groupsWithSameIcon << group; } } - if (iconUsedCount == 0) { - for (Entry* entry : asConst(historyEntriesWithSameIcon)) { - entry->setUpdateTimeinfo(false); - entry->setIcon(0); - entry->setUpdateTimeinfo(true); - } + int iconUseCount = entriesWithSameIcon.size() + groupsWithSameIcon.size(); + if (iconUseCount > 0) { + QMessageBox::StandardButton ans = MessageBox::question(this, tr("Confirm Delete"), + tr("This icon is used by %1 entries, and will be replaced " + "by the default icon. Are you sure you want to delete it?") + .arg(iconUseCount), QMessageBox::Yes | QMessageBox::No); - m_database->metadata()->removeCustomIcon(iconUuid); - m_customIconModel->setIcons(m_database->metadata()->customIconsScaledPixmaps(), - m_database->metadata()->customIconsOrder()); - if (m_customIconModel->rowCount() > 0) { - m_ui->customIconsView->setCurrentIndex(m_customIconModel->index(0, 0)); - } - else { - updateRadioButtonDefaultIcons(); + if (ans == QMessageBox::No) { + // Early out, nothing is changed + return; + } else { + // Revert matched entries to the default entry icon + for (Entry* entry : asConst(entriesWithSameIcon)) { + entry->setIcon(Entry::DefaultIconNumber); + } + + // Revert matched groups to the default group icon + for (Group* group : asConst(groupsWithSameIcon)) { + group->setIcon(Group::DefaultIconNumber); + } } } - else { - MessageBox::information(this, tr("Can't delete icon!"), - tr("Can't delete icon. Still used by %1 items.") - .arg(iconUsedCount)); + + + // Remove the icon from history entries + for (Entry* entry : asConst(historyEntriesWithSameIcon)) { + entry->setUpdateTimeinfo(false); + entry->setIcon(0); + entry->setUpdateTimeinfo(true); + } + + // Remove the icon from the database + m_database->metadata()->removeCustomIcon(iconUuid); + m_customIconModel->setIcons(m_database->metadata()->customIconsScaledPixmaps(), + m_database->metadata()->customIconsOrder()); + + // Reset the current icon view + updateRadioButtonDefaultIcons(); + + if (m_database->resolveEntry(m_currentUuid) != nullptr) { + m_ui->defaultIconsView->setCurrentIndex(m_defaultIconModel->index(Entry::DefaultIconNumber)); + } else { + m_ui->defaultIconsView->setCurrentIndex(m_defaultIconModel->index(Group::DefaultIconNumber)); } } } diff --git a/src/gui/EditWidgetIcons.h b/src/gui/EditWidgetIcons.h index 61704f97ef..3cc191d733 100644 --- a/src/gui/EditWidgetIcons.h +++ b/src/gui/EditWidgetIcons.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,18 +23,23 @@ #include #include +#include "config-keepassx.h" #include "core/Global.h" #include "core/Uuid.h" +#include "gui/MessageWidget.h" class Database; class DefaultIconModel; class CustomIconModel; +#ifdef WITH_XC_HTTP namespace qhttp { namespace client { class QHttpClient; } } +#endif + namespace Ui { class EditWidgetIcons; } @@ -58,14 +64,20 @@ class EditWidgetIcons : public QWidget void reset(); void load(const Uuid& currentUuid, Database* database, const IconStruct& iconStruct, const QString& url = ""); -public Q_SLOTS: +public slots: void setUrl(const QString& url); -private Q_SLOTS: +signals: + void messageEditEntry(QString, MessageWidget::MessageType); + void messageEditEntryDismiss(); + +private slots: void downloadFavicon(); +#ifdef WITH_XC_HTTP void fetchFavicon(const QUrl& url); void fetchFaviconFromGoogle(const QString& domain); void resetFaviconDownload(bool clearRedirect = true); +#endif void addCustomIcon(); void removeCustomIcon(); void updateWidgetsDefaultIcons(bool checked); @@ -78,12 +90,14 @@ private Q_SLOTS: Database* m_database; Uuid m_currentUuid; QString m_url; - QUrl m_redirectUrl; - bool m_fallbackToGoogle = true; - unsigned short m_redirectCount = 0; DefaultIconModel* const m_defaultIconModel; CustomIconModel* const m_customIconModel; +#ifdef WITH_XC_HTTP + QUrl m_redirectUrl; + bool m_fallbackToGoogle; + unsigned short m_redirectCount; qhttp::client::QHttpClient* m_httpClient; +#endif Q_DISABLE_COPY(EditWidgetIcons) }; diff --git a/src/gui/KMessageWidget.cpp b/src/gui/KMessageWidget.cpp new file mode 100644 index 0000000000..7f4cb94f42 --- /dev/null +++ b/src/gui/KMessageWidget.cpp @@ -0,0 +1,491 @@ +/* This file is part of the KDE libraries + * + * Copyright (c) 2011 Aurélien Gâteau + * Copyright (c) 2014 Dominik Haumann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include "KMessageWidget.h" + +#include "core/FilePath.h" +#include "core/Global.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//--------------------------------------------------------------------- +// KMessageWidgetPrivate +//--------------------------------------------------------------------- +class KMessageWidgetPrivate +{ +public: + void init(KMessageWidget *); + + KMessageWidget *q; + QFrame *content; + QLabel *iconLabel; + QLabel *textLabel; + QToolButton *closeButton; + QTimeLine *timeLine; + QIcon icon; + + KMessageWidget::MessageType messageType; + bool wordWrap; + QList buttons; + QPixmap contentSnapShot; + + void createLayout(); + void updateSnapShot(); + void updateLayout(); + void slotTimeLineChanged(qreal); + void slotTimeLineFinished(); + + int bestContentHeight() const; +}; + +void KMessageWidgetPrivate::init(KMessageWidget *q_ptr) +{ + q = q_ptr; + + q->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + + timeLine = new QTimeLine(500, q); + QObject::connect(timeLine, SIGNAL(valueChanged(qreal)), q, SLOT(slotTimeLineChanged(qreal))); + QObject::connect(timeLine, SIGNAL(finished()), q, SLOT(slotTimeLineFinished())); + + content = new QFrame(q); + content->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + wordWrap = false; + + iconLabel = new QLabel(content); + iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + iconLabel->hide(); + + textLabel = new QLabel(content); + textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); + QObject::connect(textLabel, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString))); + QObject::connect(textLabel, SIGNAL(linkHovered(QString)), q, SIGNAL(linkHovered(QString))); + + QAction *closeAction = new QAction(q); + closeAction->setText(KMessageWidget::tr("&Close")); + closeAction->setToolTip(KMessageWidget::tr("Close message")); + closeAction->setIcon(FilePath::instance()->icon("actions", "message-close", false)); + + QObject::connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(animatedHide())); + + closeButton = new QToolButton(content); + closeButton->setAutoRaise(true); + closeButton->setDefaultAction(closeAction); +#ifdef Q_OS_MAC + closeButton->setStyleSheet("QToolButton { background: transparent;" + "border-radius: 2px; padding: 3px; }" + "QToolButton::hover, QToolButton::focus {" + "border: 1px solid rgb(90, 200, 250); }"); +#endif + + q->setMessageType(KMessageWidget::Information); +} + +void KMessageWidgetPrivate::createLayout() +{ + delete content->layout(); + + content->resize(q->size()); + + qDeleteAll(buttons); + buttons.clear(); + + const auto actions = q->actions(); + for (QAction *action: actions) { + QToolButton *button = new QToolButton(content); + button->setDefaultAction(action); + button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + buttons.append(button); + } + + // AutoRaise reduces visual clutter, but we don't want to turn it on if + // there are other buttons, otherwise the close button will look different + // from the others. + closeButton->setAutoRaise(buttons.isEmpty()); + + if (wordWrap) { + QGridLayout *layout = new QGridLayout(content); + // Set alignment to make sure icon does not move down if text wraps + layout->addWidget(iconLabel, 0, 0, 1, 1, Qt::AlignHCenter | Qt::AlignTop); + layout->addWidget(textLabel, 0, 1); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + buttonLayout->addStretch(); + for (QToolButton* button: asConst(buttons)) { + // For some reason, calling show() is necessary if wordwrap is true, + // otherwise the buttons do not show up. It is not needed if + // wordwrap is false. + button->show(); + buttonLayout->addWidget(button); + } + buttonLayout->addWidget(closeButton); + layout->addItem(buttonLayout, 1, 0, 1, 2); + } else { + QHBoxLayout *layout = new QHBoxLayout(content); + layout->addWidget(iconLabel); + layout->addWidget(textLabel); + + for (QToolButton* button: asConst(buttons)) { + layout->addWidget(button); + } + + layout->addWidget(closeButton); + }; + + if (q->isVisible()) { + q->setFixedHeight(content->sizeHint().height()); + } + q->updateGeometry(); +} + +void KMessageWidgetPrivate::updateLayout() +{ + if (content->layout()) { + createLayout(); + } +} + +void KMessageWidgetPrivate::updateSnapShot() +{ + // Attention: updateSnapShot calls QWidget::render(), which causes the whole + // window layouts to be activated. Calling this method from resizeEvent() + // can lead to infinite recursion, see: + // https://bugs.kde.org/show_bug.cgi?id=311336 + contentSnapShot = QPixmap(content->size() * q->devicePixelRatio()); + contentSnapShot.setDevicePixelRatio(q->devicePixelRatio()); + contentSnapShot.fill(Qt::transparent); + content->render(&contentSnapShot, QPoint(), QRegion(), QWidget::DrawChildren); +} + +void KMessageWidgetPrivate::slotTimeLineChanged(qreal value) +{ + q->setFixedHeight(qMin(value * 2, qreal(1.0)) * content->height()); + q->update(); +} + +void KMessageWidgetPrivate::slotTimeLineFinished() +{ + if (timeLine->direction() == QTimeLine::Forward) { + // Show + // We set the whole geometry here, because it may be wrong if a + // KMessageWidget is shown right when the toplevel window is created. + content->setGeometry(0, 0, q->width(), bestContentHeight()); + + // notify about finished animation + emit q->showAnimationFinished(); + } else { + // hide and notify about finished animation + q->hide(); + emit q->hideAnimationFinished(); + } +} + +int KMessageWidgetPrivate::bestContentHeight() const +{ + int height = content->heightForWidth(q->width()); + if (height == -1) { + height = content->sizeHint().height(); + } + return height; +} + +//--------------------------------------------------------------------- +// KMessageWidget +//--------------------------------------------------------------------- +KMessageWidget::KMessageWidget(QWidget *parent) +: QFrame(parent) +, d(new KMessageWidgetPrivate) +{ + d->init(this); +} + +KMessageWidget::KMessageWidget(const QString &text, QWidget *parent) +: QFrame(parent) +, d(new KMessageWidgetPrivate) +{ + d->init(this); + setText(text); +} + +KMessageWidget::~KMessageWidget() +{ + delete d; +} + +QString KMessageWidget::text() const +{ + return d->textLabel->text(); +} + +void KMessageWidget::setText(const QString &text) +{ + d->textLabel->setText(text); + updateGeometry(); +} + +KMessageWidget::MessageType KMessageWidget::messageType() const +{ + return d->messageType; +} + +static QColor darkShade(QColor c) +{ + qreal contrast = 0.7; // taken from kcolorscheme for the dark shade + + qreal darkAmount; + if (c.lightnessF() < 0.006) { /* too dark */ + darkAmount = 0.02 + 0.40 * contrast; + } else if (c.lightnessF() > 0.93) { /* too bright */ + darkAmount = -0.06 - 0.60 * contrast; + } else { + darkAmount = (-c.lightnessF()) * (0.55 + contrast * 0.35); + } + + qreal v = c.lightnessF() + darkAmount; + v = v > 0.0 ? (v < 1.0 ? v : 1.0) : 0.0; + c.setHsvF(c.hslHueF(), c.hslSaturationF(), v); + return c; +} + +void KMessageWidget::setMessageType(KMessageWidget::MessageType type) +{ + d->messageType = type; + QColor bg0, bg1, bg2, border, fg; + switch (type) { + case Positive: + bg1.setRgb(0, 110, 40); // values taken from kcolorscheme.cpp (Positive) + break; + case Information: + bg1 = palette().highlight().color(); + break; + case Warning: + bg1.setRgb(181, 102, 0); // values taken from kcolorscheme.cpp (Neutral) + break; + case Error: + bg1.setRgb(191, 3, 3); // values taken from kcolorscheme.cpp (Negative) + break; + } + + // Colors + fg = palette().light().color(); + bg0 = bg1.lighter(110); + bg2 = bg1.darker(110); + border = darkShade(bg1); + + d->content->setStyleSheet( + QString(QLatin1String(".QFrame {" + "background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," + " stop: 0 %1," + " stop: 0.1 %2," + " stop: 1.0 %3);" + "border-radius: 5px;" + "border: 1px solid %4;" + "margin: %5px;" + "padding: 5px;" + "}" + ".QLabel { color: %6; }" + )) + .arg(bg0.name()) + .arg(bg1.name()) + .arg(bg2.name()) + .arg(border.name()) + // DefaultFrameWidth returns the size of the external margin + border width. We know our border is 1px, so we subtract this from the frame normal QStyle FrameWidth to get our margin + .arg(style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, this) - 1) + .arg(fg.name()) + ); +} + +QSize KMessageWidget::sizeHint() const +{ + ensurePolished(); + return d->content->sizeHint(); +} + +QSize KMessageWidget::minimumSizeHint() const +{ + ensurePolished(); + return d->content->minimumSizeHint(); +} + +bool KMessageWidget::event(QEvent *event) +{ + if (event->type() == QEvent::Polish && !d->content->layout()) { + d->createLayout(); + } + return QFrame::event(event); +} + +void KMessageWidget::resizeEvent(QResizeEvent *event) +{ + QFrame::resizeEvent(event); + + if (d->timeLine->state() == QTimeLine::NotRunning) { + d->content->resize(width(), d->bestContentHeight()); + } +} + +int KMessageWidget::heightForWidth(int width) const +{ + ensurePolished(); + return d->content->heightForWidth(width); +} + +void KMessageWidget::paintEvent(QPaintEvent *event) +{ + QFrame::paintEvent(event); + if (d->timeLine->state() == QTimeLine::Running) { + QPainter painter(this); + painter.setOpacity(d->timeLine->currentValue() * d->timeLine->currentValue()); + painter.drawPixmap(0, 0, d->contentSnapShot); + } +} + +bool KMessageWidget::wordWrap() const +{ + return d->wordWrap; +} + +void KMessageWidget::setWordWrap(bool wordWrap) +{ + d->wordWrap = wordWrap; + d->textLabel->setWordWrap(wordWrap); + QSizePolicy policy = sizePolicy(); + policy.setHeightForWidth(wordWrap); + setSizePolicy(policy); + d->updateLayout(); + // Without this, when user does wordWrap -> !wordWrap -> wordWrap, a minimum + // height is set, causing the widget to be too high. + // Mostly visible in test programs. + if (wordWrap) { + setMinimumHeight(0); + } +} + +bool KMessageWidget::isCloseButtonVisible() const +{ + return d->closeButton->isVisible(); +} + +void KMessageWidget::setCloseButtonVisible(bool show) +{ + d->closeButton->setVisible(show); + updateGeometry(); +} + +void KMessageWidget::addAction(QAction *action) +{ + QFrame::addAction(action); + d->updateLayout(); +} + +void KMessageWidget::removeAction(QAction *action) +{ + QFrame::removeAction(action); + d->updateLayout(); +} + +void KMessageWidget::animatedShow() +{ + if (!style()->styleHint(QStyle::SH_Widget_Animate, 0, this)) { + show(); + emit showAnimationFinished(); + return; + } + + if (isVisible()) { + return; + } + + QFrame::show(); + setFixedHeight(0); + int wantedHeight = d->bestContentHeight(); + d->content->setGeometry(0, -wantedHeight, width(), wantedHeight); + + d->updateSnapShot(); + + d->timeLine->setDirection(QTimeLine::Forward); + if (d->timeLine->state() == QTimeLine::NotRunning) { + d->timeLine->start(); + } +} + +void KMessageWidget::animatedHide() +{ + if (!style()->styleHint(QStyle::SH_Widget_Animate, 0, this)) { + hide(); + emit hideAnimationFinished(); + return; + } + + if (!isVisible()) { + hide(); + return; + } + + d->content->move(0, -d->content->height()); + d->updateSnapShot(); + + d->timeLine->setDirection(QTimeLine::Backward); + if (d->timeLine->state() == QTimeLine::NotRunning) { + d->timeLine->start(); + } +} + +bool KMessageWidget::isHideAnimationRunning() const +{ + return (d->timeLine->direction() == QTimeLine::Backward) + && (d->timeLine->state() == QTimeLine::Running); +} + +bool KMessageWidget::isShowAnimationRunning() const +{ + return (d->timeLine->direction() == QTimeLine::Forward) + && (d->timeLine->state() == QTimeLine::Running); +} + +QIcon KMessageWidget::icon() const +{ + return d->icon; +} + +void KMessageWidget::setIcon(const QIcon &icon) +{ + d->icon = icon; + if (d->icon.isNull()) { + d->iconLabel->hide(); + } else { + const int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize); + d->iconLabel->setPixmap(d->icon.pixmap(size)); + d->iconLabel->show(); + } +} + +#include "moc_KMessageWidget.cpp" diff --git a/src/gui/KMessageWidget.h b/src/gui/KMessageWidget.h new file mode 100644 index 0000000000..d47e78f9cc --- /dev/null +++ b/src/gui/KMessageWidget.h @@ -0,0 +1,342 @@ +/* This file is part of the KDE libraries + * + * Copyright (c) 2011 Aurélien Gâteau + * Copyright (c) 2014 Dominik Haumann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#ifndef KMESSAGEWIDGET_H +#define KMESSAGEWIDGET_H + +#include + +class KMessageWidgetPrivate; + +/** + * @short A widget to provide feedback or propose opportunistic interactions. + * + * KMessageWidget can be used to provide inline positive or negative + * feedback, or to implement opportunistic interactions. + * + * As a feedback widget, KMessageWidget provides a less intrusive alternative + * to "OK Only" message boxes. If you want to avoid a modal KMessageBox, + * consider using KMessageWidget instead. + * + * Examples of KMessageWidget look as follows, all of them having an icon set + * with setIcon(), and the first three show a close button: + * + * \image html kmessagewidget.png "KMessageWidget with different message types" + * + * Negative feedback + * + * The KMessageWidget can be used as a secondary indicator of failure: the + * first indicator is usually the fact the action the user expected to happen + * did not happen. + * + * Example: User fills a form, clicks "Submit". + * + * @li Expected feedback: form closes + * @li First indicator of failure: form stays there + * @li Second indicator of failure: a KMessageWidget appears on top of the + * form, explaining the error condition + * + * When used to provide negative feedback, KMessageWidget should be placed + * close to its context. In the case of a form, it should appear on top of the + * form entries. + * + * KMessageWidget should get inserted in the existing layout. Space should not + * be reserved for it, otherwise it becomes "dead space", ignored by the user. + * KMessageWidget should also not appear as an overlay to prevent blocking + * access to elements the user needs to interact with to fix the failure. + * + * Positive feedback + * + * KMessageWidget can be used for positive feedback but it shouldn't be + * overused. It is often enough to provide feedback by simply showing the + * results of an action. + * + * Examples of acceptable uses: + * + * @li Confirm success of "critical" transactions + * @li Indicate completion of background tasks + * + * Example of unadapted uses: + * + * @li Indicate successful saving of a file + * @li Indicate a file has been successfully removed + * + * Opportunistic interaction + * + * Opportunistic interaction is the situation where the application suggests to + * the user an action he could be interested in perform, either based on an + * action the user just triggered or an event which the application noticed. + * + * Example of acceptable uses: + * + * @li A browser can propose remembering a recently entered password + * @li A music collection can propose ripping a CD which just got inserted + * @li A chat application may notify the user a "special friend" just connected + * + * @author Aurélien Gâteau + * @since 4.7 + */ +class KMessageWidget : public QFrame +{ + Q_OBJECT + Q_ENUMS(MessageType) + + Q_PROPERTY(QString text READ text WRITE setText) + Q_PROPERTY(bool wordWrap READ wordWrap WRITE setWordWrap) + Q_PROPERTY(bool closeButtonVisible READ isCloseButtonVisible WRITE setCloseButtonVisible) + Q_PROPERTY(MessageType messageType READ messageType WRITE setMessageType) + Q_PROPERTY(QIcon icon READ icon WRITE setIcon) +public: + + /** + * Available message types. + * The background colors are chosen depending on the message type. + */ + enum MessageType { + Positive, + Information, + Warning, + Error + }; + + /** + * Constructs a KMessageWidget with the specified @p parent. + */ + explicit KMessageWidget(QWidget *parent = 0); + + /** + * Constructs a KMessageWidget with the specified @p parent and + * contents @p text. + */ + explicit KMessageWidget(const QString &text, QWidget *parent = 0); + + /** + * Destructor. + */ + ~KMessageWidget(); + + /** + * Get the text of this message widget. + * @see setText() + */ + QString text() const; + + /** + * Check whether word wrap is enabled. + * + * If word wrap is enabled, the message widget wraps the displayed text + * as required to the available width of the widget. This is useful to + * avoid breaking widget layouts. + * + * @see setWordWrap() + */ + bool wordWrap() const; + + /** + * Check whether the close button is visible. + * + * @see setCloseButtonVisible() + */ + bool isCloseButtonVisible() const; + + /** + * Get the type of this message. + * By default, the type is set to KMessageWidget::Information. + * + * @see KMessageWidget::MessageType, setMessageType() + */ + MessageType messageType() const; + + /** + * Add @p action to the message widget. + * For each action a button is added to the message widget in the + * order the actions were added. + * + * @param action the action to add + * @see removeAction(), QWidget::actions() + */ + void addAction(QAction *action); + + /** + * Remove @p action from the message widget. + * + * @param action the action to remove + * @see KMessageWidget::MessageType, addAction(), setMessageType() + */ + void removeAction(QAction *action); + + /** + * Returns the preferred size of the message widget. + */ + QSize sizeHint() const Q_DECL_OVERRIDE; + + /** + * Returns the minimum size of the message widget. + */ + QSize minimumSizeHint() const Q_DECL_OVERRIDE; + + /** + * Returns the required height for @p width. + * @param width the width in pixels + */ + int heightForWidth(int width) const Q_DECL_OVERRIDE; + + /** + * The icon shown on the left of the text. By default, no icon is shown. + * @since 4.11 + */ + QIcon icon() const; + + /** + * Check whether the hide animation started by calling animatedHide() + * is still running. If animations are disabled, this function always + * returns @e false. + * + * @see animatedHide(), hideAnimationFinished() + * @since 5.0 + */ + bool isHideAnimationRunning() const; + + /** + * Check whether the show animation started by calling animatedShow() + * is still running. If animations are disabled, this function always + * returns @e false. + * + * @see animatedShow(), showAnimationFinished() + * @since 5.0 + */ + bool isShowAnimationRunning() const; + +public slots: + /** + * Set the text of the message widget to @p text. + * If the message widget is already visible, the text changes on the fly. + * + * @param text the text to display, rich text is allowed + * @see text() + */ + void setText(const QString &text); + + /** + * Set word wrap to @p wordWrap. If word wrap is enabled, the text() + * of the message widget is wrapped to fit the available width. + * If word wrap is disabled, the message widget's minimum size is + * such that the entire text fits. + * + * @param wordWrap disable/enable word wrap + * @see wordWrap() + */ + void setWordWrap(bool wordWrap); + + /** + * Set the visibility of the close button. If @p visible is @e true, + * a close button is shown that calls animatedHide() if clicked. + * + * @see closeButtonVisible(), animatedHide() + */ + void setCloseButtonVisible(bool visible); + + /** + * Set the message type to @p type. + * By default, the message type is set to KMessageWidget::Information. + * + * @see messageType(), KMessageWidget::MessageType + */ + void setMessageType(KMessageWidget::MessageType type); + + /** + * Show the widget using an animation. + */ + void animatedShow(); + + /** + * Hide the widget using an animation. + */ + void animatedHide(); + + /** + * Define an icon to be shown on the left of the text + * @since 4.11 + */ + void setIcon(const QIcon &icon); + +signals: + /** + * This signal is emitted when the user clicks a link in the text label. + * The URL referred to by the href anchor is passed in contents. + * @param contents text of the href anchor + * @see QLabel::linkActivated() + * @since 4.10 + */ + void linkActivated(const QString &contents); + + /** + * This signal is emitted when the user hovers over a link in the text label. + * The URL referred to by the href anchor is passed in contents. + * @param contents text of the href anchor + * @see QLabel::linkHovered() + * @since 4.11 + */ + void linkHovered(const QString &contents); + + /** + * This signal is emitted when the hide animation is finished, started by + * calling animatedHide(). If animations are disabled, this signal is + * emitted immediately after the message widget got hidden. + * + * @note This signal is @e not emitted if the widget was hidden by + * calling hide(), so this signal is only useful in conjunction + * with animatedHide(). + * + * @see animatedHide() + * @since 5.0 + */ + void hideAnimationFinished(); + + /** + * This signal is emitted when the show animation is finished, started by + * calling animatedShow(). If animations are disabled, this signal is + * emitted immediately after the message widget got shown. + * + * @note This signal is @e not emitted if the widget was shown by + * calling show(), so this signal is only useful in conjunction + * with animatedShow(). + * + * @see animatedShow() + * @since 5.0 + */ + void showAnimationFinished(); + +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + + bool event(QEvent *event) Q_DECL_OVERRIDE; + + void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; + +private: + KMessageWidgetPrivate *const d; + friend class KMessageWidgetPrivate; + + Q_PRIVATE_SLOT(d, void slotTimeLineChanged(qreal)) + Q_PRIVATE_SLOT(d, void slotTimeLineFinished()) +}; + +#endif /* KMESSAGEWIDGET_H */ diff --git a/src/gui/KeePass1OpenWidget.cpp b/src/gui/KeePass1OpenWidget.cpp index 4f70a97877..915864241e 100644 --- a/src/gui/KeePass1OpenWidget.cpp +++ b/src/gui/KeePass1OpenWidget.cpp @@ -49,8 +49,8 @@ void KeePass1OpenWidget::openDatabase() QFile file(m_filename); if (!file.open(QIODevice::ReadOnly)) { - MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") - .append(file.errorString())); + m_ui->messageWidget->showMessage( tr("Unable to open the database.").append("\n") + .append(file.errorString()), MessageWidget::Error); return; } if (m_db) { @@ -62,11 +62,12 @@ void KeePass1OpenWidget::openDatabase() if (m_db) { m_db->metadata()->setName(QFileInfo(m_filename).completeBaseName()); - Q_EMIT editFinished(true); + emit editFinished(true); } else { - MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") - .append(reader.errorString())); + m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n") + .append(reader.errorString()), MessageWidget::Error); + m_ui->editPassword->clear(); } } diff --git a/src/gui/LineEdit.h b/src/gui/LineEdit.h index f5f0584011..1695e85516 100644 --- a/src/gui/LineEdit.h +++ b/src/gui/LineEdit.h @@ -34,7 +34,7 @@ class LineEdit : public QLineEdit protected: void resizeEvent(QResizeEvent* event) override; -private Q_SLOTS: +private slots: void updateCloseButton(const QString& text); private: diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index b0e1a1925b..7027d94c2d 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,34 +55,47 @@ #ifdef WITH_XC_HTTP class HttpPlugin: public ISettingsPage { - public: - HttpPlugin(DatabaseTabWidget * tabWidget) { - m_service = new Service(tabWidget); - } - virtual ~HttpPlugin() { - //delete m_service; - } - virtual QString name() { - return QObject::tr("Http"); - } - virtual QWidget * createWidget() { - OptionDialog * dlg = new OptionDialog(); - QObject::connect(dlg, SIGNAL(removeSharedEncryptionKeys()), m_service, SLOT(removeSharedEncryptionKeys())); - QObject::connect(dlg, SIGNAL(removeStoredPermissions()), m_service, SLOT(removeStoredPermissions())); - return dlg; - } - virtual void loadSettings(QWidget * widget) { - qobject_cast(widget)->loadSettings(); - } - virtual void saveSettings(QWidget * widget) { - qobject_cast(widget)->saveSettings(); - if (HttpSettings::isEnabled()) - m_service->start(); - else - m_service->stop(); - } - private: - Service *m_service; +public: + HttpPlugin(DatabaseTabWidget * tabWidget) + { + m_service = new Service(tabWidget); + } + + ~HttpPlugin() = default; + + QString name() override + { + return QObject::tr("Browser Integration"); + } + + QIcon icon() override + { + return FilePath::instance()->icon("apps", "internet-web-browser"); + } + + QWidget * createWidget() override + { + OptionDialog * dlg = new OptionDialog(); + QObject::connect(dlg, SIGNAL(removeSharedEncryptionKeys()), m_service, SLOT(removeSharedEncryptionKeys())); + QObject::connect(dlg, SIGNAL(removeStoredPermissions()), m_service, SLOT(removeStoredPermissions())); + return dlg; + } + + void loadSettings(QWidget * widget) override + { + qobject_cast(widget)->loadSettings(); + } + + void saveSettings(QWidget * widget) override + { + qobject_cast(widget)->saveSettings(); + if (HttpSettings::isEnabled()) + m_service->start(); + else + m_service->stop(); + } +private: + Service *m_service; }; #endif @@ -90,9 +104,9 @@ const QString MainWindow::BaseWindowTitle = "KeePassXC"; MainWindow::MainWindow() : m_ui(new Ui::MainWindow()) , m_trayIcon(nullptr) + , m_appExitCalled(false) + , m_appExiting(false) { - appExitCalled = false; - m_ui->setupUi(this); // Setup the search widget in the toolbar @@ -109,6 +123,7 @@ MainWindow::MainWindow() #endif setWindowIcon(filePath()->applicationIcon()); + m_ui->globalMessageWidget->setHidden(true); QAction* toggleViewAction = m_ui->toolBar->toggleViewAction(); toggleViewAction->setText(tr("Show toolbar")); m_ui->menuView->addAction(toggleViewAction); @@ -116,7 +131,7 @@ MainWindow::MainWindow() m_ui->toolBar->setVisible(showToolbar); connect(m_ui->toolBar, SIGNAL(visibilityChanged(bool)), this, SLOT(saveToolbarState(bool))); - m_clearHistoryAction = new QAction("Clear history", m_ui->menuFile); + m_clearHistoryAction = new QAction(tr("Clear history"), m_ui->menuFile); m_lastDatabasesActions = new QActionGroup(m_ui->menuRecentDatabases); connect(m_clearHistoryAction, SIGNAL(triggered()), this, SLOT(clearLastDatabases())); connect(m_lastDatabasesActions, SIGNAL(triggered(QAction*)), this, SLOT(openRecentDatabase(QAction*))); @@ -142,16 +157,19 @@ MainWindow::MainWindow() this, SLOT(lockDatabasesAfterInactivity())); applySettingsChanges(); + m_ui->actionDatabaseNew->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_N); setShortcut(m_ui->actionDatabaseOpen, QKeySequence::Open, Qt::CTRL + Qt::Key_O); setShortcut(m_ui->actionDatabaseSave, QKeySequence::Save, Qt::CTRL + Qt::Key_S); setShortcut(m_ui->actionDatabaseSaveAs, QKeySequence::SaveAs); setShortcut(m_ui->actionDatabaseClose, QKeySequence::Close, Qt::CTRL + Qt::Key_W); m_ui->actionLockDatabases->setShortcut(Qt::CTRL + Qt::Key_L); setShortcut(m_ui->actionQuit, QKeySequence::Quit, Qt::CTRL + Qt::Key_Q); - m_ui->actionEntryNew->setShortcut(Qt::CTRL + Qt::Key_N); + setShortcut(m_ui->actionEntryNew, QKeySequence::New, Qt::CTRL + Qt::Key_N); m_ui->actionEntryEdit->setShortcut(Qt::CTRL + Qt::Key_E); m_ui->actionEntryDelete->setShortcut(Qt::CTRL + Qt::Key_D); m_ui->actionEntryClone->setShortcut(Qt::CTRL + Qt::Key_K); + m_ui->actionEntryTotp->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_T); + m_ui->actionEntryCopyTotp->setShortcut(Qt::CTRL + Qt::Key_T); m_ui->actionEntryCopyUsername->setShortcut(Qt::CTRL + Qt::Key_B); m_ui->actionEntryCopyPassword->setShortcut(Qt::CTRL + Qt::Key_C); setShortcut(m_ui->actionEntryAutoType, QKeySequence::Paste, Qt::CTRL + Qt::Key_V); @@ -169,6 +187,7 @@ MainWindow::MainWindow() m_ui->actionChangeMasterKey->setIcon(filePath()->icon("actions", "database-change-key", false)); m_ui->actionLockDatabases->setIcon(filePath()->icon("actions", "document-encrypt", false)); m_ui->actionQuit->setIcon(filePath()->icon("actions", "application-exit")); + m_ui->actionQuit->setMenuRole(QAction::QuitRole); m_ui->actionEntryNew->setIcon(filePath()->icon("actions", "entry-new", false)); m_ui->actionEntryClone->setIcon(filePath()->icon("actions", "entry-clone", false)); @@ -181,11 +200,14 @@ MainWindow::MainWindow() m_ui->actionGroupNew->setIcon(filePath()->icon("actions", "group-new", false)); m_ui->actionGroupEdit->setIcon(filePath()->icon("actions", "group-edit", false)); m_ui->actionGroupDelete->setIcon(filePath()->icon("actions", "group-delete", false)); + m_ui->actionGroupEmptyRecycleBin->setIcon(filePath()->icon("actions", "group-empty-trash", false)); m_ui->actionSettings->setIcon(filePath()->icon("actions", "configure")); + m_ui->actionSettings->setMenuRole(QAction::PreferencesRole); m_ui->actionPasswordGenerator->setIcon(filePath()->icon("actions", "password-generator", false)); m_ui->actionAbout->setIcon(filePath()->icon("actions", "help-about")); + m_ui->actionAbout->setMenuRole(QAction::AboutRole); m_actionMultiplexer.connect(SIGNAL(currentModeChanged(DatabaseWidget::Mode)), this, SLOT(setMenuActionState(DatabaseWidget::Mode))); @@ -198,9 +220,11 @@ MainWindow::MainWindow() m_actionMultiplexer.connect(SIGNAL(entryContextMenuRequested(QPoint)), this, SLOT(showEntryContextMenu(QPoint))); - // Notify search when the active database changes + // Notify search when the active database changes or gets locked connect(m_ui->tabWidget, SIGNAL(activateDatabaseChanged(DatabaseWidget*)), search, SLOT(databaseChanged(DatabaseWidget*))); + connect(m_ui->tabWidget, SIGNAL(databaseLocked(DatabaseWidget*)), + search, SLOT(databaseChanged())); connect(m_ui->tabWidget, SIGNAL(tabNameChanged()), SLOT(updateWindowTitle())); @@ -235,6 +259,8 @@ MainWindow::MainWindow() SLOT(changeMasterKey())); connect(m_ui->actionChangeDatabaseSettings, SIGNAL(triggered()), m_ui->tabWidget, SLOT(changeDatabaseSettings())); + 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->actionRepairDatabase, SIGNAL(triggered()), this, @@ -254,6 +280,13 @@ MainWindow::MainWindow() m_actionMultiplexer.connect(m_ui->actionEntryDelete, SIGNAL(triggered()), SLOT(deleteEntries())); + m_actionMultiplexer.connect(m_ui->actionEntryTotp, SIGNAL(triggered()), + SLOT(showTotp())); + m_actionMultiplexer.connect(m_ui->actionEntrySetupTotp, SIGNAL(triggered()), + SLOT(setupTotp())); + + m_actionMultiplexer.connect(m_ui->actionEntryCopyTotp, SIGNAL(triggered()), + SLOT(copyTotp())); m_actionMultiplexer.connect(m_ui->actionEntryCopyTitle, SIGNAL(triggered()), SLOT(copyTitle())); m_actionMultiplexer.connect(m_ui->actionEntryCopyUsername, SIGNAL(triggered()), @@ -275,18 +308,40 @@ MainWindow::MainWindow() SLOT(switchToGroupEdit())); m_actionMultiplexer.connect(m_ui->actionGroupDelete, SIGNAL(triggered()), SLOT(deleteGroup())); + m_actionMultiplexer.connect(m_ui->actionGroupEmptyRecycleBin, SIGNAL(triggered()), + SLOT(emptyRecycleBin())); connect(m_ui->actionSettings, SIGNAL(triggered()), SLOT(switchToSettings())); connect(m_ui->actionPasswordGenerator, SIGNAL(toggled(bool)), SLOT(switchToPasswordGen(bool))); connect(m_ui->passwordGeneratorWidget, SIGNAL(dialogTerminated()), SLOT(closePasswordGen())); + connect(m_ui->welcomeWidget, SIGNAL(newDatabase()), SLOT(switchToNewDatabase())); + connect(m_ui->welcomeWidget, SIGNAL(openDatabase()), SLOT(switchToOpenDatabase())); + connect(m_ui->welcomeWidget, SIGNAL(openDatabaseFile(QString)), SLOT(switchToDatabaseFile(QString))); + connect(m_ui->welcomeWidget, SIGNAL(importKeePass1Database()), SLOT(switchToKeePass1Database())); + connect(m_ui->welcomeWidget, SIGNAL(importCsv()), SLOT(switchToImportCsv())); + connect(m_ui->actionAbout, SIGNAL(triggered()), SLOT(showAboutDialog())); #ifdef Q_OS_MAC setUnifiedTitleAndToolBarOnMac(true); #endif + connect(m_ui->tabWidget, SIGNAL(messageGlobal(QString,MessageWidget::MessageType)), this, SLOT(displayGlobalMessage(QString, MessageWidget::MessageType))); + connect(m_ui->tabWidget, SIGNAL(messageDismissGlobal()), this, SLOT(hideGlobalMessage())); + connect(m_ui->tabWidget, SIGNAL(messageTab(QString,MessageWidget::MessageType)), this, SLOT(displayTabMessage(QString, MessageWidget::MessageType))); + connect(m_ui->tabWidget, SIGNAL(messageDismissTab()), this, SLOT(hideTabMessage())); + + m_screenLockListener = new ScreenLockListener(this); + connect(m_screenLockListener, SIGNAL(screenLocked()), SLOT(handleScreenLock())); + updateTrayIcon(); + + if (config()->hasAccessError()) { + m_ui->globalMessageWidget->showMessage( + tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error); + } + } MainWindow::~MainWindow() @@ -295,7 +350,7 @@ MainWindow::~MainWindow() void MainWindow::appExit() { - appExitCalled = true; + m_appExitCalled = true; close(); } @@ -344,6 +399,11 @@ void MainWindow::openRecentDatabase(QAction* action) void MainWindow::clearLastDatabases() { config()->set("LastDatabases", QVariant()); + bool inWelcomeWidget = (m_ui->stackedWidget->currentIndex() == 2); + + if (inWelcomeWidget) { + m_ui->welcomeWidget->refreshLastDatabases(); + } } void MainWindow::openDatabase(const QString& fileName, const QString& pw, const QString& keyFile) @@ -354,8 +414,8 @@ void MainWindow::openDatabase(const QString& fileName, const QString& pw, const void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) { int currentIndex = m_ui->stackedWidget->currentIndex(); - bool inDatabaseTabWidget = (currentIndex == 0); - bool inWelcomeWidget = (currentIndex == 2); + bool inDatabaseTabWidget = (currentIndex == DatabaseTabScreen); + bool inWelcomeWidget = (currentIndex == WelcomeScreen); if (inDatabaseTabWidget && m_ui->tabWidget->currentIndex() != -1) { DatabaseWidget* dbWidget = m_ui->tabWidget->currentDatabaseWidget(); @@ -371,6 +431,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) bool singleEntrySelected = dbWidget->numberOfSelectedEntries() == 1; bool entriesSelected = dbWidget->numberOfSelectedEntries() > 0; bool groupSelected = dbWidget->isGroupSelected(); + bool recycleBinSelected = dbWidget->isRecycleBinSelected(); m_ui->actionEntryNew->setEnabled(!inSearch); m_ui->actionEntryClone->setEnabled(singleEntrySelected); @@ -382,11 +443,17 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionEntryCopyURL->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUrl()); m_ui->actionEntryCopyNotes->setEnabled(singleEntrySelected && dbWidget->currentEntryHasNotes()); m_ui->menuEntryCopyAttribute->setEnabled(singleEntrySelected); + m_ui->menuEntryTotp->setEnabled(true); m_ui->actionEntryAutoType->setEnabled(singleEntrySelected); m_ui->actionEntryOpenUrl->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUrl()); + m_ui->actionEntryTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp()); + m_ui->actionEntryCopyTotp->setEnabled(singleEntrySelected && dbWidget->currentEntryHasTotp()); + m_ui->actionEntrySetupTotp->setEnabled(singleEntrySelected); m_ui->actionGroupNew->setEnabled(groupSelected); m_ui->actionGroupEdit->setEnabled(groupSelected); m_ui->actionGroupDelete->setEnabled(groupSelected && dbWidget->canDeleteCurrentGroup()); + m_ui->actionGroupEmptyRecycleBin->setVisible(recycleBinSelected); + m_ui->actionGroupEmptyRecycleBin->setEnabled(recycleBinSelected); m_ui->actionChangeMasterKey->setEnabled(true); m_ui->actionChangeDatabaseSettings->setEnabled(true); m_ui->actionDatabaseSave->setEnabled(true); @@ -398,6 +465,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) break; } case DatabaseWidget::EditMode: + case DatabaseWidget::ImportMode: case DatabaseWidget::LockedMode: { const QList entryActions = m_ui->menuEntries->actions(); for (QAction* action : entryActions) { @@ -414,6 +482,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionEntryCopyURL->setEnabled(false); m_ui->actionEntryCopyNotes->setEnabled(false); m_ui->menuEntryCopyAttribute->setEnabled(false); + m_ui->menuEntryTotp->setEnabled(false); m_ui->actionChangeMasterKey->setEnabled(false); m_ui->actionChangeDatabaseSettings->setEnabled(false); @@ -446,6 +515,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionEntryCopyURL->setEnabled(false); m_ui->actionEntryCopyNotes->setEnabled(false); m_ui->menuEntryCopyAttribute->setEnabled(false); + m_ui->menuEntryTotp->setEnabled(false); m_ui->actionChangeMasterKey->setEnabled(false); m_ui->actionChangeDatabaseSettings->setEnabled(false); @@ -462,13 +532,13 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionDatabaseNew->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->actionDatabaseOpen->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->menuRecentDatabases->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); - m_ui->actionImportKeePass1->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); + m_ui->menuImport->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->actionDatabaseMerge->setEnabled(inDatabaseTabWidget); m_ui->actionRepairDatabase->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->actionLockDatabases->setEnabled(m_ui->tabWidget->hasLockableDatabases()); - if ((3 == currentIndex) != m_ui->actionPasswordGenerator->isChecked()) { + if ((currentIndex == PasswordGeneratorScreen) != m_ui->actionPasswordGenerator->isChecked()) { bool blocked = m_ui->actionPasswordGenerator->blockSignals(true); m_ui->actionPasswordGenerator->toggle(); m_ui->actionPasswordGenerator->blockSignals(blocked); @@ -480,7 +550,7 @@ void MainWindow::updateWindowTitle() QString customWindowTitlePart; int stackedWidgetIndex = m_ui->stackedWidget->currentIndex(); int tabWidgetIndex = m_ui->tabWidget->currentIndex(); - if (stackedWidgetIndex == 0 && tabWidgetIndex != -1) { + if (stackedWidgetIndex == DatabaseTabScreen && tabWidgetIndex != -1) { customWindowTitlePart = m_ui->tabWidget->tabText(tabWidgetIndex); if (m_ui->tabWidget->readOnly(tabWidgetIndex)) { customWindowTitlePart.append(QString(" [%1]").arg(tr("read-only"))); @@ -496,29 +566,37 @@ void MainWindow::updateWindowTitle() windowTitle = QString("%1 - %2").arg(customWindowTitlePart, BaseWindowTitle); } + if (customWindowTitlePart.isEmpty() || stackedWidgetIndex == 1) { + setWindowFilePath(""); + } else { + setWindowFilePath(m_ui->tabWidget->databasePath(tabWidgetIndex)); + } + + setWindowModified(m_ui->tabWidget->isModified(tabWidgetIndex)); + setWindowTitle(windowTitle); } void MainWindow::showAboutDialog() { AboutDialog* aboutDialog = new AboutDialog(this); - aboutDialog->show(); + aboutDialog->open(); } void MainWindow::switchToDatabases() { if (m_ui->tabWidget->currentIndex() == -1) { - m_ui->stackedWidget->setCurrentIndex(2); + m_ui->stackedWidget->setCurrentIndex(WelcomeScreen); } else { - m_ui->stackedWidget->setCurrentIndex(0); + m_ui->stackedWidget->setCurrentIndex(DatabaseTabScreen); } } void MainWindow::switchToSettings() { m_ui->settingsWidget->loadSettings(); - m_ui->stackedWidget->setCurrentIndex(1); + m_ui->stackedWidget->setCurrentIndex(SettingsScreen); } void MainWindow::switchToPasswordGen(bool enabled) @@ -527,7 +605,7 @@ void MainWindow::switchToPasswordGen(bool enabled) m_ui->passwordGeneratorWidget->loadSettings(); m_ui->passwordGeneratorWidget->regeneratePassword(); m_ui->passwordGeneratorWidget->setStandaloneMode(true); - m_ui->stackedWidget->setCurrentIndex(3); + m_ui->stackedWidget->setCurrentIndex(PasswordGeneratorScreen); } else { m_ui->passwordGeneratorWidget->saveSettings(); switchToDatabases(); @@ -539,6 +617,36 @@ void MainWindow::closePasswordGen() switchToPasswordGen(false); } +void MainWindow::switchToNewDatabase() +{ + m_ui->tabWidget->newDatabase(); + switchToDatabases(); +} + +void MainWindow::switchToOpenDatabase() +{ + m_ui->tabWidget->openDatabase(); + switchToDatabases(); +} + +void MainWindow::switchToDatabaseFile(QString file) +{ + m_ui->tabWidget->openDatabase(file); + switchToDatabases(); +} + +void MainWindow::switchToKeePass1Database() +{ + m_ui->tabWidget->importKeePass1Database(); + switchToDatabases(); +} + +void MainWindow::switchToImportCsv() +{ + m_ui->tabWidget->importCsv(); + switchToDatabases(); +} + void MainWindow::databaseStatusChanged(DatabaseWidget *) { updateTrayIcon(); @@ -546,11 +654,11 @@ void MainWindow::databaseStatusChanged(DatabaseWidget *) void MainWindow::databaseTabChanged(int tabIndex) { - if (tabIndex != -1 && m_ui->stackedWidget->currentIndex() == 2) { - m_ui->stackedWidget->setCurrentIndex(0); + if (tabIndex != -1 && m_ui->stackedWidget->currentIndex() == WelcomeScreen) { + m_ui->stackedWidget->setCurrentIndex(DatabaseTabScreen); } - else if (tabIndex == -1 && m_ui->stackedWidget->currentIndex() == 0) { - m_ui->stackedWidget->setCurrentIndex(2); + else if (tabIndex == -1 && m_ui->stackedWidget->currentIndex() == DatabaseTabScreen) { + m_ui->stackedWidget->setCurrentIndex(WelcomeScreen); } m_actionMultiplexer.setCurrentObject(m_ui->tabWidget->currentDatabaseWidget()); @@ -558,9 +666,15 @@ void MainWindow::databaseTabChanged(int tabIndex) void MainWindow::closeEvent(QCloseEvent* event) { + // ignore double close events (happens on macOS when closing from the dock) + if (m_appExiting) { + event->accept(); + return; + } + bool minimizeOnClose = isTrayIconEnabled() && config()->get("GUI/MinimizeOnClose").toBool(); - if (minimizeOnClose && !appExitCalled) + if (minimizeOnClose && !m_appExitCalled) { event->ignore(); hideWindow(); @@ -575,6 +689,7 @@ void MainWindow::closeEvent(QCloseEvent* event) bool accept = saveLastDatabases(); if (accept) { + m_appExiting = true; saveWindowInformation(); event->accept(); @@ -647,10 +762,17 @@ void MainWindow::updateTrayIcon() QAction* actionToggle = new QAction(tr("Toggle window"), menu); menu->addAction(actionToggle); +#ifdef Q_OS_MAC + QAction* actionQuit = new QAction(tr("Quit KeePassXC"), menu); + menu->addAction(actionQuit); + + connect(actionQuit, SIGNAL(triggered()), SLOT(appExit())); +#else menu->addAction(m_ui->actionQuit); connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), SLOT(trayIconTriggered(QSystemTrayIcon::ActivationReason))); +#endif connect(actionToggle, SIGNAL(triggered()), SLOT(toggleWindow())); m_trayIcon->setContextMenu(menu); @@ -730,7 +852,9 @@ void MainWindow::trayIconTriggered(QSystemTrayIcon::ActivationReason reason) void MainWindow::hideWindow() { +#ifndef Q_OS_MAC setWindowState(windowState() | Qt::WindowMinimized); +#endif QTimer::singleShot(0, this, SLOT(hide())); if (config()->get("security/lockdatabaseminimize").toBool()) { @@ -803,8 +927,9 @@ void MainWindow::repairDatabase() KeePass2Writer writer; writer.writeDatabase(saveFileName, dbRepairWidget->database()); if (writer.hasError()) { - QMessageBox::critical(this, tr("Error"), - tr("Writing the database failed.").append("\n\n").append(writer.errorString())); + displayGlobalMessage( + tr("Writing the database failed.").append("\n").append(writer.errorString()), + MessageWidget::Error); } } } @@ -812,11 +937,49 @@ void MainWindow::repairDatabase() bool MainWindow::isTrayIconEnabled() const { -#ifdef Q_OS_MAC - // systray not useful on OS X - return false; -#else return config()->get("GUI/ShowTrayIcon").toBool() && QSystemTrayIcon::isSystemTrayAvailable(); -#endif +} + +void MainWindow::displayGlobalMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton) +{ + m_ui->globalMessageWidget->setCloseButtonVisible(showClosebutton); + m_ui->globalMessageWidget->showMessage(text, type); +} + +void MainWindow::displayTabMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton) +{ + m_ui->globalMessageWidget->setCloseButtonVisible(showClosebutton); + m_ui->tabWidget->currentDatabaseWidget()->showMessage(text, type); +} + +void MainWindow::hideGlobalMessage() +{ + m_ui->globalMessageWidget->hideMessage(); +} + +void MainWindow::hideTabMessage() +{ + if (m_ui->stackedWidget->currentIndex() == DatabaseTabScreen) { + m_ui->tabWidget->currentDatabaseWidget()->hideMessage(); + } +} + +void MainWindow::showYubiKeyPopup() +{ + displayGlobalMessage(tr("Please touch the button on your YubiKey!"), MessageWidget::Information, false); + setEnabled(false); +} + +void MainWindow::hideYubiKeyPopup() +{ + hideGlobalMessage(); + setEnabled(true); +} + +void MainWindow::handleScreenLock() +{ + if (config()->get("security/lockdatabasescreenlock").toBool()){ + lockDatabasesAfterInactivity(); + } } diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index ff92260f45..caf3f58544 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,7 +24,9 @@ #include #include "core/SignalMultiplexer.h" +#include "core/ScreenLockListener.h" #include "gui/DatabaseWidget.h" +#include "gui/Application.h" namespace Ui { class MainWindow; @@ -39,22 +42,40 @@ class MainWindow : public QMainWindow MainWindow(); ~MainWindow(); -public Q_SLOTS: + enum StackedWidgetIndex + { + DatabaseTabScreen = 0, + SettingsScreen = 1, + WelcomeScreen = 2, + PasswordGeneratorScreen = 3 + }; + +public slots: void openDatabase(const QString& fileName, const QString& pw = QString(), const QString& keyFile = QString()); void appExit(); + void displayGlobalMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton = true); + void displayTabMessage(const QString& text, MessageWidget::MessageType type, bool showClosebutton = true); + void hideGlobalMessage(); + void showYubiKeyPopup(); + void hideYubiKeyPopup(); protected: void closeEvent(QCloseEvent* event) override; void changeEvent(QEvent* event) override; -private Q_SLOTS: +private slots: void setMenuActionState(DatabaseWidget::Mode mode = DatabaseWidget::None); void updateWindowTitle(); void showAboutDialog(); void switchToDatabases(); void switchToSettings(); void switchToPasswordGen(bool enabled); + void switchToNewDatabase(); + void switchToOpenDatabase(); + void switchToDatabaseFile(QString file); + void switchToKeePass1Database(); + void switchToImportCsv(); void closePasswordGen(); void databaseStatusChanged(DatabaseWidget *dbWidget); void databaseTabChanged(int tabIndex); @@ -72,6 +93,8 @@ private Q_SLOTS: void toggleWindow(); void lockDatabasesAfterInactivity(); void repairDatabase(); + void hideTabMessage(); + void handleScreenLock(); private: static void setShortcut(QAction* action, QKeySequence::StandardKey standard, int fallback = 0); @@ -93,10 +116,15 @@ private Q_SLOTS: InactivityTimer* m_inactivityTimer; int m_countDefaultAttributes; QSystemTrayIcon* m_trayIcon; + ScreenLockListener* m_screenLockListener; Q_DISABLE_COPY(MainWindow) - bool appExitCalled; + bool m_appExitCalled; + bool m_appExiting; }; +#define KEEPASSXC_MAIN_WINDOW (qobject_cast(qApp) ? \ + qobject_cast(qobject_cast(qApp)->mainWindow()) : nullptr) + #endif // KEEPASSX_MAINWINDOW_H diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index 188ef1586b..2ed42d0ec4 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -2,6 +2,9 @@ MainWindow + + true + 0 @@ -14,6 +17,9 @@ KeePassXC + + true + 0 @@ -27,8 +33,24 @@ 0 + + + + + 0 + 0 + + + + + + + 0 + 0 + + 2 @@ -83,7 +105,43 @@ - + + + + + Qt::Horizontal + + + QSizePolicy::MinimumExpanding + + + + 50 + 20 + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::MinimumExpanding + + + + 50 + 20 + + + + + @@ -104,18 +162,25 @@ 0 0 800 - 26 + 21 - Database + &Database &Recent databases + + + Import + + + + @@ -127,7 +192,7 @@ - + @@ -155,9 +220,21 @@ + + + false + + + Timed one-time password + + + + + + @@ -170,12 +247,14 @@ &Groups + + - Tools + &Tools @@ -203,6 +282,7 @@ false + @@ -254,9 +334,9 @@ - - Merge from KeePassX database - + + Merge from KeePassX database + @@ -333,11 +413,6 @@ Database settings - - - &Import KeePass 1 database - - false @@ -445,13 +520,52 @@ &Export to CSV file + + + Import KeePass 1 database + + + + + Import CSV file + + Re&pair database + + + Show TOTP + + + + + Setup TOTP + + + + + Copy &TOTP + + + + + Empty recycle bin + + + false + + + + MessageWidget + QWidget +
gui/MessageWidget.h
+ 1 +
DatabaseTabWidget QTabWidget diff --git a/src/gui/MessageWidget.cpp b/src/gui/MessageWidget.cpp new file mode 100644 index 0000000000..de981b92a7 --- /dev/null +++ b/src/gui/MessageWidget.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 Pedro Alves + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "MessageWidget.h" + +MessageWidget::MessageWidget(QWidget* parent) + :KMessageWidget(parent) +{ + +} + +void MessageWidget::showMessage(const QString& text, MessageWidget::MessageType type) +{ + setMessageType(type); + setText(text); + animatedShow(); +} + +void MessageWidget::hideMessage() +{ + animatedHide(); +} diff --git a/src/gui/MessageWidget.h b/src/gui/MessageWidget.h new file mode 100644 index 0000000000..03ebee3eb7 --- /dev/null +++ b/src/gui/MessageWidget.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2015 Pedro Alves + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef MESSAGEWIDGET_H +#define MESSAGEWIDGET_H + +#include "gui/KMessageWidget.h" + +class MessageWidget : public KMessageWidget +{ + Q_OBJECT + +public: + explicit MessageWidget(QWidget* parent = 0); + +public slots: + void showMessage(const QString& text, MessageWidget::MessageType type); + void hideMessage(); + +}; + +#endif // MESSAGEWIDGET_H diff --git a/src/gui/PasswordComboBox.cpp b/src/gui/PasswordComboBox.cpp deleted file mode 100644 index 1f6c068f1c..0000000000 --- a/src/gui/PasswordComboBox.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2013 Michael Curtis - * Copyright (C) 2014 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "PasswordComboBox.h" - -#include - -#include "core/PasswordGenerator.h" - -PasswordComboBox::PasswordComboBox(QWidget* parent) - : QComboBox(parent) - , m_generator(nullptr) - , m_alternatives(10) -{ - setEditable(true); - setEcho(false); -} - -PasswordComboBox::~PasswordComboBox() -{ -} - -void PasswordComboBox::setEcho(bool echo) -{ - lineEdit()->setEchoMode(echo ? QLineEdit::Normal : QLineEdit::Password); - - QString current = currentText(); - - if (echo) { - // add fake item to show visual indication that a popup is available - addItem(""); - -#ifdef Q_OS_MAC - // Qt on Mac OS doesn't seem to know the generic monospace family (tested with 4.8.6) - setStyleSheet("QComboBox { font-family: monospace,Menlo,Monaco; }"); -#else - setStyleSheet("QComboBox { font-family: monospace,Courier New; }"); -#endif - } - else { - // clear items so the combobox indicates that no popup menu is available - clear(); - - setStyleSheet("QComboBox { font-family: initial; }"); - } - - setEditText(current); -} - -void PasswordComboBox::setGenerator(PasswordGenerator* generator) -{ - m_generator = generator; -} - -void PasswordComboBox::setNumberAlternatives(int alternatives) -{ - m_alternatives = alternatives; -} - -void PasswordComboBox::showPopup() -{ - // no point in showing a bunch of hidden passwords - if (lineEdit()->echoMode() == QLineEdit::Password) { - hidePopup(); - return; - } - - // keep existing password as the first item in the popup - QString current = currentText(); - clear(); - addItem(current); - - if (m_generator && m_generator->isValid()) { - for (int alternative = 0; alternative < m_alternatives; alternative++) { - QString password = m_generator->generatePassword(); - - addItem(password); - } - } - - QComboBox::showPopup(); -} diff --git a/src/gui/PasswordEdit.cpp b/src/gui/PasswordEdit.cpp index 98a5e2a500..54b0ca2881 100644 --- a/src/gui/PasswordEdit.cpp +++ b/src/gui/PasswordEdit.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,7 +70,7 @@ void PasswordEdit::setShowPassword(bool show) } } updateStylesheet(); - Q_EMIT showPasswordChanged(show); + emit showPasswordChanged(show); } bool PasswordEdit::passwordsEqual() const diff --git a/src/gui/PasswordEdit.h b/src/gui/PasswordEdit.h index 994576d233..d5439f1a06 100644 --- a/src/gui/PasswordEdit.h +++ b/src/gui/PasswordEdit.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,13 +32,13 @@ class PasswordEdit : public QLineEdit explicit PasswordEdit(QWidget* parent = nullptr); void enableVerifyMode(PasswordEdit* baseEdit); -public Q_SLOTS: +public slots: void setShowPassword(bool show); -Q_SIGNALS: +signals: void showPasswordChanged(bool show); -private Q_SLOTS: +private slots: void updateStylesheet(); void autocompletePassword(QString password); diff --git a/src/gui/PasswordGeneratorWidget.cpp b/src/gui/PasswordGeneratorWidget.cpp index 4a4b438e31..3753071d1a 100644 --- a/src/gui/PasswordGeneratorWidget.cpp +++ b/src/gui/PasswordGeneratorWidget.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,31 +20,41 @@ #include "ui_PasswordGeneratorWidget.h" #include +#include #include "core/Config.h" #include "core/PasswordGenerator.h" #include "core/FilePath.h" +#include "gui/Clipboard.h" PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent) : QWidget(parent) , m_updatingSpinBox(false) - , m_generator(new PasswordGenerator()) + , m_passwordGenerator(new PasswordGenerator()) + , m_dicewareGenerator(new PassphraseGenerator()) , m_ui(new Ui::PasswordGeneratorWidget()) { m_ui->setupUi(this); m_ui->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show")); - connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updateApplyEnabled(QString))); + connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updateButtonsEnabled(QString))); connect(m_ui->editNewPassword, SIGNAL(textChanged(QString)), SLOT(updatePasswordStrength(QString))); connect(m_ui->togglePasswordButton, SIGNAL(toggled(bool)), SLOT(togglePasswordShown(bool))); connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(applyPassword())); - connect(m_ui->buttonGenerate, SIGNAL(clicked()), SLOT(generatePassword())); + connect(m_ui->buttonCopy, SIGNAL(clicked()), SLOT(copyPassword())); + connect(m_ui->buttonGenerate, SIGNAL(clicked()), SLOT(regeneratePassword())); - connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(sliderMoved())); - connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(spinBoxChanged())); + connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(passwordSliderMoved())); + connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(passwordSpinBoxChanged())); + connect(m_ui->sliderWordCount, SIGNAL(valueChanged(int)), SLOT(dicewareSliderMoved())); + connect(m_ui->spinBoxWordCount, SIGNAL(valueChanged(int)), SLOT(dicewareSpinBoxChanged())); + + connect(m_ui->editWordSeparator, SIGNAL(textChanged(QString)), SLOT(updateGenerator())); + connect(m_ui->comboBoxWordList, SIGNAL(currentIndexChanged(int)), SLOT(updateGenerator())); connect(m_ui->optionButtons, SIGNAL(buttonClicked(int)), SLOT(updateGenerator())); + connect(m_ui->tabWidget, SIGNAL(currentChanged(int)), SLOT(updateGenerator())); // set font size of password quality and entropy labels dynamically to 80% of // the default font size, but make it no smaller than 8pt @@ -54,6 +65,20 @@ PasswordGeneratorWidget::PasswordGeneratorWidget(QWidget* parent) m_ui->entropyLabel->setFont(defaultFont); m_ui->strengthLabel->setFont(defaultFont); } + + // set default separator to Space + m_ui->editWordSeparator->setText(" "); + + QDir path(filePath()->dataPath("wordlists/")); + QStringList files = path.entryList(QDir::Files); + m_ui->comboBoxWordList->addItems(files); + if (files.size() > 1) { + m_ui->comboBoxWordList->setVisible(true); + m_ui->labelWordList->setVisible(true); + } else { + m_ui->comboBoxWordList->setVisible(false); + m_ui->labelWordList->setVisible(false); + } loadSettings(); reset(); @@ -65,28 +90,44 @@ PasswordGeneratorWidget::~PasswordGeneratorWidget() void PasswordGeneratorWidget::loadSettings() { + // Password config m_ui->checkBoxLower->setChecked(config()->get("generator/LowerCase", true).toBool()); m_ui->checkBoxUpper->setChecked(config()->get("generator/UpperCase", true).toBool()); m_ui->checkBoxNumbers->setChecked(config()->get("generator/Numbers", true).toBool()); m_ui->checkBoxSpecialChars->setChecked(config()->get("generator/SpecialChars", false).toBool()); - + m_ui->checkBoxExtASCII->setChecked(config()->get("generator/EASCII", false).toBool()); m_ui->checkBoxExcludeAlike->setChecked(config()->get("generator/ExcludeAlike", true).toBool()); m_ui->checkBoxEnsureEvery->setChecked(config()->get("generator/EnsureEvery", true).toBool()); - m_ui->spinBoxLength->setValue(config()->get("generator/Length", 16).toInt()); + + // Diceware config + m_ui->spinBoxWordCount->setValue(config()->get("generator/WordCount", 6).toInt()); + m_ui->editWordSeparator->setText(config()->get("generator/WordSeparator", " ").toString()); + m_ui->comboBoxWordList->setCurrentText(config()->get("generator/WordList", "eff_large.wordlist").toString()); + + // Password or diceware? + m_ui->tabWidget->setCurrentIndex(config()->get("generator/Type", 0).toInt()); } void PasswordGeneratorWidget::saveSettings() { + // Password config config()->set("generator/LowerCase", m_ui->checkBoxLower->isChecked()); config()->set("generator/UpperCase", m_ui->checkBoxUpper->isChecked()); config()->set("generator/Numbers", m_ui->checkBoxNumbers->isChecked()); config()->set("generator/SpecialChars", m_ui->checkBoxSpecialChars->isChecked()); - + config()->set("generator/EASCII", m_ui->checkBoxExtASCII->isChecked()); config()->set("generator/ExcludeAlike", m_ui->checkBoxExcludeAlike->isChecked()); config()->set("generator/EnsureEvery", m_ui->checkBoxEnsureEvery->isChecked()); - config()->set("generator/Length", m_ui->spinBoxLength->value()); + + // Diceware config + config()->set("generator/WordCount", m_ui->spinBoxWordCount->value()); + config()->set("generator/WordSeparator", m_ui->editWordSeparator->text()); + config()->set("generator/WordList", m_ui->comboBoxWordList->currentText()); + + // Password or diceware? + config()->set("generator/Type", m_ui->tabWidget->currentIndex()); } void PasswordGeneratorWidget::reset() @@ -99,6 +140,7 @@ void PasswordGeneratorWidget::reset() void PasswordGeneratorWidget::setStandaloneMode(bool standalone) { + m_standalone = standalone; if (standalone) { m_ui->buttonApply->setText(tr("Close")); togglePasswordShown(true); @@ -108,22 +150,39 @@ void PasswordGeneratorWidget::setStandaloneMode(bool standalone) } void PasswordGeneratorWidget::regeneratePassword() -{ - if (m_generator->isValid()) { - QString password = m_generator->generatePassword(); - m_ui->editNewPassword->setText(password); - updatePasswordStrength(password); +{ + if (m_ui->tabWidget->currentIndex() == Password) { + if (m_passwordGenerator->isValid()) { + QString password = m_passwordGenerator->generatePassword(); + m_ui->editNewPassword->setText(password); + updatePasswordStrength(password); + } + } else { + if (m_dicewareGenerator->isValid()) { + QString password = m_dicewareGenerator->generatePassphrase(); + m_ui->editNewPassword->setText(password); + updatePasswordStrength(password); + } } } -void PasswordGeneratorWidget::updateApplyEnabled(const QString& password) +void PasswordGeneratorWidget::updateButtonsEnabled(const QString& password) { - m_ui->buttonApply->setEnabled(!password.isEmpty()); + if (!m_standalone) { + m_ui->buttonApply->setEnabled(!password.isEmpty()); + } + m_ui->buttonCopy->setEnabled(!password.isEmpty()); } void PasswordGeneratorWidget::updatePasswordStrength(const QString& password) { - double entropy = m_generator->calculateEntropy(password); + double entropy = 0.0; + if (m_ui->tabWidget->currentIndex() == Password) { + entropy = m_passwordGenerator->calculateEntropy(password); + } else { + entropy = m_dicewareGenerator->calculateEntropy(password); + } + m_ui->entropyLabel->setText(tr("Entropy: %1 bit").arg(QString::number(entropy, 'f', 2))); if (entropy > m_ui->entropyProgressBar->maximum()) { @@ -134,22 +193,19 @@ void PasswordGeneratorWidget::updatePasswordStrength(const QString& password) colorStrengthIndicator(entropy); } -void PasswordGeneratorWidget::generatePassword() +void PasswordGeneratorWidget::applyPassword() { - if (m_generator->isValid()) { - QString password = m_generator->generatePassword(); - m_ui->editNewPassword->setText(password); - } + saveSettings(); + emit appliedPassword(m_ui->editNewPassword->text()); + emit dialogTerminated(); } -void PasswordGeneratorWidget::applyPassword() +void PasswordGeneratorWidget::copyPassword() { - saveSettings(); - Q_EMIT appliedPassword(m_ui->editNewPassword->text()); - Q_EMIT dialogTerminated(); + clipboard()->setText(m_ui->editNewPassword->text()); } -void PasswordGeneratorWidget::sliderMoved() +void PasswordGeneratorWidget::passwordSliderMoved() { if (m_updatingSpinBox) { return; @@ -160,7 +216,7 @@ void PasswordGeneratorWidget::sliderMoved() updateGenerator(); } -void PasswordGeneratorWidget::spinBoxChanged() +void PasswordGeneratorWidget::passwordSpinBoxChanged() { if (m_updatingSpinBox) { return; @@ -176,6 +232,20 @@ void PasswordGeneratorWidget::spinBoxChanged() updateGenerator(); } +void PasswordGeneratorWidget::dicewareSliderMoved() +{ + m_ui->spinBoxWordCount->setValue(m_ui->sliderWordCount->value()); + + updateGenerator(); +} + +void PasswordGeneratorWidget::dicewareSpinBoxChanged() +{ + m_ui->sliderWordCount->setValue(m_ui->spinBoxWordCount->value()); + + updateGenerator(); +} + void PasswordGeneratorWidget::togglePasswordShown(bool showing) { m_ui->editNewPassword->setShowPassword(showing); @@ -196,13 +266,13 @@ void PasswordGeneratorWidget::colorStrengthIndicator(double entropy) // Set the color and background based on entropy // colors are taking from the KDE breeze palette // - if (entropy < 35) { + if (entropy < 40) { m_ui->entropyProgressBar->setStyleSheet(style.arg("#c0392b")); m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Poor"))); - } else if (entropy >= 35 && entropy < 55) { + } else if (entropy >= 40 && entropy < 65) { m_ui->entropyProgressBar->setStyleSheet(style.arg("#f39c1f")); m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Weak"))); - } else if (entropy >= 55 && entropy < 100) { + } else if (entropy >= 65 && entropy < 100) { m_ui->entropyProgressBar->setStyleSheet(style.arg("#11d116")); m_ui->strengthLabel->setText(tr("Password Quality: %1").arg(tr("Good"))); } else { @@ -231,6 +301,10 @@ PasswordGenerator::CharClasses PasswordGeneratorWidget::charClasses() classes |= PasswordGenerator::SpecialCharacters; } + if (m_ui->checkBoxExtASCII->isChecked()) { + classes |= PasswordGenerator::EASCII; + } + return classes; } @@ -251,44 +325,74 @@ PasswordGenerator::GeneratorFlags PasswordGeneratorWidget::generatorFlags() void PasswordGeneratorWidget::updateGenerator() { - PasswordGenerator::CharClasses classes = charClasses(); - PasswordGenerator::GeneratorFlags flags = generatorFlags(); - - int minLength = 0; - if (flags.testFlag(PasswordGenerator::CharFromEveryGroup)) { - if (classes.testFlag(PasswordGenerator::LowerLetters)) { - minLength++; + if (m_ui->tabWidget->currentIndex() == Password) { + PasswordGenerator::CharClasses classes = charClasses(); + PasswordGenerator::GeneratorFlags flags = generatorFlags(); + + int minLength = 0; + if (flags.testFlag(PasswordGenerator::CharFromEveryGroup)) { + if (classes.testFlag(PasswordGenerator::LowerLetters)) { + minLength++; + } + if (classes.testFlag(PasswordGenerator::UpperLetters)) { + minLength++; + } + if (classes.testFlag(PasswordGenerator::Numbers)) { + minLength++; + } + if (classes.testFlag(PasswordGenerator::SpecialCharacters)) { + minLength++; + } + if (classes.testFlag(PasswordGenerator::EASCII)) { + minLength++; + } } - if (classes.testFlag(PasswordGenerator::UpperLetters)) { - minLength++; - } - if (classes.testFlag(PasswordGenerator::Numbers)) { - minLength++; + minLength = qMax(minLength, 1); + + if (m_ui->spinBoxLength->value() < minLength) { + m_updatingSpinBox = true; + m_ui->spinBoxLength->setValue(minLength); + m_ui->sliderLength->setValue(minLength); + m_updatingSpinBox = false; } - if (classes.testFlag(PasswordGenerator::SpecialCharacters)) { - minLength++; + + m_ui->spinBoxLength->setMinimum(minLength); + m_ui->sliderLength->setMinimum(minLength); + + m_passwordGenerator->setLength(m_ui->spinBoxLength->value()); + m_passwordGenerator->setCharClasses(classes); + m_passwordGenerator->setFlags(flags); + + if (m_passwordGenerator->isValid()) { + m_ui->buttonGenerate->setEnabled(true); + } else { + m_ui->buttonGenerate->setEnabled(false); } - } - minLength = qMax(minLength, 1); + } else { + int minWordCount = 1; - if (m_ui->spinBoxLength->value() < minLength) { - m_updatingSpinBox = true; - m_ui->spinBoxLength->setValue(minLength); - m_ui->sliderLength->setValue(minLength); - m_updatingSpinBox = false; - } + if (m_ui->spinBoxWordCount->value() < minWordCount) { + m_updatingSpinBox = true; + m_ui->spinBoxWordCount->setValue(minWordCount); + m_ui->sliderWordCount->setValue(minWordCount); + m_updatingSpinBox = false; + } - m_ui->spinBoxLength->setMinimum(minLength); - m_ui->sliderLength->setMinimum(minLength); + m_ui->spinBoxWordCount->setMinimum(minWordCount); + m_ui->sliderWordCount->setMinimum(minWordCount); - m_generator->setLength(m_ui->spinBoxLength->value()); - m_generator->setCharClasses(classes); - m_generator->setFlags(flags); + m_dicewareGenerator->setWordCount(m_ui->spinBoxWordCount->value()); + if (!m_ui->comboBoxWordList->currentText().isEmpty()) { + QString path = filePath()->dataPath("wordlists/" + m_ui->comboBoxWordList->currentText()); + m_dicewareGenerator->setWordList(path); + } + m_dicewareGenerator->setWordSeparator(m_ui->editWordSeparator->text()); - if (m_generator->isValid()) { - m_ui->buttonGenerate->setEnabled(true); - } else { - m_ui->buttonGenerate->setEnabled(false); + if (m_dicewareGenerator->isValid()) { + m_ui->buttonGenerate->setEnabled(true); + } else { + m_ui->buttonGenerate->setEnabled(false); + } } regeneratePassword(); diff --git a/src/gui/PasswordGeneratorWidget.h b/src/gui/PasswordGeneratorWidget.h index b8803f85e1..1301064615 100644 --- a/src/gui/PasswordGeneratorWidget.h +++ b/src/gui/PasswordGeneratorWidget.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2013 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,50 +24,62 @@ #include #include "core/PasswordGenerator.h" +#include "core/PassphraseGenerator.h" namespace Ui { class PasswordGeneratorWidget; } class PasswordGenerator; +class PassphraseGenerator; class PasswordGeneratorWidget : public QWidget { Q_OBJECT public: + enum GeneratorTypes + { + Password = 0, + Diceware = 1 + }; explicit PasswordGeneratorWidget(QWidget* parent = nullptr); ~PasswordGeneratorWidget(); void loadSettings(); void saveSettings(); void reset(); void setStandaloneMode(bool standalone); +public Q_SLOTS: void regeneratePassword(); -Q_SIGNALS: +signals: void appliedPassword(const QString& password); void dialogTerminated(); -private Q_SLOTS: +private slots: void applyPassword(); - void generatePassword(); - void updateApplyEnabled(const QString& password); + void copyPassword(); + void updateButtonsEnabled(const QString& password); void updatePasswordStrength(const QString& password); void togglePasswordShown(bool hidden); - void sliderMoved(); - void spinBoxChanged(); + void passwordSliderMoved(); + void passwordSpinBoxChanged(); + void dicewareSliderMoved(); + void dicewareSpinBoxChanged(); void colorStrengthIndicator(double entropy); void updateGenerator(); private: bool m_updatingSpinBox; + bool m_standalone = false; PasswordGenerator::CharClasses charClasses(); PasswordGenerator::GeneratorFlags generatorFlags(); - const QScopedPointer m_generator; + const QScopedPointer m_passwordGenerator; + const QScopedPointer m_dicewareGenerator; const QScopedPointer m_ui; }; diff --git a/src/gui/PasswordGeneratorWidget.ui b/src/gui/PasswordGeneratorWidget.ui index d451178025..0b143b89e6 100644 --- a/src/gui/PasswordGeneratorWidget.ui +++ b/src/gui/PasswordGeneratorWidget.ui @@ -7,7 +7,7 @@ 0 0 575 - 284 + 305 @@ -31,14 +31,14 @@ - + QLayout::SetMinimumSize - 10 + 0 0 @@ -174,61 +174,6 @@ QProgressBar::chunk {
- - - - &Length: - - - spinBoxLength - - - - - - - 15 - - - 6 - - - - - 1 - - - 128 - - - 20 - - - Qt::Horizontal - - - QSlider::TicksBelow - - - 8 - - - - - - - 1 - - - 999 - - - 20 - - - - - @@ -239,179 +184,427 @@ QProgressBar::chunk {
- + - - - Character Types + + + + 0 + 0 + + + + + 0 + 0 + + + + QTabWidget::North - - - - - - - - 0 - 0 - - - - - 0 - 25 - - - - Qt::StrongFocus - - - Upper Case Letters - - - A-Z - - - true - - - optionButtons - - - - - - - - 0 - 0 - - - - - 0 - 25 - - - - Qt::StrongFocus - - - Lower Case Letters - - - a-z - - - true - - - optionButtons - - - - - - - - 0 - 0 - - - - - 0 - 25 - - - - Qt::StrongFocus - - - Numbers - - - 0-9 - - - true - - - optionButtons - - - - - - - - 0 - 0 - - - - - 0 - 25 - - - - Qt::StrongFocus - - - Special Characters - - - /*_& ... - - - true - - - optionButtons - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Exclude look-alike characters - - - optionButtons - - - - - - - Pick characters from every group - - - optionButtons - - - - + + QTabWidget::Rounded + + + 0 + + + + Password + + + + + + + + Character Types + + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + Qt::StrongFocus + + + Upper Case Letters + + + A-Z + + + true + + + optionButtons + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + Qt::StrongFocus + + + Lower Case Letters + + + a-z + + + true + + + optionButtons + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + Qt::StrongFocus + + + Numbers + + + 0-9 + + + true + + + optionButtons + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + Qt::StrongFocus + + + Special Characters + + + /*_& ... + + + true + + + optionButtons + + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + + 16777215 + 16777215 + + + + Qt::StrongFocus + + + Extended ASCII + + + Extended ASCII + + + true + + + optionButtons + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Exclude look-alike characters + + + optionButtons + + + + + + + Pick characters from every group + + + optionButtons + + + + + + + + + + + + 15 + + + 6 + + + + + &Length: + + + spinBoxLength + + + + + + + 1 + + + 128 + + + 20 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 8 + + + + + + + 1 + + + 999 + + + 20 + + + + + + + + + + Passphrase + + + + + + + + + + + 0 + 0 + + + + Wordlist: + + + + + + + + 0 + 0 + + + + + + + + Word Count: + + + spinBoxLength + + + + + + + QLayout::SetMinimumSize + + + + + 1 + + + 40 + + + 6 + + + 6 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 8 + + + + + + + 1 + + + 100 + + + 6 + + + + + + + + + Word Separator: + + + + + + + + + + + + + + + + - + + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -419,6 +612,13 @@ QProgressBar::chunk { + + + + Copy + + + @@ -433,6 +633,9 @@ QProgressBar::chunk { + + + @@ -440,6 +643,7 @@ QProgressBar::chunk { PasswordEdit QLineEdit
gui/PasswordEdit.h
+ 1
@@ -452,9 +656,6 @@ QProgressBar::chunk { checkBoxNumbers checkBoxSpecialChars checkBoxExcludeAlike - checkBoxEnsureEvery - buttonGenerate - buttonApply diff --git a/src/gui/SearchWidget.cpp b/src/gui/SearchWidget.cpp index 933686dfa5..7aa5f2901a 100644 --- a/src/gui/SearchWidget.cpp +++ b/src/gui/SearchWidget.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Jonathan White + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,10 +22,12 @@ #include #include #include +#include +#include "core/Config.h" #include "core/FilePath.h" -SearchWidget::SearchWidget(QWidget *parent) +SearchWidget::SearchWidget(QWidget* parent) : QWidget(parent) , m_ui(new Ui::SearchWidget()) { @@ -34,58 +37,63 @@ SearchWidget::SearchWidget(QWidget *parent) m_searchTimer->setSingleShot(true); connect(m_ui->searchEdit, SIGNAL(textChanged(QString)), SLOT(startSearchTimer())); - connect(m_ui->searchIcon, SIGNAL(pressed()), m_ui->searchEdit, SLOT(setFocus())); - connect(m_ui->clearIcon, SIGNAL(pressed()), m_ui->searchEdit, SLOT(clear())); - connect(m_ui->clearIcon, SIGNAL(pressed()), m_ui->searchEdit, SLOT(setFocus())); + connect(m_ui->clearIcon, SIGNAL(triggered(bool)), m_ui->searchEdit, SLOT(clear())); connect(m_searchTimer, SIGNAL(timeout()), this, SLOT(startSearch())); connect(this, SIGNAL(escapePressed()), m_ui->searchEdit, SLOT(clear())); new QShortcut(Qt::CTRL + Qt::Key_F, this, SLOT(searchFocus()), nullptr, Qt::ApplicationShortcut); - new QShortcut(Qt::Key_Escape, m_ui->searchEdit, SLOT(clear()), nullptr, Qt::ApplicationShortcut); + new QShortcut(Qt::Key_Escape, m_ui->searchEdit, SLOT(clear()), nullptr, Qt::ApplicationShortcut); m_ui->searchEdit->installEventFilter(this); - QMenu *searchMenu = new QMenu(); + QMenu* searchMenu = new QMenu(); m_actionCaseSensitive = searchMenu->addAction(tr("Case Sensitive"), this, SLOT(updateCaseSensitive())); m_actionCaseSensitive->setObjectName("actionSearchCaseSensitive"); m_actionCaseSensitive->setCheckable(true); + m_actionLimitGroup = searchMenu->addAction(tr("Limit search to selected group"), this, SLOT(updateLimitGroup())); + m_actionLimitGroup->setObjectName("actionSearchLimitGroup"); + m_actionLimitGroup->setCheckable(true); + m_actionLimitGroup->setChecked(config()->get("SearchLimitGroup", false).toBool()); + m_ui->searchIcon->setIcon(filePath()->icon("actions", "system-search")); m_ui->searchIcon->setMenu(searchMenu); - m_ui->searchIcon->setPopupMode(QToolButton::MenuButtonPopup); + m_ui->searchEdit->addAction(m_ui->searchIcon, QLineEdit::LeadingPosition); m_ui->clearIcon->setIcon(filePath()->icon("actions", "edit-clear-locationbar-rtl")); - m_ui->clearIcon->setEnabled(false); + m_ui->clearIcon->setVisible(false); + m_ui->searchEdit->addAction(m_ui->clearIcon, QLineEdit::TrailingPosition); + + // Fix initial visibility of actions (bug in Qt) + for (QToolButton* toolButton : m_ui->searchEdit->findChildren()) { + toolButton->setVisible(toolButton->defaultAction()->isVisible()); + } } SearchWidget::~SearchWidget() { - } -bool SearchWidget::eventFilter(QObject *obj, QEvent *event) +bool SearchWidget::eventFilter(QObject* obj, QEvent* event) { if (event->type() == QEvent::KeyPress) { - QKeyEvent *keyEvent = static_cast(event); + QKeyEvent* keyEvent = static_cast(event); if (keyEvent->key() == Qt::Key_Escape) { emit escapePressed(); return true; - } - else if (keyEvent->matches(QKeySequence::Copy)) { + } else if (keyEvent->matches(QKeySequence::Copy)) { // If Control+C is pressed in the search edit when no text // is selected, copy the password of the current entry if (!m_ui->searchEdit->hasSelectedText()) { emit copyPressed(); return true; } - } - else if (keyEvent->matches(QKeySequence::MoveToNextLine)) { + } else if (keyEvent->matches(QKeySequence::MoveToNextLine)) { if (m_ui->searchEdit->cursorPosition() == m_ui->searchEdit->text().length()) { // If down is pressed at EOL, move the focus to the entry view emit downPressed(); return true; - } - else { + } else { // Otherwise move the cursor to EOL m_ui->searchEdit->setCursorPosition(m_ui->searchEdit->text().length()); return true; @@ -100,12 +108,13 @@ void SearchWidget::connectSignals(SignalMultiplexer& mx) { mx.connect(this, SIGNAL(search(QString)), SLOT(search(QString))); mx.connect(this, SIGNAL(caseSensitiveChanged(bool)), SLOT(setSearchCaseSensitive(bool))); + mx.connect(this, SIGNAL(limitGroupChanged(bool)), SLOT(setSearchLimitGroup(bool))); mx.connect(this, SIGNAL(copyPressed()), SLOT(copyPassword())); mx.connect(this, SIGNAL(downPressed()), SLOT(setFocus())); mx.connect(m_ui->searchEdit, SIGNAL(returnPressed()), SLOT(switchToEntryEdit())); } -void SearchWidget::databaseChanged(DatabaseWidget *dbWidget) +void SearchWidget::databaseChanged(DatabaseWidget* dbWidget) { if (dbWidget != nullptr) { // Set current search text from this database @@ -113,6 +122,7 @@ void SearchWidget::databaseChanged(DatabaseWidget *dbWidget) // Enforce search policy emit caseSensitiveChanged(m_actionCaseSensitive->isChecked()); + emit limitGroupChanged(m_actionLimitGroup->isChecked()); } else { m_ui->searchEdit->clear(); } @@ -133,7 +143,7 @@ void SearchWidget::startSearch() } bool hasText = m_ui->searchEdit->text().length() > 0; - m_ui->clearIcon->setEnabled(hasText); + m_ui->clearIcon->setVisible(hasText); search(m_ui->searchEdit->text()); } @@ -149,6 +159,19 @@ void SearchWidget::setCaseSensitive(bool state) updateCaseSensitive(); } +void SearchWidget::updateLimitGroup() +{ + config()->set("SearchLimitGroup", m_actionLimitGroup->isChecked()); + emit limitGroupChanged(m_actionLimitGroup->isChecked()); +} + +void SearchWidget::setLimitGroup(bool state) +{ + m_actionLimitGroup->setChecked(state); + updateLimitGroup(); +} + + void SearchWidget::searchFocus() { m_ui->searchEdit->setFocus(); diff --git a/src/gui/SearchWidget.h b/src/gui/SearchWidget.h index d2b94d979d..2441ef60b4 100644 --- a/src/gui/SearchWidget.h +++ b/src/gui/SearchWidget.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Jonathan White + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,11 +19,11 @@ #ifndef KEEPASSX_SEARCHWIDGET_H #define KEEPASSX_SEARCHWIDGET_H -#include #include +#include -#include "gui/DatabaseWidget.h" #include "core/SignalMultiplexer.h" +#include "gui/DatabaseWidget.h" namespace Ui { class SearchWidget; @@ -33,36 +34,40 @@ class SearchWidget : public QWidget Q_OBJECT public: - explicit SearchWidget(QWidget *parent = 0); + explicit SearchWidget(QWidget* parent = 0); ~SearchWidget(); void connectSignals(SignalMultiplexer& mx); void setCaseSensitive(bool state); + void setLimitGroup(bool state); protected: - bool eventFilter(QObject *obj, QEvent *event); + bool eventFilter(QObject* obj, QEvent* event); signals: - void search(const QString &text); + void search(const QString& text); void caseSensitiveChanged(bool state); + void limitGroupChanged(bool state); void escapePressed(); void copyPressed(); void downPressed(); void enterPressed(); public slots: - void databaseChanged(DatabaseWidget* dbWidget); + void databaseChanged(DatabaseWidget* dbWidget = 0); private slots: void startSearchTimer(); void startSearch(); void updateCaseSensitive(); + void updateLimitGroup(); void searchFocus(); private: const QScopedPointer m_ui; QTimer* m_searchTimer; - QAction *m_actionCaseSensitive; + QAction* m_actionCaseSensitive; + QAction* m_actionLimitGroup; Q_DISABLE_COPY(SearchWidget) }; diff --git a/src/gui/SearchWidget.ui b/src/gui/SearchWidget.ui index 46c2699f0a..1583ebe964 100644 --- a/src/gui/SearchWidget.ui +++ b/src/gui/SearchWidget.ui @@ -30,20 +30,17 @@ 0 - - - Qt::ClickFocus + + + Qt::Horizontal - - Search + + + 40 + 20 + - - Qt::ToolButtonIconOnly - - - true - - + @@ -51,33 +48,26 @@ padding:3px - Find + Search... false - - - - Qt::ClickFocus - - - Clear - - - Qt::ToolButtonIconOnly - - - true - - -
+ + + Search + + + + + Clear + + - searchIcon searchEdit diff --git a/src/gui/SettingsWidget.cpp b/src/gui/SettingsWidget.cpp index 5696ff121a..e8fe9fcb9a 100644 --- a/src/gui/SettingsWidget.cpp +++ b/src/gui/SettingsWidget.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +23,8 @@ #include "autotype/AutoType.h" #include "core/Config.h" #include "core/Translator.h" +#include "core/FilePath.h" +#include "core/Global.h" class SettingsWidget::ExtraPage { @@ -57,17 +60,12 @@ SettingsWidget::SettingsWidget(QWidget* parent) m_secUi->setupUi(m_secWidget); m_generalUi->setupUi(m_generalWidget); - add(tr("General"), m_generalWidget); - add(tr("Security"), m_secWidget); - - m_generalUi->autoTypeShortcutWidget->setVisible(autoType()->isAvailable()); - m_generalUi->autoTypeShortcutLabel->setVisible(autoType()->isAvailable()); -#ifdef Q_OS_MAC - // systray not useful on OS X - m_generalUi->systrayShowCheckBox->setVisible(false); - m_generalUi->systrayMinimizeOnCloseCheckBox->setVisible(false); - m_generalUi->systrayMinimizeToTrayCheckBox->setVisible(false); -#endif + addPage(tr("General"), FilePath::instance()->icon("categories", "preferences-other"), m_generalWidget); + addPage(tr("Security"), FilePath::instance()->icon("status", "security-high"), m_secWidget); + + if (!autoType()->isAvailable()) { + m_generalUi->generalSettingsTabWidget->removeTab(1); + } connect(this, SIGNAL(accepted()), SLOT(saveSettings())); connect(this, SIGNAL(rejected()), SLOT(reject())); @@ -87,16 +85,22 @@ SettingsWidget::~SettingsWidget() { } -void SettingsWidget::addSettingsPage(ISettingsPage *page) +void SettingsWidget::addSettingsPage(ISettingsPage* page) { - QWidget * widget = page->createWidget(); + QWidget* widget = page->createWidget(); widget->setParent(this); m_extraPages.append(ExtraPage(page, widget)); - add(page->name(), widget); + addPage(page->name(), page->icon(), widget); } void SettingsWidget::loadSettings() { + + if (config()->hasAccessError()) { + showMessage( + tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error); + } + m_generalUi->rememberLastDatabasesCheckBox->setChecked(config()->get("RememberLastDatabases").toBool()); m_generalUi->rememberLastKeyFilesCheckBox->setChecked(config()->get("RememberLastKeyFiles").toBool()); m_generalUi->openPreviousDatabasesOnStartupCheckBox->setChecked( @@ -107,6 +111,7 @@ void SettingsWidget::loadSettings() m_generalUi->minimizeOnCopyCheckBox->setChecked(config()->get("MinimizeOnCopy").toBool()); m_generalUi->useGroupIconOnEntryCreationCheckBox->setChecked(config()->get("UseGroupIconOnEntryCreation").toBool()); m_generalUi->autoTypeEntryTitleMatchCheckBox->setChecked(config()->get("AutoTypeEntryTitleMatch").toBool()); + m_generalUi->ignoreGroupExpansionCheckBox->setChecked(config()->get("IgnoreGroupExpansion").toBool()); m_generalUi->languageComboBox->clear(); QList > languages = Translator::availableLanguages(); @@ -122,6 +127,7 @@ void SettingsWidget::loadSettings() m_generalUi->systrayMinimizeToTrayCheckBox->setChecked(config()->get("GUI/MinimizeToTray").toBool()); m_generalUi->systrayMinimizeOnCloseCheckBox->setChecked(config()->get("GUI/MinimizeOnClose").toBool()); m_generalUi->systrayMinimizeOnStartup->setChecked(config()->get("GUI/MinimizeOnStartup").toBool()); + m_generalUi->autoTypeAskCheckBox->setChecked(config()->get("security/autotypeask").toBool()); if (autoType()->isAvailable()) { m_globalAutoTypeKey = static_cast(config()->get("GlobalAutoTypeKey").toInt()); @@ -131,26 +137,37 @@ void SettingsWidget::loadSettings() } } + m_secUi->clearClipboardCheckBox->setChecked(config()->get("security/clearclipboard").toBool()); m_secUi->clearClipboardSpinBox->setValue(config()->get("security/clearclipboardtimeout").toInt()); m_secUi->lockDatabaseIdleCheckBox->setChecked(config()->get("security/lockdatabaseidle").toBool()); m_secUi->lockDatabaseIdleSpinBox->setValue(config()->get("security/lockdatabaseidlesec").toInt()); m_secUi->lockDatabaseMinimizeCheckBox->setChecked(config()->get("security/lockdatabaseminimize").toBool()); + m_secUi->lockDatabaseOnScreenLockCheckBox->setChecked(config()->get("security/lockdatabasescreenlock").toBool()); m_secUi->passwordCleartextCheckBox->setChecked(config()->get("security/passwordscleartext").toBool()); m_secUi->passwordRepeatCheckBox->setChecked(config()->get("security/passwordsrepeat").toBool()); - m_secUi->autoTypeAskCheckBox->setChecked(config()->get("security/autotypeask").toBool()); - Q_FOREACH (const ExtraPage& page, m_extraPages) + for (const ExtraPage& page: asConst(m_extraPages)) { page.loadSettings(); + } - setCurrentRow(0); + setCurrentPage(0); } void SettingsWidget::saveSettings() { + + if (config()->hasAccessError()) { + showMessage( + tr("Access error for config file %1").arg(config()->getFileName()), MessageWidget::Error); + // We prevent closing the settings page if we could not write to + // the config file. + return; + } + config()->set("RememberLastDatabases", m_generalUi->rememberLastDatabasesCheckBox->isChecked()); config()->set("RememberLastKeyFiles", m_generalUi->rememberLastKeyFilesCheckBox->isChecked()); config()->set("OpenPreviousDatabasesOnStartup", @@ -162,9 +179,12 @@ void SettingsWidget::saveSettings() config()->set("MinimizeOnCopy", m_generalUi->minimizeOnCopyCheckBox->isChecked()); config()->set("UseGroupIconOnEntryCreation", m_generalUi->useGroupIconOnEntryCreationCheckBox->isChecked()); + config()->set("IgnoreGroupExpansion", + m_generalUi->ignoreGroupExpansionCheckBox->isChecked()); config()->set("AutoTypeEntryTitleMatch", m_generalUi->autoTypeEntryTitleMatchCheckBox->isChecked()); int currentLangIndex = m_generalUi->languageComboBox->currentIndex(); + config()->set("GUI/Language", m_generalUi->languageComboBox->itemData(currentLangIndex).toString()); config()->set("GUI/ShowTrayIcon", m_generalUi->systrayShowCheckBox->isChecked()); @@ -172,6 +192,8 @@ void SettingsWidget::saveSettings() config()->set("GUI/MinimizeOnClose", m_generalUi->systrayMinimizeOnCloseCheckBox->isChecked()); config()->set("GUI/MinimizeOnStartup", m_generalUi->systrayMinimizeOnStartup->isChecked()); + config()->set("security/autotypeask", m_generalUi->autoTypeAskCheckBox->isChecked()); + if (autoType()->isAvailable()) { config()->set("GlobalAutoTypeKey", m_generalUi->autoTypeShortcutWidget->key()); config()->set("GlobalAutoTypeModifiers", @@ -183,16 +205,16 @@ void SettingsWidget::saveSettings() config()->set("security/lockdatabaseidle", m_secUi->lockDatabaseIdleCheckBox->isChecked()); config()->set("security/lockdatabaseidlesec", m_secUi->lockDatabaseIdleSpinBox->value()); config()->set("security/lockdatabaseminimize", m_secUi->lockDatabaseMinimizeCheckBox->isChecked()); + config()->set("security/lockdatabasescreenlock", m_secUi->lockDatabaseOnScreenLockCheckBox->isChecked()); config()->set("security/passwordscleartext", m_secUi->passwordCleartextCheckBox->isChecked()); config()->set("security/passwordsrepeat", m_secUi->passwordRepeatCheckBox->isChecked()); - config()->set("security/autotypeask", m_secUi->autoTypeAskCheckBox->isChecked()); - - Q_FOREACH (const ExtraPage& page, m_extraPages) + for (const ExtraPage& page: asConst(m_extraPages)) { page.saveSettings(); + } - Q_EMIT editFinished(true); + emit editFinished(true); } void SettingsWidget::reject() @@ -202,7 +224,7 @@ void SettingsWidget::reject() autoType()->registerGlobalShortcut(m_globalAutoTypeKey, m_globalAutoTypeModifiers); } - Q_EMIT editFinished(false); + emit editFinished(false); } void SettingsWidget::enableAutoSaveOnExit(bool checked) diff --git a/src/gui/SettingsWidget.h b/src/gui/SettingsWidget.h index 2362062999..f2fc9f2db9 100644 --- a/src/gui/SettingsWidget.h +++ b/src/gui/SettingsWidget.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +30,7 @@ class ISettingsPage { public: virtual ~ISettingsPage() {} virtual QString name() = 0; + virtual QIcon icon() = 0; virtual QWidget * createWidget() = 0; virtual void loadSettings(QWidget * widget) = 0; virtual void saveSettings(QWidget * widget) = 0; @@ -44,10 +46,10 @@ class SettingsWidget : public EditWidget void addSettingsPage(ISettingsPage * page); void loadSettings(); -Q_SIGNALS: +signals: void editFinished(bool accepted); -private Q_SLOTS: +private slots: void saveSettings(); void reject(); void enableAutoSaveOnExit(bool checked); diff --git a/src/gui/SettingsWidgetGeneral.ui b/src/gui/SettingsWidgetGeneral.ui index eb92097770..2fe0f4089e 100644 --- a/src/gui/SettingsWidgetGeneral.ui +++ b/src/gui/SettingsWidgetGeneral.ui @@ -7,187 +7,364 @@ 0 0 684 - 452 + 732 - - - QFormLayout::AllNonFixedFieldsGrow + + + 0 - - - - Remember last databases - - - true - - - - - - - Remember last key files - - - true - - - - - - - Load previous databases on startup - - - - - - - Automatically save on exit - - - - - - - Automatically save after every change - - - - - - - Automatically reload the database when modified externally - - - - - - - Minimize when copying to clipboard - - - - - - - Use group icon on entry creation - - - - - - - Global Auto-Type shortcut - - - - - - - - - - Use entry title to match windows for global auto-type - - - - - - - Language - - - - - - - - - - QLayout::SetMaximumSize - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - - 0 - 0 - - - - Hide window to system tray when minimized - - - - - - - - - QLayout::SetMaximumSize - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Hide window to system tray instead of app exit - - - - - - - - - QLayout::SetMaximumSize - - - - - Minimize window at application startup - - - - - - - - - Show a system tray icon + + 0 + + + 0 + + + 0 + + + + + 0 + + + Basic Settings + + + + + + Remember last databases + + + true + + + + + + + Remember last key files and security dongles + + + true + + + + + + + Load previous databases on startup + + + + + + + Automatically save on exit + + + + + + + Automatically save after every change + + + + + + + Automatically reload the database when modified externally + + + + + + + Minimize when copying to clipboard + + + + + + + Minimize window at application startup + + + + + + + Use group icon on entry creation + + + true + + + + + + + Don't mark database as modified for non-data changes (e.g., expanding groups) + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 30 + + + + + + + + Show a system tray icon + + + + + + + 0 + + + QLayout::SetMaximumSize + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + false + + + + 0 + 0 + + + + Hide window to system tray when minimized + + + + + + + + + 0 + + + QLayout::SetMaximumSize + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + false + + + Hide window to system tray instead of app exit + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 30 + + + + + + + + 15 + + + + + + 0 + 0 + + + + Language + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + + + + + + Auto-Type + + + + + + Use entry title and URL to match windows for global Auto-Type + + + + + + + Always ask before performing Auto-Type + + + true + + + + + + + 15 + + + + + + 0 + 0 + + + + Global Auto-Type shortcut + + + Qt::AlignLeading + + + + + + + + 0 + 0 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + @@ -199,15 +376,6 @@
autotype/ShortcutWidget.h
- - rememberLastDatabasesCheckBox - rememberLastKeyFilesCheckBox - openPreviousDatabasesOnStartupCheckBox - autoSaveOnExitCheckBox - autoSaveAfterEveryChangeCheckBox - minimizeOnCopyCheckBox - autoTypeShortcutWidget - diff --git a/src/gui/SettingsWidgetSecurity.ui b/src/gui/SettingsWidgetSecurity.ui index d664736ae5..679c470ad5 100644 --- a/src/gui/SettingsWidgetSecurity.ui +++ b/src/gui/SettingsWidgetSecurity.ui @@ -6,91 +6,157 @@ 0 0 - 374 - 303 + 595 + 443
- - - - - Clear clipboard after + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Timeouts + + + + + Clear clipboard after + + + + + + + false + + + + 0 + 0 + + + + sec + + + 1 + + + 999 + + + 10 + + + + + + + + 0 + 0 + + + + Lock databases after inactivity of + + + + + + + false + + + + 0 + 0 + + + + sec + + + 10 + + + 9999 + + + 240 + + + + - - - - false - - - sec - - - 1 - - - 999 - - - - - - - Lock databases after inactivity of - - - - - - - false - - - sec - - - 10 - - - 9999 - - - - - - - Lock databases after minimizing the window + + + + Convenience + + + + + Lock databases when session is locked or lid is closed + + + + + + + Lock databases after minimizing the window + + + + + + + Don't require password repeat when it is visible + + + + + + + Show passwords in cleartext by default + + + + - - - - Show passwords in cleartext by default + + + + Qt::Vertical - - - - - - Don't require password repeat when it is visible + + QSizePolicy::Expanding - - - - - - Always ask before performing auto-type + + + 20 + 30 + - + - - clearClipboardCheckBox - clearClipboardSpinBox - diff --git a/src/gui/SetupTotpDialog.cpp b/src/gui/SetupTotpDialog.cpp new file mode 100644 index 0000000000..5521773bd6 --- /dev/null +++ b/src/gui/SetupTotpDialog.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2017 Weslly Honorato <weslly@protonmail.com> + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "SetupTotpDialog.h" +#include "ui_SetupTotpDialog.h" +#include "totp/totp.h" + + +SetupTotpDialog::SetupTotpDialog(DatabaseWidget* parent, Entry* entry) + : QDialog(parent) + , m_ui(new Ui::SetupTotpDialog()) +{ + m_entry = entry; + m_parent = parent; + + m_ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + + this->setFixedSize(this->sizeHint()); + + connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close())); + connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(setupTotp())); + connect(m_ui->customSettingsCheckBox, SIGNAL(toggled(bool)), SLOT(toggleCustom(bool))); +} + + +void SetupTotpDialog::setupTotp() +{ + quint8 digits; + + if (m_ui->radio8Digits->isChecked()) { + digits = 8; + } else { + digits = 6; + } + + quint8 step = m_ui->stepSpinBox->value(); + QString seed = QTotp::parseOtpString(m_ui->seedEdit->text(), digits, step); + m_entry->setTotp(seed, step, digits); + emit m_parent->entrySelectionChanged(); + close(); +} + +void SetupTotpDialog::toggleCustom(bool status) +{ + m_ui->digitsLabel->setEnabled(status); + m_ui->radio6Digits->setEnabled(status); + m_ui->radio8Digits->setEnabled(status); + + m_ui->stepLabel->setEnabled(status); + m_ui->stepSpinBox->setEnabled(status); +} + + +void SetupTotpDialog::setSeed(QString value) +{ + m_ui->seedEdit->setText(value); +} + +void SetupTotpDialog::setStep(quint8 step) +{ + m_ui->stepSpinBox->setValue(step); + + if (step != QTotp::defaultStep) { + m_ui->customSettingsCheckBox->setChecked(true); + } +} + +void SetupTotpDialog::setDigits(quint8 digits) +{ + if (digits == 8) { + m_ui->radio8Digits->setChecked(true); + m_ui->radio6Digits->setChecked(false); + } else { + m_ui->radio6Digits->setChecked(true); + m_ui->radio8Digits->setChecked(false); + } + + if (digits != QTotp::defaultDigits) { + m_ui->customSettingsCheckBox->setChecked(true); + } +} + + +SetupTotpDialog::~SetupTotpDialog() +{ +} diff --git a/src/gui/SetupTotpDialog.h b/src/gui/SetupTotpDialog.h new file mode 100644 index 0000000000..243a05f9fb --- /dev/null +++ b/src/gui/SetupTotpDialog.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017 Weslly Honorato <weslly@protonmail.com> + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_SETUPTOTPDIALOG_H +#define KEEPASSX_SETUPTOTPDIALOG_H + +#include +#include +#include "core/Entry.h" +#include "core/Database.h" +#include "gui/DatabaseWidget.h" + +namespace Ui { + class SetupTotpDialog; +} + +class SetupTotpDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SetupTotpDialog(DatabaseWidget* parent = nullptr, Entry* entry = nullptr); + ~SetupTotpDialog(); + void setSeed(QString value); + void setStep(quint8 step); + void setDigits(quint8 digits); + +private Q_SLOTS: + void toggleCustom(bool status); + void setupTotp(); + +private: + QScopedPointer m_ui; + +protected: + Entry* m_entry; + DatabaseWidget* m_parent; +}; + +#endif // KEEPASSX_SETUPTOTPDIALOG_H diff --git a/src/gui/SetupTotpDialog.ui b/src/gui/SetupTotpDialog.ui new file mode 100644 index 0000000000..a6d8062871 --- /dev/null +++ b/src/gui/SetupTotpDialog.ui @@ -0,0 +1,137 @@ + + + SetupTotpDialog + + + + 0 + 0 + 282 + 257 + + + + Setup TOTP + + + + + + + + Key: + + + + + + + + + + + + Use custom settings + + + + + + + Note: Change these settings only if you know what you are doing. + + + true + + + + + + + QFormLayout::ExpandingFieldsGrow + + + QFormLayout::DontWrapRows + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + + + false + + + Time step: + + + + + + + false + + + 8 digits + + + + + + + false + + + 6 digits + + + true + + + + + + + false + + + Code size: + + + + + + + false + + + sec + + + 1 + + + 60 + + + 30 + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + diff --git a/src/gui/TotpDialog.cpp b/src/gui/TotpDialog.cpp new file mode 100644 index 0000000000..17cc1120f6 --- /dev/null +++ b/src/gui/TotpDialog.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2017 Weslly Honorato <weslly@protonmail.com> + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TotpDialog.h" +#include "ui_TotpDialog.h" + +#include "core/Config.h" +#include "core/Entry.h" +#include "gui/DatabaseWidget.h" +#include "gui/Clipboard.h" + +#include +#include +#include + + +TotpDialog::TotpDialog(DatabaseWidget* parent, Entry* entry) + : QDialog(parent) + , m_ui(new Ui::TotpDialog()) +{ + m_entry = entry; + m_parent = parent; + m_step = m_entry->totpStep(); + + m_ui->setupUi(this); + + uCounter = resetCounter(); + updateProgressBar(); + + QTimer* timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(updateProgressBar())); + connect(timer, SIGNAL(timeout()), this, SLOT(updateSeconds())); + timer->start(m_step * 10); + + updateTotp(); + + setAttribute(Qt::WA_DeleteOnClose); + + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Copy")); + + connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close())); + connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(copyToClipboard())); +} + +void TotpDialog::copyToClipboard() +{ + clipboard()->setText(m_entry->totp()); + if (config()->get("MinimizeOnCopy").toBool()) { + m_parent->window()->showMinimized(); + } +} + +void TotpDialog::updateProgressBar() +{ + if (uCounter < 100) { + m_ui->progressBar->setValue(static_cast(100 - uCounter)); + m_ui->progressBar->update(); + uCounter++; + } else { + updateTotp(); + uCounter = resetCounter(); + } +} + + +void TotpDialog::updateSeconds() +{ + uint epoch = QDateTime::currentDateTime().toTime_t() - 1; + m_ui->timerLabel->setText(tr("Expires in") + " " + QString::number(m_step - (epoch % m_step)) + " " + tr("seconds")); +} + +void TotpDialog::updateTotp() +{ + QString totpCode = m_entry->totp(); + QString firstHalf = totpCode.left(totpCode.size()/2); + QString secondHalf = totpCode.right(totpCode.size()/2); + m_ui->totpLabel->setText(firstHalf + " " + secondHalf); +} + +double TotpDialog::resetCounter() +{ + uint epoch = QDateTime::currentDateTime().toTime_t(); + double counter = qRound(static_cast(epoch % m_step) / m_step * 100); + return counter; +} + +TotpDialog::~TotpDialog() +{ +} diff --git a/src/gui/TotpDialog.h b/src/gui/TotpDialog.h new file mode 100644 index 0000000000..33eac66585 --- /dev/null +++ b/src/gui/TotpDialog.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2017 Weslly Honorato <weslly@protonmail.com> + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_TOTPDIALOG_H +#define KEEPASSX_TOTPDIALOG_H + +#include +#include +#include "core/Entry.h" +#include "core/Database.h" +#include "gui/DatabaseWidget.h" + +namespace Ui { + class TotpDialog; +} + +class TotpDialog : public QDialog +{ + Q_OBJECT + +public: + explicit TotpDialog(DatabaseWidget* parent = nullptr, Entry* entry = nullptr); + ~TotpDialog(); + +private: + double uCounter; + quint8 m_step; + QScopedPointer m_ui; + +private Q_SLOTS: + void updateTotp(); + void updateProgressBar(); + void updateSeconds(); + void copyToClipboard(); + double resetCounter(); + +protected: + Entry* m_entry; + DatabaseWidget* m_parent; +}; + +#endif // KEEPASSX_TOTPDIALOG_H diff --git a/src/gui/TotpDialog.ui b/src/gui/TotpDialog.ui new file mode 100644 index 0000000000..e11e761e99 --- /dev/null +++ b/src/gui/TotpDialog.ui @@ -0,0 +1,60 @@ + + + TotpDialog + + + + 0 + 0 + 264 + 194 + + + + Timed Password + + + + + + + 53 + + + + 000000 + + + Qt::AlignCenter + + + + + + + 0 + + + false + + + + + + + + + + + + + + QDialogButtonBox::Close|QDialogButtonBox::Ok + + + + + + + + diff --git a/src/gui/UnlockDatabaseDialog.cpp b/src/gui/UnlockDatabaseDialog.cpp index 679493903d..3aca54cf25 100644 --- a/src/gui/UnlockDatabaseDialog.cpp +++ b/src/gui/UnlockDatabaseDialog.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 KeePassXC Team + * Copyright (C) 2016 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 @@ -19,18 +19,17 @@ #include "UnlockDatabaseWidget.h" #include "autotype/AutoType.h" -#include "gui/DragTabBar.h" #include "core/Database.h" +#include "gui/DragTabBar.h" - -UnlockDatabaseDialog::UnlockDatabaseDialog(QWidget *parent) +UnlockDatabaseDialog::UnlockDatabaseDialog(QWidget* parent) : QDialog(parent) , m_view(new UnlockDatabaseWidget(this)) { connect(m_view, SIGNAL(editFinished(bool)), this, SLOT(complete(bool))); } -void UnlockDatabaseDialog::setDBFilename(const QString &filename) +void UnlockDatabaseDialog::setDBFilename(const QString& filename) { m_view->load(filename); } @@ -40,7 +39,7 @@ void UnlockDatabaseDialog::clearForms() m_view->clearForms(); } -Database *UnlockDatabaseDialog::database() +Database* UnlockDatabaseDialog::database() { return m_view->database(); } @@ -49,8 +48,25 @@ void UnlockDatabaseDialog::complete(bool r) { if (r) { accept(); - Q_EMIT unlockDone(true); + emit unlockDone(true); } else { reject(); } } + +Database* UnlockDatabaseDialog::openDatabasePrompt(QString databaseFilename) +{ + + UnlockDatabaseDialog* unlockDatabaseDialog = new UnlockDatabaseDialog(); + unlockDatabaseDialog->setObjectName("Open database"); + unlockDatabaseDialog->setDBFilename(databaseFilename); + unlockDatabaseDialog->show(); + unlockDatabaseDialog->exec(); + + Database* db = unlockDatabaseDialog->database(); + if (!db) { + qWarning("Could not open database %s.", qPrintable(databaseFilename)); + } + delete unlockDatabaseDialog; + return db; +} diff --git a/src/gui/UnlockDatabaseDialog.h b/src/gui/UnlockDatabaseDialog.h index 1ba6d2e065..55830c97e3 100644 --- a/src/gui/UnlockDatabaseDialog.h +++ b/src/gui/UnlockDatabaseDialog.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 KeePassXC Team + * Copyright (C) 2016 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 @@ -31,15 +31,16 @@ class UnlockDatabaseDialog : public QDialog { Q_OBJECT public: - explicit UnlockDatabaseDialog(QWidget *parent = Q_NULLPTR); + explicit UnlockDatabaseDialog(QWidget* parent = Q_NULLPTR); void setDBFilename(const QString& filename); void clearForms(); Database* database(); + static Database* openDatabasePrompt(QString databaseFilename); -Q_SIGNALS: +signals: void unlockDone(bool); -public Q_SLOTS: +public slots: void complete(bool r); private: diff --git a/src/gui/UnlockDatabaseWidget.cpp b/src/gui/UnlockDatabaseWidget.cpp index a005d0e603..d6beb1339e 100644 --- a/src/gui/UnlockDatabaseWidget.cpp +++ b/src/gui/UnlockDatabaseWidget.cpp @@ -33,6 +33,7 @@ void UnlockDatabaseWidget::clearForms() m_ui->comboKeyFile->clear(); m_ui->checkPassword->setChecked(false); m_ui->checkKeyFile->setChecked(false); + m_ui->checkChallengeResponse->setChecked(false); m_ui->buttonTogglePassword->setChecked(false); m_db = nullptr; } diff --git a/src/gui/WelcomeWidget.cpp b/src/gui/WelcomeWidget.cpp index 842546ecc8..9dc23d5289 100644 --- a/src/gui/WelcomeWidget.cpp +++ b/src/gui/WelcomeWidget.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,13 +19,58 @@ #include "WelcomeWidget.h" #include "ui_WelcomeWidget.h" +#include "config-keepassx.h" +#include "core/FilePath.h" +#include "core/Config.h" + WelcomeWidget::WelcomeWidget(QWidget* parent) : QWidget(parent) , m_ui(new Ui::WelcomeWidget()) { m_ui->setupUi(this); + + m_ui->welcomeLabel->setText(m_ui->welcomeLabel->text() + " " + KEEPASSX_VERSION); + QFont welcomeLabelFont = m_ui->welcomeLabel->font(); + welcomeLabelFont.setBold(true); + welcomeLabelFont.setPointSize(welcomeLabelFont.pointSize() + 4); + m_ui->welcomeLabel->setFont(welcomeLabelFont); + + m_ui->iconLabel->setPixmap(filePath()->applicationIcon().pixmap(64)); + + refreshLastDatabases(); + + bool recent_visibility = (m_ui->recentListWidget->count() > 0); + m_ui->startLabel->setVisible(!recent_visibility); + m_ui->recentListWidget->setVisible(recent_visibility); + m_ui->recentLabel->setVisible(recent_visibility); + + connect(m_ui->buttonNewDatabase, SIGNAL(clicked()), SIGNAL(newDatabase())); + connect(m_ui->buttonOpenDatabase, SIGNAL(clicked()), SIGNAL(openDatabase())); + connect(m_ui->buttonImportKeePass1, SIGNAL(clicked()), SIGNAL(importKeePass1Database())); + connect(m_ui->buttonImportCSV, SIGNAL(clicked()), SIGNAL(importCsv())); + connect(m_ui->recentListWidget, SIGNAL(itemActivated(QListWidgetItem*)), this, + SLOT(openDatabaseFromFile(QListWidgetItem*))); } WelcomeWidget::~WelcomeWidget() { } + +void WelcomeWidget::openDatabaseFromFile(QListWidgetItem* item) +{ + if (item->text().isEmpty()) { + return; + } + emit openDatabaseFile(item->text()); +} + +void WelcomeWidget::refreshLastDatabases() +{ + m_ui->recentListWidget->clear(); + const QStringList lastDatabases = config()->get("LastDatabases", QVariant()).toStringList(); + for (const QString& database : lastDatabases) { + QListWidgetItem *itm = new QListWidgetItem; + itm->setText(database); + m_ui->recentListWidget->addItem(itm); + } +} \ No newline at end of file diff --git a/src/gui/WelcomeWidget.h b/src/gui/WelcomeWidget.h index 80a0dde1c2..71ceda3542 100644 --- a/src/gui/WelcomeWidget.h +++ b/src/gui/WelcomeWidget.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +20,7 @@ #define KEEPASSX_WELCOMEWIDGET_H #include +#include namespace Ui { class WelcomeWidget; @@ -31,6 +33,17 @@ class WelcomeWidget : public QWidget public: explicit WelcomeWidget(QWidget* parent = nullptr); ~WelcomeWidget(); + void refreshLastDatabases(); + +signals: + void newDatabase(); + void openDatabase(); + void openDatabaseFile(QString); + void importKeePass1Database(); + void importCsv(); + +private slots: + void openDatabaseFromFile(QListWidgetItem* item); private: const QScopedPointer m_ui; diff --git a/src/gui/WelcomeWidget.ui b/src/gui/WelcomeWidget.ui index 4382e7c77e..da6bc859cf 100644 --- a/src/gui/WelcomeWidget.ui +++ b/src/gui/WelcomeWidget.ui @@ -2,17 +2,187 @@ WelcomeWidget + + + 0 + 0 + 450 + 419 + + + + + 0 + 0 + + + + + 450 + 0 + + - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + - Welcome! + Welcome to KeePassXC Qt::AlignCenter + + + + Start storing your passwords securely in a KeePassXC database + + + Qt::AlignCenter + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + Create new database + + + + + + + Open existing database + + + + + + + + + Import from KeePass 1 + + + + + + + Import from CSV + + + + + + + + + Qt::Vertical + + + QSizePolicy::Minimum + + + + 0 + 5 + + + + + + + + Recent databases + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 110 + + + + diff --git a/src/gui/csvImport/CsvImportWidget.cpp b/src/gui/csvImport/CsvImportWidget.cpp new file mode 100644 index 0000000000..23db871f38 --- /dev/null +++ b/src/gui/csvImport/CsvImportWidget.cpp @@ -0,0 +1,310 @@ +/* + * Copyright (C) 2016 Enrico Mariotti + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CsvImportWidget.h" +#include "ui_CsvImportWidget.h" + +#include +#include +#include + +#include "format/KeePass2Writer.h" +#include "gui/MessageBox.h" +#include "gui/MessageWidget.h" + +//I wanted to make the CSV import GUI future-proof, so if one day you need entries +//to have a new field, all you have to do is uncomment a row or two here, and the GUI will follow: +//dynamic generation of comboBoxes, labels, placement and so on. Try it for immense fun! +const QStringList CsvImportWidget::m_columnHeader = QStringList() + << QObject::tr("Group") + << QObject::tr("Title") + << QObject::tr("Username") + << QObject::tr("Password") + << QObject::tr("URL") + << QObject::tr("Notes") +// << QObject::tr("Future field1") +// << QObject::tr("Future field2") +// << QObject::tr("Future field3") + ; + +CsvImportWidget::CsvImportWidget(QWidget *parent) + : QWidget(parent) + , m_ui(new Ui::CsvImportWidget()) + , m_parserModel(new CsvParserModel(this)) + , m_comboModel(new QStringListModel(this)) + , m_comboMapper(new QSignalMapper(this)) +{ + m_ui->setupUi(this); + + m_ui->comboBoxCodec->addItems(QStringList() <<"UTF-8" <<"Windows-1252" <<"UTF-16" <<"UTF-16LE"); + m_ui->comboBoxFieldSeparator->addItems(QStringList() <<"," <<";" <<"-" <<":" <<"."); + m_ui->comboBoxTextQualifier->addItems(QStringList() <<"\"" <<"'" <<":" <<"." <<"|"); + m_ui->comboBoxComment->addItems(QStringList() <<"#" <<";" <<":" <<"@"); + 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); + + QComboBox* combo = new QComboBox(this); + font = combo->font(); + font.setBold(false); + combo->setFont(font); + m_combos.append(combo); + combo->setModel(m_comboModel); + m_comboMapper->setMapping(combo, i); + connect(combo, SIGNAL(currentIndexChanged(int)), m_comboMapper, SLOT(map())); + + //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); + } + + m_parserModel->setHeaderLabels(m_columnHeader); + m_ui->tableViewFields->setModel(m_parserModel); + + connect(m_ui->spinBoxSkip, SIGNAL(valueChanged(int)), SLOT(skippedChanged(int))); + connect(m_ui->comboBoxCodec, SIGNAL(currentIndexChanged(int)), SLOT(parse())); + connect(m_ui->comboBoxTextQualifier, SIGNAL(currentIndexChanged(int)), SLOT(parse())); + connect(m_ui->comboBoxComment, SIGNAL(currentIndexChanged(int)), SLOT(parse())); + connect(m_ui->comboBoxFieldSeparator, SIGNAL(currentIndexChanged(int)), SLOT(parse())); + connect(m_ui->checkBoxBackslash, SIGNAL(toggled(bool)), SLOT(parse())); + connect(m_ui->checkBoxFieldNames, SIGNAL(toggled(bool)), SLOT(updatePreview())); + connect(m_comboMapper, SIGNAL(mapped(int)), this, SLOT(comboChanged(int))); + + connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(writeDatabase())); + connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); +} + +void CsvImportWidget::comboChanged(int comboId) { + QComboBox* currentSender = qobject_cast(m_comboMapper->mapping(comboId)); + if (currentSender->currentIndex() != -1) + //this line is the one that actually updates GUI table + m_parserModel->mapColumns(currentSender->currentIndex(), comboId); + updateTableview(); +} + +void CsvImportWidget::skippedChanged(int rows) { + m_parserModel->setSkippedRows(rows); + updateTableview(); +} + +CsvImportWidget::~CsvImportWidget() {} + +void CsvImportWidget::configParser() { + m_parserModel->setBackslashSyntax(m_ui->checkBoxBackslash->isChecked()); + m_parserModel->setComment(m_ui->comboBoxComment->currentText().at(0)); + m_parserModel->setTextQualifier(m_ui->comboBoxTextQualifier->currentText().at(0)); + m_parserModel->setCodec(m_ui->comboBoxCodec->currentText()); + m_parserModel->setFieldSeparator(m_ui->comboBoxFieldSeparator->currentText().at(0)); +} + +void CsvImportWidget::updateTableview() { + m_ui->tableViewFields->resizeRowsToContents(); + m_ui->tableViewFields->resizeColumnsToContents(); + + for (int c = 0; c < m_ui->tableViewFields->horizontalHeader()->count(); ++c) + m_ui->tableViewFields->horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch); +} + +void CsvImportWidget::updatePreview() { + + int minSkip = 0; + if (m_ui->checkBoxFieldNames->isChecked()) + minSkip = 1; + m_ui->labelSizeRowsCols->setText(m_parserModel->getFileInfo()); + 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")); + + for (int i = 1; i < m_parserModel->getCsvCols(); ++i) { + if (m_ui->checkBoxFieldNames->isChecked()) { + columnName = m_parserModel->getCsvTable().at(0).at(i); + if (columnName.isEmpty()) + columnName = "<" + tr("Empty fieldname ") + QString::number(++emptyId) + ">"; + list << columnName; + } else { + list << QString(tr("column ")) + QString::number(i); + } + } + m_comboModel->setStringList(list); + + int j=1; + for (QComboBox* b : m_combos) { + if (j < m_parserModel->getCsvCols()) + b->setCurrentIndex(j); + else + b->setCurrentIndex(0); + ++j; + } +} + +void CsvImportWidget::load(const QString& filename, Database* const db) { + //QApplication::processEvents(); + m_db = db; + m_parserModel->setFilename(filename); + m_ui->labelFilename->setText(filename); + Group* group = m_db->rootGroup(); + group->setUuid(Uuid::random()); + group->setNotes(tr("Imported from CSV file").append("\n").append(tr("Original data: ")) + filename); + parse(); +} + +void CsvImportWidget::parse() { + configParser(); + QApplication::setOverrideCursor(Qt::WaitCursor); + //QApplication::processEvents(); + bool good = m_parserModel->parse(); + updatePreview(); + QApplication::restoreOverrideCursor(); + if (!good) + m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file !").append("\n") + .append(formatStatusText()), MessageWidget::Warning); + else + m_ui->messageWidget->setHidden(true); + QWidget::adjustSize(); +} + + +QString CsvImportWidget::formatStatusText() const { + QString text = m_parserModel->getStatus(); + int items = text.count('\n'); + if (items > 2) { + return text.section('\n', 0, 1) + .append("\n[").append(QString::number(items - 2)) + .append(tr(" more messages skipped]")); + } + if (items == 1) { + text.append(QString("\n")); + } + return text; +} + +void CsvImportWidget::writeDatabase() { + + setRootGroup(); + for (int r = 0; r < m_parserModel->rowCount(); ++r) { + //use validity of second column as a GO/NOGO for all others fields + if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) + continue; + Entry* entry = new Entry(); + entry->setUuid(Uuid::random()); + entry->setGroup(splitGroups(m_parserModel->data(m_parserModel->index(r, 0)).toString())); + entry->setTitle(m_parserModel->data(m_parserModel->index(r, 1)).toString()); + entry->setUsername(m_parserModel->data(m_parserModel->index(r, 2)).toString()); + entry->setPassword(m_parserModel->data(m_parserModel->index(r, 3)).toString()); + entry->setUrl(m_parserModel->data(m_parserModel->index(r, 4)).toString()); + entry->setNotes(m_parserModel->data(m_parserModel->index(r, 5)).toString()); + } + QBuffer buffer; + buffer.open(QBuffer::ReadWrite); + + KeePass2Writer writer; + writer.writeDatabase(&buffer, m_db); + if (writer.hasError()) + MessageBox::warning(this, tr("Error"), tr("CSV import: writer has errors:\n") + .append((writer.errorString())), QMessageBox::Ok, QMessageBox::Ok); + emit editFinished(true); +} + + +void CsvImportWidget::setRootGroup() { + QString groupLabel; + QStringList groupList; + bool is_root = false; + bool is_empty = false; + bool is_label = false; + + for (int r = 0; r < m_parserModel->rowCount(); ++r) { + //use validity of second column as a GO/NOGO for all others fields + if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) + continue; + groupLabel = m_parserModel->data(m_parserModel->index(r, 0)).toString(); + //check if group name is either "root", "" (empty) or some other label + groupList = groupLabel.split("/", QString::SkipEmptyParts); + if (groupList.isEmpty()) + is_empty = true; + else + if (not groupList.first().compare("Root", Qt::CaseSensitive)) + is_root = true; + else if (not groupLabel.compare("")) + is_empty = true; + else + is_label = true; + + groupList.clear(); + } + + if ((is_empty and is_root) or (is_label and not is_empty and is_root)) + m_db->rootGroup()->setName("CSV IMPORTED"); + else + m_db->rootGroup()->setName("Root"); +} + +Group *CsvImportWidget::splitGroups(QString label) { + //extract group names from nested path provided in "label" + Group *current = m_db->rootGroup(); + if (label.isEmpty()) + return current; + + QStringList groupList = label.split("/", QString::SkipEmptyParts); + //avoid the creation of a subgroup with the same name as Root + if (m_db->rootGroup()->name() == "Root" && groupList.first() == "Root") + groupList.removeFirst(); + + for (const QString& groupName : groupList) { + Group *children = hasChildren(current, groupName); + if (children == nullptr) { + Group *brandNew = new Group(); + brandNew->setParent(current); + brandNew->setName(groupName); + brandNew->setUuid(Uuid::random()); + current = brandNew; + } else { + Q_ASSERT(children != nullptr); + current = children; + } + } + return current; +} + +Group* CsvImportWidget::hasChildren(Group* current, QString groupName) { + //returns the group whose name is "groupName" and is child of "current" group + for (Group * group : current->children()) { + if (group->name() == groupName) + return group; + } + return nullptr; +} + +void CsvImportWidget::reject() { + emit editFinished(false); +} diff --git a/src/gui/csvImport/CsvImportWidget.h b/src/gui/csvImport/CsvImportWidget.h new file mode 100644 index 0000000000..463a92c5c2 --- /dev/null +++ b/src/gui/csvImport/CsvImportWidget.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2016 Enrico Mariotti + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_CSVIMPORTWIDGET_H +#define KEEPASSX_CSVIMPORTWIDGET_H + +#include +#include +#include +#include +#include +#include +#include + +#include "core/Metadata.h" +#include "gui/csvImport/CsvParserModel.h" +#include "keys/PasswordKey.h" + + +namespace Ui { + class CsvImportWidget; +} + +class CsvImportWidget : public QWidget +{ + Q_OBJECT + +public: + explicit CsvImportWidget(QWidget* parent = nullptr); + ~CsvImportWidget(); + void load(const QString& filename, Database* const db); + +signals: + void editFinished(bool accepted); + +private slots: + void parse(); + void comboChanged(int comboId); + void skippedChanged(int rows); + void writeDatabase(); + void updatePreview(); + void setRootGroup(); + void reject(); + +private: + Q_DISABLE_COPY(CsvImportWidget) + const QScopedPointer m_ui; + CsvParserModel* const m_parserModel; + QStringListModel* const m_comboModel; + QSignalMapper* m_comboMapper; + QList m_combos; + Database* m_db; + + static const QStringList m_columnHeader; + void configParser(); + void updateTableview(); + Group* splitGroups(QString label); + Group* hasChildren(Group* current, QString groupName); + QString formatStatusText() const; +}; + +#endif // KEEPASSX_CSVIMPORTWIDGET_H diff --git a/src/gui/csvImport/CsvImportWidget.ui b/src/gui/csvImport/CsvImportWidget.ui new file mode 100644 index 0000000000..df0af79f14 --- /dev/null +++ b/src/gui/csvImport/CsvImportWidget.ui @@ -0,0 +1,484 @@ + + + CsvImportWidget + + + + 0 + 0 + 892 + 525 + + + + + + + + + + + + + + + + 0 + 0 + + + + + 11 + 75 + true + + + + Import CSV fields + + + + + + + + 0 + 0 + + + + filename + + + + + + + + 0 + 0 + + + + size, rows, columns + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 758 + 24 + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 75 + true + + + + Encoding + + + + + + + 50 + false + + + + Codec + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 50 + false + + + + false + + + + + + + + 50 + false + + + + Text is qualified by + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 50 + false + + + + false + + + + + + + + 50 + false + + + + Fields are separated by + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 50 + false + + + + false + + + + + + + + 50 + false + + + + Comments start with + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + 50 + false + + + + false + + + + + + + + 50 + false + + + + First record has field names + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 50 + false + + + + Number of headers line to discard + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + false + + + + + + + + + + Qt::Horizontal + + + + 122 + 20 + + + + + + + + + 0 + 0 + + + + + 50 + false + + + + Consider '\' an escape character + + + + + + + + 50 + false + true + + + + + + + + + + + + + + + 0 + 0 + + + + + 0 + 200 + + + + + 75 + true + + + + Preview + + + false + + + + + + + 0 + 0 + + + + + 50 + false + + + + true + + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + false + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Column layout + + + + + + 6 + + + 6 + + + 0 + + + + + + + + + + + MessageWidget + QWidget +
gui/MessageWidget.h
+ 1 +
+
+ + +
diff --git a/src/gui/csvImport/CsvImportWizard.cpp b/src/gui/csvImport/CsvImportWizard.cpp new file mode 100644 index 0000000000..06ee231101 --- /dev/null +++ b/src/gui/csvImport/CsvImportWizard.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 Enrico Mariotti + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CsvImportWizard.h" + +#include +#include + +#include "gui/MessageBox.h" + + +CsvImportWizard::CsvImportWizard(QWidget *parent) + : DialogyWidget(parent) +{ + m_layout = new QGridLayout(this); + m_pages = new QStackedWidget(parent); + m_layout->addWidget(m_pages, 0, 0); + + m_pages->addWidget(key = new ChangeMasterKeyWidget(m_pages)); + m_pages->addWidget(parse = new CsvImportWidget(m_pages)); + key->headlineLabel()->setText(tr("Import CSV file")); + QFont headLineFont = key->headlineLabel()->font(); + headLineFont.setBold(true); + headLineFont.setPointSize(headLineFont.pointSize() + 2); + key->headlineLabel()->setFont(headLineFont); + + connect(key, SIGNAL(editFinished(bool)), this, SLOT(keyFinished(bool))); + connect(parse, SIGNAL(editFinished(bool)), this, SLOT(parseFinished(bool))); +} + +CsvImportWizard::~CsvImportWizard() +{} + +void CsvImportWizard::load(const QString& filename, Database* database) +{ + m_db = database; + parse->load(filename, database); + key->clearForms(); +} + +void CsvImportWizard::keyFinished(bool accepted) +{ + if (!accepted) { + emit(importFinished(false)); + return; + } + + m_pages->setCurrentIndex(m_pages->currentIndex()+1); + + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + bool result = m_db->setKey(key->newMasterKey()); + QApplication::restoreOverrideCursor(); + + if (!result) { + MessageBox::critical(this, tr("Error"), tr("Unable to calculate master key")); + emit(importFinished(false)); + } +} + +void CsvImportWizard::parseFinished(bool accepted) +{ + emit(importFinished(accepted)); +} diff --git a/src/gui/csvImport/CsvImportWizard.h b/src/gui/csvImport/CsvImportWizard.h new file mode 100644 index 0000000000..317018d996 --- /dev/null +++ b/src/gui/csvImport/CsvImportWizard.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2016 Enrico Mariotti + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_CSVIMPORTWIZARD_H +#define KEEPASSX_CSVIMPORTWIZARD_H + +#include "CsvImportWidget.h" + +#include +#include + +#include "core/Database.h" +#include "gui/ChangeMasterKeyWidget.h" +#include "gui/DialogyWidget.h" + +class CsvImportWidget; + +class CsvImportWizard : public DialogyWidget +{ + Q_OBJECT + +public: + explicit CsvImportWizard(QWidget *parent = nullptr); + ~CsvImportWizard(); + void load(const QString& filename, Database *database); + +signals: + void importFinished(bool accepted); + +private slots: + void keyFinished(bool accepted); + void parseFinished(bool accepted); + +private: + Database* m_db; + CsvImportWidget* parse; + ChangeMasterKeyWidget* key; + QStackedWidget *m_pages; + QGridLayout *m_layout; +}; + +#endif //KEEPASSX_CSVIMPORTWIZARD_H diff --git a/src/gui/csvImport/CsvParserModel.cpp b/src/gui/csvImport/CsvParserModel.cpp new file mode 100644 index 0000000000..d4af2b7850 --- /dev/null +++ b/src/gui/csvImport/CsvParserModel.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2016 Enrico Mariotti + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CsvParserModel.h" + +CsvParserModel::CsvParserModel(QObject *parent) + : QAbstractTableModel(parent) + , m_skipped(0) +{} + +CsvParserModel::~CsvParserModel() +{} + +void CsvParserModel::setFilename(const QString& filename) { + m_filename = filename; +} + +QString CsvParserModel::getFileInfo(){ + QString a(QString::number(getFileSize()).append(tr(" byte, "))); + a.append(QString::number(getCsvRows())).append(tr(" rows, ")); + a.append(QString::number(qMax(0, getCsvCols()-1))).append(tr(" columns")); + return a; +} + +bool CsvParserModel::parse() { + bool r; + beginResetModel(); + m_columnMap.clear(); + if (CsvParser::isFileLoaded()) { + r = CsvParser::reparse(); + } else { + QFile csv(m_filename); + r = CsvParser::parse(&csv); + } + for (int i = 0; i < columnCount(); ++i) + m_columnMap.insert(i,0); + addEmptyColumn(); + endResetModel(); + return r; +} + +void CsvParserModel::addEmptyColumn() { + for (int i = 0; i < m_table.size(); ++i) { + CsvRow r = m_table.at(i); + r.prepend(QString("")); + m_table.replace(i, r); + } +} + +void CsvParserModel::mapColumns(int csvColumn, int dbColumn) { + if ((csvColumn < 0) || (dbColumn < 0)) + return; + beginResetModel(); + if (csvColumn >= getCsvCols()) + m_columnMap[dbColumn] = 0; //map to the empty column + else + m_columnMap[dbColumn] = csvColumn; + endResetModel(); +} + +void CsvParserModel::setSkippedRows(int skipped) { + m_skipped = skipped; + QModelIndex topLeft = createIndex(skipped,0); + QModelIndex bottomRight = createIndex(m_skipped+rowCount(), columnCount()); + emit dataChanged(topLeft, bottomRight); + emit layoutChanged(); +} + +void CsvParserModel::setHeaderLabels(QStringList l) { + m_columnHeader = l; +} + +int CsvParserModel::rowCount(const QModelIndex &parent) const { + if (parent.isValid()) + return 0; + return getCsvRows(); +} + +int CsvParserModel::columnCount(const QModelIndex &parent) const { + if (parent.isValid()) + return 0; + return m_columnHeader.size(); +} + +QVariant CsvParserModel::data(const QModelIndex &index, int role) const { + if ((index.column() >= m_columnHeader.size()) + || (index.row()+m_skipped >= rowCount()) + || !index.isValid()) { + return QVariant(); + } + if (role == Qt::DisplayRole) + return m_table.at(index.row()+m_skipped).at(m_columnMap[index.column()]); + return QVariant(); +} + +QVariant CsvParserModel::headerData(int section, Qt::Orientation orientation, int role) const { + if (role == Qt::DisplayRole) { + if (orientation == Qt::Horizontal) { + if ((section < 0) || (section >= m_columnHeader.size())) + return QVariant(); + return m_columnHeader.at(section); + } else if (orientation == Qt::Vertical) { + if (section+m_skipped >= rowCount()) + return QVariant(); + return QString::number(section+1); + } + } + return QVariant(); +} + + diff --git a/src/gui/csvImport/CsvParserModel.h b/src/gui/csvImport/CsvParserModel.h new file mode 100644 index 0000000000..b092092bae --- /dev/null +++ b/src/gui/csvImport/CsvParserModel.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2016 Enrico Mariotti + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_CSVPARSERMODEL_H +#define KEEPASSX_CSVPARSERMODEL_H + +#include +#include + +#include "core/CsvParser.h" +#include "core/Group.h" + +class CsvParserModel : public QAbstractTableModel, public CsvParser +{ + Q_OBJECT + +public: + explicit CsvParserModel(QObject *parent = nullptr); + ~CsvParserModel(); + void setFilename(const QString& filename); + QString getFileInfo(); + bool parse(); + + void setHeaderLabels(QStringList l); + void mapColumns(int csvColumn, int dbColumn); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + +public slots: + void setSkippedRows(int skipped); + +private: + int m_skipped; + QString m_filename; + QStringList m_columnHeader; + //first column of model must be empty (aka combobox row "Not present in CSV file") + void addEmptyColumn(); + //mapping CSV columns to keepassx columns + QMap m_columnMap; +}; + +#endif //KEEPASSX_CSVPARSERMODEL_H + diff --git a/src/gui/entry/AutoTypeAssociationsModel.cpp b/src/gui/entry/AutoTypeAssociationsModel.cpp index 49f6786b34..4a76233b41 100644 --- a/src/gui/entry/AutoTypeAssociationsModel.cpp +++ b/src/gui/entry/AutoTypeAssociationsModel.cpp @@ -103,7 +103,7 @@ QVariant AutoTypeAssociationsModel::data(const QModelIndex& index, int role) con void AutoTypeAssociationsModel::associationChange(int i) { - Q_EMIT dataChanged(index(i, 0), index(i, columnCount() - 1)); + emit dataChanged(index(i, 0), index(i, columnCount() - 1)); } void AutoTypeAssociationsModel::associationAboutToAdd(int i) diff --git a/src/gui/entry/AutoTypeAssociationsModel.h b/src/gui/entry/AutoTypeAssociationsModel.h index c75168c322..cef8bc66b1 100644 --- a/src/gui/entry/AutoTypeAssociationsModel.h +++ b/src/gui/entry/AutoTypeAssociationsModel.h @@ -36,7 +36,7 @@ class AutoTypeAssociationsModel : public QAbstractListModel QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; -public Q_SLOTS: +public slots: void associationChange(int i); void associationAboutToAdd(int i); void associationAdd(); diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index 66fdc90969..aea0ac8884 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -75,8 +76,11 @@ EditEntryWidget::EditEntryWidget(QWidget* parent) setupProperties(); setupHistory(); - connect(this, SIGNAL(accepted()), SLOT(saveEntry())); + connect(this, SIGNAL(accepted()), SLOT(acceptEntry())); connect(this, SIGNAL(rejected()), SLOT(cancel())); + connect(this, SIGNAL(apply()), SLOT(saveEntry())); + connect(m_iconsWidget, SIGNAL(messageEditEntry(QString, MessageWidget::MessageType)), SLOT(showMessage(QString, MessageWidget::MessageType))); + connect(m_iconsWidget, SIGNAL(messageEditEntryDismiss()), SLOT(hideMessage())); m_mainUi->passwordGenerator->layout()->setContentsMargins(0, 0, 0, 0); } @@ -88,7 +92,7 @@ EditEntryWidget::~EditEntryWidget() void EditEntryWidget::setupMain() { m_mainUi->setupUi(m_mainWidget); - add(tr("Entry"), m_mainWidget); + addPage(tr("Entry"), FilePath::instance()->icon("actions", "document-edit"), m_mainWidget); m_mainUi->togglePasswordButton->setIcon(filePath()->onOffIcon("actions", "password-show")); m_mainUi->togglePasswordGeneratorButton->setIcon(filePath()->icon("actions", "password-generator", false)); @@ -113,7 +117,7 @@ void EditEntryWidget::setupMain() void EditEntryWidget::setupAdvanced() { m_advancedUi->setupUi(m_advancedWidget); - add(tr("Advanced"), m_advancedWidget); + addPage(tr("Advanced"), FilePath::instance()->icon("categories", "preferences-other"), m_advancedWidget); m_attachmentsModel->setEntryAttachments(m_entryAttachments); m_advancedUi->attachmentsView->setModel(m_attachmentsModel); @@ -130,6 +134,8 @@ void EditEntryWidget::setupAdvanced() connect(m_advancedUi->addAttributeButton, SIGNAL(clicked()), SLOT(insertAttribute())); connect(m_advancedUi->editAttributeButton, SIGNAL(clicked()), SLOT(editCurrentAttribute())); connect(m_advancedUi->removeAttributeButton, SIGNAL(clicked()), SLOT(removeCurrentAttribute())); + connect(m_advancedUi->protectAttributeButton, SIGNAL(toggled(bool)), SLOT(protectCurrentAttribute(bool))); + connect(m_advancedUi->revealAttributeButton, SIGNAL(clicked(bool)), SLOT(revealCurrentAttribute())); connect(m_advancedUi->attributesView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(updateCurrentAttribute())); @@ -137,13 +143,13 @@ void EditEntryWidget::setupAdvanced() void EditEntryWidget::setupIcon() { - add(tr("Icon"), m_iconsWidget); + addPage(tr("Icon"), FilePath::instance()->icon("apps", "preferences-desktop-icons"), m_iconsWidget); } void EditEntryWidget::setupAutoType() { m_autoTypeUi->setupUi(m_autoTypeWidget); - add(tr("Auto-Type"), m_autoTypeWidget); + addPage(tr("Auto-Type"), FilePath::instance()->icon("actions", "key-enter"), m_autoTypeWidget); m_autoTypeDefaultSequenceGroup->addButton(m_autoTypeUi->inheritSequenceButton); m_autoTypeDefaultSequenceGroup->addButton(m_autoTypeUi->customSequenceButton); @@ -175,13 +181,13 @@ void EditEntryWidget::setupAutoType() void EditEntryWidget::setupProperties() { - add(tr("Properties"), m_editWidgetProperties); + addPage(tr("Properties"), FilePath::instance()->icon("actions", "document-properties"), m_editWidgetProperties); } void EditEntryWidget::setupHistory() { m_historyUi->setupUi(m_historyWidget); - add(tr("History"), m_historyWidget); + addPage(tr("History"), FilePath::instance()->icon("actions", "view-history"), m_historyWidget); m_sortModel->setSourceModel(m_historyModel); m_sortModel->setDynamicSortFilter(true); @@ -208,7 +214,7 @@ void EditEntryWidget::emitHistoryEntryActivated(const QModelIndex& index) Q_ASSERT(!m_history); Entry* entry = m_historyModel->entryFromIndex(index); - Q_EMIT historyEntryActivated(entry); + emit historyEntryActivated(entry); } void EditEntryWidget::histEntryActivated(const QModelIndex& index) @@ -289,8 +295,8 @@ void EditEntryWidget::loadEntry(Entry* entry, bool create, bool history, const Q setForms(entry); setReadOnly(m_history); - setCurrentRow(0); - setRowHidden(m_historyWidget, m_history); + setCurrentPage(0); + setPageHidden(m_historyWidget, m_history || m_entry->historyItems().count() < 1); } void EditEntryWidget::setForms(const Entry* entry, bool restore) @@ -349,6 +355,11 @@ void EditEntryWidget::setForms(const Entry* entry, bool restore) m_advancedUi->attributesEdit->setEnabled(false); } + QList sizes = m_advancedUi->attributesSplitter->sizes(); + sizes.replace(0, m_advancedUi->attributesSplitter->width() * 0.3); + sizes.replace(1, m_advancedUi->attributesSplitter->width() * 0.7); + m_advancedUi->attributesSplitter->setSizes(sizes); + IconStruct iconStruct; iconStruct.uuid = entry->iconUuid(); iconStruct.number = entry->iconNumber(); @@ -397,16 +408,17 @@ void EditEntryWidget::saveEntry() { if (m_history) { clear(); - Q_EMIT editFinished(false); + hideMessage(); + emit editFinished(false); return; } if (!passwordsEqual()) { - MessageBox::warning(this, tr("Error"), tr("Different passwords supplied.")); + showMessage(tr("Different passwords supplied."), MessageWidget::Error); return; } - if (m_advancedUi->attributesView->currentIndex().isValid()) { + if (m_advancedUi->attributesView->currentIndex().isValid() && m_advancedUi->attributesEdit->isEnabled()) { QString key = m_attributesModel->keyByIndex(m_advancedUi->attributesView->currentIndex()); m_entryAttributes->set(key, m_advancedUi->attributesEdit->toPlainText(), m_entryAttributes->isProtected(key)); @@ -429,10 +441,13 @@ void EditEntryWidget::saveEntry() if (!m_create) { m_entry->endUpdate(); } +} +void EditEntryWidget::acceptEntry() +{ + saveEntry(); clear(); - - Q_EMIT editFinished(true); + emit editFinished(true); } void EditEntryWidget::updateEntryData(Entry* entry) const @@ -476,7 +491,8 @@ void EditEntryWidget::cancel() { if (m_history) { clear(); - Q_EMIT editFinished(false); + hideMessage(); + emit editFinished(false); return; } @@ -487,7 +503,7 @@ void EditEntryWidget::cancel() clear(); - Q_EMIT editFinished(false); + emit editFinished(false); } void EditEntryWidget::clear() @@ -499,6 +515,7 @@ void EditEntryWidget::clear() m_autoTypeAssoc->clear(); m_historyModel->clear(); m_iconsWidget->reset(); + hideMessage(); } bool EditEntryWidget::hasBeenModified() const @@ -573,46 +590,96 @@ void EditEntryWidget::removeCurrentAttribute() QModelIndex index = m_advancedUi->attributesView->currentIndex(); if (index.isValid()) { - m_entryAttributes->remove(m_attributesModel->keyByIndex(index)); + if (MessageBox::question(this, tr("Confirm Remove"), tr("Are you sure you want to remove this attribute?"), + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + m_entryAttributes->remove(m_attributesModel->keyByIndex(index)); + } } } void EditEntryWidget::updateCurrentAttribute() { QModelIndex newIndex = m_advancedUi->attributesView->currentIndex(); + QString newKey = m_attributesModel->keyByIndex(newIndex); - if (m_history) { - if (newIndex.isValid()) { - QString key = m_attributesModel->keyByIndex(newIndex); - m_advancedUi->attributesEdit->setPlainText(m_entryAttributes->value(key)); - m_advancedUi->attributesEdit->setEnabled(true); + if (!m_history && m_currentAttribute != newIndex) { + // Save changes to the currently selected attribute if editing is enabled + if (m_currentAttribute.isValid() && m_advancedUi->attributesEdit->isEnabled()) { + QString currKey = m_attributesModel->keyByIndex(m_currentAttribute); + m_entryAttributes->set(currKey, m_advancedUi->attributesEdit->toPlainText(), + m_entryAttributes->isProtected(currKey)); + } + } + + displayAttribute(newIndex, m_entryAttributes->isProtected(newKey)); + + m_currentAttribute = newIndex; +} + +void EditEntryWidget::displayAttribute(QModelIndex index, bool showProtected) +{ + // Block signals to prevent extra calls + m_advancedUi->protectAttributeButton->blockSignals(true); + + if (index.isValid()) { + QString key = m_attributesModel->keyByIndex(index); + if (showProtected) { + m_advancedUi->attributesEdit->setPlainText(tr("[PROTECTED] Press reveal to view or edit")); + m_advancedUi->attributesEdit->setEnabled(false); + m_advancedUi->revealAttributeButton->setEnabled(true); + m_advancedUi->protectAttributeButton->setChecked(true); } else { - m_advancedUi->attributesEdit->setPlainText(""); - m_advancedUi->attributesEdit->setEnabled(false); + m_advancedUi->attributesEdit->setPlainText(m_entryAttributes->value(key)); + m_advancedUi->attributesEdit->setEnabled(true); + m_advancedUi->revealAttributeButton->setEnabled(false); + m_advancedUi->protectAttributeButton->setChecked(false); } + + // Don't allow editing in history view + m_advancedUi->protectAttributeButton->setEnabled(!m_history); + m_advancedUi->editAttributeButton->setEnabled(!m_history); + m_advancedUi->removeAttributeButton->setEnabled(!m_history); } else { - if (m_currentAttribute != newIndex) { - if (m_currentAttribute.isValid()) { - QString key = m_attributesModel->keyByIndex(m_currentAttribute); - m_entryAttributes->set(key, m_advancedUi->attributesEdit->toPlainText(), - m_entryAttributes->isProtected(key)); - } - - if (newIndex.isValid()) { - QString key = m_attributesModel->keyByIndex(newIndex); - m_advancedUi->attributesEdit->setPlainText(m_entryAttributes->value(key)); - m_advancedUi->attributesEdit->setEnabled(true); - } - else { - m_advancedUi->attributesEdit->setPlainText(""); - m_advancedUi->attributesEdit->setEnabled(false); - } - - m_advancedUi->editAttributeButton->setEnabled(newIndex.isValid()); - m_advancedUi->removeAttributeButton->setEnabled(newIndex.isValid()); - m_currentAttribute = newIndex; + m_advancedUi->attributesEdit->setPlainText(""); + m_advancedUi->attributesEdit->setEnabled(false); + m_advancedUi->revealAttributeButton->setEnabled(false); + m_advancedUi->protectAttributeButton->setChecked(false); + m_advancedUi->protectAttributeButton->setEnabled(false); + m_advancedUi->editAttributeButton->setEnabled(false); + m_advancedUi->removeAttributeButton->setEnabled(false); + } + + m_advancedUi->protectAttributeButton->blockSignals(false); +} + +void EditEntryWidget::protectCurrentAttribute(bool state) +{ + QModelIndex index = m_advancedUi->attributesView->currentIndex(); + if (!m_history && index.isValid()) { + QString key = m_attributesModel->keyByIndex(index); + if (state) { + // Save the current text and protect the attribute + m_entryAttributes->set(key, m_advancedUi->attributesEdit->toPlainText(), true); + } else { + // Unprotect the current attribute value (don't save text as it is obscured) + m_entryAttributes->set(key, m_entryAttributes->value(key), false); + } + + // Display the attribute + displayAttribute(index, state); + } +} + +void EditEntryWidget::revealCurrentAttribute() +{ + if (! m_advancedUi->attributesEdit->isEnabled()) { + QModelIndex index = m_advancedUi->attributesView->currentIndex(); + if (index.isValid()) { + QString key = m_attributesModel->keyByIndex(index); + m_advancedUi->attributesEdit->setPlainText(m_entryAttributes->value(key)); + m_advancedUi->attributesEdit->setEnabled(true); } } } @@ -632,15 +699,13 @@ void EditEntryWidget::insertAttachment() QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { - MessageBox::warning(this, tr("Error"), - tr("Unable to open file").append(":\n").append(file.errorString())); + showMessage(tr("Unable to open file").append(":\n").append(file.errorString()), MessageWidget::Error); return; } QByteArray data; if (!Tools::readAllFromDevice(&file, data)) { - MessageBox::warning(this, tr("Error"), - tr("Unable to open file").append(":\n").append(file.errorString())); + showMessage(tr("Unable to open file").append(":\n").append(file.errorString()), MessageWidget::Error); return; } @@ -667,13 +732,11 @@ void EditEntryWidget::saveCurrentAttachment() QFile file(savePath); if (!file.open(QIODevice::WriteOnly)) { - MessageBox::warning(this, tr("Error"), - tr("Unable to save the attachment:\n").append(file.errorString())); + showMessage(tr("Unable to save the attachment:\n").append(file.errorString()), MessageWidget::Error); return; } if (file.write(attachmentData) != attachmentData.size()) { - MessageBox::warning(this, tr("Error"), - tr("Unable to save the attachment:\n").append(file.errorString())); + showMessage(tr("Unable to save the attachment:\n").append(file.errorString()), MessageWidget::Error); return; } } @@ -694,20 +757,17 @@ void EditEntryWidget::openAttachment(const QModelIndex& index) QTemporaryFile* file = new QTemporaryFile(tmpFileTemplate, this); if (!file->open()) { - MessageBox::warning(this, tr("Error"), - tr("Unable to save the attachment:\n").append(file->errorString())); + showMessage(tr("Unable to save the attachment:\n").append(file->errorString()), MessageWidget::Error); return; } if (file->write(attachmentData) != attachmentData.size()) { - MessageBox::warning(this, tr("Error"), - tr("Unable to save the attachment:\n").append(file->errorString())); + showMessage(tr("Unable to save the attachment:\n").append(file->errorString()), MessageWidget::Error); return; } if (!file->flush()) { - MessageBox::warning(this, tr("Error"), - tr("Unable to save the attachment:\n").append(file->errorString())); + showMessage(tr("Unable to save the attachment:\n").append(file->errorString()), MessageWidget::Error); return; } @@ -732,8 +792,13 @@ void EditEntryWidget::removeCurrentAttachment() return; } - QString key = m_attachmentsModel->keyByIndex(index); - m_entryAttachments->remove(key); + QMessageBox::StandardButton ans = MessageBox::question(this, tr("Confirm Remove"), + tr("Are you sure you want to remove this attachment?"), + QMessageBox::Yes | QMessageBox::No); + if (ans == QMessageBox::Yes) { + QString key = m_attachmentsModel->keyByIndex(index); + m_entryAttachments->remove(key); + } } void EditEntryWidget::updateAutoTypeEnabled() diff --git a/src/gui/entry/EditEntryWidget.h b/src/gui/entry/EditEntryWidget.h index c8045d93c8..2888d43a8a 100644 --- a/src/gui/entry/EditEntryWidget.h +++ b/src/gui/entry/EditEntryWidget.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -63,11 +64,12 @@ class EditEntryWidget : public EditWidget void clear(); bool hasBeenModified() const; -Q_SIGNALS: +signals: void editFinished(bool accepted); void historyEntryActivated(Entry* entry); -private Q_SLOTS: +private slots: + void acceptEntry(); void saveEntry(); void cancel(); void togglePasswordGeneratorButton(bool checked); @@ -76,6 +78,8 @@ private Q_SLOTS: void editCurrentAttribute(); void removeCurrentAttribute(); void updateCurrentAttribute(); + void protectCurrentAttribute(bool state); + void revealCurrentAttribute(); void insertAttachment(); void saveCurrentAttachment(); void openAttachment(const QModelIndex& index); @@ -110,6 +114,8 @@ private Q_SLOTS: QMenu* createPresetsMenu(); void updateEntryData(Entry* entry) const; + void displayAttribute(QModelIndex index, bool showProtected); + Entry* m_entry; Database* m_database; diff --git a/src/gui/entry/EditEntryWidgetAdvanced.ui b/src/gui/entry/EditEntryWidgetAdvanced.ui index 61380bb903..2c7f95ddec 100644 --- a/src/gui/entry/EditEntryWidgetAdvanced.ui +++ b/src/gui/entry/EditEntryWidgetAdvanced.ui @@ -28,19 +28,50 @@ Additional attributes - + - - - - - + + + Qt::Horizontal + + false + + + + 0 + 0 + + + + QAbstractScrollArea::AdjustToContents + + + QListView::Adjust + + + + + false + + + + 0 + 0 + + + + + 170 + 0 + + + - + @@ -49,22 +80,22 @@ - + false - Edit + Remove - + false - Remove + Edit Name @@ -81,6 +112,35 @@ + + + + true + + + margin-left:50%;margin-right:50% + + + Protect + + + true + + + + + + + false + + + Reveal + + + false + + +
@@ -103,7 +163,7 @@
- + @@ -172,11 +232,12 @@ attributesView attributesEdit addAttributeButton - editAttributeButton removeAttributeButton + editAttributeButton attachmentsView addAttachmentButton removeAttachmentButton + openAttachmentButton saveAttachmentButton
diff --git a/src/gui/entry/EditEntryWidgetAutoType.ui b/src/gui/entry/EditEntryWidgetAutoType.ui index c1f2436803..a8090f7680 100644 --- a/src/gui/entry/EditEntryWidgetAutoType.ui +++ b/src/gui/entry/EditEntryWidgetAutoType.ui @@ -88,167 +88,178 @@
- - - - - - - false - - - true - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - - 0 - 0 - - - - - 0 - 25 - - - - + - - - - - - - false - - - - 0 - 0 - - - - - 0 - 25 - - - - - - - - - - - - - - - - - - Window title: - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 1 - 10 - - - - - - - - Use default se&quence - - - - - - - Set custo&m sequence: - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 1 - - - - - - - - false - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - + + + Window Associations + + + + + + + + false + + + true + + + false + + + false + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + 0 + 0 + + + + + 0 + 25 + + + + + + + + + + + + false + + + + 0 + 0 + + + + + 0 + 25 + + + + - + + + + + + + + + + + + + Window title: + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 1 + 10 + + + + + + + + Use default se&quence + + + + + + + Set custo&m sequence: + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 1 + + + + + + + + false + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + diff --git a/src/gui/entry/EditEntryWidgetHistory.ui b/src/gui/entry/EditEntryWidgetHistory.ui index 2ee8e08f34..8390f22fa3 100644 --- a/src/gui/entry/EditEntryWidgetHistory.ui +++ b/src/gui/entry/EditEntryWidgetHistory.ui @@ -25,9 +25,15 @@ + + true + true + + 160 + diff --git a/src/gui/entry/EditEntryWidgetMain.ui b/src/gui/entry/EditEntryWidgetMain.ui index 8df6c45a9e..c22d4b8b10 100644 --- a/src/gui/entry/EditEntryWidgetMain.ui +++ b/src/gui/entry/EditEntryWidgetMain.ui @@ -148,6 +148,12 @@ 1 + + + 0 + 100 + + @@ -186,6 +192,7 @@ PasswordEdit QLineEdit
gui/PasswordEdit.h
+ 1 diff --git a/src/gui/entry/EditEntryWidget_p.h b/src/gui/entry/EditEntryWidget_p.h index cdae8bd3d7..0e37c1fe8e 100644 --- a/src/gui/entry/EditEntryWidget_p.h +++ b/src/gui/entry/EditEntryWidget_p.h @@ -18,46 +18,8 @@ #ifndef KEEPASSX_EDITENTRYWIDGET_P_H #define KEEPASSX_EDITENTRYWIDGET_P_H -#include +#include #include -#include -#include - -class CategoryListViewDelegate : public QStyledItemDelegate -{ -public: - explicit CategoryListViewDelegate(QObject* parent) : QStyledItemDelegate(parent) {} - - QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const - { - QSize size = QStyledItemDelegate::sizeHint(option, index); - size.setHeight(qMax(size.height(), 22)); - return size; - } -}; - -class CategoryListWidget : public QListWidget -{ -public: - explicit CategoryListWidget(QWidget* parent = 0) : QListWidget(parent) - { - setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding); - setItemDelegate(new CategoryListViewDelegate(this)); - } - - virtual QSize sizeHint() const - { - QSize sizeHint = QListWidget::sizeHint(); - - int width = sizeHintForColumn(0) + frameWidth() * 2 + 5; - if (verticalScrollBar()->isVisible()) { - width += verticalScrollBar()->width(); - } - sizeHint.setWidth(width); - - return sizeHint; - } -}; class AttributesListView : public QListView { @@ -65,14 +27,13 @@ class AttributesListView : public QListView explicit AttributesListView(QWidget* parent = 0) : QListView(parent) { setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); - setItemDelegate(new CategoryListViewDelegate(this)); } - virtual QSize sizeHint() const + QSize sizeHint() const override { QSize sizeHint = QListView::sizeHint(); - int width = sizeHintForColumn(0) + frameWidth() * 2 + 5; + int width = sizeHintForColumn(0) + frameWidth() * 2; if (verticalScrollBar()->isVisible()) { width += verticalScrollBar()->width(); } diff --git a/src/gui/entry/EntryAttachmentsModel.cpp b/src/gui/entry/EntryAttachmentsModel.cpp index 39ed69f1f6..0826413807 100644 --- a/src/gui/entry/EntryAttachmentsModel.cpp +++ b/src/gui/entry/EntryAttachmentsModel.cpp @@ -97,7 +97,7 @@ QString EntryAttachmentsModel::keyByIndex(const QModelIndex& index) const void EntryAttachmentsModel::attachmentChange(const QString& key) { int row = m_entryAttachments->keys().indexOf(key); - Q_EMIT dataChanged(index(row, 0), index(row, columnCount()-1)); + emit dataChanged(index(row, 0), index(row, columnCount()-1)); } void EntryAttachmentsModel::attachmentAboutToAdd(const QString& key) diff --git a/src/gui/entry/EntryAttachmentsModel.h b/src/gui/entry/EntryAttachmentsModel.h index c2e238aeb0..6abcdc2e29 100644 --- a/src/gui/entry/EntryAttachmentsModel.h +++ b/src/gui/entry/EntryAttachmentsModel.h @@ -34,7 +34,7 @@ class EntryAttachmentsModel : public QAbstractListModel QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QString keyByIndex(const QModelIndex& index) const; -private Q_SLOTS: +private slots: void attachmentChange(const QString& key); void attachmentAboutToAdd(const QString& key); void attachmentAdd(); diff --git a/src/gui/entry/EntryAttributesModel.cpp b/src/gui/entry/EntryAttributesModel.cpp index b22380ae8a..1b1eab2200 100644 --- a/src/gui/entry/EntryAttributesModel.cpp +++ b/src/gui/entry/EntryAttributesModel.cpp @@ -147,7 +147,7 @@ void EntryAttributesModel::attributeChange(const QString& key) { int row = m_attributes.indexOf(key); Q_ASSERT(row != -1); - Q_EMIT dataChanged(index(row, 0), index(row, columnCount()-1)); + emit dataChanged(index(row, 0), index(row, columnCount()-1)); } void EntryAttributesModel::attributeAboutToAdd(const QString& key) @@ -213,7 +213,7 @@ void EntryAttributesModel::attributeRename(const QString& oldKey, const QString& m_nextRenameDataChange = false; QModelIndex keyIndex = index(m_attributes.indexOf(newKey), 0); - Q_EMIT dataChanged(keyIndex, keyIndex); + emit dataChanged(keyIndex, keyIndex); } } diff --git a/src/gui/entry/EntryAttributesModel.h b/src/gui/entry/EntryAttributesModel.h index 1eec8bff73..7d613c1f0d 100644 --- a/src/gui/entry/EntryAttributesModel.h +++ b/src/gui/entry/EntryAttributesModel.h @@ -38,7 +38,7 @@ class EntryAttributesModel : public QAbstractListModel QModelIndex indexByKey(const QString& key) const; QString keyByIndex(const QModelIndex& index) const; -private Q_SLOTS: +private slots: void attributeChange(const QString& key); void attributeAboutToAdd(const QString& key); void attributeAdd(); diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp index d606a777e1..6bc10376f7 100644 --- a/src/gui/entry/EntryModel.cpp +++ b/src/gui/entry/EntryModel.cpp @@ -19,6 +19,7 @@ #include #include +#include #include "core/DatabaseIcons.h" #include "core/Entry.h" @@ -63,7 +64,7 @@ void EntryModel::setGroup(Group* group) makeConnections(group); endResetModel(); - Q_EMIT switchedToGroupMode(); + emit switchedToGroupMode(); } void EntryModel::setEntryList(const QList& entries) @@ -100,7 +101,7 @@ void EntryModel::setEntryList(const QList& entries) } endResetModel(); - Q_EMIT switchedToEntryListMode(); + emit switchedToEntryListMode(); } int EntryModel::rowCount(const QModelIndex& parent) const @@ -127,8 +128,10 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const } Entry* entry = entryFromIndex(index); + EntryAttributes* attr = entry->attributes(); if (role == Qt::DisplayRole) { + QString result; switch (index.column()) { case ParentGroup: if (entry->group()) { @@ -136,11 +139,23 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const } break; case Title: - return entry->title(); + result = entry->resolveMultiplePlaceholders(entry->title()); + if (attr->isReference(EntryAttributes::TitleKey)) { + result.prepend(tr("Ref: ","Reference abbreviation")); + } + return result; case Username: - return entry->username(); + result = entry->resolveMultiplePlaceholders(entry->username()); + if (attr->isReference(EntryAttributes::UserNameKey)) { + result.prepend(tr("Ref: ","Reference abbreviation")); + } + return result; case Url: - return entry->url(); + result = entry->resolveMultiplePlaceholders(entry->url()); + if (attr->isReference(EntryAttributes::URLKey)) { + result.prepend(tr("Ref: ","Reference abbreviation")); + } + return result; } } else if (role == Qt::DecorationRole) { @@ -166,6 +181,12 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const } return font; } + else if (role == Qt::TextColorRole) { + if (entry->hasReferences()) { + QPalette p; + return QVariant(p.color(QPalette::Active, QPalette::Mid)); + } + } return QVariant(); } @@ -294,7 +315,7 @@ void EntryModel::entryRemoved() void EntryModel::entryDataChanged(Entry* entry) { int row = m_entries.indexOf(entry); - Q_EMIT dataChanged(index(row, 0), index(row, columnCount()-1)); + emit dataChanged(index(row, 0), index(row, columnCount()-1)); } void EntryModel::severConnections() diff --git a/src/gui/entry/EntryModel.h b/src/gui/entry/EntryModel.h index 0183c47be7..d12982d83c 100644 --- a/src/gui/entry/EntryModel.h +++ b/src/gui/entry/EntryModel.h @@ -52,14 +52,14 @@ class EntryModel : public QAbstractTableModel void setEntryList(const QList& entries); -Q_SIGNALS: +signals: void switchedToEntryListMode(); void switchedToGroupMode(); -public Q_SLOTS: +public slots: void setGroup(Group* group); -private Q_SLOTS: +private slots: void entryAboutToAdd(Entry* entry); void entryAdded(Entry* entry); void entryAboutToRemove(Entry* entry); diff --git a/src/gui/entry/EntryView.cpp b/src/gui/entry/EntryView.cpp index 31fae3e58c..1bdd4fbcf5 100644 --- a/src/gui/entry/EntryView.cpp +++ b/src/gui/entry/EntryView.cpp @@ -57,7 +57,7 @@ void EntryView::keyPressEvent(QKeyEvent* event) emitEntryActivated(currentIndex()); #ifdef Q_OS_MAC // Pressing return does not emit the QTreeView::activated signal on mac os - Q_EMIT activated(currentIndex()); + emit activated(currentIndex()); #endif } @@ -83,7 +83,7 @@ void EntryView::setFirstEntryActive() setCurrentEntry(m_model->entryFromIndex(index)); } else { - Q_EMIT entrySelectionChanged(); + emit entrySelectionChanged(); } } @@ -96,7 +96,7 @@ void EntryView::emitEntryActivated(const QModelIndex& index) { Entry* entry = entryFromIndex(index); - Q_EMIT entryActivated(entry, static_cast(m_sortModel->mapToSource(index).column())); + emit entryActivated(entry, static_cast(m_sortModel->mapToSource(index).column())); } void EntryView::setModel(QAbstractItemModel* model) diff --git a/src/gui/entry/EntryView.h b/src/gui/entry/EntryView.h index fb9e3566a8..6a545f62af 100644 --- a/src/gui/entry/EntryView.h +++ b/src/gui/entry/EntryView.h @@ -42,17 +42,17 @@ class EntryView : public QTreeView int numberOfSelectedEntries(); void setFirstEntryActive(); -public Q_SLOTS: +public slots: void setGroup(Group* group); -Q_SIGNALS: +signals: void entryActivated(Entry* entry, EntryModel::ModelColumn column); void entrySelectionChanged(); protected: void keyPressEvent(QKeyEvent* event) override; -private Q_SLOTS: +private slots: void emitEntryActivated(const QModelIndex& index); void switchToEntryListMode(); void switchToGroupMode(); diff --git a/src/gui/group/EditGroupWidget.cpp b/src/gui/group/EditGroupWidget.cpp index 177c62bb07..da9875fb4e 100644 --- a/src/gui/group/EditGroupWidget.cpp +++ b/src/gui/group/EditGroupWidget.cpp @@ -19,6 +19,7 @@ #include "ui_EditGroupWidgetMain.h" #include "core/Metadata.h" +#include "core/FilePath.h" #include "gui/EditWidgetIcons.h" #include "gui/EditWidgetProperties.h" @@ -33,16 +34,20 @@ EditGroupWidget::EditGroupWidget(QWidget* parent) { m_mainUi->setupUi(m_editGroupWidgetMain); - add(tr("Group"), m_editGroupWidgetMain); - add(tr("Icon"), m_editGroupWidgetIcons); - add(tr("Properties"), m_editWidgetProperties); + addPage(tr("Group"), FilePath::instance()->icon("actions", "document-edit"), m_editGroupWidgetMain); + addPage(tr("Icon"), FilePath::instance()->icon("apps", "preferences-desktop-icons"), m_editGroupWidgetIcons); + addPage(tr("Properties"), FilePath::instance()->icon("actions", "document-properties"), m_editWidgetProperties); connect(m_mainUi->expireCheck, SIGNAL(toggled(bool)), m_mainUi->expireDatePicker, SLOT(setEnabled(bool))); connect(m_mainUi->autoTypeSequenceCustomRadio, SIGNAL(toggled(bool)), m_mainUi->autoTypeSequenceCustomEdit, SLOT(setEnabled(bool))); + connect(this, SIGNAL(apply()), SLOT(apply())); connect(this, SIGNAL(accepted()), SLOT(save())); connect(this, SIGNAL(rejected()), SLOT(cancel())); + + connect(m_editGroupWidgetIcons, SIGNAL(messageEditEntry(QString, MessageWidget::MessageType)), SLOT(showMessage(QString, MessageWidget::MessageType))); + connect(m_editGroupWidgetIcons, SIGNAL(messageEditEntryDismiss()), SLOT(hideMessage())); } EditGroupWidget::~EditGroupWidget() @@ -91,12 +96,19 @@ void EditGroupWidget::loadGroup(Group* group, bool create, Database* database) m_editWidgetProperties->setFields(group->timeInfo(), group->uuid()); - setCurrentRow(0); + setCurrentPage(0); m_mainUi->editName->setFocus(); } void EditGroupWidget::save() +{ + apply(); + clear(); + emit editFinished(true); +} + +void EditGroupWidget::apply() { m_group->setName(m_mainUi->editName->text()); m_group->setNotes(m_mainUi->editNotes->toPlainText()); @@ -124,9 +136,6 @@ void EditGroupWidget::save() else { m_group->setIcon(iconStruct.uuid); } - - clear(); - Q_EMIT editFinished(true); } void EditGroupWidget::cancel() @@ -137,7 +146,7 @@ void EditGroupWidget::cancel() } clear(); - Q_EMIT editFinished(false); + emit editFinished(false); } void EditGroupWidget::clear() diff --git a/src/gui/group/EditGroupWidget.h b/src/gui/group/EditGroupWidget.h index 94ad891db3..2d18449343 100644 --- a/src/gui/group/EditGroupWidget.h +++ b/src/gui/group/EditGroupWidget.h @@ -43,10 +43,13 @@ class EditGroupWidget : public EditWidget void loadGroup(Group* group, bool create, Database* database); void clear(); -Q_SIGNALS: +signals: void editFinished(bool accepted); + void messageEditEntry(QString, MessageWidget::MessageType); + void messageEditEntryDismiss(); -private Q_SLOTS: +private slots: + void apply(); void save(); void cancel(); diff --git a/src/gui/group/EditGroupWidgetMain.ui b/src/gui/group/EditGroupWidgetMain.ui index b8abf762c8..20ce2f4148 100644 --- a/src/gui/group/EditGroupWidgetMain.ui +++ b/src/gui/group/EditGroupWidgetMain.ui @@ -6,116 +6,147 @@ 0 0 - 676 - 356 + 579 + 407 - - - - - QFormLayout::ExpandingFieldsGrow + + + 10 + + + 0 + + + 0 + + + 0 + + + + + Name - - - - Name + + + + + + + + + Notes + + + + + + + + 0 + 0 + + + + + 16777215 + 120 + + + + + + + + Expires + + + + + + + + + + false + + + true + + + + + + + Search + + + + + + + + + + Auto-Type + + + + + + + &Use default Auto-Type sequence of parent group + + + + + + + Set default Auto-Type se&quence + + + + + + + + + Qt::Horizontal - - - - - - - - - Notes + + QSizePolicy::Fixed - - - - - - - - - Expires + + + 13 + 1 + - + - - + + false - - true - - - - - - - Search - - - - - - - - - - Auto-type - - - - - - - - - - Use default auto-type sequence of parent group - - - - - - - Set default auto-type sequence - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 20 - 1 - - - - - - - - false - - - - - + + + + Qt::Vertical + + + + 20 + 40 + + + + diff --git a/src/gui/group/GroupModel.cpp b/src/gui/group/GroupModel.cpp index 5aafc1a79a..87eacf2758 100644 --- a/src/gui/group/GroupModel.cpp +++ b/src/gui/group/GroupModel.cpp @@ -365,7 +365,7 @@ QMimeData* GroupModel::mimeData(const QModelIndexList& indexes) const void GroupModel::groupDataChanged(Group* group) { QModelIndex ix = index(group); - Q_EMIT dataChanged(ix, ix); + emit dataChanged(ix, ix); } void GroupModel::groupAboutToRemove(Group* group) diff --git a/src/gui/group/GroupModel.h b/src/gui/group/GroupModel.h index 0ef0ba9901..899aa3fd15 100644 --- a/src/gui/group/GroupModel.h +++ b/src/gui/group/GroupModel.h @@ -49,7 +49,7 @@ class GroupModel : public QAbstractItemModel private: QModelIndex parent(Group* group) const; -private Q_SLOTS: +private slots: void groupDataChanged(Group* group); void groupAboutToRemove(Group* group); void groupRemoved(); diff --git a/src/gui/group/GroupView.cpp b/src/gui/group/GroupView.cpp index 18f7de804c..e9649e441d 100644 --- a/src/gui/group/GroupView.cpp +++ b/src/gui/group/GroupView.cpp @@ -112,7 +112,7 @@ void GroupView::expandGroup(Group* group, bool expand) void GroupView::emitGroupChanged(const QModelIndex& index) { - Q_EMIT groupChanged(m_model->groupFromIndex(index)); + emit groupChanged(m_model->groupFromIndex(index)); } void GroupView::setModel(QAbstractItemModel* model) @@ -123,7 +123,7 @@ void GroupView::setModel(QAbstractItemModel* model) void GroupView::emitGroupChanged() { - Q_EMIT groupChanged(currentGroup()); + emit groupChanged(currentGroup()); } void GroupView::syncExpandedState(const QModelIndex& parent, int start, int end) diff --git a/src/gui/group/GroupView.h b/src/gui/group/GroupView.h index 69ca828176..eaa2907258 100644 --- a/src/gui/group/GroupView.h +++ b/src/gui/group/GroupView.h @@ -36,10 +36,10 @@ class GroupView : public QTreeView void setCurrentGroup(Group* group); void expandGroup(Group* group, bool expand = true); -Q_SIGNALS: +signals: void groupChanged(Group* group); -private Q_SLOTS: +private slots: void expandedChanged(const QModelIndex& index); void emitGroupChanged(const QModelIndex& index); void emitGroupChanged(); diff --git a/src/http/AccessControlDialog.cpp b/src/http/AccessControlDialog.cpp index fea47026fe..ef02215a3a 100644 --- a/src/http/AccessControlDialog.cpp +++ b/src/http/AccessControlDialog.cpp @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file AccessControlDialog.cpp - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #include "AccessControlDialog.h" #include "ui_AccessControlDialog.h" @@ -36,10 +41,11 @@ void AccessControlDialog::setUrl(const QString &url) "Please select whether you want to allow access.")).arg(QUrl(url).host())); } -void AccessControlDialog::setItems(const QList &items) +void AccessControlDialog::setItems(const QList &items) { - Q_FOREACH (Entry * entry, items) + for (Entry* entry: items) { ui->itemsList->addItem(entry->title() + " - " + entry->username()); + } } bool AccessControlDialog::remember() const diff --git a/src/http/AccessControlDialog.h b/src/http/AccessControlDialog.h index 4ecef986d7..76392eff10 100644 --- a/src/http/AccessControlDialog.h +++ b/src/http/AccessControlDialog.h @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file AccessControlDialog.h - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #ifndef ACCESSCONTROLDIALOG_H #define ACCESSCONTROLDIALOG_H diff --git a/src/http/CMakeLists.txt b/src/http/CMakeLists.txt index 53fe7e1762..8a3b197ab9 100644 --- a/src/http/CMakeLists.txt +++ b/src/http/CMakeLists.txt @@ -13,13 +13,6 @@ if(WITH_XC_HTTP) Server.cpp Service.cpp ) - set(keepasshttp_FORMS - AccessControlDialog.ui - HttpPasswordGeneratorWidget.ui - OptionDialog.ui - ) - - qt5_wrap_ui(keepasshttp_SOURCES ${keepasshttp_FORMS}) add_library(keepasshttp STATIC ${keepasshttp_SOURCES}) target_link_libraries(keepasshttp qhttp Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network) diff --git a/src/http/EntryConfig.cpp b/src/http/EntryConfig.cpp index 3a7c17eac3..309afafaca 100644 --- a/src/http/EntryConfig.cpp +++ b/src/http/EntryConfig.cpp @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file EntryConfig.cpp - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #include "EntryConfig.h" #include diff --git a/src/http/EntryConfig.h b/src/http/EntryConfig.h index 40633162f6..d5e9876eed 100644 --- a/src/http/EntryConfig.h +++ b/src/http/EntryConfig.h @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file EntryConfig.h - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #ifndef ENTRYCONFIG_H #define ENTRYCONFIG_H diff --git a/src/http/HttpPasswordGeneratorWidget.cpp b/src/http/HttpPasswordGeneratorWidget.cpp index 30e4f71e79..55e5b08fc7 100644 --- a/src/http/HttpPasswordGeneratorWidget.cpp +++ b/src/http/HttpPasswordGeneratorWidget.cpp @@ -1,19 +1,20 @@ /* - * Copyright (C) 2013 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #include "HttpPasswordGeneratorWidget.h" #include "ui_HttpPasswordGeneratorWidget.h" @@ -32,13 +33,10 @@ HttpPasswordGeneratorWidget::HttpPasswordGeneratorWidget(QWidget* parent) { m_ui->setupUi(this); - connect(m_ui->buttonApply, SIGNAL(clicked()), SLOT(saveSettings())); - connect(m_ui->sliderLength, SIGNAL(valueChanged(int)), SLOT(sliderMoved())); connect(m_ui->spinBoxLength, SIGNAL(valueChanged(int)), SLOT(spinBoxChanged())); connect(m_ui->optionButtons, SIGNAL(buttonClicked(int)), SLOT(updateGenerator())); - m_ui->buttonApply->setEnabled(true); loadSettings(); reset(); diff --git a/src/http/HttpPasswordGeneratorWidget.h b/src/http/HttpPasswordGeneratorWidget.h index 2b2ace39b6..8ef6091b6d 100644 --- a/src/http/HttpPasswordGeneratorWidget.h +++ b/src/http/HttpPasswordGeneratorWidget.h @@ -1,19 +1,20 @@ /* - * Copyright (C) 2013 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #ifndef KEEPASSX_HTTPPASSWORDGENERATORWIDGET_H #define KEEPASSX_HTTPPASSWORDGENERATORWIDGET_H @@ -35,10 +36,10 @@ class HttpPasswordGeneratorWidget : public QWidget explicit HttpPasswordGeneratorWidget(QWidget* parent = nullptr); ~HttpPasswordGeneratorWidget(); void loadSettings(); + void saveSettings(); void reset(); -private Q_SLOTS: - void saveSettings(); +private slots: void sliderMoved(); void spinBoxChanged(); diff --git a/src/http/HttpPasswordGeneratorWidget.ui b/src/http/HttpPasswordGeneratorWidget.ui index 29399bcd6e..066b9c512a 100644 --- a/src/http/HttpPasswordGeneratorWidget.ui +++ b/src/http/HttpPasswordGeneratorWidget.ui @@ -6,14 +6,26 @@ 0 0 - 434 - 250 + 500 + 181 + + 0 + + + 0 + + + 0 + + + 0 + @@ -168,42 +180,8 @@ - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Accept - - - - - - - - PasswordComboBox - QComboBox -
gui/PasswordComboBox.h
-
-
sliderLength spinBoxLength @@ -213,7 +191,6 @@ checkBoxSpecialChars checkBoxExcludeAlike checkBoxEnsureEvery - buttonApply diff --git a/src/http/HttpSettings.cpp b/src/http/HttpSettings.cpp index e51f87cfbb..60a35940c5 100644 --- a/src/http/HttpSettings.cpp +++ b/src/http/HttpSettings.cpp @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file HttpSettings.cpp - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #include "HttpSettings.h" #include "core/Config.h" diff --git a/src/http/HttpSettings.h b/src/http/HttpSettings.h index bea5648c9f..a4aee1a63a 100644 --- a/src/http/HttpSettings.h +++ b/src/http/HttpSettings.h @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file HttpSettings.h - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #ifndef HTTPSETTINGS_H #define HTTPSETTINGS_H diff --git a/src/http/OptionDialog.cpp b/src/http/OptionDialog.cpp index 5245d333ba..9fb66bd6f7 100644 --- a/src/http/OptionDialog.cpp +++ b/src/http/OptionDialog.cpp @@ -1,29 +1,43 @@ -/** - *************************************************************************** - * @file OptionDialog.cpp - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #include "OptionDialog.h" #include "ui_OptionDialog.h" #include "HttpSettings.h" +#include "core/FilePath.h" + #include OptionDialog::OptionDialog(QWidget *parent) : QWidget(parent), - ui(new Ui::OptionDialog()) + m_ui(new Ui::OptionDialog()) { - ui->setupUi(this); - connect(ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SIGNAL(removeSharedEncryptionKeys())); - connect(ui->removeStoredPermissions, SIGNAL(clicked()), this, SIGNAL(removeStoredPermissions())); + m_ui->setupUi(this); + connect(m_ui->removeSharedEncryptionKeys, SIGNAL(clicked()), this, SIGNAL(removeSharedEncryptionKeys())); + connect(m_ui->removeStoredPermissions, SIGNAL(clicked()), this, SIGNAL(removeStoredPermissions())); + + m_ui->warningWidget->showMessage(tr("The following options can be dangerous!\nChange them only if you know what you are doing."), MessageWidget::Warning); + m_ui->warningWidget->setIcon(FilePath::instance()->icon("status", "dialog-warning")); + m_ui->warningWidget->setCloseButtonVisible(false); + + m_ui->tabWidget->setEnabled(m_ui->enableHttpServer->isChecked()); + connect(m_ui->enableHttpServer, SIGNAL(toggled(bool)), m_ui->tabWidget, SLOT(setEnabled(bool))); } OptionDialog::~OptionDialog() @@ -33,65 +47,48 @@ OptionDialog::~OptionDialog() void OptionDialog::loadSettings() { HttpSettings settings; - ui->enableHttpServer->setChecked(settings.isEnabled()); + m_ui->enableHttpServer->setChecked(settings.isEnabled()); - ui->showNotification->setChecked(settings.showNotification()); - ui->bestMatchOnly->setChecked(settings.bestMatchOnly()); - ui->unlockDatabase->setChecked(settings.unlockDatabase()); - ui->matchUrlScheme->setChecked(settings.matchUrlScheme()); + m_ui->showNotification->setChecked(settings.showNotification()); + m_ui->bestMatchOnly->setChecked(settings.bestMatchOnly()); + m_ui->unlockDatabase->setChecked(settings.unlockDatabase()); + m_ui->matchUrlScheme->setChecked(settings.matchUrlScheme()); if (settings.sortByUsername()) - ui->sortByUsername->setChecked(true); + m_ui->sortByUsername->setChecked(true); else - ui->sortByTitle->setChecked(true); - ui->httpPort->setText(QString::number(settings.httpPort())); + m_ui->sortByTitle->setChecked(true); + m_ui->httpPort->setText(QString::number(settings.httpPort())); -/* - ui->checkBoxLower->setChecked(settings.passwordUseLowercase()); - ui->checkBoxNumbers->setChecked(settings.passwordUseNumbers()); - ui->checkBoxUpper->setChecked(settings.passwordUseUppercase()); - ui->checkBoxSpecialChars->setChecked(settings.passwordUseSpecial()); - ui->checkBoxEnsureEvery->setChecked(settings.passwordEveryGroup()); - ui->checkBoxExcludeAlike->setChecked(settings.passwordExcludeAlike()); - ui->spinBoxLength->setValue(settings.passwordLength()); -*/ + m_ui->alwaysAllowAccess->setChecked(settings.alwaysAllowAccess()); + m_ui->alwaysAllowUpdate->setChecked(settings.alwaysAllowUpdate()); + m_ui->searchInAllDatabases->setChecked(settings.searchInAllDatabases()); + m_ui->supportKphFields->setChecked(settings.supportKphFields()); - ui->alwaysAllowAccess->setChecked(settings.alwaysAllowAccess()); - ui->alwaysAllowUpdate->setChecked(settings.alwaysAllowUpdate()); - ui->searchInAllDatabases->setChecked(settings.searchInAllDatabases()); - ui->supportKphFields->setChecked(settings.supportKphFields()); + m_ui->passwordGenerator->loadSettings(); } void OptionDialog::saveSettings() { HttpSettings settings; - settings.setEnabled(ui->enableHttpServer->isChecked()); + settings.setEnabled(m_ui->enableHttpServer->isChecked()); - settings.setShowNotification(ui->showNotification->isChecked()); - settings.setBestMatchOnly(ui->bestMatchOnly->isChecked()); - settings.setUnlockDatabase(ui->unlockDatabase->isChecked()); - settings.setMatchUrlScheme(ui->matchUrlScheme->isChecked()); - settings.setSortByUsername(ui->sortByUsername->isChecked()); + settings.setShowNotification(m_ui->showNotification->isChecked()); + settings.setBestMatchOnly(m_ui->bestMatchOnly->isChecked()); + settings.setUnlockDatabase(m_ui->unlockDatabase->isChecked()); + settings.setMatchUrlScheme(m_ui->matchUrlScheme->isChecked()); + settings.setSortByUsername(m_ui->sortByUsername->isChecked()); - int port = ui->httpPort->text().toInt(); + int port = m_ui->httpPort->text().toInt(); if (port < 1024) { QMessageBox::warning(this, tr("Cannot bind to privileged ports"), tr("Cannot bind to privileged ports below 1024!\nUsing default port 19455.")); port = 19455; } settings.setHttpPort(port); + settings.setAlwaysAllowAccess(m_ui->alwaysAllowAccess->isChecked()); + settings.setAlwaysAllowUpdate(m_ui->alwaysAllowUpdate->isChecked()); + settings.setSearchInAllDatabases(m_ui->searchInAllDatabases->isChecked()); + settings.setSupportKphFields(m_ui->supportKphFields->isChecked()); -/* - settings.setPasswordUseLowercase(ui->checkBoxLower->isChecked()); - settings.setPasswordUseNumbers(ui->checkBoxNumbers->isChecked()); - settings.setPasswordUseUppercase(ui->checkBoxUpper->isChecked()); - settings.setPasswordUseSpecial(ui->checkBoxSpecialChars->isChecked()); - settings.setPasswordEveryGroup(ui->checkBoxEnsureEvery->isChecked()); - settings.setPasswordExcludeAlike(ui->checkBoxExcludeAlike->isChecked()); - settings.setPasswordLength(ui->spinBoxLength->value()); -*/ - - settings.setAlwaysAllowAccess(ui->alwaysAllowAccess->isChecked()); - settings.setAlwaysAllowUpdate(ui->alwaysAllowUpdate->isChecked()); - settings.setSearchInAllDatabases(ui->searchInAllDatabases->isChecked()); - settings.setSupportKphFields(ui->supportKphFields->isChecked()); + m_ui->passwordGenerator->saveSettings(); } diff --git a/src/http/OptionDialog.h b/src/http/OptionDialog.h index adec9f6951..6139f929b9 100644 --- a/src/http/OptionDialog.h +++ b/src/http/OptionDialog.h @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file OptionDialog.h - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #ifndef OPTIONDIALOG_H #define OPTIONDIALOG_H @@ -29,16 +34,16 @@ class OptionDialog : public QWidget explicit OptionDialog(QWidget *parent = nullptr); ~OptionDialog(); -public Q_SLOTS: +public slots: void loadSettings(); void saveSettings(); -Q_SIGNALS: +signals: void removeSharedEncryptionKeys(); void removeStoredPermissions(); private: - QScopedPointer ui; + QScopedPointer m_ui; }; #endif // OPTIONDIALOG_H diff --git a/src/http/OptionDialog.ui b/src/http/OptionDialog.ui index c9aae49ef8..abe9947727 100644 --- a/src/http/OptionDialog.ui +++ b/src/http/OptionDialog.ui @@ -6,27 +6,38 @@ 0 0 - 605 - 429 + 577 + 404 Dialog + + 0 + + + 0 + + + 0 + + + 0 + + + This is required for accessing your databases from ChromeIPass or PassIFox + - Enable KeepassXC HTTP protocol -This is required for accessing your databases from ChromeIPass or PassIFox + Enable KeePassHTTP server - - QTabWidget::Rounded - 0 @@ -40,13 +51,18 @@ This is required for accessing your databases from ChromeIPass or PassIFox Sh&ow a notification when credentials are requested + + true + + + Only returns the best matches for a specific URL instead of all entries for the whole domain. + - &Return only best matching entries for a URL instead -of all entries for the whole domain + &Return only best matching entries @@ -55,13 +71,18 @@ of all entries for the whole domain Re&quest to unlock the database if it is locked + + true +
+ + Only entries with the same scheme (http://, https://, ftp://, ...) are returned. + - &Match URL schemes -Only entries with the same scheme (http://, https://, ftp://, ...) are returned + &Match URL schemes @@ -110,7 +131,7 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< - Password generator + Password Generator @@ -135,20 +156,14 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< Advanced - + - - - - 75 - true - - - - color: rgb(255, 0, 0); - - - The following options can be dangerous. Change them only if you know what you are doing. + + + + 0 + 0 + @@ -168,35 +183,21 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< - - Searc&h in all opened databases for matching entries + + Only the selected database has to be connected with a client. - - - - - Only the selected database has to be connected with a client! - - - 30 + Searc&h in all opened databases for matching entries - - &Return advanced string fields which start with "KPH: " - - - - - - + Automatically creating or updating string fields is not supported. - - 30 + + &Return advanced string fields which start with "KPH: " @@ -217,25 +218,8 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< - - - - - d0000 - - - Default port: 19455 - - - - - - - KeePassXC will listen to this port on 127.0.0.1 - - - - + + @@ -251,6 +235,29 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned< + + + + + 0 + 0 + + + + d0000 + + + Default port: 19455 + + + + + + + KeePassXC will listen to this port on 127.0.0.1 + + + @@ -279,6 +286,12 @@ Only entries with the same scheme (http://, https://, ftp://, ...) are returned<
http/HttpPasswordGeneratorWidget.h
1 + + MessageWidget + QWidget +
gui/MessageWidget.h
+ 1 +
diff --git a/src/http/Protocol.cpp b/src/http/Protocol.cpp index 5b60110dee..d6d5557a1e 100644 --- a/src/http/Protocol.cpp +++ b/src/http/Protocol.cpp @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file Response.cpp - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #include "Protocol.h" #include @@ -17,6 +22,7 @@ #include "crypto/Random.h" #include "crypto/SymmetricCipher.h" #include "crypto/SymmetricCipherGcrypt.h" +#include "core/Global.h" namespace KeepassHttpProtocol { @@ -370,8 +376,9 @@ QVariant Response::getEntries() const QList res; res.reserve(m_entries.size()); - Q_FOREACH (const Entry &entry, m_entries) + for (const Entry& entry: asConst(m_entries)) { res.append(qobject2qvariant(&entry)); + } return res; } @@ -383,14 +390,16 @@ void Response::setEntries(const QList &entries) QList encryptedEntries; encryptedEntries.reserve(m_count); - Q_FOREACH (const Entry &entry, entries) { + for (const Entry& entry: entries) { Entry encryptedEntry(encrypt(entry.name(), m_cipher), encrypt(entry.login(), m_cipher), entry.password().isNull() ? QString() : encrypt(entry.password(), m_cipher), encrypt(entry.uuid(), m_cipher)); - Q_FOREACH (const StringField & field, entry.stringFields()) + const auto stringFields = entry.stringFields(); + for (const StringField& field: stringFields) { encryptedEntry.addStringField(encrypt(field.key(), m_cipher), encrypt(field.value(), m_cipher)); + } encryptedEntries << encryptedEntry; } m_entries = encryptedEntries; @@ -508,8 +517,9 @@ QVariant Entry::getStringFields() const QList res; res.reserve(m_stringFields.size()); - Q_FOREACH (const StringField &stringfield, m_stringFields) + for (const StringField& stringfield: asConst(m_stringFields)) { res.append(qobject2qvariant(&stringfield)); + } return res; } diff --git a/src/http/Protocol.h b/src/http/Protocol.h index e20d19c318..ff48fe58cb 100644 --- a/src/http/Protocol.h +++ b/src/http/Protocol.h @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file Response.h - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #ifndef RESPONSE_H #define RESPONSE_H diff --git a/src/http/Server.cpp b/src/http/Server.cpp index 5304c7f0f6..faac7be23c 100644 --- a/src/http/Server.cpp +++ b/src/http/Server.cpp @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file Server.cpp - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #include #include diff --git a/src/http/Server.h b/src/http/Server.h index 8421de06cd..08cdfa24a8 100644 --- a/src/http/Server.h +++ b/src/http/Server.h @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file Server.h - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #ifndef SERVER_H #define SERVER_H diff --git a/src/http/Service.cpp b/src/http/Service.cpp index aac5d6b0ad..639898da2a 100644 --- a/src/http/Service.cpp +++ b/src/http/Service.cpp @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file Service.cpp - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #include #include @@ -23,12 +28,15 @@ #include "core/Database.h" #include "core/Entry.h" +#include "core/Global.h" #include "core/Group.h" #include "core/EntrySearcher.h" #include "core/Metadata.h" #include "core/Uuid.h" #include "core/PasswordGenerator.h" +#include + static const unsigned char KEEPASSHTTP_UUID_DATA[] = { 0x34, 0x69, 0x7a, 0x40, 0x8a, 0x5b, 0x41, 0xc0, 0x9f, 0x36, 0x89, 0x7d, 0x62, 0x3e, 0xcb, 0x31 @@ -81,6 +89,8 @@ bool Service::isDatabaseOpened() const case DatabaseWidget::ViewMode: case DatabaseWidget::EditMode: return true; + default: + break; } return false; } @@ -98,6 +108,8 @@ bool Service::openDatabase() case DatabaseWidget::ViewMode: case DatabaseWidget::EditMode: return true; + default: + break; } } //if (HttpSettings::showNotification() @@ -187,8 +199,9 @@ bool Service::removeFirstDomain(QString & hostname) QList Service::searchEntries(Database* db, const QString& hostname) { QList entries; - if (Group* rootGroup = db->rootGroup()) - Q_FOREACH (Entry* entry, EntrySearcher().search(hostname, rootGroup, Qt::CaseInsensitive)) { + if (Group* rootGroup = db->rootGroup()) { + const auto results = EntrySearcher().search(hostname, rootGroup, Qt::CaseInsensitive); + for (Entry* entry: results) { QString title = entry->title(); QString url = entry->url(); @@ -199,6 +212,7 @@ QList Service::searchEntries(Database* db, const QString& hostname) || (matchUrlScheme(url) && hostname.endsWith(QUrl(url).host())) ) entries.append(entry); } + } return entries; } @@ -221,8 +235,9 @@ QList Service::searchEntries(const QString& text) QString hostname = QUrl(text).host(); QList entries; do { - Q_FOREACH (Database* db, databases) + for (Database* db: asConst(databases)) { entries << searchEntries(db, hostname); + } } while(entries.isEmpty() && removeFirstDomain(hostname)); return entries; @@ -244,12 +259,15 @@ Service::Access Service::checkAccess(const Entry *entry, const QString & host, c KeepassHttpProtocol::Entry Service::prepareEntry(const Entry* entry) { - KeepassHttpProtocol::Entry res(entry->title(), entry->username(), entry->password(), entry->uuid().toHex()); + KeepassHttpProtocol::Entry res(entry->resolvePlaceholder(entry->title()), entry->resolvePlaceholder(entry->username()), entry->resolvePlaceholder(entry->password()), entry->uuid().toHex()); if (HttpSettings::supportKphFields()) { const EntryAttributes * attr = entry->attributes(); - Q_FOREACH (const QString& key, attr->keys()) - if (key.startsWith(QLatin1String("KPH: "))) + const auto keys = attr->keys(); + for (const QString& key: keys) { + if (key.startsWith(QLatin1String("KPH: "))) { res.addStringField(key, attr->value(key)); + } + } } return res; } @@ -316,7 +334,8 @@ QList Service::findMatchingEntries(const QString& /* //Check entries for authorization QList pwEntriesToConfirm; QList pwEntries; - Q_FOREACH (Entry * entry, searchEntries(url)) { + const auto entries = searchEntries(url); + for (Entry* entry: entries) { switch(checkAccess(entry, host, submitHost, realm)) { case Denied: continue; @@ -350,7 +369,7 @@ QList Service::findMatchingEntries(const QString& /* int res = dlg.exec(); if (dlg.remember()) { - Q_FOREACH (Entry * entry, pwEntriesToConfirm) { + for (Entry* entry: asConst(pwEntriesToConfirm)) { EntryConfig config; config.load(entry); if (res == QDialog::Accepted) { @@ -381,28 +400,22 @@ QList Service::findMatchingEntries(const QString& /* const QString baseSubmitURL = url.toString(QUrl::StripTrailingSlash | QUrl::RemovePath | QUrl::RemoveQuery | QUrl::RemoveFragment); //Cache priorities - QHash priorities; + QHash priorities; priorities.reserve(pwEntries.size()); - Q_FOREACH (const Entry * entry, pwEntries) + for (const Entry* entry: asConst(pwEntries)) { priorities.insert(entry, sortPriority(entry, host, submitUrl, baseSubmitURL)); + } //Sort by priorities - qSort(pwEntries.begin(), pwEntries.end(), SortEntries(priorities, HttpSettings::sortByTitle() ? "Title" : "UserName")); + std::sort(pwEntries.begin(), pwEntries.end(), SortEntries(priorities, HttpSettings::sortByTitle() ? "Title" : "UserName")); } - //if (pwEntries.count() > 0) - //{ - // var names = (from e in resp.Entries select e.Name).Distinct(); - // var n = String.Join("\n ", names.ToArray()); - // if (HttpSettings::receiveCredentialNotification()) - // ShowNotification(QString("%0: %1 is receiving credentials for:\n%2").arg(Id).arg(host).arg(n))); - //} - //Fill the list QList result; result.reserve(pwEntries.count()); - Q_FOREACH (Entry * entry, pwEntries) + for (Entry* entry: asConst(pwEntries)) { result << prepareEntry(entry); + } return result; } @@ -414,12 +427,19 @@ int Service::countMatchingEntries(const QString &, const QString &url, const QSt QList Service::searchAllEntries(const QString &) { QList result; - if (DatabaseWidget * dbWidget = m_dbTabWidget->currentDatabaseWidget()) - if (Database * db = dbWidget->database()) - if (Group * rootGroup = db->rootGroup()) - Q_FOREACH (Entry * entry, rootGroup->entriesRecursive()) - if (!entry->url().isEmpty() || QUrl(entry->title()).isValid()) - result << KeepassHttpProtocol::Entry(entry->title(), entry->username(), QString(), entry->uuid().toHex()); + if (DatabaseWidget* dbWidget = m_dbTabWidget->currentDatabaseWidget()) { + if (Database* db = dbWidget->database()) { + if (Group* rootGroup = db->rootGroup()) { + const auto entries = rootGroup->entriesRecursive(); + for (Entry* entry: entries) { + if (!entry->url().isEmpty() || QUrl(entry->title()).isValid()) { + result << KeepassHttpProtocol::Entry(entry->title(), entry->username(), + QString(), entry->uuid().toHex()); + } + } + } + } + } return result; } @@ -428,11 +448,15 @@ Group * Service::findCreateAddEntryGroup() if (DatabaseWidget * dbWidget = m_dbTabWidget->currentDatabaseWidget()) if (Database * db = dbWidget->database()) if (Group * rootGroup = db->rootGroup()) { - const QString groupName = QLatin1String(KEEPASSHTTP_GROUP_NAME);//TODO: setting to decide where new keys are created + //TODO: setting to decide where new keys are created + const QString groupName = QLatin1String(KEEPASSHTTP_GROUP_NAME); - Q_FOREACH (const Group * g, rootGroup->groupsRecursive(true)) - if (g->name() == groupName) + const auto groups = rootGroup->groupsRecursive(true); + for (const Group * g: groups) { + if (g->name() == groupName) { return db->resolveGroup(g->uuid()); + } + } Group * group; group = new Group(); @@ -505,14 +529,18 @@ void Service::removeSharedEncryptionKeys() QMessageBox::Ok); } else if (Entry* entry = getConfigEntry()) { QStringList keysToRemove; - Q_FOREACH (const QString& key, entry->attributes()->keys()) - if (key.startsWith(ASSOCIATE_KEY_PREFIX)) + const auto keys = entry->attributes()->keys(); + for (const QString& key: keys) { + if (key.startsWith(ASSOCIATE_KEY_PREFIX)) { keysToRemove << key; + } + } if(keysToRemove.count()) { entry->beginUpdate(); - Q_FOREACH (const QString& key, keysToRemove) + for (const QString& key: asConst(keysToRemove)) { entry->attributes()->remove(key); + } entry->endUpdate(); const int count = keysToRemove.count(); @@ -546,7 +574,7 @@ void Service::removeStoredPermissions() progress.setWindowModality(Qt::WindowModal); uint counter = 0; - Q_FOREACH (Entry* entry, entries) { + for (Entry* entry: asConst(entries)) { if (progress.wasCanceled()) return; if (entry->attributes()->contains(KEEPASSHTTP_NAME)) { diff --git a/src/http/Service.h b/src/http/Service.h index 6452d605ac..d60d884bb2 100644 --- a/src/http/Service.h +++ b/src/http/Service.h @@ -1,15 +1,20 @@ -/** - *************************************************************************** - * @file Service.h - * - * @brief - * - * Copyright (C) 2013 - * - * @author Francois Ferrand - * @date 4/2013 - *************************************************************************** - */ +/* +* Copyright (C) 2013 Francois Ferrand +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ #ifndef SERVICE_H #define SERVICE_H @@ -38,7 +43,7 @@ class Service : public KeepassHttpProtocol::Server virtual void updateEntry(const QString& id, const QString& uuid, const QString& login, const QString& password, const QString& url); virtual QString generatePassword(); -public Q_SLOTS: +public slots: void removeSharedEncryptionKeys(); void removeStoredPermissions(); diff --git a/src/keys/ChallengeResponseKey.h b/src/keys/ChallengeResponseKey.h new file mode 100644 index 0000000000..698846a039 --- /dev/null +++ b/src/keys/ChallengeResponseKey.h @@ -0,0 +1,32 @@ +/* +* Copyright (C) 2014 Kyle Manna +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#ifndef KEEPASSX_CHALLENGE_RESPONSE_KEY_H +#define KEEPASSX_CHALLENGE_RESPONSE_KEY_H + +#include + +class ChallengeResponseKey +{ +public: + virtual ~ChallengeResponseKey() {} + virtual QByteArray rawKey() const = 0; + virtual bool challenge(const QByteArray& challenge) = 0; +}; + +#endif // KEEPASSX_CHALLENGE_RESPONSE_KEY_H diff --git a/src/keys/CompositeKey.cpp b/src/keys/CompositeKey.cpp index 88116c1048..3b1a82a225 100644 --- a/src/keys/CompositeKey.cpp +++ b/src/keys/CompositeKey.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer +* Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +18,7 @@ #include "CompositeKey.h" #include "CompositeKey_p.h" +#include "ChallengeResponseKey.h" #include #include @@ -46,11 +48,12 @@ void CompositeKey::clear() { qDeleteAll(m_keys); m_keys.clear(); + m_challengeResponseKeys.clear(); } bool CompositeKey::isEmpty() const { - return m_keys.isEmpty(); + return m_keys.isEmpty() && m_challengeResponseKeys.isEmpty(); } CompositeKey* CompositeKey::clone() const @@ -70,6 +73,9 @@ CompositeKey& CompositeKey::operator=(const CompositeKey& key) for (const Key* subKey : asConst(key.m_keys)) { addKey(*subKey); } + for (const auto subKey : asConst(key.m_challengeResponseKeys)) { + addChallengeResponseKey(subKey); + } return *this; } @@ -168,11 +174,40 @@ QByteArray CompositeKey::transformKeyRaw(const QByteArray& key, const QByteArray return result; } +bool CompositeKey::challenge(const QByteArray& seed, QByteArray& result) const +{ + // if no challenge response was requested, return nothing to + // maintain backwards compatibility with regular databases. + if (m_challengeResponseKeys.length() == 0) { + result.clear(); + return true; + } + + CryptoHash cryptoHash(CryptoHash::Sha256); + + for (const auto key : m_challengeResponseKeys) { + // if the device isn't present or fails, return an error + if (!key->challenge(seed)) { + return false; + } + cryptoHash.addData(key->rawKey()); + } + + result = cryptoHash.result(); + return true; +} + void CompositeKey::addKey(const Key& key) { m_keys.append(key.clone()); } +void CompositeKey::addChallengeResponseKey(QSharedPointer key) +{ + m_challengeResponseKeys.append(key); +} + + int CompositeKey::transformKeyBenchmark(int msec) { TransformKeyBenchmarkThread thread1(msec); diff --git a/src/keys/CompositeKey.h b/src/keys/CompositeKey.h index f8666aadc2..12e2d955d8 100644 --- a/src/keys/CompositeKey.h +++ b/src/keys/CompositeKey.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer +* Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,8 +21,10 @@ #include #include +#include #include "keys/Key.h" +#include "keys/ChallengeResponseKey.h" class CompositeKey : public Key { @@ -37,7 +40,10 @@ class CompositeKey : public Key QByteArray rawKey() const; QByteArray transform(const QByteArray& seed, quint64 rounds, bool* ok, QString* errorString) const; + bool challenge(const QByteArray& seed, QByteArray &result) const; + void addKey(const Key& key); + void addChallengeResponseKey(QSharedPointer key); static int transformKeyBenchmark(int msec); static CompositeKey readFromLine(QString line); @@ -47,6 +53,7 @@ class CompositeKey : public Key quint64 rounds, bool* ok, QString* errorString); QList m_keys; + QList> m_challengeResponseKeys; }; #endif // KEEPASSX_COMPOSITEKEY_H diff --git a/src/keys/YkChallengeResponseKey.cpp b/src/keys/YkChallengeResponseKey.cpp new file mode 100644 index 0000000000..cfb4a1dfe7 --- /dev/null +++ b/src/keys/YkChallengeResponseKey.cpp @@ -0,0 +1,110 @@ +/* +* Copyright (C) 2014 Kyle Manna +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ +#include "keys/YkChallengeResponseKey.h" +#include "keys/drivers/YubiKey.h" + +#include "core/Tools.h" +#include "crypto/CryptoHash.h" +#include "crypto/Random.h" +#include "gui/MainWindow.h" + +#include +#include +#include +#include +#include +#include + +YkChallengeResponseKey::YkChallengeResponseKey(int slot, bool blocking) + : m_slot(slot), + m_blocking(blocking) +{ + if (KEEPASSXC_MAIN_WINDOW) { + connect(this, SIGNAL(userInteractionRequired()), KEEPASSXC_MAIN_WINDOW, SLOT(showYubiKeyPopup())); + connect(this, SIGNAL(userConfirmed()), KEEPASSXC_MAIN_WINDOW, SLOT(hideYubiKeyPopup())); + } +} + +QByteArray YkChallengeResponseKey::rawKey() const +{ + return m_key; +} + +/** + * Assumes yubikey()->init() was called + */ +bool YkChallengeResponseKey::challenge(const QByteArray& challenge) +{ + return this->challenge(challenge, 1); +} + +bool YkChallengeResponseKey::challenge(const QByteArray& challenge, unsigned retries) +{ + Q_ASSERT(retries > 0); + + do { + --retries; + + if (m_blocking) { + emit userInteractionRequired(); + } + + QFuture future = QtConcurrent::run([this, challenge]() { + return YubiKey::instance()->challenge(m_slot, true, challenge, m_key); + }); + + QEventLoop loop; + QFutureWatcher watcher; + watcher.setFuture(future); + connect(&watcher, SIGNAL(finished()), &loop, SLOT(quit())); + loop.exec(); + + if (m_blocking) { + emit userConfirmed(); + } + + if (future.result() != YubiKey::ERROR) { + return true; + } + + // if challenge failed, retry to detect YubiKeys in the event the YubiKey was un-plugged and re-plugged + if (retries > 0 && YubiKey::instance()->init() != true) { + continue; + } + + } while (retries > 0); + + return false; +} + +QString YkChallengeResponseKey::getName() const +{ + unsigned int serial; + QString fmt(QObject::tr("YubiKey[%1] Challenge Response - Slot %2 - %3")); + + YubiKey::instance()->getSerial(serial); + + return fmt.arg(QString::number(serial), + QString::number(m_slot), + (m_blocking) ? QObject::tr("Press") : QObject::tr("Passive")); +} + +bool YkChallengeResponseKey::isBlocking() const +{ + return m_blocking; +} diff --git a/src/keys/YkChallengeResponseKey.h b/src/keys/YkChallengeResponseKey.h new file mode 100644 index 0000000000..66d821a692 --- /dev/null +++ b/src/keys/YkChallengeResponseKey.h @@ -0,0 +1,59 @@ +/* +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#ifndef KEEPASSX_YK_CHALLENGERESPONSEKEY_H +#define KEEPASSX_YK_CHALLENGERESPONSEKEY_H + +#include "core/Global.h" +#include "keys/ChallengeResponseKey.h" +#include "keys/drivers/YubiKey.h" + +#include + +class YkChallengeResponseKey : public QObject, public ChallengeResponseKey +{ + Q_OBJECT + +public: + + YkChallengeResponseKey(int slot = -1, bool blocking = false); + + QByteArray rawKey() const; + bool challenge(const QByteArray& challenge); + bool challenge(const QByteArray& challenge, unsigned retries); + QString getName() const; + bool isBlocking() const; + +signals: + /** + * Emitted whenever user interaction is required to proceed with the challenge-response protocol. + * You can use this to show a helpful dialog informing the user that his assistance is required. + */ + void userInteractionRequired(); + + /** + * Emitted when the user has provided their required input. + */ + void userConfirmed(); + +private: + QByteArray m_key; + int m_slot; + bool m_blocking; +}; + +#endif // KEEPASSX_YK_CHALLENGERESPONSEKEY_H diff --git a/src/keys/drivers/YubiKey.cpp b/src/keys/drivers/YubiKey.cpp new file mode 100644 index 0000000000..6fb44ec89e --- /dev/null +++ b/src/keys/drivers/YubiKey.cpp @@ -0,0 +1,213 @@ +/* +* Copyright (C) 2014 Kyle Manna +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#include + +#include + +#include +#include +#include +#include + +#include "core/Global.h" +#include "crypto/Random.h" + +#include "YubiKey.h" + +// Cast the void pointer from the generalized class definition +// to the proper pointer type from the now included system headers +#define m_yk (static_cast(m_yk_void)) +#define m_ykds (static_cast(m_ykds_void)) + +YubiKey::YubiKey() : m_yk_void(NULL), m_ykds_void(NULL), m_mutex(QMutex::Recursive) +{ +} + +YubiKey* YubiKey::m_instance(Q_NULLPTR); + +YubiKey* YubiKey::instance() +{ + if (!m_instance) { + m_instance = new YubiKey(); + } + + return m_instance; +} + +bool YubiKey::init() +{ + m_mutex.lock(); + + // previously initialized + if (m_yk != NULL && m_ykds != NULL) { + + if (yk_get_status(m_yk, m_ykds)) { + // Still connected + m_mutex.unlock(); + return true; + } else { + // Initialized but not connected anymore, re-init + deinit(); + } + } + + if (!yk_init()) { + m_mutex.unlock(); + return false; + } + + // TODO: handle multiple attached hardware devices + m_yk_void = static_cast(yk_open_first_key()); + if (m_yk == NULL) { + m_mutex.unlock(); + return false; + } + + m_ykds_void = static_cast(ykds_alloc()); + if (m_ykds == NULL) { + yk_close_key(m_yk); + m_yk_void = NULL; + m_mutex.unlock(); + return false; + } + + m_mutex.unlock(); + return true; +} + +bool YubiKey::deinit() +{ + m_mutex.lock(); + + if (m_yk) { + yk_close_key(m_yk); + m_yk_void = NULL; + } + + if (m_ykds) { + ykds_free(m_ykds); + m_ykds_void = NULL; + } + + m_mutex.unlock(); + + return true; +} + +void YubiKey::detect() +{ + if (init()) { + for (int i = 1; i < 3; i++) { + YubiKey::ChallengeResult result; + QByteArray rand = randomGen()->randomArray(1); + QByteArray resp; + + result = challenge(i, false, rand, resp); + if (result == YubiKey::ALREADY_RUNNING) { + emit alreadyRunning(); + return; + } else if (result != YubiKey::ERROR) { + emit detected(i, result == YubiKey::WOULDBLOCK); + return; + } + } + } + emit notFound(); +} + +bool YubiKey::getSerial(unsigned int& serial) +{ + m_mutex.lock(); + int result = yk_get_serial(m_yk, 1, 0, &serial); + m_mutex.unlock(); + + if (!result) { + return false; + } + + return true; +} + +YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByteArray& challenge, QByteArray& response) +{ + if (!m_mutex.tryLock()) { + return ALREADY_RUNNING; + } + + int yk_cmd = (slot == 1) ? SLOT_CHAL_HMAC1 : SLOT_CHAL_HMAC2; + QByteArray paddedChallenge = challenge; + + // ensure that YubiKey::init() succeeded + if (m_yk == NULL) { + m_mutex.unlock(); + return ERROR; + } + + // yk_challenge_response() insists on 64 byte response buffer */ + response.resize(64); + + /* The challenge sent to the yubikey should always be 64 bytes for + * compatibility with all configurations. Follow PKCS7 padding. + * + * There is some question whether or not 64 byte fixed length + * configurations even work, some docs say avoid it. + */ + const int padLen = 64 - paddedChallenge.size(); + if (padLen > 0) { + paddedChallenge.append(QByteArray(padLen, padLen)); + } + + const unsigned char *c; + unsigned char *r; + c = reinterpret_cast(paddedChallenge.constData()); + r = reinterpret_cast(response.data()); + + int ret = yk_challenge_response(m_yk, yk_cmd, mayBlock, paddedChallenge.size(), c, response.size(), r); + emit challenged(); + + m_mutex.unlock(); + + if (!ret) { + if (yk_errno == YK_EWOULDBLOCK) { + return WOULDBLOCK; + } else if (yk_errno == YK_ETIMEOUT) { + return ERROR; + } else if (yk_errno) { + + /* Something went wrong, close the key, so that the next call to + * can try to re-open. + * + * Likely caused by the YubiKey being unplugged. + */ + + if (yk_errno == YK_EUSBERR) { + qWarning() << "USB error:" << yk_usb_strerror(); + } else { + qWarning() << "YubiKey core error:" << yk_strerror(yk_errno); + } + + return ERROR; + } + } + + // actual HMAC-SHA1 response is only 20 bytes + response.resize(20); + + return SUCCESS; +} diff --git a/src/keys/drivers/YubiKey.h b/src/keys/drivers/YubiKey.h new file mode 100644 index 0000000000..1467b9fd15 --- /dev/null +++ b/src/keys/drivers/YubiKey.h @@ -0,0 +1,118 @@ +/* +* Copyright (C) 2014 Kyle Manna +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#ifndef KEEPASSX_YUBIKEY_H +#define KEEPASSX_YUBIKEY_H + +#include +#include + +/** + * Singleton class to manage the interface to the hardware + */ +class YubiKey : public QObject +{ + Q_OBJECT + +public: + enum ChallengeResult { ERROR = -1, SUCCESS = 0, WOULDBLOCK, ALREADY_RUNNING }; + + /** + * @brief YubiKey::instance - get instance of singleton + * @return instance + */ + static YubiKey* instance(); + + /** + * @brief YubiKey::init - initialize yubikey library and hardware + * @return true on success + */ + bool init(); + + /** + * @brief YubiKey::deinit - cleanup after init + * @return true on success + */ + bool deinit(); + + /** + * @brief YubiKey::challenge - issue a challenge + * + * This operation could block if the YubiKey requires a touch to trigger. + * + * TODO: Signal to the UI that the system is waiting for challenge response + * touch. + * + * @param slot YubiKey configuration slot + * @param mayBlock operation is allowed to block + * @param challenge challenge input to YubiKey + * @param response response output from YubiKey + * @return true on success + */ + ChallengeResult challenge(int slot, bool mayBlock, const QByteArray& challenge, QByteArray& response); + + /** + * @brief YubiKey::getSerial - serial number of YubiKey + * @param serial serial number + * @return true on success + */ + bool getSerial(unsigned int& serial); + + /** + * @brief YubiKey::detect - probe for attached YubiKeys + */ + void detect(); + +signals: + /** Emitted in response to detect() when a device is found + * + * @slot is the slot number detected + * @blocking signifies if the YK is setup in passive mode or if requires + * the user to touch it for a response + */ + void detected(int slot, bool blocking); + + /** + * Emitted when the YubiKey was challenged and has returned a response. + */ + void challenged(); + + /** + * Emitted when no Yubikey could be found. + */ + void notFound(); + + /** + * Emitted when detection is already running. + */ + void alreadyRunning(); + +private: + explicit YubiKey(); + static YubiKey* m_instance; + + // Create void ptr here to avoid ifdef header include mess + void* m_yk_void; + void* m_ykds_void; + + QMutex m_mutex; + + Q_DISABLE_COPY(YubiKey) +}; + +#endif // KEEPASSX_YUBIKEY_H diff --git a/src/keys/drivers/YubiKeyStub.cpp b/src/keys/drivers/YubiKeyStub.cpp new file mode 100644 index 0000000000..9f6314f0ee --- /dev/null +++ b/src/keys/drivers/YubiKeyStub.cpp @@ -0,0 +1,70 @@ +/* +* Copyright (C) 2014 Kyle Manna +* Copyright (C) 2017 KeePassXC Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 or (at your option) +* version 3 of the License. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#include + +#include "core/Global.h" +#include "crypto/Random.h" + +#include "YubiKey.h" + +YubiKey::YubiKey() : m_yk_void(NULL), m_ykds_void(NULL) +{ +} + +YubiKey* YubiKey::m_instance(Q_NULLPTR); + +YubiKey* YubiKey::instance() +{ + if (!m_instance) { + m_instance = new YubiKey(); + } + + return m_instance; +} + +bool YubiKey::init() +{ + return false; +} + +bool YubiKey::deinit() +{ + return false; +} + +void YubiKey::detect() +{ +} + +bool YubiKey::getSerial(unsigned int& serial) +{ + Q_UNUSED(serial); + + return false; +} + +YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByteArray& chal, QByteArray& resp) +{ + Q_UNUSED(slot); + Q_UNUSED(mayBlock); + Q_UNUSED(chal); + Q_UNUSED(resp); + + return ERROR; +} diff --git a/src/main.cpp b/src/main.cpp index 0618cefaee..7c4402b998 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,8 +27,13 @@ #include "crypto/Crypto.h" #include "gui/Application.h" #include "gui/MainWindow.h" +#include "gui/csvImport/CsvImportWizard.h" #include "gui/MessageBox.h" +#if defined(WITH_ASAN) && defined(WITH_LSAN) +#include +#endif + #ifdef QT_STATIC #include @@ -51,6 +57,13 @@ int main(int argc, char** argv) // don't set organizationName as that changes the return value of // QStandardPaths::writableLocation(QDesktopServices::DataLocation) +#ifndef QT_DEBUG + if (app.isAlreadyRunning()) { + qWarning() << QCoreApplication::translate("Main", "Another instance of KeePassXC is already running.").toUtf8().constData(); + return 0; + } +#endif + QApplication::setQuitOnLastWindowClosed(false); if (!Crypto::init()) { @@ -97,7 +110,15 @@ int main(int argc, char** argv) MainWindow mainWindow; app.setMainWindow(&mainWindow); - + + QObject::connect(&app, &Application::anotherInstanceStarted, + [&]() { + mainWindow.ensurePolished(); + mainWindow.setWindowState(mainWindow.windowState() & ~Qt::WindowMinimized); + mainWindow.show(); + mainWindow.raise(); + mainWindow.activateWindow(); + }); QObject::connect(&app, SIGNAL(openFile(QString)), &mainWindow, SLOT(openDatabase(QString))); // start minimized if configured @@ -110,6 +131,15 @@ int main(int argc, char** argv) mainWindow.show(); } + if (config()->get("OpenPreviousDatabasesOnStartup").toBool()) { + const QStringList filenames = config()->get("LastOpenedDatabases").toStringList(); + for (const QString& filename : filenames) { + if (!filename.isEmpty() && QFile::exists(filename)) { + mainWindow.openDatabase(filename, QString(), QString()); + } + } + } + for (int ii=0; ii < args.length(); ii++) { QString filename = args[ii]; if (!filename.isEmpty() && QFile::exists(filename)) { @@ -122,14 +152,13 @@ int main(int argc, char** argv) } } - if (config()->get("OpenPreviousDatabasesOnStartup").toBool()) { - const QStringList filenames = config()->get("LastOpenedDatabases").toStringList(); - for (const QString& filename : filenames) { - if (!filename.isEmpty() && QFile::exists(filename)) { - mainWindow.openDatabase(filename, QString(), QString()); - } - } - } - - return app.exec(); + int exitCode = app.exec(); + +#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(); + __lsan_disable(); +#endif + + return exitCode; } diff --git a/src/streams/LayeredStream.h b/src/streams/LayeredStream.h index 8586b4134f..4ca7aba9ad 100644 --- a/src/streams/LayeredStream.h +++ b/src/streams/LayeredStream.h @@ -37,7 +37,7 @@ class LayeredStream : public QIODevice QIODevice* const m_baseDevice; -private Q_SLOTS: +private slots: void closeStream(); }; diff --git a/src/totp/base32.cpp b/src/totp/base32.cpp new file mode 100644 index 0000000000..4c81cb4911 --- /dev/null +++ b/src/totp/base32.cpp @@ -0,0 +1,68 @@ +// Base32 implementation +// Source: https://github.com/google/google-authenticator-libpam/blob/master/src/base32.c +// +// Copyright 2010 Google Inc. +// Author: Markus Gutschke +// Modifications Copyright 2017 KeePassXC team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "base32.h" + +Base32::Base32() +{ +} + +QByteArray Base32::base32_decode(const QByteArray encoded) +{ + QByteArray result; + + int buffer = 0; + int bitsLeft = 0; + + for (char ch : encoded) { + if (ch == 0 || ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '-' || ch == '=') { + continue; + } + + buffer <<= 5; + + // Deal with commonly mistyped characters + if (ch == '0') { + ch = 'O'; + } else if (ch == '1') { + ch = 'L'; + } else if (ch == '8') { + ch = 'B'; + } + + // Look up one base32 digit + if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { + ch = (ch & 0x1F) - 1; + } else if (ch >= '2' && ch <= '7') { + ch -= '2' - 26; + } else { + return QByteArray(); + } + + buffer |= ch; + bitsLeft += 5; + + if (bitsLeft >= 8) { + result.append(static_cast (buffer >> (bitsLeft - 8))); + bitsLeft -= 8; + } + } + + return result; +} \ No newline at end of file diff --git a/src/totp/base32.h b/src/totp/base32.h new file mode 100644 index 0000000000..75343fa43e --- /dev/null +++ b/src/totp/base32.h @@ -0,0 +1,34 @@ +// Base32 implementation +// Source: https://github.com/google/google-authenticator-libpam/blob/master/src/base32.h +// +// Copyright 2010 Google Inc. +// Author: Markus Gutschke +// Modifications Copyright 2017 KeePassXC team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BASE32_H +#define BASE32_H + +#include +#include + +class Base32 +{ +public: + Base32(); + static QByteArray base32_decode(const QByteArray encoded); +}; + + +#endif //BASE32_H diff --git a/src/totp/totp.cpp b/src/totp/totp.cpp new file mode 100644 index 0000000000..51af0e0861 --- /dev/null +++ b/src/totp/totp.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2017 Weslly Honorato <weslly@protonmail.com> + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "totp.h" +#include "base32.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +const quint8 QTotp::defaultStep = 30; +const quint8 QTotp::defaultDigits = 6; + +QTotp::QTotp() +{ +} + +QString QTotp::parseOtpString(QString key, quint8 &digits, quint8 &step) +{ + QUrl url(key); + + QString seed; + uint q_digits, q_step; + + // Default OTP url format + if (url.isValid() && url.scheme() == "otpauth") { + QUrlQuery query(url); + + seed = query.queryItemValue("secret"); + + q_digits = query.queryItemValue("digits").toUInt(); + if (q_digits == 6 || q_digits == 8) { + digits = q_digits; + } + + q_step = query.queryItemValue("period").toUInt(); + if (q_step > 0 && q_step <= 60) { + step = q_step; + } + + + } else { + // Compatibility with "KeeOtp" plugin string format + QRegExp rx("key=(.+)", Qt::CaseInsensitive, QRegExp::RegExp); + + if (rx.exactMatch(key)) { + QUrlQuery query(key); + + seed = query.queryItemValue("key"); + q_digits = query.queryItemValue("size").toUInt(); + if (q_digits == 6 || q_digits == 8) { + digits = q_digits; + } + + q_step = query.queryItemValue("step").toUInt(); + if (q_step > 0 && q_step <= 60) { + step = q_step; + } + + } else { + seed = key; + } + } + + if (digits == 0) { + digits = defaultDigits; + } + + if (step == 0) { + step = defaultStep; + } + + return seed; +} + +QString QTotp::generateTotp(const QByteArray key, quint64 time, + const quint8 numDigits = defaultDigits, const quint8 step = defaultStep) +{ + quint64 current = qToBigEndian(time / step); + + QByteArray secret = Base32::base32_decode(key); + if (secret.isEmpty()) { + return "Invalid TOTP secret key"; + } + + QMessageAuthenticationCode code(QCryptographicHash::Sha1); + code.setKey(secret); + code.addData(QByteArray(reinterpret_cast(¤t), sizeof(current))); + QByteArray hmac = code.result(); + + int offset = (hmac[hmac.length() - 1] & 0xf); + int binary = + ((hmac[offset] & 0x7f) << 24) + | ((hmac[offset + 1] & 0xff) << 16) + | ((hmac[offset + 2] & 0xff) << 8) + | (hmac[offset + 3] & 0xff); + + quint32 digitsPower = pow(10, numDigits); + + quint64 password = binary % digitsPower; + return QString("%1").arg(password, numDigits, 10, QChar('0')); +} diff --git a/src/gui/PasswordComboBox.h b/src/totp/totp.h similarity index 53% rename from src/gui/PasswordComboBox.h rename to src/totp/totp.h index 7c54e278b5..642b4f9a31 100644 --- a/src/gui/PasswordComboBox.h +++ b/src/totp/totp.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2013 Michael Curtis - * Copyright (C) 2014 Felix Geyer + * Copyright (C) 2017 Weslly Honorato <weslly@protonmail.com> + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,31 +16,19 @@ * along with this program. If not, see . */ -#ifndef KEEPASSX_PASSWORDCOMBOBOX_H -#define KEEPASSX_PASSWORDCOMBOBOX_H +#ifndef QTOTP_H +#define QTOTP_H -#include +#include -class PasswordGenerator; - -class PasswordComboBox : public QComboBox +class QTotp { - Q_OBJECT - public: - explicit PasswordComboBox(QWidget* parent = nullptr); - ~PasswordComboBox(); - - void setGenerator(PasswordGenerator* generator); - void setNumberAlternatives(int alternatives); - void showPopup(); - -public Q_SLOTS: - void setEcho(bool echo); - -private: - PasswordGenerator* m_generator; - int m_alternatives; + QTotp(); + static QString parseOtpString(QString rawSecret, quint8 &digits, quint8 &step); + static QString generateTotp(const QByteArray key, quint64 time, const quint8 numDigits, const quint8 step); + static const quint8 defaultStep; + static const quint8 defaultDigits; }; -#endif // KEEPASSX_PASSWORDCOMBOBOX_H +#endif // QTOTP_H diff --git a/src/zxcvbn/zxcvbn.cpp b/src/zxcvbn/zxcvbn.cpp index c999adfaeb..52c0bb1f3f 100644 --- a/src/zxcvbn/zxcvbn.cpp +++ b/src/zxcvbn/zxcvbn.cpp @@ -1,4 +1,4 @@ -/********************************************************************************** +/********************************************************************************** * C implementation of the zxcvbn password strength estimation method. * Copyright (c) 2015, Tony Evans * All rights reserved. diff --git a/src/zxcvbn/zxcvbn.h b/src/zxcvbn/zxcvbn.h index 2d3ec52c1a..796d6b47bf 100644 --- a/src/zxcvbn/zxcvbn.h +++ b/src/zxcvbn/zxcvbn.h @@ -1,4 +1,4 @@ -#ifndef ZXCVBN_H_F98183CE2A01_INCLUDED +#ifndef ZXCVBN_H_F98183CE2A01_INCLUDED #define ZXCVBN_H_F98183CE2A01_INCLUDED /********************************************************************************** * C implementation of the zxcvbn password strength estimation method. diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5840a5b4be..67661f55c0 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -100,6 +100,10 @@ set(testsupport_SOURCES modeltest.cpp FailDevice.cpp) add_library(testsupport STATIC ${testsupport_SOURCES}) target_link_libraries(testsupport ${MHD_LIBRARIES} Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Test) +if(YUBIKEY_FOUND) + set(TEST_LIBRARIES ${TEST_LIBRARIES} ${YUBIKEY_LIBRARIES}) +endif() + add_unit_test(NAME testgroup SOURCES TestGroup.cpp LIBS ${TEST_LIBRARIES}) @@ -154,6 +158,12 @@ endif() add_unit_test(NAME testentry SOURCES TestEntry.cpp LIBS ${TEST_LIBRARIES}) +add_unit_test(NAME testtotp SOURCES TestTotp.cpp + LIBS ${TEST_LIBRARIES}) + +add_unit_test(NAME testcsvparser SOURCES TestCsvParser.cpp + LIBS ${TEST_LIBRARIES}) + add_unit_test(NAME testrandom SOURCES TestRandom.cpp LIBS ${TEST_LIBRARIES}) @@ -166,6 +176,13 @@ add_unit_test(NAME testexporter SOURCES TestExporter.cpp add_unit_test(NAME testcsvexporter SOURCES TestCsvExporter.cpp LIBS ${TEST_LIBRARIES}) +add_unit_test(NAME testykchallengeresponsekey + SOURCES TestYkChallengeResponseKey.cpp TestYkChallengeResponseKey.h + LIBS ${TEST_LIBRARIES}) + +add_unit_test(NAME testdatabase SOURCES TestDatabase.cpp + LIBS ${TEST_LIBRARIES}) + if(WITH_GUI_TESTS) add_subdirectory(gui) endif(WITH_GUI_TESTS) diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp index c5c1a59330..be73efd475 100644 --- a/tests/TestAutoType.cpp +++ b/tests/TestAutoType.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -96,14 +97,20 @@ void TestAutoType::init() m_entry4->setPassword("custom_attr"); m_entry4->attributes()->set("CUSTOM","Attribute",false); association.window = "//^CustomAttr1$//"; - association.sequence = "{PASSWORD}:{CUSTOM}"; + association.sequence = "{PASSWORD}:{S:CUSTOM}"; m_entry4->autoTypeAssociations()->add(association); association.window = "//^CustomAttr2$//"; - association.sequence = "{CuStOm}"; + association.sequence = "{S:CuStOm}"; m_entry4->autoTypeAssociations()->add(association); association.window = "//^CustomAttr3$//"; association.sequence = "{PaSSworD}"; m_entry4->autoTypeAssociations()->add(association); + + m_entry5 = new Entry(); + m_entry5->setGroup(m_group); + m_entry5->setPassword("example5"); + m_entry5->setTitle("some title"); + m_entry5->setUrl("http://example.org"); } void TestAutoType::cleanup() @@ -172,6 +179,28 @@ void TestAutoType::testGlobalAutoTypeTitleMatch() QString("%1%2").arg(m_entry2->password(), m_test->keyToString(Qt::Key_Enter))); } +void TestAutoType::testGlobalAutoTypeUrlMatch() +{ + config()->set("AutoTypeEntryTitleMatch", true); + + m_test->setActiveWindowTitle("Dummy - http://example.org/ - "); + m_autoType->performGlobalAutoType(m_dbList); + + QCOMPARE(m_test->actionChars(), + QString("%1%2").arg(m_entry5->password(), m_test->keyToString(Qt::Key_Enter))); +} + +void TestAutoType::testGlobalAutoTypeUrlSubdomainMatch() +{ + config()->set("AutoTypeEntryTitleMatch", true); + + m_test->setActiveWindowTitle("Dummy - http://sub.example.org/ - "); + m_autoType->performGlobalAutoType(m_dbList); + + QCOMPARE(m_test->actionChars(), + QString("%1%2").arg(m_entry5->password(), m_test->keyToString(Qt::Key_Enter))); +} + void TestAutoType::testGlobalAutoTypeTitleMatchDisabled() { m_test->setActiveWindowTitle("An Entry Title!"); diff --git a/tests/TestAutoType.h b/tests/TestAutoType.h index c585fec257..0cd4a5bdd9 100644 --- a/tests/TestAutoType.h +++ b/tests/TestAutoType.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,7 +32,7 @@ class TestAutoType : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void init(); void cleanup(); @@ -42,6 +43,8 @@ private Q_SLOTS: void testGlobalAutoTypeWithNoMatch(); void testGlobalAutoTypeWithOneMatch(); void testGlobalAutoTypeTitleMatch(); + void testGlobalAutoTypeUrlMatch(); + void testGlobalAutoTypeUrlSubdomainMatch(); void testGlobalAutoTypeTitleMatchDisabled(); void testGlobalAutoTypeRegExp(); @@ -56,6 +59,7 @@ private Q_SLOTS: Entry* m_entry2; Entry* m_entry3; Entry* m_entry4; + Entry* m_entry5; }; #endif // KEEPASSX_TESTAUTOTYPE_H diff --git a/tests/TestCryptoHash.h b/tests/TestCryptoHash.h index 05700f3497..d31501baed 100644 --- a/tests/TestCryptoHash.h +++ b/tests/TestCryptoHash.h @@ -24,7 +24,7 @@ class TestCryptoHash : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void test(); }; diff --git a/tests/TestCsvExporter.h b/tests/TestCsvExporter.h index a8cfe7f257..39597f752f 100644 --- a/tests/TestCsvExporter.h +++ b/tests/TestCsvExporter.h @@ -31,7 +31,7 @@ class TestCsvExporter : public QObject public: static const QString ExpectedHeaderLine; -private Q_SLOTS: +private slots: void init(); void initTestCase(); void cleanup(); diff --git a/tests/TestCsvParser.cpp b/tests/TestCsvParser.cpp new file mode 100644 index 0000000000..57bc683a21 --- /dev/null +++ b/tests/TestCsvParser.cpp @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2015 Enrico Mariotti + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TestCsvParser.h" + +#include + +QTEST_GUILESS_MAIN(TestCsvParser) + +void TestCsvParser::initTestCase() +{ + parser = new CsvParser(); +} + +void TestCsvParser::cleanupTestCase() +{ + delete parser; +} + +void TestCsvParser::init() +{ + file = new QTemporaryFile(); + if (not file->open()) + QFAIL("Cannot open file!"); + parser->setBackslashSyntax(false); + parser->setComment('#'); + parser->setFieldSeparator(','); + parser->setTextQualifier(QChar('"')); +} + +void TestCsvParser::cleanup() +{ + file->remove(); +} + +/****************** TEST CASES ******************/ +void TestCsvParser::testMissingQuote() { + parser->setTextQualifier(':'); + QTextStream out(file); + out << "A,B\n:BM,1"; + QEXPECT_FAIL("", "Bad format", Continue); + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QWARN(parser->getStatus().toLatin1()); +} + +void TestCsvParser::testMalformed() { + parser->setTextQualifier(':'); + QTextStream out(file); + out << "A,B,C\n:BM::,1,:2:"; + QEXPECT_FAIL("", "Bad format", Continue); + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QWARN(parser->getStatus().toLatin1()); +} + +void TestCsvParser::testBackslashSyntax() { + parser->setBackslashSyntax(true); + parser->setTextQualifier(QChar('X')); + QTextStream out(file); + //attended result: one"\t\"wo + out << "Xone\\\"\\\\t\\\\\\\"w\noX\n" + << "X13X,X2\\X,X,\"\"3\"X\r" + << "3,X\"4\"X,,\n" + << "XX\n" + << "\\"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.at(0).at(0) == "one\"\\t\\\"w\no"); + QVERIFY(t.at(1).at(0) == "13"); + QVERIFY(t.at(1).at(1) == "2X,"); + QVERIFY(t.at(1).at(2) == "\"\"3\"X"); + QVERIFY(t.at(2).at(0) == "3"); + QVERIFY(t.at(2).at(1) == "\"4\""); + QVERIFY(t.at(2).at(2) == ""); + QVERIFY(t.at(2).at(3) == ""); + QVERIFY(t.at(3).at(0) == "\\"); + QVERIFY(t.size() == 4); +} + +void TestCsvParser::testQuoted() { + QTextStream out(file); + out << "ro,w,\"end, of \"\"\"\"\"\"row\"\"\"\"\"\n" + << "2\n"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.at(0).at(0) == "ro"); + QVERIFY(t.at(0).at(1) == "w"); + QVERIFY(t.at(0).at(2) == "end, of \"\"\"row\"\""); + QVERIFY(t.at(1).at(0) == "2"); + QVERIFY(t.size() == 2); +} + +void TestCsvParser::testEmptySimple() { + QTextStream out(file); + out <<""; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 0); +} + +void TestCsvParser::testEmptyQuoted() { + QTextStream out(file); + out <<"\"\""; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 0); +} + +void TestCsvParser::testEmptyNewline() { + QTextStream out(file); + out <<"\"\n\""; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 0); +} + +void TestCsvParser::testEmptyFile() +{ + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 0); +} + +void TestCsvParser::testNewline() +{ + QTextStream out(file); + out << "1,2\n\n\n"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 1); + QVERIFY(t.at(0).at(0) == "1"); + QVERIFY(t.at(0).at(1) == "2"); +} + +void TestCsvParser::testCR() +{ + QTextStream out(file); + out << "1,2\r3,4"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 2); + QVERIFY(t.at(0).at(0) == "1"); + QVERIFY(t.at(0).at(1) == "2"); + QVERIFY(t.at(1).at(0) == "3"); + QVERIFY(t.at(1).at(1) == "4"); +} + +void TestCsvParser::testLF() +{ + QTextStream out(file); + out << "1,2\n3,4"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 2); + QVERIFY(t.at(0).at(0) == "1"); + QVERIFY(t.at(0).at(1) == "2"); + QVERIFY(t.at(1).at(0) == "3"); + QVERIFY(t.at(1).at(1) == "4"); +} + +void TestCsvParser::testCRLF() +{ + QTextStream out(file); + out << "1,2\r\n3,4"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 2); + QVERIFY(t.at(0).at(0) == "1"); + QVERIFY(t.at(0).at(1) == "2"); + QVERIFY(t.at(1).at(0) == "3"); + QVERIFY(t.at(1).at(1) == "4"); +} + +void TestCsvParser::testComments() +{ + QTextStream out(file); + out << " #one\n" + << " \t # two, three \r\n" + << " #, sing\t with\r" + << " #\t me!\n" + << "useful,text #1!"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 1); + QVERIFY(t.at(0).at(0) == "useful"); + QVERIFY(t.at(0).at(1) == "text #1!"); +} + +void TestCsvParser::testColumns() { + QTextStream out(file); + out << "1,2\n" + << ",,,,,,,,,a\n" + << "a,b,c,d\n"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(parser->getCsvCols() == 10); +} + +void TestCsvParser::testSimple() { + QTextStream out(file); + out << ",,2\r,2,3\n" + << "A,,B\"\n" + << " ,,\n"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 4); + QVERIFY(t.at(0).at(0) == ""); + QVERIFY(t.at(0).at(1) == ""); + QVERIFY(t.at(0).at(2) == "2"); + QVERIFY(t.at(1).at(0) == ""); + QVERIFY(t.at(1).at(1) == "2"); + QVERIFY(t.at(1).at(2) == "3"); + QVERIFY(t.at(2).at(0) == "A"); + QVERIFY(t.at(2).at(1) == ""); + QVERIFY(t.at(2).at(2) == "B\""); + QVERIFY(t.at(3).at(0) == " "); + QVERIFY(t.at(3).at(1) == ""); + QVERIFY(t.at(3).at(2) == ""); +} + +void TestCsvParser::testSeparator() { + parser->setFieldSeparator('\t'); + QTextStream out(file); + out << "\t\t2\r\t2\t3\n" + << "A\t\tB\"\n" + << " \t\t\n"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 4); + QVERIFY(t.at(0).at(0) == ""); + QVERIFY(t.at(0).at(1) == ""); + QVERIFY(t.at(0).at(2) == "2"); + QVERIFY(t.at(1).at(0) == ""); + QVERIFY(t.at(1).at(1) == "2"); + QVERIFY(t.at(1).at(2) == "3"); + QVERIFY(t.at(2).at(0) == "A"); + QVERIFY(t.at(2).at(1) == ""); + QVERIFY(t.at(2).at(2) == "B\""); + QVERIFY(t.at(3).at(0) == " "); + QVERIFY(t.at(3).at(1) == ""); + QVERIFY(t.at(3).at(2) == ""); +} + +void TestCsvParser::testMultiline() +{ + parser->setTextQualifier(QChar(':')); + QTextStream out(file); + out << ":1\r\n2a::b:,:3\r4:\n" + << "2\n"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.at(0).at(0) == "1\n2a:b"); + QVERIFY(t.at(0).at(1) == "3\n4"); + QVERIFY(t.at(1).at(0) == "2"); + QVERIFY(t.size() == 2); +} + +void TestCsvParser::testEmptyReparsing() +{ + parser->parse(nullptr); + QVERIFY(parser->reparse()); + t = parser->getCsvTable(); + QVERIFY(t.size() == 0); +} + +void TestCsvParser::testReparsing() +{ + QTextStream out(file); + out << ":te\r\nxt1:,:te\rxt2:,:end of \"this\n string\":\n" + << "2\n"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + + QEXPECT_FAIL("", "Wrong qualifier", Continue); + QVERIFY(t.at(0).at(0) == "te\nxt1"); + + parser->setTextQualifier(QChar(':')); + + QVERIFY(parser->reparse()); + t = parser->getCsvTable(); + QVERIFY(t.at(0).at(0) == "te\nxt1"); + QVERIFY(t.at(0).at(1) == "te\nxt2"); + QVERIFY(t.at(0).at(2) == "end of \"this\n string\""); + QVERIFY(t.at(1).at(0) == "2"); + QVERIFY(t.size() == 2); +} + +void TestCsvParser::testQualifier() { + parser->setTextQualifier(QChar('X')); + QTextStream out(file); + out << "X1X,X2XX,X,\"\"3\"\"\"X\r" + << "3,X\"4\"X,,\n"; + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 2); + QVERIFY(t.at(0).at(0) == "1"); + QVERIFY(t.at(0).at(1) == "2X,"); + QVERIFY(t.at(0).at(2) == "\"\"3\"\"\"X"); + QVERIFY(t.at(1).at(0) == "3"); + QVERIFY(t.at(1).at(1) == "\"4\""); + QVERIFY(t.at(1).at(2) == ""); + QVERIFY(t.at(1).at(3) == ""); +} + +void TestCsvParser::testUnicode() { + //QString m("Texte en fran\u00e7ais"); + //CORRECT QString g("\u20AC"); + //CORRECT QChar g(0x20AC); + //ERROR QChar g("\u20AC"); + parser->setFieldSeparator(QChar('A')); + QTextStream out(file); + out << QString("€1A2śA\"3śAż\"Ażac"); + + QVERIFY(parser->parse(file)); + t = parser->getCsvTable(); + QVERIFY(t.size() == 1); + QVERIFY(t.at(0).at(0) == "€1"); + QVERIFY(t.at(0).at(1) == "2ś"); + QVERIFY(t.at(0).at(2) == "3śAż"); + QVERIFY(t.at(0).at(3) == "żac"); +} diff --git a/tests/TestCsvParser.h b/tests/TestCsvParser.h new file mode 100644 index 0000000000..0cf8b94d36 --- /dev/null +++ b/tests/TestCsvParser.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2015 Enrico Mariotti + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_TESTCSVPARSER_H +#define KEEPASSX_TESTCSVPARSER_H + +#include +#include +#include + +#include "core/CsvParser.h" + +class CsvParser; + +class TestCsvParser : public QObject +{ + Q_OBJECT + +public: + +private slots: + void init(); + void cleanup(); + void initTestCase(); + void cleanupTestCase(); + + void testUnicode(); + void testLF(); + void testEmptyReparsing(); + void testSimple(); + void testEmptyQuoted(); + void testEmptyNewline(); + void testSeparator(); + void testCR(); + void testCRLF(); + void testMalformed(); + void testQualifier(); + void testNewline(); + void testEmptySimple(); + void testMissingQuote(); + void testComments(); + void testBackslashSyntax(); + void testReparsing(); + void testEmptyFile(); + void testQuoted(); + void testMultiline(); + void testColumns(); + +private: + QTemporaryFile* file; + CsvParser* parser; + CsvTable t; + void dumpRow(CsvTable table, int row); +}; + +#endif // KEEPASSX_TESTCSVPARSER_H diff --git a/tests/TestDatabase.cpp b/tests/TestDatabase.cpp new file mode 100644 index 0000000000..284ba4bfb3 --- /dev/null +++ b/tests/TestDatabase.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2017 Vladimir Svyatski + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TestDatabase.h" + +#include +#include +#include + +#include "config-keepassx-tests.h" +#include "core/Database.h" +#include "crypto/Crypto.h" +#include "keys/PasswordKey.h" +#include "core/Metadata.h" +#include "core/Group.h" +#include "format/KeePass2Writer.h" + +QTEST_GUILESS_MAIN(TestDatabase) + +void TestDatabase::initTestCase() +{ + QVERIFY(Crypto::init()); +} + +void TestDatabase::testEmptyRecycleBinOnDisabled() +{ + QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/RecycleBinDisabled.kdbx"); + CompositeKey key; + key.addKey(PasswordKey("123")); + Database* db = Database::openDatabaseFile(filename, key); + QVERIFY(db); + + QSignalSpy spyModified(db, SIGNAL(modifiedImmediate())); + + db->emptyRecycleBin(); + //The database must be unmodified in this test after emptying the recycle bin. + QCOMPARE(spyModified.count(), 0); + + delete db; +} + +void TestDatabase::testEmptyRecycleBinOnNotCreated() +{ + QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/RecycleBinNotYetCreated.kdbx"); + CompositeKey key; + key.addKey(PasswordKey("123")); + Database* db = Database::openDatabaseFile(filename, key); + QVERIFY(db); + + QSignalSpy spyModified(db, SIGNAL(modifiedImmediate())); + + db->emptyRecycleBin(); + //The database must be unmodified in this test after emptying the recycle bin. + QCOMPARE(spyModified.count(), 0); + + delete db; +} + +void TestDatabase::testEmptyRecycleBinOnEmpty() +{ + QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/RecycleBinEmpty.kdbx"); + CompositeKey key; + key.addKey(PasswordKey("123")); + Database* db = Database::openDatabaseFile(filename, key); + QVERIFY(db); + + QSignalSpy spyModified(db, SIGNAL(modifiedImmediate())); + + db->emptyRecycleBin(); + //The database must be unmodified in this test after emptying the recycle bin. + QCOMPARE(spyModified.count(), 0); + + delete db; +} + +void TestDatabase::testEmptyRecycleBinWithHierarchicalData() +{ + QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/RecycleBinWithData.kdbx"); + CompositeKey key; + key.addKey(PasswordKey("123")); + Database* db = Database::openDatabaseFile(filename, key); + QVERIFY(db); + + QFile originalFile(filename); + qint64 initialSize = originalFile.size(); + + db->emptyRecycleBin(); + QVERIFY(db->metadata()->recycleBin()); + QVERIFY(db->metadata()->recycleBin()->entries().empty()); + QVERIFY(db->metadata()->recycleBin()->children().empty()); + + QTemporaryFile afterCleanup; + KeePass2Writer writer; + writer.writeDatabase(&afterCleanup, db); + QVERIFY(afterCleanup.size() < initialSize); + + delete db; +} diff --git a/tests/TestDatabase.h b/tests/TestDatabase.h new file mode 100644 index 0000000000..46deb58aae --- /dev/null +++ b/tests/TestDatabase.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2017 Vladimir Svyatski + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_TESTDATABASE_H +#define KEEPASSX_TESTDATABASE_H + +#include + +class TestDatabase : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void testEmptyRecycleBinOnDisabled(); + void testEmptyRecycleBinOnNotCreated(); + void testEmptyRecycleBinOnEmpty(); + void testEmptyRecycleBinWithHierarchicalData(); +}; + +#endif // KEEPASSX_TESTDATABASE_H diff --git a/tests/TestDeletedObjects.h b/tests/TestDeletedObjects.h index 27b70cced7..d96452093b 100644 --- a/tests/TestDeletedObjects.h +++ b/tests/TestDeletedObjects.h @@ -29,7 +29,7 @@ class TestDeletedObjects : public QObject private: void createAndDelete(Database* db, int delObjectsSize); -private Q_SLOTS: +private slots: void initTestCase(); void testDeletedObjectsFromFile(); void testDeletedObjectsFromNewDb(); diff --git a/tests/TestEntry.h b/tests/TestEntry.h index ed772d505f..0c97c0b9d6 100644 --- a/tests/TestEntry.h +++ b/tests/TestEntry.h @@ -26,7 +26,7 @@ class TestEntry : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testHistoryItemDeletion(); void testCopyDataFrom(); diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp index d5a16ebab5..e0c8bb490e 100644 --- a/tests/TestEntryModel.cpp +++ b/tests/TestEntryModel.cpp @@ -181,6 +181,12 @@ void TestEntryModel::testAttributesModel() QCOMPARE(spyAboutToRemove.count(), 1); QCOMPARE(spyRemoved.count(), 1); + // test attribute protection + QString value = entryAttributes->value("2nd"); + entryAttributes->set("2nd", value, true); + QVERIFY(entryAttributes->isProtected("2nd")); + QCOMPARE(entryAttributes->value("2nd"), value); + QSignalSpy spyReset(model, SIGNAL(modelReset())); entryAttributes->clear(); model->setEntryAttributes(0); diff --git a/tests/TestEntryModel.h b/tests/TestEntryModel.h index 778392f20e..df80331e86 100644 --- a/tests/TestEntryModel.h +++ b/tests/TestEntryModel.h @@ -24,7 +24,7 @@ class TestEntryModel : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void test(); void testAttachmentsModel(); diff --git a/tests/TestEntrySearcher.h b/tests/TestEntrySearcher.h index 7c45451dc8..3965c22e03 100644 --- a/tests/TestEntrySearcher.h +++ b/tests/TestEntrySearcher.h @@ -28,7 +28,7 @@ class TestEntrySearcher : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void cleanupTestCase(); diff --git a/tests/TestExporter.h b/tests/TestExporter.h index 15f9a7c33f..8c99452528 100644 --- a/tests/TestExporter.h +++ b/tests/TestExporter.h @@ -25,7 +25,7 @@ class TestExporter : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testToDbExporter(); }; diff --git a/tests/TestGroup.cpp b/tests/TestGroup.cpp index e87e6cedce..50997dcca1 100644 --- a/tests/TestGroup.cpp +++ b/tests/TestGroup.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -567,3 +568,189 @@ Database* TestGroup::createMergeTestDatabase() return db; } + +void TestGroup::testFindEntry() +{ + Database* db = new Database(); + + Entry* entry1 = new Entry(); + entry1->setTitle(QString("entry1")); + entry1->setGroup(db->rootGroup()); + entry1->setUuid(Uuid::random()); + + Group* group1 = new Group(); + group1->setName("group1"); + + Entry* entry2 = new Entry(); + + entry2->setTitle(QString("entry2")); + entry2->setGroup(group1); + entry2->setUuid(Uuid::random()); + + group1->setParent(db->rootGroup()); + + Entry* entry; + + entry = db->rootGroup()->findEntry(entry1->uuid().toHex()); + QVERIFY(entry != nullptr); + QCOMPARE(entry->title(), QString("entry1")); + + entry = db->rootGroup()->findEntry(QString("entry1")); + QVERIFY(entry != nullptr); + QCOMPARE(entry->title(), QString("entry1")); + + // We also can find the entry with the leading slash. + entry = db->rootGroup()->findEntry(QString("/entry1")); + QVERIFY(entry != nullptr); + QCOMPARE(entry->title(), QString("entry1")); + + // But two slashes should not be accepted. + entry = db->rootGroup()->findEntry(QString("//entry1")); + QVERIFY(entry == nullptr); + + entry = db->rootGroup()->findEntry(entry2->uuid().toHex()); + QVERIFY(entry != nullptr); + QCOMPARE(entry->title(), QString("entry2")); + + entry = db->rootGroup()->findEntry(QString("group1/entry2")); + QVERIFY(entry != nullptr); + QCOMPARE(entry->title(), QString("entry2")); + + entry = db->rootGroup()->findEntry(QString("/entry2")); + QVERIFY(entry == nullptr); + + // We also can find the entry with the leading slash. + entry = db->rootGroup()->findEntry(QString("/group1/entry2")); + QVERIFY(entry != nullptr); + QCOMPARE(entry->title(), QString("entry2")); + + // Should also find the entry only by title. + entry = db->rootGroup()->findEntry(QString("entry2")); + QVERIFY(entry != nullptr); + QCOMPARE(entry->title(), QString("entry2")); + + entry = db->rootGroup()->findEntry(QString("invalid/path/to/entry2")); + QVERIFY(entry == nullptr); + + entry = db->rootGroup()->findEntry(QString("entry27")); + QVERIFY(entry == nullptr); + + // A valid UUID that does not exist in this database. + entry = db->rootGroup()->findEntry(QString("febfb01ebcdf9dbd90a3f1579dc75281")); + QVERIFY(entry == nullptr); + + // An invalid UUID. + entry = db->rootGroup()->findEntry(QString("febfb01ebcdf9dbd90a3f1579dc")); + QVERIFY(entry == nullptr); + + delete db; +} + +void TestGroup::testFindGroupByPath() +{ + Database* db = new Database(); + + Group* group1 = new Group(); + group1->setName("group1"); + group1->setParent(db->rootGroup()); + + Group* group2 = new Group(); + group2->setName("group2"); + group2->setParent(group1); + + Group* group; + + group = db->rootGroup()->findGroupByPath("/"); + QVERIFY(group != nullptr); + QCOMPARE(group->uuid(), db->rootGroup()->uuid()); + + // We also accept it if the leading slash is missing. + group = db->rootGroup()->findGroupByPath(""); + QVERIFY(group != nullptr); + QCOMPARE(group->uuid(), db->rootGroup()->uuid()); + + group = db->rootGroup()->findGroupByPath("/group1/"); + QVERIFY(group != nullptr); + QCOMPARE(group->uuid(), group1->uuid()); + + // We also accept it if the leading slash is missing. + group = db->rootGroup()->findGroupByPath("group1/"); + QVERIFY(group != nullptr); + QCOMPARE(group->uuid(), group1->uuid()); + + // Too many slashes at the end + group = db->rootGroup()->findGroupByPath("group1//"); + QVERIFY(group == nullptr); + + // Missing a slash at the end. + group = db->rootGroup()->findGroupByPath("/group1"); + QVERIFY(group != nullptr); + QCOMPARE(group->uuid(), group1->uuid()); + + // Too many slashes at the start + group = db->rootGroup()->findGroupByPath("//group1"); + QVERIFY(group == nullptr); + + group = db->rootGroup()->findGroupByPath("/group1/group2/"); + QVERIFY(group != nullptr); + QCOMPARE(group->uuid(), group2->uuid()); + + // We also accept it if the leading slash is missing. + group = db->rootGroup()->findGroupByPath("group1/group2/"); + QVERIFY(group != nullptr); + QCOMPARE(group->uuid(), group2->uuid()); + + group = db->rootGroup()->findGroupByPath("group1/group2"); + QVERIFY(group != nullptr); + QCOMPARE(group->uuid(), group2->uuid()); + + group = db->rootGroup()->findGroupByPath("invalid"); + QVERIFY(group == nullptr); + + delete db; +} + +void TestGroup::testPrint() +{ + Database* db = new Database(); + + QString output = db->rootGroup()->print(); + QCOMPARE(output, QString("[empty]\n")); + + output = db->rootGroup()->print(true); + QCOMPARE(output, QString("[empty]\n")); + + Entry* entry1 = new Entry(); + entry1->setTitle(QString("entry1")); + entry1->setGroup(db->rootGroup()); + entry1->setUuid(Uuid::random()); + + output = db->rootGroup()->print(); + QCOMPARE(output, QString("entry1\n")); + + output = db->rootGroup()->print(true); + QCOMPARE(output, QString("entry1 " + entry1->uuid().toHex() + "\n")); + + + Group* group1 = new Group(); + group1->setName("group1"); + + Entry* entry2 = new Entry(); + + entry2->setTitle(QString("entry2")); + entry2->setGroup(group1); + entry2->setUuid(Uuid::random()); + + group1->setParent(db->rootGroup()); + + output = db->rootGroup()->print(); + QVERIFY(output.contains(QString("entry1\n"))); + QVERIFY(output.contains(QString("group1/\n"))); + QVERIFY(output.contains(QString(" entry2\n"))); + + output = db->rootGroup()->print(true); + QVERIFY(output.contains(QString("entry1 " + entry1->uuid().toHex() + "\n"))); + QVERIFY(output.contains(QString("group1/ " + group1->uuid().toHex() + "\n"))); + QVERIFY(output.contains(QString(" entry2 " + entry2->uuid().toHex() + "\n"))); + delete db; +} diff --git a/tests/TestGroup.h b/tests/TestGroup.h index 4a891ae6f2..16bb42acdc 100644 --- a/tests/TestGroup.h +++ b/tests/TestGroup.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +26,7 @@ class TestGroup : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testParenting(); void testSignals(); @@ -38,6 +39,9 @@ private Q_SLOTS: void testMergeConflict(); void testMergeDatabase(); void testMergeConflictKeepBoth(); + void testFindEntry(); + void testFindGroupByPath(); + void testPrint(); private: Database* createMergeTestDatabase(); diff --git a/tests/TestGroupModel.cpp b/tests/TestGroupModel.cpp index 3608cc4757..1faf82aa2f 100644 --- a/tests/TestGroupModel.cpp +++ b/tests/TestGroupModel.cpp @@ -131,7 +131,7 @@ void TestGroupModel::test() QCOMPARE(spyMoved.count(), 3); QVERIFY(index12.isValid()); QCOMPARE(model->data(index12).toString(), QString("group12")); - QCOMPARE(model->data(index12.child(0, 0)).toString(), QString("group121")); + QCOMPARE(model->data(index12.model()->index(0, 0, index12)).toString(), QString("group121")); delete group12; QCOMPARE(spyAboutToAdd.count(), 1); diff --git a/tests/TestGroupModel.h b/tests/TestGroupModel.h index 093af9e0ff..1b5c0ab464 100644 --- a/tests/TestGroupModel.h +++ b/tests/TestGroupModel.h @@ -24,7 +24,7 @@ class TestGroupModel : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void test(); }; diff --git a/tests/TestHashedBlockStream.h b/tests/TestHashedBlockStream.h index 9aeac14118..6c36f8e6a7 100644 --- a/tests/TestHashedBlockStream.h +++ b/tests/TestHashedBlockStream.h @@ -24,7 +24,7 @@ class TestHashedBlockStream : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testWriteRead(); void testReset(); diff --git a/tests/TestKeePass1Reader.h b/tests/TestKeePass1Reader.h index 20acd4bb9e..9a5ab9e49c 100644 --- a/tests/TestKeePass1Reader.h +++ b/tests/TestKeePass1Reader.h @@ -27,7 +27,7 @@ class TestKeePass1Reader : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testBasic(); void testMasterKey(); diff --git a/tests/TestKeePass2RandomStream.h b/tests/TestKeePass2RandomStream.h index b001a05a22..967ed9c9e1 100644 --- a/tests/TestKeePass2RandomStream.h +++ b/tests/TestKeePass2RandomStream.h @@ -24,7 +24,7 @@ class TestKeePass2RandomStream : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void test(); }; diff --git a/tests/TestKeePass2Reader.h b/tests/TestKeePass2Reader.h index 6f090de38a..76ffe0297f 100644 --- a/tests/TestKeePass2Reader.h +++ b/tests/TestKeePass2Reader.h @@ -24,7 +24,7 @@ class TestKeePass2Reader : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testNonAscii(); void testCompressed(); diff --git a/tests/TestKeePass2Writer.h b/tests/TestKeePass2Writer.h index 8228838230..36a51dce6a 100644 --- a/tests/TestKeePass2Writer.h +++ b/tests/TestKeePass2Writer.h @@ -26,7 +26,7 @@ class TestKeePass2Writer : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testBasic(); void testProtectedAttributes(); diff --git a/tests/TestKeePass2XmlReader.h b/tests/TestKeePass2XmlReader.h index ff83e25978..628964b46d 100644 --- a/tests/TestKeePass2XmlReader.h +++ b/tests/TestKeePass2XmlReader.h @@ -27,7 +27,7 @@ class TestKeePass2XmlReader : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testMetadata(); void testCustomIcons(); diff --git a/tests/TestKeys.cpp b/tests/TestKeys.cpp index d5b35b1fb5..dea0436f0f 100644 --- a/tests/TestKeys.cpp +++ b/tests/TestKeys.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tests/TestKeys.h b/tests/TestKeys.h index a6d0b7e1a4..06ed3b0a12 100644 --- a/tests/TestKeys.h +++ b/tests/TestKeys.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +25,7 @@ class TestKeys : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testComposite(); void testCompositeKeyReadFromLine(); diff --git a/tests/TestModified.h b/tests/TestModified.h index ee598addff..518bea7c02 100644 --- a/tests/TestModified.h +++ b/tests/TestModified.h @@ -24,7 +24,7 @@ class TestModified : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testSignals(); void testGroupSets(); diff --git a/tests/TestRandom.h b/tests/TestRandom.h index c879f94501..323d6b6139 100644 --- a/tests/TestRandom.h +++ b/tests/TestRandom.h @@ -38,7 +38,7 @@ class TestRandom : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testUInt(); void testUIntRange(); diff --git a/tests/TestSymmetricCipher.cpp b/tests/TestSymmetricCipher.cpp index 698ecb204c..4f78693d6f 100644 --- a/tests/TestSymmetricCipher.cpp +++ b/tests/TestSymmetricCipher.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -123,6 +124,127 @@ void TestSymmetricCipher::testAes256CbcDecryption() plainText); } +void TestSymmetricCipher::testTwofish256CbcEncryption() +{ + // NIST MCT Known-Answer Tests (cbc_e_m.txt) + // https://www.schneier.com/code/twofish-kat.zip + + QVector keys { + QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000"), + QByteArray::fromHex("D0A260EB41755B19374BABF259A79DB3EA7162E65490B03B1AE4871FB35EF23B"), + QByteArray::fromHex("8D55E4849A4DED08D89881E6708EDD26BEEE942073DFB3790B2798B240ACD74A"), + QByteArray::fromHex("606EFDC2066A837AF0430EBE4CF1F21071CCB236C33B4B9D82404FDB05C74621"), + QByteArray::fromHex("B119AA9485CEEEB4CC778AF21121E54DE4BDBA3498C61C8FD9004AA0C71909C3") + }; + QVector ivs { + QByteArray::fromHex("00000000000000000000000000000000"), + QByteArray::fromHex("EA7162E65490B03B1AE4871FB35EF23B"), + QByteArray::fromHex("549FF6C6274F034211C31FADF3F22571"), + QByteArray::fromHex("CF222616B0E4F8E48967D769456B916B"), + QByteArray::fromHex("957108025BFD57125B40057BC2DE4FE2") + }; + QVector plainTexts { + QByteArray::fromHex("00000000000000000000000000000000"), + QByteArray::fromHex("D0A260EB41755B19374BABF259A79DB3"), + QByteArray::fromHex("5DF7846FDB38B611EFD32A1429294095"), + QByteArray::fromHex("ED3B19469C276E7228DB8F583C7F2F36"), + QByteArray::fromHex("D177575683A46DCE3C34844C5DD0175D") + }; + QVector cipherTexts { + QByteArray::fromHex("EA7162E65490B03B1AE4871FB35EF23B"), + QByteArray::fromHex("549FF6C6274F034211C31FADF3F22571"), + QByteArray::fromHex("CF222616B0E4F8E48967D769456B916B"), + QByteArray::fromHex("957108025BFD57125B40057BC2DE4FE2"), + QByteArray::fromHex("6F725C5950133F82EF021A94CADC8508") + }; + + SymmetricCipher cipher(SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Encrypt); + bool ok; + + for (int i = 0; i < keys.size(); ++i) { + cipher.init(keys[i], ivs[i]); + QByteArray ptNext = plainTexts[i]; + QByteArray ctPrev = ivs[i]; + QByteArray ctCur; + QCOMPARE(cipher.blockSize(), 16); + for (int j = 0; j < 5000; ++j) { + ctCur = cipher.process(ptNext, &ok); + if (!ok) + break; + ptNext = ctPrev; + ctPrev = ctCur; + + ctCur = cipher.process(ptNext, &ok); + if (!ok) + break; + ptNext = ctPrev; + ctPrev = ctCur; + } + + QVERIFY(ok); + QCOMPARE(ctCur, cipherTexts[i]); + } +} + +void TestSymmetricCipher::testTwofish256CbcDecryption() +{ + // NIST MCT Known-Answer Tests (cbc_d_m.txt) + // https://www.schneier.com/code/twofish-kat.zip + + QVector keys { + QByteArray::fromHex("0000000000000000000000000000000000000000000000000000000000000000"), + QByteArray::fromHex("1B1FE8F5A911CD4C0D800EDCE8ED0A942CBA6271A1044F90C30BA8FE91E1C163"), + QByteArray::fromHex("EBA31FF8D2A24FDD769A937353E23257294A33394E4D17A668060AD8230811A1"), + QByteArray::fromHex("1DCF1915C389AB273F80F897BF008F058ED89F58A95C1BE523C4B11295ED2D0F"), + QByteArray::fromHex("491B9A66D3ED4EF19F02180289D5B1A1C2596AE568540A95DC5244198A9B8869") + }; + QVector ivs { + QByteArray::fromHex("00000000000000000000000000000000"), + QByteArray::fromHex("1B1FE8F5A911CD4C0D800EDCE8ED0A94"), + QByteArray::fromHex("F0BCF70D7BB382917B1A9DAFBB0F38C3"), + QByteArray::fromHex("F66C06ED112BE4FA491A6BE4ECE2BD52"), + QByteArray::fromHex("54D483731064E5D6A082E09536D53EA4") + }; + QVector plainTexts { + QByteArray::fromHex("2CBA6271A1044F90C30BA8FE91E1C163"), + QByteArray::fromHex("05F05148EF495836AB0DA226B2E9D0C2"), + QByteArray::fromHex("A792AC61E7110C434BC2BBCAB6E53CAE"), + QByteArray::fromHex("4C81F5BDC1081170FF96F50B1F76A566"), + QByteArray::fromHex("BD959F5B787037631A37051EA5F369F8") + }; + QVector cipherTexts { + QByteArray::fromHex("00000000000000000000000000000000"), + QByteArray::fromHex("2CBA6271A1044F90C30BA8FE91E1C163"), + QByteArray::fromHex("05F05148EF495836AB0DA226B2E9D0C2"), + QByteArray::fromHex("A792AC61E7110C434BC2BBCAB6E53CAE"), + QByteArray::fromHex("4C81F5BDC1081170FF96F50B1F76A566") + }; + + SymmetricCipher cipher(SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Decrypt); + bool ok; + + for (int i = 0; i < keys.size(); ++i) { + cipher.init(keys[i], ivs[i]); + QByteArray ctNext = cipherTexts[i]; + QByteArray ptCur; + QCOMPARE(cipher.blockSize(), 16); + for (int j = 0; j < 5000; ++j) { + ptCur = cipher.process(ctNext, &ok); + if (!ok) + break; + ctNext = ptCur; + + ptCur = cipher.process(ctNext, &ok); + if (!ok) + break; + ctNext = ptCur; + } + + QVERIFY(ok); + QCOMPARE(ptCur, plainTexts[i]); + } +} + void TestSymmetricCipher::testSalsa20() { // http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/verified.test-vectors?logsort=rev&rev=210&view=markup diff --git a/tests/TestSymmetricCipher.h b/tests/TestSymmetricCipher.h index 1ac45793f1..0099895000 100644 --- a/tests/TestSymmetricCipher.h +++ b/tests/TestSymmetricCipher.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,10 +25,12 @@ class TestSymmetricCipher : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testAes256CbcEncryption(); void testAes256CbcDecryption(); + void testTwofish256CbcEncryption(); + void testTwofish256CbcDecryption(); void testSalsa20(); void testPadding(); void testStreamReset(); diff --git a/tests/TestTotp.cpp b/tests/TestTotp.cpp new file mode 100644 index 0000000000..e22c2567ea --- /dev/null +++ b/tests/TestTotp.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2017 Weslly Honorato <weslly@protonmail.com> + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TestTotp.h" + +#include +#include +#include +#include +#include + +#include "crypto/Crypto.h" +#include "totp/totp.h" +#include "totp/base32.h" + +QTEST_GUILESS_MAIN(TestTotp) + +void TestTotp::initTestCase() +{ + QVERIFY(Crypto::init()); +} + + +void TestTotp::testParseSecret() +{ + quint8 digits = 0; + quint8 step = 0; + QString secret = "otpauth://totp/ACME%20Co:john@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30"; + QCOMPARE(QTotp::parseOtpString(secret, digits, step), QString("HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ")); + QCOMPARE(digits, quint8(6)); + QCOMPARE(step, quint8(30)); + + digits = QTotp::defaultDigits; + step = QTotp::defaultStep; + secret = "key=HXDMVJECJJWSRBY%3d&step=25&size=8"; + QCOMPARE(QTotp::parseOtpString(secret, digits, step), QString("HXDMVJECJJWSRBY=")); + QCOMPARE(digits, quint8(8)); + QCOMPARE(step, quint8(25)); + + digits = 0; + step = 0; + secret = "gezdgnbvgy3tqojqgezdgnbvgy3tqojq"; + QCOMPARE(QTotp::parseOtpString(secret, digits, step), QString("gezdgnbvgy3tqojqgezdgnbvgy3tqojq")); + QCOMPARE(digits, quint8(6)); + QCOMPARE(step, quint8(30)); +} + +void TestTotp::testBase32() +{ + QByteArray key = QString("JBSW Y3DP EB3W 64TM MQXC 4LQA").toLatin1(); + QByteArray secret = Base32::base32_decode(key); + QCOMPARE(QString::fromLatin1(secret), QString("Hello world...")); + + key = QString("gezdgnbvgy3tqojqgezdgnbvgy3tqojq").toLatin1(); + secret = Base32::base32_decode(key); + QCOMPARE(QString::fromLatin1(secret), QString("12345678901234567890")); + + key = QString("ORSXG5A=").toLatin1(); + secret = Base32::base32_decode(key); + QCOMPARE(QString::fromLatin1(secret), QString("test")); + + key = QString("MZXW6YTBOI======").toLatin1(); + secret = Base32::base32_decode(key); + QCOMPARE(QString::fromLatin1(secret), QString("foobar")); +} + +void TestTotp::testTotpCode() +{ + // Test vectors from RFC 6238 + // https://tools.ietf.org/html/rfc6238#appendix-B + + QByteArray seed = QString("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ").toLatin1(); + + quint64 time = 1234567890; + QString output = QTotp::generateTotp(seed, time, 6, 30); + QCOMPARE(output, QString("005924")); + + time = 1111111109; + output = QTotp::generateTotp(seed, time, 6, 30); + QCOMPARE(output, QString("081804")); + + time = 1111111111; + output = QTotp::generateTotp(seed, time, 8, 30); + QCOMPARE(output, QString("14050471")); + + time = 2000000000; + output = QTotp::generateTotp(seed, time, 8, 30); + QCOMPARE(output, QString("69279037")); +} diff --git a/tests/TestTotp.h b/tests/TestTotp.h new file mode 100644 index 0000000000..d197294dd3 --- /dev/null +++ b/tests/TestTotp.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017 Weslly Honorato <weslly@protonmail.com> + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_TESTTOTP_H +#define KEEPASSX_TESTTOTP_H + +#include + +class Totp; + +class TestTotp : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void testParseSecret(); + void testBase32(); + void testTotpCode(); +}; + +#endif // KEEPASSX_TESTTOTP_H diff --git a/tests/TestWildcardMatcher.h b/tests/TestWildcardMatcher.h index c241c7553a..e237709370 100644 --- a/tests/TestWildcardMatcher.h +++ b/tests/TestWildcardMatcher.h @@ -26,7 +26,7 @@ class TestWildcardMatcher : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void testMatcher(); void testMatcher_data(); diff --git a/tests/TestYkChallengeResponseKey.cpp b/tests/TestYkChallengeResponseKey.cpp new file mode 100644 index 0000000000..558920f4a1 --- /dev/null +++ b/tests/TestYkChallengeResponseKey.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2014 Kyle Manna + * Copyright (C) 2017 KeePassXC Team + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TestYkChallengeResponseKey.h" + +#include +#include + +#include "crypto/Crypto.h" +#include "keys/YkChallengeResponseKey.h" + +QTEST_GUILESS_MAIN(TestYubiKeyChalResp) + +void TestYubiKeyChalResp::initTestCase() +{ + m_detected = 0; + m_key = NULL; + + // crypto subsystem needs to be initialized for YubiKey testing + QVERIFY(Crypto::init()); +} + +void TestYubiKeyChalResp::cleanupTestCase() +{ + if (m_key) + delete m_key; +} + +void TestYubiKeyChalResp::init() +{ + bool result = YubiKey::instance()->init(); + + if (!result) { + QSKIP("Unable to connect to YubiKey", SkipAll); + } +} + +void TestYubiKeyChalResp::detectDevices() +{ + connect(YubiKey::instance(), SIGNAL(detected(int,bool)), + SLOT(ykDetected(int,bool)), + Qt::QueuedConnection); + QtConcurrent::run(YubiKey::instance(), &YubiKey::detect); + + // need to wait for the hardware (that's hopefully plugged in)... + QTest::qWait(2000); + QVERIFY2(m_detected > 0, "Is a YubiKey attached?"); +} + +void TestYubiKeyChalResp::getSerial() +{ + unsigned int serial; + QVERIFY(YubiKey::instance()->getSerial(serial)); +} + +void TestYubiKeyChalResp::keyGetName() +{ + QVERIFY(m_key); + QVERIFY(m_key->getName().length() > 0); +} + +void TestYubiKeyChalResp::keyIssueChallenge() +{ + QVERIFY(m_key); + if (m_key->isBlocking()) { + /* Testing active mode in unit tests is unreasonable */ + QSKIP("YubiKey not in passive mode", SkipSingle); + } + + QByteArray ba("UnitTest"); + QVERIFY(m_key->challenge(ba)); + + /* TODO Determine if it's reasonable to provide a fixed secret key for + * verification testing. Obviously simple technically, but annoying + * if devs need to re-program their yubikeys or have a spare test key + * for unit tests to past. + * + * Might be worth it for integrity verification though. + */ +} + +void TestYubiKeyChalResp::ykDetected(int slot, bool blocking) +{ + Q_UNUSED(blocking); + + if (slot > 0) + m_detected++; + + /* Key used for later testing */ + if (!m_key) + m_key = new YkChallengeResponseKey(slot, blocking); +} + +void TestYubiKeyChalResp::deinit() +{ + QVERIFY(YubiKey::instance()->deinit()); +} diff --git a/tests/TestYkChallengeResponseKey.h b/tests/TestYkChallengeResponseKey.h new file mode 100644 index 0000000000..2bc344ec00 --- /dev/null +++ b/tests/TestYkChallengeResponseKey.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2014 Kyle Manna + * Copyright (C) 2017 KeePassXC Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_TESTYUBIKEYCHALRESP_H +#define KEEPASSX_TESTYUBIKEYCHALRESP_H + +#include + +#include "keys/YkChallengeResponseKey.h" + +class TestYubiKeyChalResp: public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void cleanupTestCase(); + + void init(); + + /* Order is important! + * Need to init and detectDevices() before proceeding + */ + void detectDevices(); + + void getSerial(); + void keyGetName(); + void keyIssueChallenge(); + + void deinit(); + + /* Callback for detectDevices() */ + void ykDetected(int slot, bool blocking); + +private: + int m_detected; + YkChallengeResponseKey *m_key; +}; + +#endif // KEEPASSX_TESTYUBIKEYCHALRESP_H diff --git a/tests/data/RecycleBinDisabled.kdbx b/tests/data/RecycleBinDisabled.kdbx new file mode 100644 index 0000000000..0bbfb3efee Binary files /dev/null and b/tests/data/RecycleBinDisabled.kdbx differ diff --git a/tests/data/RecycleBinEmpty.kdbx b/tests/data/RecycleBinEmpty.kdbx new file mode 100644 index 0000000000..7d264fb3ee Binary files /dev/null and b/tests/data/RecycleBinEmpty.kdbx differ diff --git a/tests/data/RecycleBinNotYetCreated.kdbx b/tests/data/RecycleBinNotYetCreated.kdbx new file mode 100644 index 0000000000..90771e5040 Binary files /dev/null and b/tests/data/RecycleBinNotYetCreated.kdbx differ diff --git a/tests/data/RecycleBinWithData.kdbx b/tests/data/RecycleBinWithData.kdbx new file mode 100644 index 0000000000..66d1c93026 Binary files /dev/null and b/tests/data/RecycleBinWithData.kdbx differ diff --git a/tests/gui/TemporaryFile.cpp b/tests/gui/TemporaryFile.cpp index 879a558a93..7c7a1c5d4c 100644 --- a/tests/gui/TemporaryFile.cpp +++ b/tests/gui/TemporaryFile.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Danny Su + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tests/gui/TemporaryFile.h b/tests/gui/TemporaryFile.h index b16e2161a7..f1cff3ef43 100644 --- a/tests/gui/TemporaryFile.h +++ b/tests/gui/TemporaryFile.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2016 Danny Su + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 0c776e0218..9abe31f38a 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +26,8 @@ #include #include #include +#include +#include #include #include #include @@ -45,6 +48,9 @@ #include "format/KeePass2Reader.h" #include "gui/DatabaseTabWidget.h" #include "gui/DatabaseWidget.h" +#include "gui/CloneDialog.h" +#include "gui/TotpDialog.h" +#include "gui/SetupTotpDialog.h" #include "gui/FileDialog.h" #include "gui/MainWindow.h" #include "gui/MessageBox.h" @@ -225,6 +231,7 @@ void TestGui::testEditEntry() // Select the first entry in the database EntryView* entryView = m_dbWidget->findChild("entryView"); QModelIndex entryItem = entryView->model()->index(0, 1); + Entry* entry = entryView->entryFromIndex(entryItem); clickIndex(entryItem, entryView, Qt::LeftButton); // Confirm the edit action button is enabled @@ -241,15 +248,33 @@ void TestGui::testEditEntry() QLineEdit* titleEdit = editEntryWidget->findChild("titleEdit"); QTest::keyClicks(titleEdit, "_test"); - // Save the edit + // Apply the edit QDialogButtonBox* editEntryWidgetButtonBox = editEntryWidget->findChild("buttonBox"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Apply), Qt::LeftButton); + QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode); + QCOMPARE(entry->title(), QString("Sample Entry_test")); + QCOMPARE(entry->historyItems().size(), 1); + + // Test protected attributes + editEntryWidget->setCurrentPage(1); + QPlainTextEdit* attrTextEdit = editEntryWidget->findChild("attributesEdit"); + QTest::mouseClick(editEntryWidget->findChild("addAttributeButton"), Qt::LeftButton); + QString attrText = "TEST TEXT"; + QTest::keyClicks(attrTextEdit, attrText); + QCOMPARE(attrTextEdit->toPlainText(), attrText); + QTest::mouseClick(editEntryWidget->findChild("protectAttributeButton"), Qt::LeftButton); + QVERIFY(attrTextEdit->toPlainText().contains("PROTECTED")); + QTest::mouseClick(editEntryWidget->findChild("revealAttributeButton"), Qt::LeftButton); + QCOMPARE(attrTextEdit->toPlainText(), attrText); + editEntryWidget->setCurrentPage(0); + + // Save the edit (press OK) QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); // Confirm edit was made QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode); - Entry* entry = entryView->entryFromIndex(entryItem); QCOMPARE(entry->title(), QString("Sample Entry_test")); - QCOMPARE(entry->historyItems().size(), 1); + QCOMPARE(entry->historyItems().size(), 2); // Confirm modified indicator is showing QTRY_COMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("%1*").arg(m_dbFileName)); @@ -301,11 +326,13 @@ void TestGui::testAddEntry() QTest::keyClicks(titleEdit, "something 3"); QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + QApplication::processEvents(); + // Confirm that 4 entries now exist QTRY_COMPARE(entryView->model()->rowCount(), 4); } -void TestGui::testEntryEntropy() +void TestGui::testPasswordEntryEntropy() { QToolBar* toolBar = m_mainWindow->findChild("toolBar"); @@ -379,6 +406,99 @@ void TestGui::testEntryEntropy() // We are done } +void TestGui::testDicewareEntryEntropy() +{ + QToolBar* toolBar = m_mainWindow->findChild("toolBar"); + + // Find the new entry action + QAction* entryNewAction = m_mainWindow->findChild("actionEntryNew"); + QVERIFY(entryNewAction->isEnabled()); + + // Find the button associated with the new entry action + QWidget* entryNewWidget = toolBar->widgetForAction(entryNewAction); + QVERIFY(entryNewWidget->isVisible()); + QVERIFY(entryNewWidget->isEnabled()); + + // Click the new entry button and check that we enter edit mode + QTest::mouseClick(entryNewWidget, Qt::LeftButton); + QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode); + + // Add entry "test" and confirm added + EditEntryWidget* editEntryWidget = m_dbWidget->findChild("editEntryWidget"); + QLineEdit* titleEdit = editEntryWidget->findChild("titleEdit"); + QTest::keyClicks(titleEdit, "test"); + + // Open the password generator + QToolButton* generatorButton = editEntryWidget->findChild("togglePasswordGeneratorButton"); + QTest::mouseClick(generatorButton, Qt::LeftButton); + + // Select Diceware + QTabWidget* tabWidget = editEntryWidget->findChild("tabWidget"); + QWidget* dicewareWidget = editEntryWidget->findChild("dicewareWidget"); + tabWidget->setCurrentWidget(dicewareWidget); + + QComboBox* comboBoxWordList = dicewareWidget->findChild("comboBoxWordList"); + comboBoxWordList->setCurrentText("eff_large.wordlist"); + QSpinBox* spinBoxWordCount = dicewareWidget->findChild("spinBoxWordCount"); + spinBoxWordCount->setValue(6); + + // Type in some password + QLabel* entropyLabel = editEntryWidget->findChild("entropyLabel"); + QLabel* strengthLabel = editEntryWidget->findChild("strengthLabel"); + + QCOMPARE(entropyLabel->text(), QString("Entropy: 77.55 bit")); + QCOMPARE(strengthLabel->text(), QString("Password Quality: Good")); +} + +void TestGui::testTotp() +{ + QToolBar* toolBar = m_mainWindow->findChild("toolBar"); + EntryView* entryView = m_dbWidget->findChild("entryView"); + + QCOMPARE(entryView->model()->rowCount(), 1); + + QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode); + QModelIndex item = entryView->model()->index(0, 1); + Entry* entry = entryView->entryFromIndex(item); + + clickIndex(item, entryView, Qt::LeftButton); + + triggerAction("actionEntrySetupTotp"); + + SetupTotpDialog* setupTotpDialog = m_dbWidget->findChild("SetupTotpDialog"); + + Tools::wait(100); + + QLineEdit* seedEdit = setupTotpDialog->findChild("seedEdit"); + + QString exampleSeed = "gezdgnbvgy3tqojqgezdgnbvgy3tqojq"; + QTest::keyClicks(seedEdit, exampleSeed); + + QDialogButtonBox* setupTotpButtonBox = setupTotpDialog->findChild("buttonBox"); + QTest::mouseClick(setupTotpButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + + QAction* entryEditAction = m_mainWindow->findChild("actionEntryEdit"); + QWidget* entryEditWidget = toolBar->widgetForAction(entryEditAction); + QTest::mouseClick(entryEditWidget, Qt::LeftButton); + QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode); + EditEntryWidget* editEntryWidget = m_dbWidget->findChild("editEntryWidget"); + + editEntryWidget->setCurrentPage(1); + QPlainTextEdit* attrTextEdit = editEntryWidget->findChild("attributesEdit"); + QTest::mouseClick(editEntryWidget->findChild("revealAttributeButton"), Qt::LeftButton); + QCOMPARE(attrTextEdit->toPlainText(), exampleSeed); + + QDialogButtonBox* editEntryWidgetButtonBox = editEntryWidget->findChild("buttonBox"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + + triggerAction("actionEntryTotp"); + + TotpDialog* totpDialog = m_dbWidget->findChild("TotpDialog"); + QLabel* totpLabel = totpDialog->findChild("totpLabel"); + + QCOMPARE(totpLabel->text().replace(" ", ""), entry->totp()); +} + void TestGui::testSearch() { // Add canned entries for consistent testing @@ -393,19 +513,24 @@ void TestGui::testSearch() EntryView* entryView = m_dbWidget->findChild("entryView"); QVERIFY(entryView->isVisible()); + QAction* clearButton = searchWidget->findChild("clearIcon"); + QVERIFY(!clearButton->isVisible()); + // Enter search QTest::mouseClick(searchTextEdit, Qt::LeftButton); QTRY_VERIFY(searchTextEdit->hasFocus()); + QTRY_VERIFY(!clearButton->isVisible()); // Search for "ZZZ" QTest::keyClicks(searchTextEdit, "ZZZ"); QTRY_COMPARE(searchTextEdit->text(), QString("ZZZ")); + QTRY_VERIFY(clearButton->isVisible()); QTRY_VERIFY(m_dbWidget->isInSearchMode()); QTRY_COMPARE(entryView->model()->rowCount(), 0); // Press the search clear button - QToolButton* clearButton = searchWidget->findChild("clearIcon"); - QTest::mouseClick(clearButton, Qt::LeftButton); + clearButton->trigger(); QTRY_VERIFY(searchTextEdit->text().isEmpty()); QTRY_VERIFY(searchTextEdit->hasFocus()); + QTRY_VERIFY(!clearButton->isVisible()); // Escape clears searchedit and retains focus QTest::keyClicks(searchTextEdit, "ZZZ"); QTest::keyClick(searchTextEdit, Qt::Key_Escape); @@ -452,7 +577,12 @@ void TestGui::testSearch() QModelIndex rootGroupIndex = groupView->model()->index(0, 0); clickIndex(groupView->model()->index(0, 0, rootGroupIndex), groupView, Qt::LeftButton); QCOMPARE(groupView->currentGroup()->name(), QString("General")); + + searchWidget->setLimitGroup(false); + QTRY_COMPARE(entryView->model()->rowCount(), 2); + searchWidget->setLimitGroup(true); QTRY_COMPARE(entryView->model()->rowCount(), 0); + // reset clickIndex(rootGroupIndex, groupView, Qt::LeftButton); QCOMPARE(groupView->currentGroup(), m_db->rootGroup()); @@ -563,12 +693,60 @@ void TestGui::testCloneEntry() triggerAction("actionEntryClone"); + CloneDialog* cloneDialog = m_dbWidget->findChild("CloneDialog"); + QDialogButtonBox* cloneButtonBox = cloneDialog->findChild("buttonBox"); + QTest::mouseClick(cloneButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + QCOMPARE(entryView->model()->rowCount(), 2); Entry* entryClone = entryView->entryFromIndex(entryView->model()->index(1, 1)); QVERIFY(entryOrg->uuid() != entryClone->uuid()); QCOMPARE(entryClone->title(), entryOrg->title() + QString(" - Clone")); } +void TestGui::testEntryPlaceholders() +{ + QToolBar* toolBar = m_mainWindow->findChild("toolBar"); + EntryView* entryView = m_dbWidget->findChild("entryView"); + + // Find the new entry action + QAction* entryNewAction = m_mainWindow->findChild("actionEntryNew"); + QVERIFY(entryNewAction->isEnabled()); + + // Find the button associated with the new entry action + QWidget* entryNewWidget = toolBar->widgetForAction(entryNewAction); + QVERIFY(entryNewWidget->isVisible()); + QVERIFY(entryNewWidget->isEnabled()); + + // Click the new entry button and check that we enter edit mode + QTest::mouseClick(entryNewWidget, Qt::LeftButton); + QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode); + + // Add entry "test" and confirm added + EditEntryWidget* editEntryWidget = m_dbWidget->findChild("editEntryWidget"); + QLineEdit* titleEdit = editEntryWidget->findChild("titleEdit"); + QTest::keyClicks(titleEdit, "test"); + QLineEdit* usernameEdit = editEntryWidget->findChild("usernameEdit"); + QTest::keyClicks(usernameEdit, "john"); + QLineEdit* urlEdit = editEntryWidget->findChild("urlEdit"); + QTest::keyClicks(urlEdit, "{TITLE}.{USERNAME}"); + QDialogButtonBox* editEntryWidgetButtonBox = editEntryWidget->findChild("buttonBox"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + + QCOMPARE(entryView->model()->rowCount(), 2); + + QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode); + QModelIndex item = entryView->model()->index(1, 1); + Entry* entry = entryView->entryFromIndex(item); + + QCOMPARE(entry->title(), QString("test")); + QCOMPARE(entry->url(), QString("{TITLE}.{USERNAME}")); + + // Test password copy + QClipboard *clipboard = QApplication::clipboard(); + m_dbWidget->copyURL(); + QTRY_COMPARE(clipboard->text(), QString("test.john")); +} + void TestGui::testDragAndDropEntry() { EntryView* entryView = m_dbWidget->findChild("entryView"); diff --git a/tests/gui/TestGui.h b/tests/gui/TestGui.h index c2e0e372ec..904e5f21e7 100644 --- a/tests/gui/TestGui.h +++ b/tests/gui/TestGui.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2011 Felix Geyer + * Copyright (C) 2017 KeePassXC Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,7 +34,7 @@ class TestGui : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void init(); void cleanup(); @@ -44,10 +45,13 @@ private Q_SLOTS: void testTabs(); void testEditEntry(); void testAddEntry(); - void testEntryEntropy(); + void testPasswordEntryEntropy(); + void testDicewareEntryEntropy(); + void testTotp(); void testSearch(); void testDeleteEntry(); void testCloneEntry(); + void testEntryPlaceholders(); void testDragAndDropEntry(); void testDragAndDropGroup(); void testSaveAs(); diff --git a/tests/gui/TestGuiPixmaps.h b/tests/gui/TestGuiPixmaps.h index ef0b664b5d..6e649c0f71 100644 --- a/tests/gui/TestGuiPixmaps.h +++ b/tests/gui/TestGuiPixmaps.h @@ -26,7 +26,7 @@ class TestGuiPixmaps : public QObject { Q_OBJECT -private Q_SLOTS: +private slots: void initTestCase(); void testDatabaseIcons(); void testEntryIcons(); diff --git a/tests/modeltest.cpp b/tests/modeltest.cpp index 360a7bef1d..6bf8124cf9 100644 --- a/tests/modeltest.cpp +++ b/tests/modeltest.cpp @@ -448,7 +448,8 @@ void ModelTest::data() QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole ); if ( textAlignmentVariant.isValid() ) { int alignment = textAlignmentVariant.toInt(); - QCOMPARE( alignment, ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) ); + QCOMPARE( alignment, static_cast( alignment & ( Qt::AlignHorizontal_Mask + | Qt::AlignVertical_Mask ) ) ); } // General Purpose roles that should return a QColor diff --git a/tests/modeltest.h b/tests/modeltest.h index 3dcf18cebf..fdc5cf2f61 100644 --- a/tests/modeltest.h +++ b/tests/modeltest.h @@ -46,7 +46,7 @@ class ModelTest : public QObject public: ModelTest( QAbstractItemModel *model, QObject *parent = 0 ); -private Q_SLOTS: +private slots: void nonDestructiveBasicTest(); void rowCount(); void columnCount(); @@ -55,7 +55,7 @@ private Q_SLOTS: void parent(); void data(); -protected Q_SLOTS: +protected slots: void runAllTests(); void layoutAboutToBeChanged(); void layoutChanged(); diff --git a/utils/fix_mac.sh b/utils/fix_mac.sh new file mode 100755 index 0000000000..2e4e84e5e4 --- /dev/null +++ b/utils/fix_mac.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Canonical path to qt5 directory +QT="/usr/local/Cellar/qt" +if [ ! -d "$QT" ]; then + # Alternative (old) path to qt5 directory + QT+="5" + if [ ! -d "$QT" ]; then + echo "Qt/Qt5 not found!" + exit + fi +fi +QT5_DIR="$QT/$(ls $QT | sort -r | head -n1)" +echo $QT5_DIR + +# Change qt5 framework ids +for framework in $(find "$QT5_DIR/lib" -regex ".*/\(Qt[a-zA-Z]*\)\.framework/Versions/5/\1"); do + echo "$framework" + install_name_tool -id "$framework" "$framework" +done diff --git a/utils/kdbx-merge.cpp b/utils/kdbx-merge.cpp deleted file mode 100644 index da780ea1bb..0000000000 --- a/utils/kdbx-merge.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2010 Felix Geyer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include "core/Database.h" -#include "crypto/Crypto.h" -#include "format/KeePass2Reader.h" -#include "format/KeePass2Writer.h" -#include "keys/CompositeKey.h" - -int main(int argc, char **argv) -{ - - QCoreApplication app(argc, argv); - - QCommandLineParser parser; - parser.setApplicationDescription(QCoreApplication::translate("main", "Merge 2 KeePassXC database files.")); - parser.addPositionalArgument("database1", QCoreApplication::translate("main", "path of the database to merge into.")); - parser.addPositionalArgument("database2", QCoreApplication::translate("main", "path of the database to merge from.")); - - QCommandLineOption samePasswordOption(QStringList() << "s" << "same-password", - QCoreApplication::translate("main", "use the same password for both database files.")); - - parser.addHelpOption(); - parser.addOption(samePasswordOption); - parser.process(app); - - const QStringList args = parser.positionalArguments(); - if (args.size() != 2) { - parser.showHelp(); - return 1; - } - - if (!Crypto::init()) { - qFatal("Fatal error while testing the cryptographic functions:\n%s", qPrintable(Crypto::errorString())); - } - - static QTextStream inputTextStream(stdin, QIODevice::ReadOnly); - - QString line1 = inputTextStream.readLine(); - CompositeKey key1 = CompositeKey::readFromLine(line1); - - CompositeKey key2; - if (parser.isSet("same-password")) { - key2 = *key1.clone(); - } - else { - QString line2 = inputTextStream.readLine(); - key2 = CompositeKey::readFromLine(line2); - } - - - QString databaseFilename1 = args.at(0); - QFile dbFile1(databaseFilename1); - if (!dbFile1.exists()) { - qCritical("File %s does not exist.", qPrintable(databaseFilename1)); - return 1; - } - if (!dbFile1.open(QIODevice::ReadOnly)) { - qCritical("Unable to open file %s.", qPrintable(databaseFilename1)); - return 1; - } - - KeePass2Reader reader1; - Database* db1 = reader1.readDatabase(&dbFile1, key1); - - if (reader1.hasError()) { - qCritical("Error while parsing the database:\n%s\n", qPrintable(reader1.errorString())); - return 1; - } - - - QString databaseFilename2 = args.at(1); - QFile dbFile2(databaseFilename2); - if (!dbFile2.exists()) { - qCritical("File %s does not exist.", qPrintable(databaseFilename2)); - return 1; - } - if (!dbFile2.open(QIODevice::ReadOnly)) { - qCritical("Unable to open file %s.", qPrintable(databaseFilename2)); - return 1; - } - - KeePass2Reader reader2; - Database* db2 = reader2.readDatabase(&dbFile2, key2); - - if (reader2.hasError()) { - qCritical("Error while parsing the database:\n%s\n", qPrintable(reader2.errorString())); - return 1; - } - - db1->merge(db2); - - QSaveFile saveFile(databaseFilename1); - if (!saveFile.open(QIODevice::WriteOnly)) { - qCritical("Unable to open file %s for writing.", qPrintable(databaseFilename1)); - return 1; - } - - KeePass2Writer writer; - writer.writeDatabase(&saveFile, db1); - - if (writer.hasError()) { - qCritical("Error while updating the database:\n%s\n", qPrintable(writer.errorString())); - return 1; - } - - if (!saveFile.commit()) { - qCritical("Error while updating the database:\n%s\n", qPrintable(writer.errorString())); - return 0; - } - - qDebug("Successfully merged the database files.\n"); - return 1; - -}