diff options
author | Janek Bevendorff <janek@jbev.net> | 2017-10-22 01:28:08 +0300 |
---|---|---|
committer | Janek Bevendorff <janek@jbev.net> | 2017-10-22 01:28:08 +0300 |
commit | 6d46717cfc2d61bfc6a5335b02e95c6b1d9bf482 (patch) | |
tree | 6582a28ee275e7852c1cf6251d89e477a423e274 | |
parent | 2bce9c8add07226e9a05e9e0fd0e5e66b236d5b6 (diff) | |
parent | 3088371631cf8a57a1431f170fb9a54dce6f65ba (diff) |
Release 2.2.22.2.2
- Fixed entries with empty URLs being reported to KeePassHTTP clients [#1031]
- Fixed YubiKey detection and enabled CLI tool for AppImage binary [#1100]
- Added AppStream description [#1082]
- Improved TOTP compatibility and added new Base32 implementation [#1069]
- Fixed error handling when processing invalid cipher stream [#1099]
- Fixed double warning display when opening a database [#1037]
- Fixed unlocking databases with --pw-stdin [#1087]
- Added ability to override QT_PLUGIN_PATH environment variable for AppImages [#1079]
- Fixed transform seed not being regenerated when saving the database [#1068]
- Fixed only one YubiKey slot being polled [#1048]
- Corrected an issue with entry icons while merging [#1008]
- Corrected desktop and tray icons in Snap package [#1030]
- Fixed screen lock and Google fallback settings [#1029]
76 files changed, 1996 insertions, 712 deletions
diff --git a/.gitignore b/.gitignore index 0521a42e3..479c589ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ CMakeLists.txt.* build*/ +cmake-build-*/ release*/ .idea/ *.iml diff --git a/AppImage-Recipe.sh b/AppImage-Recipe.sh index 2707fe96b..c421aa79e 100755 --- a/AppImage-Recipe.sh +++ b/AppImage-Recipe.sh @@ -34,6 +34,7 @@ fi APP="$1" LOWERAPP="$(echo "$APP" | tr '[:upper:]' '[:lower:]')" VERSION="$2" +export ARCH=x86_64 mkdir -p $APP.AppDir wget -q https://github.com/probonopd/AppImages/raw/master/functions.sh -O ./functions.sh @@ -42,6 +43,8 @@ wget -q https://github.com/probonopd/AppImages/raw/master/functions.sh -O ./func LIB_DIR=./usr/lib if [ -d ./usr/lib/x86_64-linux-gnu ]; then LIB_DIR=./usr/lib/x86_64-linux-gnu +elif [ -d ./usr/lib64 ]; then + LIB_DIR=./usr/lib64 fi cd $APP.AppDir @@ -51,7 +54,7 @@ rm -R ./usr/local rmdir ./opt 2> /dev/null # bundle Qt platform plugins and themes -QXCB_PLUGIN="$(find /usr/lib -name 'libqxcb.so' 2> /dev/null)" +QXCB_PLUGIN="$(find /usr/lib* -name 'libqxcb.so' 2> /dev/null)" if [ "$QXCB_PLUGIN" == "" ]; then QXCB_PLUGIN="$(find /opt/qt*/plugins -name 'libqxcb.so' 2> /dev/null)" fi @@ -71,18 +74,22 @@ get_desktop get_icon cat << EOF > ./usr/bin/keepassxc_env #!/usr/bin/env bash -#export QT_QPA_PLATFORMTHEME=gtk2 export LD_LIBRARY_PATH="..$(dirname ${QT_PLUGIN_PATH})/lib:\${LD_LIBRARY_PATH}" -export QT_PLUGIN_PATH="..${QT_PLUGIN_PATH}" +export QT_PLUGIN_PATH="..${QT_PLUGIN_PATH}:\${KPXC_QT_PLUGIN_PATH}" # unset XDG_DATA_DIRS to make tray icon work in Ubuntu Unity -# see https://github.com/probonopd/AppImageKit/issues/351 +# see https://github.com/AppImage/AppImageKit/issues/351 unset XDG_DATA_DIRS -exec keepassxc "\$@" +if [ "\${1}" == "cli" ]; then + shift + exec keepassxc-cli "\$@" +else + exec keepassxc "\$@" +fi EOF chmod +x ./usr/bin/keepassxc_env -sed -i 's/Exec=keepassxc/Exec=keepassxc_env/' keepassxc.desktop +sed -i 's/Exec=keepassxc/Exec=keepassxc_env/' org.keepassxc.desktop get_desktopintegration $LOWERAPP GLIBC_NEEDED=$(glibc_needed) @@ -91,5 +98,5 @@ cd .. generate_type2_appimage -mv ../out/*.AppImage .. +mv ../out/*.AppImage ../KeePassXC-${VERSION}-${ARCH}.AppImage rmdir ../out > /dev/null 2>&1 @@ -1,3 +1,20 @@ +2.2.2 (2017-10-22) +========================= + +- Fixed entries with empty URLs being reported to KeePassHTTP clients [#1031] +- Fixed YubiKey detection and enabled CLI tool for AppImage binary [#1100] +- Added AppStream description [#1082] +- Improved TOTP compatibility and added new Base32 implementation [#1069] +- Fixed error handling when processing invalid cipher stream [#1099] +- Fixed double warning display when opening a database [#1037] +- Fixed unlocking databases with --pw-stdin [#1087] +- Added ability to override QT_PLUGIN_PATH environment variable for AppImages [#1079] +- Fixed transform seed not being regenerated when saving the database [#1068] +- Fixed only one YubiKey slot being polled [#1048] +- Corrected an issue with entry icons while merging [#1008] +- Corrected desktop and tray icons in Snap package [#1030] +- Fixed screen lock and Google fallback settings [#1029] + 2.2.1 (2017-10-01) ========================= diff --git a/CMakeLists.txt b/CMakeLists.txt index 976b32937..63281f93b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,9 +49,21 @@ set(CMAKE_AUTOUIC ON) set(KEEPASSXC_VERSION_MAJOR "2") set(KEEPASSXC_VERSION_MINOR "2") -set(KEEPASSXC_VERSION_PATCH "1") +set(KEEPASSXC_VERSION_PATCH "2") set(KEEPASSXC_VERSION "${KEEPASSXC_VERSION_MAJOR}.${KEEPASSXC_VERSION_MINOR}.${KEEPASSXC_VERSION_PATCH}") +# Distribution info +set(KEEPASSXC_DIST True) +set(KEEPASSXC_DIST_TYPE "Other" CACHE STRING "KeePassXC Distribution type") +set_property(CACHE KEEPASSXC_DIST_TYPE PROPERTY STRINGS Snap AppImage Other) +if(KEEPASSXC_DIST_TYPE STREQUAL "Snap") + set(KEEPASSXC_DIST_SNAP True) +elseif(KEEPASSXC_DIST_TYPE STREQUAL "AppImage") + set(KEEPASSXC_DIST_APPIMAGE True) +elseif(KEEPASSXC_DIST_TYPE STREQUAL "Other") + unset(KEEPASSXC_DIST) +endif() + if("${CMAKE_C_COMPILER}" MATCHES "clang$" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_COMPILER_IS_CLANG 1) endif() @@ -214,10 +214,6 @@ Files: share/icons/database/C65_W.png Copyright: none License: public-domain -Files: src/crypto/salsa20/* -Copyright: none -License: public-domain - Files: src/streams/qtiocompressor.* src/streams/QtIOCompressor tests/modeltest.* @@ -241,8 +237,3 @@ Files: src/gui/KMessageWidget.h Copyright: 2011 Aurélien Gâteau <agateau@kde.org> 2014 Dominik Haumann <dhaumann@kde.org> 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 7da658219..6f7ace34c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,49 +14,68 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -FROM ubuntu:14.04 +FROM centos:7 RUN set -x \ - && apt-get update \ - && apt-get install --yes software-properties-common + && curl "https://copr.fedorainfracloud.org/coprs/bugzy/keepassxc/repo/epel-7/bugzy-keepassxc-epel-7.repo" \ + > /etc/yum.repos.d/bugzy-keepassxc-epel-7.repo RUN set -x \ - && add-apt-repository ppa:george-edison55/cmake-3.x - -ENV QT_VERSION=qt59 + && curl "https://copr.fedorainfracloud.org/coprs/sic/backports/repo/epel-7/sic-backports-epel-7.repo" \ + > /etc/yum.repos.d/sic-backports-epel-7.repo RUN set -x \ - && add-apt-repository --yes ppa:beineri/opt-${QT_VERSION}-trusty - + && yum clean -y all \ + && yum upgrade -y +# build and runtime dependencies RUN set -x \ - && apt-get update \ - && apt-get install --yes \ - g++ \ + && yum install -y \ + make \ + automake \ + gcc-c++ \ cmake \ - libgcrypt20-dev \ - ${QT_VERSION}base \ - ${QT_VERSION}tools \ - ${QT_VERSION}x11extras \ - libxi-dev \ - libxtst-dev \ - zlib1g-dev \ - libyubikey-dev \ - libykpers-1-dev \ - xvfb \ + libgcrypt16-devel \ + qt5-qtbase-devel \ + qt5-linguist \ + qt5-qttools \ + zlib-devel \ + qt5-qtx11extras \ + qt5-qtx11extras-devel \ + libXi-devel \ + libXtst-devel + +# AppImage dependencies +RUN set -x \ + && yum install -y \ wget \ - file \ - fuse \ - python + fuse-libs +# build libyubikey +ENV YUBIKEY_VERSION=1.13 +RUN set -x && yum install -y libusb-devel RUN set -x \ - && apt-get install --yes mesa-common-dev - + && wget "https://developers.yubico.com/yubico-c/Releases/libyubikey-${YUBIKEY_VERSION}.tar.gz" \ + && tar xf libyubikey-${YUBIKEY_VERSION}.tar.gz \ + && cd libyubikey-${YUBIKEY_VERSION} \ + && ./configure --prefix=/usr --libdir=/usr/lib64 \ + && make \ + && make install \ + && cd .. \ + && rm -Rf libyubikey-${YUBIKEY_VERSION}* + +# build libykpers-1 +ENV YKPERS_VERSION=1.18.0 +RUN set -x \ + && wget "https://developers.yubico.com/yubikey-personalization/Releases/ykpers-${YKPERS_VERSION}.tar.gz" \ + && tar xf ykpers-${YKPERS_VERSION}.tar.gz \ + && cd ykpers-${YKPERS_VERSION} \ + && ./configure --prefix=/usr --libdir=/usr/lib64 \ + && make \ + && make install \ + && cd .. \ + && rm -Rf ykpers-${YKPERS_VERSION}* + VOLUME /keepassxc/src VOLUME /keepassxc/out WORKDIR /keepassxc - -ENV CMAKE_PREFIX_PATH=/opt/${QT_VERSION}/lib/cmake -ENV LD_LIBRARY_PATH=/opt/${QT_VERSION}/lib -RUN set -x \ - && echo /opt/${QT_VERSION}/lib > /etc/ld.so.conf.d/${QT_VERSION}.conf diff --git a/LICENSE.APACHE-2.0 b/LICENSE.APACHE-2.0 deleted file mode 100644 index 9c8f3ea08..000000000 --- a/LICENSE.APACHE-2.0 +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - 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.
\ No newline at end of file @@ -14,7 +14,7 @@ KeePass Cross-platform Community Edition - 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, and [passafari](https://github.com/mmichaa/passafari.safariextension/) in Safari. +- KeePassHTTP support for use with KeePassHTTP-Connector for [Mozilla Firefox](https://addons.mozilla.org/en-US/firefox/addon/keepasshttp-connector/) and [Google Chrome or Chromium](https://chrome.google.com/webstore/detail/keepasshttp-connector/dafgdjggglmmknipkhngniifhplpcldb), 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. diff --git a/release-tool b/release-tool index 680cdca2c..10c6a14c3 100755 --- a/release-tool +++ b/release-tool @@ -119,9 +119,11 @@ EOF Sign previously compiled release packages Options: - -f, --files Files to sign (required) - -g, --gpg-key GPG key used to sign the files (default: '${GPG_KEY}') - -h, --help Show this help + -f, --files Files to sign (required) + -g, --gpg-key GPG key used to sign the files (default: '${GPG_KEY}') + --signtool Specify the signtool executable (default: 'signtool') + --signtool-key Provide a key to be used with signtool (for Windows EXE) + -h, --help Show this help EOF fi } @@ -257,19 +259,18 @@ checkChangeLog() { grep -qPzo "${RELEASE_NAME} \(\d{4}-\d{2}-\d{2}\)\n=+\n" CHANGELOG if [ $? -ne 0 ]; then - exitError "CHANGELOG does not contain any information about the '${RELEASE_NAME}' release!" + exitError "'CHANGELOG' has not been updated to the '${RELEASE_NAME}' release!" fi } -checkTransifexCommandExists() { - command -v tx > /dev/null - if [ 0 -ne $? ]; then - exitError "Transifex tool 'tx' not installed! Please install it using 'pip install transifex-client'" +checkAppStreamInfo() { + if [ ! -f share/linux/org.keepassxc.appdata.xml ]; then + exitError "No AppStream info file found!" 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'" + grep -qPzo "<release version=\"${RELEASE_NAME}\" date=\"\d{4}-\d{2}-\d{2}\">" share/linux/org.keepassxc.appdata.xml + if [ $? -ne 0 ]; then + exitError "'share/linux/org.keepassxc.appdata.xml' has not been updated to the '${RELEASE_NAME}' release!" fi } @@ -281,7 +282,24 @@ checkSnapcraft() { grep -qPzo "version: ${RELEASE_NAME}" snapcraft.yaml if [ $? -ne 0 ]; then - exitError "snapcraft.yaml has not been updated to the '${RELEASE_NAME}' release!" + exitError "'snapcraft.yaml' has not been updated to the '${RELEASE_NAME}' release!" + fi +} + +checkTransifexCommandExists() { + command -v tx > /dev/null + if [ 0 -ne $? ]; then + exitError "Transifex tool 'tx' not installed! Please install it using 'pip install transifex-client'" + fi +} + +checkQt5LUpdateExists() { + command -v lupdate > /dev/null + if [ 0 -eq $? ] && ! $(lupdate -version | grep -q "lupdate version 5\."); then + 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 fi } @@ -296,6 +314,7 @@ performChecks() { logInfo "Validating toolset and repository..." checkTransifexCommandExists + checkQt5LUpdateExists checkGitRepository checkReleaseDoesNotExist checkWorkingTreeClean @@ -309,6 +328,7 @@ performChecks() { checkVersionInCMake checkChangeLog + checkAppStreamInfo checkSnapcraft logInfo "\e[1m\e[32mAll checks passed!\e[0m" @@ -528,10 +548,10 @@ build() { checkWorkingTreeClean OUTPUT_DIR="$(realpath "$OUTPUT_DIR")" - + logInfo "Checking out release tag '${TAG_NAME}'..." git checkout "$TAG_NAME" - + logInfo "Creating output directory..." mkdir -p "$OUTPUT_DIR" @@ -598,7 +618,8 @@ build() { # Building on Linux without Docker container logInfo "Configuring build..." cmake -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=Off $CMAKE_OPTIONS \ - -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" "$SRC_DIR" + -DCMAKE_INSTALL_PREFIX="${INSTALL_PREFIX}" \ + -DKEEPASSXC_DIST_TYPE=AppImage "$SRC_DIR" logInfo "Compiling sources..." make $MAKE_OPTIONS @@ -615,7 +636,7 @@ build() { logInfo "Launching Docker container to compile sources..." docker run --name "$DOCKER_CONTAINER_NAME" --rm \ - --cap-add SYS_ADMIN --device /dev/fuse \ + --cap-add SYS_ADMIN --security-opt apparmor:unconfined --device /dev/fuse \ -e "CC=${CC}" -e "CXX=${CXX}" \ -v "$(realpath "$SRC_DIR"):/keepassxc/src:ro" \ -v "$(realpath "$OUTPUT_DIR"):/keepassxc/out:rw" \ @@ -644,6 +665,8 @@ build() { # ----------------------------------------------------------------------- sign() { SIGN_FILES=() + SIGNTOOL="signtool" + SIGNTOOL_KEY="" while [ $# -ge 1 ]; do local arg="$1" @@ -657,6 +680,14 @@ sign() { -g|--gpg-key) GPG_KEY="$2" shift ;; + + --signtool) + SIGNTOOL="$2" + shift ;; + + --signtool-key) + SIGNTOOL_KEY="$2" + shift ;; -h|--help) printUsage "sign" @@ -675,13 +706,30 @@ sign() { printUsage "sign" exit 1 fi + + if [[ -n "$SIGNTOOL_KEY" && ! -f "$SIGNTOOL_KEY" ]]; then + exitError "Signtool Key was not found!" + elif [[ -f "$SIGNTOOL_KEY" && ! -x $(command -v "${SIGNTOOL}") ]]; then + exitError "signtool program not found on PATH!" + fi for f in "${SIGN_FILES[@]}"; do if [ ! -f "$f" ]; then exitError "File '${f}' does not exist!" fi + + if [[ -n "$SIGNTOOL_KEY" && ${f: -4} == '.exe' ]]; then + logInfo "Signing file '${f}' using signtool...\n" + read -s -p "Signtool Key Password: " password + echo + "${SIGNTOOL}" sign -f "${SIGNTOOL_KEY}" -p ${password} -v -t http://timestamp.comodoca.com/authenticode ${f} + + if [ 0 -ne $? ]; then + exitError "Signing failed!" + fi + fi - logInfo "Signing file '${f}'..." + logInfo "Signing file '${f}' using release key..." gpg --output "${f}.sig" --armor --local-user "$GPG_KEY" --detach-sig "$f" if [ 0 -ne $? ]; then diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index a609add79..6323ece88 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -30,7 +30,8 @@ if(UNIX AND NOT APPLE) 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 "categories" EXCLUDE) - install(FILES linux/keepassxc.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) + install(FILES linux/org.keepassxc.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications) + install(FILES linux/org.keepassxc.appdata.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo) install(FILES linux/keepassxc.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/mime/packages) endif(UNIX AND NOT APPLE) diff --git a/share/linux/keepassxc.xml b/share/linux/keepassxc.xml index 757047d2b..b26b4db25 100644 --- a/share/linux/keepassxc.xml +++ b/share/linux/keepassxc.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'> <mime-type type="application/x-keepass2"> - <comment>KeePass 2 database</comment> + <comment>KeePass 2 Database</comment> <glob pattern="*.kdbx"/> <icon name="application-x-keepassxc"/> </mime-type> diff --git a/share/linux/org.keepassxc.appdata.xml b/share/linux/org.keepassxc.appdata.xml new file mode 100644 index 000000000..563450a4f --- /dev/null +++ b/share/linux/org.keepassxc.appdata.xml @@ -0,0 +1,218 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright 2017 KeePassXC Team <team@keepassxc.org> --> +<component type="desktop-application"> + <id>org.keepassxc</id> + <name>KeePassXC</name> + <metadata_license>CC-BY-3.0</metadata_license> + <project_license>GPL-3.0+</project_license> + <icon type="stock">keepassxc</icon> + <url type="homepage">https://keepassxc.org</url> + <mimetypes> + <mimetype>application/x-keepass2</mimetype> + </mimetypes> + <summary>Community-driven port of the Windows application “KeePass Password Safe”</summary> + <description> + <p> + 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. + </p> + </description> + + <launchable type="desktop-id">org.keepassxc.desktop</launchable> + + <screenshots> + <screenshot type="default"> + <image>https://keepassxc.org/images/screenshots/linux/screen_001.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_002.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_003.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_004.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_005.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_006.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_007.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_008.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_009.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_010.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_011.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_012.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_013.png</image> + </screenshot> + <screenshot> + <image>https://keepassxc.org/images/screenshots/linux/screen_014.png</image> + </screenshot> + </screenshots> + + <releases> + <release version="2.2.2" date="2017-10-22"> + <description> + <ul> + <li>Fixed entries with empty URLs being reported to KeePassHTTP clients [#1031]</li> + <li>Fixed YubiKey detection and enabled CLI tool for AppImage binary [#1100]</li> + <li>Added AppStream description [#1082]</li> + <li>Improved TOTP compatibility and added new Base32 implementation [#1069]</li> + <li>Fixed error handling when processing invalid cipher stream [#1099]</li> + <li>Fixed double warning display when opening a database [#1037]</li> + <li>Fixed unlocking databases with --pw-stdin [#1087]</li> + <li>Added ability to override QT_PLUGIN_PATH environment variable for AppImages [#1079]</li> + <li>Fixed transform seed not being regenerated when saving the database [#1068]</li> + <li>Fixed only one YubiKey slot being polled [#1048]</li> + <li>Corrected an issue with entry icons while merging [#1008]</li> + <li>Corrected desktop and tray icons in Snap package [#1030]</li> + <li>Fixed screen lock and Google fallback settings [#1029]</li> + </ul> + </description> + </release><release version="2.2.1" date="2017-10-01"> + <description> + <ul> + <li>Corrected multiple snap issues [#934, #1011]</li> + <li>Corrected multiple custom icon issues [#708, #719, #994]</li> + <li>Corrected multiple Yubikey issues [#880]</li> + <li>Fixed single instance preventing load on occasion [#997]</li> + <li>Keep entry history when merging databases [#970]</li> + <li>Prevent data loss if passwords were mismatched [#1007]</li> + <li>Fixed crash after merge [#941]</li> + <li>Added configurable auto-type default delay [#703]</li> + <li>Unlock database dialog window comes to front [#663]</li> + <li>Translation and compiling fixes</li> + </ul> + </description> + </release> + <release version="2.2.0" date="2017-06-23"> + <description> + <ul> + <li>Added YubiKey 2FA integration for unlocking databases [#127]</li> + <li>Added TOTP support [#519]</li> + <li>Added CSV import tool [#146, #490]</li> + <li>Added KeePassXC CLI tool [#254]</li> + <li>Added diceware password generator [#373]</li> + <li>Added support for entry references [#370, #378]</li> + <li>Added support for Twofish encryption [#167]</li> + <li>Enabled DEP and ASLR for in-memory protection [#371]</li> + <li>Enabled single instance mode [#510]</li> + <li>Enabled portable mode [#645]</li> + <li>Enabled database lock on screensaver and session lock [#545]</li> + <li>Redesigned welcome screen with common features and recent databases [#292]</li> + <li>Multiple updates to search behavior [#168, #213, #374, #471, #603, #654]</li> + <li>Added auto-type fields {CLEARFIELD}, {SPACE}, {{}, {}} [#267, #427, #480]</li> + <li>Fixed auto-type errors on Linux [#550]</li> + <li>Prompt user prior to executing a cmd:// URL [#235]</li> + <li>Entry attributes can be protected (hidden) [#220]</li> + <li>Added extended ascii to password generator [#538]</li> + <li>Added new database icon to toolbar [#289]</li> + <li>Added context menu entry to empty recycle bin in databases [#520]</li> + <li>Added "apply" button to entry and group edit windows [#624]</li> + <li>Added macOS tray icon and enabled minimize on close [#583]</li> + <li>Fixed issues with unclean shutdowns [#170, #580]</li> + <li>Changed keyboard shortcut to create new database to CTRL+SHIFT+N [#515]</li> + <li>Compare window title to entry URLs [#556]</li> + <li>Implemented inline error messages [#162]</li> + <li>Ignore group expansion and other minor changes when making database "dirty" [#464]</li> + <li>Updated license and copyright information on souce files [#632]</li> + <li>Added contributors list to about dialog [#629]</li> + </ul> + </description> + </release> + <release version="2.1.4" date="2017-04-09"> + <description> + <ul> + <li>Bumped KeePassHTTP version to 1.8.4.2</li> + <li>KeePassHTTP confirmation window comes to foreground [#466]</li> + </ul> + </description> + </release> + <release version="2.1.3" date="2017-03-03"> + <description> + <ul> + <li>Fix possible overflow in zxcvbn library [#363]</li> + <li>Revert HiDPI setting to avoid problems on laptop screens [#332]</li> + <li>Set file meta properties in Windows executable [#330]</li> + <li>Suppress error message when auto-reloading a locked database [#345]</li> + <li>Improve usability of question dialog when database is already locked by a different instance [#346]</li> + <li>Fix compiler warnings in QHttp library [#351]</li> + <li>Use unified toolbar on Mac OS X [#361]</li> + <li>Fix an issue on X11 where the main window would be raised instead of closed on Alt+F4 [#362]</li> + </ul> + </description> + </release> + <release version="2.1.2" date="2017-02-17"> + <description> + <ul> + <li>Ask for save location when creating a new database [#302]</li> + <li>Remove Libmicrohttpd dependency to clean up the code and ensure better OS X compatibility [#317, #265]</li> + <li>Prevent Qt from degrading Wifi network performance on certain platforms [#318]</li> + <li>Visually refine user interface on OS X and other platforms [#299]</li> + <li>Remove unusable tray icon setting on OS X [#293]</li> + <li>Fix compositing glitches on Ubuntu and prevent flashing when minimizing to the tray at startup [#307]</li> + <li>Fix AppImage tray icon on Ubuntu [#277, #273]</li> + <li>Fix global menu disappearing after restoring KeePassXC from the tray on Ubuntu [#276]</li> + <li>Fix result order in entry search [#320]</li> + <li>Enable HiDPI scaling on supported platforms [#315]</li> + <li>Remove empty directories from installation target [#282]</li> + </ul> + </description> + </release> + <release version="2.1.1" date="2017-02-06"> + <description> + <ul> + <li>Enabled HTTP plugin build; plugin is disabled by default and limited to localhost [#147]</li> + <li>Escape HTML in dialog boxes [#247]</li> + <li>Corrected crashes in favicon download and password generator [#233, #226]</li> + <li>Increase font size of password meter [#228]</li> + <li>Fixed compatibility with Qt 5.8 [#211]</li> + <li>Use consistent button heights in password generator [#229]</li> + </ul> + </description> + </release> + <release version="2.1.0" date="2017-01-22"> + <description> + <ul> + <li>Show unlock dialog when using autotype on a closed database [#10, #89]</li> + <li>Show different tray icon when database is locked [#37, #46]</li> + <li>Support autotype on Windows and OS X [#42, #60, #63]</li> + <li>Add delay feature to autotype [#76, #77]</li> + <li>Add password strength meter [#84, #92]</li> + <li>Add option for automatically locking the database when minimizing the window [#57]</li> + <li>Add feature to download favicons and use them as entry icons [#30]</li> + <li>Automatically reload and merge database when the file changed on disk [#22, #33, #93]</li> + <li>Add tool for merging two databases [#22, #47, #143]</li> + <li>Add --pw-stdin commandline option to unlock the database by providing a password on STDIN [#54]</li> + <li>Add utility script for reading the database password from KWallet [#55]</li> + <li>Fix some KeePassHTTP settings not being remembered [#34, #65]</li> + <li>Make search box persistent [#15, #67, #157]</li> + <li>Enhance search feature by scoping the search to selected group [#16, #118]</li> + <li>Improve interaction between search field and entry list [#131, #141]</li> + <li>Add stand-alone password-generator [#18, #92]</li> + <li>Don't require password repetition when password is visible [#27, #92]</li> + <li>Add support for entry attributes in autotype sequences [#107]</li> + <li>Always focus password field when opening the database unlock widget [#116, #117]</li> + <li>Fix compilation errors on various platforms [#53, #126, #130]</li> + <li>Restructure and improve kdbx-extract utility [#160]</li> + </ul> + </description> + </release> + </releases> +</component> diff --git a/share/linux/keepassxc.desktop b/share/linux/org.keepassxc.desktop index 1e72c4f84..d3b007bdc 100644 --- a/share/linux/keepassxc.desktop +++ b/share/linux/org.keepassxc.desktop @@ -1,13 +1,16 @@ [Desktop Entry] Name=KeePassXC -GenericName=Community Password Manager +GenericName=Password Manager GenericName[de]=Passwortverwaltung GenericName[es]=Gestor de contraseñas GenericName[fr]=Gestionnaire de mot de passe GenericName[ru]=менеджер паролей +Comment=Community-driven port of the Windows application “KeePass Password Safe” Exec=keepassxc %f +TryExec=keepassxc Icon=keepassxc Terminal=false Type=Application -Categories=Qt;Utility; +Version=1.0 +Categories=Utility;Security;Qt; MimeType=application/x-keepass2; diff --git a/share/translations/keepassx_cs.ts b/share/translations/keepassx_cs.ts index 6904b188e..737c2b03e 100644 --- a/share/translations/keepassx_cs.ts +++ b/share/translations/keepassx_cs.ts @@ -67,6 +67,10 @@ Jádro systému: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>K hlášení chyby vždy připojte následující údaje:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation>Distribuce: %1</translation> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1095,7 +1099,7 @@ Chcete ji přesto otevřít?</translation> </message> <message> <source>Custom icon already exists</source> - <translation type="unfinished"/> + <translation>Tato vlastní ikona už existuje</translation> </message> </context> <context> @@ -1319,6 +1323,17 @@ Jedná se o jednosměrný převod. Databázi, vzniklou z importu, nepůjde otev </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>Nedaří se vyvolat výzva-odpověď.</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Nedaří se spočítat hlavní klíč</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> @@ -1338,7 +1353,7 @@ Jedná se o jednosměrný převod. Databázi, vzniklou z importu, nepůjde otev </message> <message> <source>Existing single-instance lock file is invalid. Launching new instance.</source> - <translation type="unfinished"/> + <translation>Existující uzamykací soubor, zajišťující spuštění pouze jedné instance, není platný. Spouští se nová instance.</translation> </message> </context> <context> diff --git a/share/translations/keepassx_da.ts b/share/translations/keepassx_da.ts index 55e91dd02..563f6adb3 100644 --- a/share/translations/keepassx_da.ts +++ b/share/translations/keepassx_da.ts @@ -67,6 +67,10 @@ Kerne: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Inkludér følgende information når du indrapporterer en fejl:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1314,6 +1318,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Kan ikke beregne hovednøgle</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_de.ts b/share/translations/keepassx_de.ts index 8c55f99ad..2fd20f04a 100644 --- a/share/translations/keepassx_de.ts +++ b/share/translations/keepassx_de.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Geben Sie folgende Informationen an, wenn Sie einen Bug melden:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation>Distribution: %1</translation> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1092,7 +1096,7 @@ Möchten Sie diese dennoch öffnen?</translation> </message> <message> <source>Custom icon already exists</source> - <translation type="unfinished"/> + <translation>Es gibt bereits ein eigenes Symbol </translation> </message> </context> <context> @@ -1316,6 +1320,17 @@ Dieser Vorgang ist nur in eine Richtung möglich. Die importierte Datenbank kann </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>Fehler beim Ausführen des Challenge-Response-Verfahrens</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Berechnung des Hauptschlüssels gescheitert</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> @@ -1335,7 +1350,7 @@ Dieser Vorgang ist nur in eine Richtung möglich. Die importierte Datenbank kann </message> <message> <source>Existing single-instance lock file is invalid. Launching new instance.</source> - <translation type="unfinished"/> + <translation>Vorhandene einmal-Sperrdatei ist ungültig. Starte neuen Vorgang. </translation> </message> </context> <context> diff --git a/share/translations/keepassx_el.ts b/share/translations/keepassx_el.ts index a641c0d5e..5224c0242 100644 --- a/share/translations/keepassx_el.ts +++ b/share/translations/keepassx_el.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</source> <source>Include the following information whenever you report a bug:</source> <translation>Συμπεριλάβετε τις ακόλουθες πληροφορίες όποτε αναφέρετε κάποιο σφάλμα:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1312,6 +1316,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Σε θέση να υπολογίσει το κύριο κλειδί</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_en.ts b/share/translations/keepassx_en.ts index c971512ab..7cc9fc3c3 100644 --- a/share/translations/keepassx_en.ts +++ b/share/translations/keepassx_en.ts @@ -66,6 +66,10 @@ Kernel: %3 %4</source> <source>Include the following information whenever you report a bug:</source> <translation type="unfinished"></translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"></translation> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1310,6 +1314,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_es.ts b/share/translations/keepassx_es.ts index 0fa7b14c6..f8176b807 100644 --- a/share/translations/keepassx_es.ts +++ b/share/translations/keepassx_es.ts @@ -67,6 +67,10 @@ Núcleo: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Incluya la información siguiente cuando informe sobre un error:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1318,6 +1322,17 @@ Esta migración es en único sentido. No podrá abrir la base de datos importada </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>No se pudo hacer el desafío/respuesta:</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>No se puede calcular la clave maestra</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_eu.ts b/share/translations/keepassx_eu.ts index 738dd29c5..ffbb4a9a5 100644 --- a/share/translations/keepassx_eu.ts +++ b/share/translations/keepassx_eu.ts @@ -65,6 +65,10 @@ Kernel: %3 %4</source> <source>Include the following information whenever you report a bug:</source> <translation type="unfinished"/> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1301,6 +1305,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Ezin izan da gako nagusia kalkulatu</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_fi.ts b/share/translations/keepassx_fi.ts index 5f1862565..c7d61473e 100644 --- a/share/translations/keepassx_fi.ts +++ b/share/translations/keepassx_fi.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Sisällytä seuraavat tiedot aina kun ilmoitat ongelmasta:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1315,6 +1319,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Pääavaimen laskeminen ei onnistu</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_fr.ts b/share/translations/keepassx_fr.ts index aa04ae5c0..90580e146 100644 --- a/share/translations/keepassx_fr.ts +++ b/share/translations/keepassx_fr.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Inclure l'information suivante lorsque vous signaler un bug:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1319,6 +1323,17 @@ Il s'agit d'une migration à sens unique. Vous ne pourrez pas ouvrir l </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>Impossible de lancer une challenge-réponse.</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Impossible de calculer la clé maître</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_hu.ts b/share/translations/keepassx_hu.ts index d4c2880f0..dc9877054 100644 --- a/share/translations/keepassx_hu.ts +++ b/share/translations/keepassx_hu.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Minden hibajelentésnél legyenek mellékelve ezek az információk:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation>Disztribúció: %1</translation> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1094,7 +1098,7 @@ Mindenképp megnyitja?</translation> </message> <message> <source>Custom icon already exists</source> - <translation type="unfinished"/> + <translation>Az egyéni ikon már létezik</translation> </message> </context> <context> @@ -1318,6 +1322,17 @@ Ez egyirányú migráció. Nem lehet majd megnyitni az importált adatbázist a </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>Nem lehet kiutalni a kihívás-választ.</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Nem lehet kiszámítani a mesterkulcsot</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> @@ -1337,7 +1352,7 @@ Ez egyirányú migráció. Nem lehet majd megnyitni az importált adatbázist a </message> <message> <source>Existing single-instance lock file is invalid. Launching new instance.</source> - <translation type="unfinished"/> + <translation>A meglévő egypéldányos zárolási fájl érvénytelen. Új példány indítása.</translation> </message> </context> <context> diff --git a/share/translations/keepassx_id.ts b/share/translations/keepassx_id.ts index 8f7cd0232..f7db658d2 100644 --- a/share/translations/keepassx_id.ts +++ b/share/translations/keepassx_id.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Sertakan informasi berikut setiap Anda melaporkan bug:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1318,6 +1322,17 @@ Ini adalah migrasi satu arah. Anda tidak akan bisa membuka basis data yang diimp </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Tidak bisa mengkalkulasi kunci utama</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_it.ts b/share/translations/keepassx_it.ts index f60f0b264..5125a8b63 100644 --- a/share/translations/keepassx_it.ts +++ b/share/translations/keepassx_it.ts @@ -3,7 +3,7 @@ <name>AboutDialog</name> <message> <source>About KeePassXC</source> - <translation>A proposito di KeePassXC</translation> + <translation>Info su KeePassXC</translation> </message> <message> <source>About</source> @@ -15,11 +15,11 @@ </message> <message> <source>Debug Info</source> - <translation>Informazioni di debug</translation> + <translation>Informazioni debug</translation> </message> <message> <source>Copy to clipboard</source> - <translation>Copia negli appunti</translation> + <translation>Copia negli Appunti</translation> </message> <message> <source>Version %1 @@ -49,7 +49,7 @@ Kernel: %3 %4</translation> </message> <message> <source>Report bugs at: <a href="https://github.com/keepassxreboot/keepassxc/issues" style="text-decoration: underline;">https://github.com</a></source> - <translation>Segnala eventuali problemi su: <a href="https://github.com/keepassxreboot/keepassxc/issues" style="text-decoration: underline;">https://github.com</a></translation> + <translation>Segnala eventuali problemi in: <a href="https://github.com/keepassxreboot/keepassxc/issues" style="text-decoration: underline;">https://github.com</a></translation> </message> <message> <source>KeePassXC is distributed under the terms of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source> @@ -57,7 +57,7 @@ Kernel: %3 %4</translation> </message> <message> <source>Project Maintainers:</source> - <translation>Manutentori del progetto:</translation> + <translation>Manutenzione progetto:</translation> </message> <message> <source><a href="https://github.com/keepassxreboot/keepassxc/graphs/contributors">See Contributions on GitHub</a></source> @@ -65,7 +65,11 @@ Kernel: %3 %4</translation> </message> <message> <source>Include the following information whenever you report a bug:</source> - <translation>Includi le seguenti informazioni quando segnali un problema:</translation> + <translation>Quando segnali un problema includi le seguenti informazioni:</translation> + </message> + <message> + <source>Distribution: %1</source> + <translation>Distribuzione: %1</translation> </message> </context> <context> @@ -85,23 +89,23 @@ Kernel: %3 %4</translation> <message> <source>%1 has requested access to passwords for the following item(s). Please select whether you want to allow access.</source> - <translation>%1 ha richiesto accesso alle passwords per il seguente elemento(i). -Perfavore seleziona se vuoi consentire l'accesso.</translation> + <translation>%1 ha richiesto accesso alle passwords per il seguente elemento/i. +Seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>KeePassXC HTTP Confirm Access</source> - <translation>KeePassXC HTTP Conferma Accesso</translation> + <translation>KeePassXC HTTP conferma accesso</translation> </message> </context> <context> <name>AutoType</name> <message> <source>Couldn't find an entry that matches the window title:</source> - <translation>Impossibile trovare una voce che corrisponda al titolo della finestra</translation> + <translation>Impossibile trovare un elemento che corrisponda al titolo della finestra:</translation> </message> <message> <source>Auto-Type - KeePassXC</source> - <translation>Auto-Completamento - KeePassXC</translation> + <translation>Auto completamento - KeePassXC</translation> </message> </context> <context> @@ -123,11 +127,11 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> <name>AutoTypeSelectDialog</name> <message> <source>Select entry to Auto-Type:</source> - <translation>Seleziona una voce per Auto-Type:</translation> + <translation>Seleziona un elemento per l'auto completamento:</translation> </message> <message> <source>Auto-Type - KeePassXC</source> - <translation>Auto-Completamento - KeePassXC</translation> + <translation> KeePassXC - Auto completamento</translation> </message> </context> <context> @@ -170,7 +174,7 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>Select a key file</source> - <translation>Seleziona il file chiave</translation> + <translation>Seleziona un file chiave</translation> </message> <message> <source>Do you really want to use an empty string as password?</source> @@ -178,7 +182,7 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>Different passwords supplied.</source> - <translation>Sono state fornite password differenti.</translation> + <translation>Sono state inserite password differenti.</translation> </message> <message> <source>Failed to set %1 as the Key file: @@ -196,7 +200,7 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>Refresh</source> - <translation>Ricarica</translation> + <translation>Aggiorna</translation> </message> <message> <source>Empty password</source> @@ -204,18 +208,18 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>Changing master key failed: no YubiKey inserted.</source> - <translation>Cambio password principale fallito: nessuna YubiKey inserita.</translation> + <translation>Modifica password principale fallitoa. Nessuna YubiKey inserita.</translation> </message> </context> <context> <name>CloneDialog</name> <message> <source>Clone Options</source> - <translation>Opzioni di clonazione</translation> + <translation>Opzioni clonazione</translation> </message> <message> <source>Replace username and password with references</source> - <translation>Sostituisci nome user e password con riferimenti</translation> + <translation>Sostituisci nome utente e password con riferimenti</translation> </message> <message> <source>Copy history</source> @@ -238,7 +242,7 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>size, rows, columns</source> - <translation>dimensione, righe. colonne</translation> + <translation>dimensione, righe, colonne</translation> </message> <message> <source>Encoding</source> @@ -262,11 +266,11 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>First record has field names</source> - <translation>Il primo record ha i nomi dei campi</translation> + <translation>Il primo record contiene i nomi dei campi</translation> </message> <message> <source>Number of headers line to discard</source> - <translation>Numero di righe di intestazione da scartare</translation> + <translation>Numero righe di intestazione da scartare</translation> </message> <message> <source>Consider '\' an escape character</source> @@ -278,7 +282,7 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>Column layout</source> - <translation>Disposizione di colonna</translation> + <translation>Disposizione colonna</translation> </message> <message> <source>Not present in CSV file</source> @@ -286,7 +290,7 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>Empty fieldname </source> - <translation>Nome di campo vuoto</translation> + <translation>Nome campo vuoto</translation> </message> <message> <source>column </source> @@ -302,7 +306,7 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>Error(s) detected in CSV file !</source> - <translation>Errore(i) rilevati nel file CSV!</translation> + <translation>Errore/i rilevati nel file CSV!</translation> </message> <message> <source> more messages skipped]</source> @@ -315,7 +319,7 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> <message> <source>CSV import: writer has errors: </source> - <translation>Importazione CSV: lo scrittore ha errori: + <translation>Importazione CSV: rilevati errori: </translation> </message> </context> @@ -323,7 +327,7 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> <name>CsvImportWizard</name> <message> <source>Import CSV file</source> - <translation>Importare un file CSV</translation> + <translation>Importa file CSV</translation> </message> <message> <source>Error</source> @@ -389,7 +393,7 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>Refresh</source> - <translation>Ricarica</translation> + <translation>Aggiorna</translation> </message> <message> <source>Challenge Response:</source> @@ -416,36 +420,36 @@ Perfavore seleziona se vuoi consentire l'accesso.</translation> </message> <message> <source>Unable to open the database.</source> - <translation>Impossibile aprire il database</translation> + <translation>Impossibile aprire il database.</translation> </message> <message> <source>Success</source> - <translation>Successo</translation> + <translation>Completato</translation> </message> <message> <source>The database has been successfully repaired You can now save it.</source> - <translation>Il database è stato riparato con successo + <translation>Il database è stato correttamente riparato. Adesso puoi salvarlo.</translation> </message> <message> <source>Unable to repair the database.</source> - <translation>Impossibile riparare il database</translation> + <translation>Impossibile riparare il database.</translation> </message> </context> <context> <name>DatabaseSettingsWidget</name> <message> <source>Database name:</source> - <translation>Nome del database:</translation> + <translation>Nome database:</translation> </message> <message> <source>Database description:</source> - <translation>Descrizione del database:</translation> + <translation>Descrizione database:</translation> </message> <message> <source>Transform rounds:</source> - <translation>Round di trasformazione:</translation> + <translation>Arrotondamenti trasformazione:</translation> </message> <message> <source>Default username:</source> @@ -453,23 +457,23 @@ Adesso puoi salvarlo.</translation> </message> <message> <source> MiB</source> - <translation>MiB</translation> + <translation> MB</translation> </message> <message> <source>Benchmark</source> - <translation>Prestazione</translation> + <translation>Prestazioni</translation> </message> <message> <source>Max. history items:</source> - <translation>Max. oggetti nella cronologia:</translation> + <translation>Oggetti max. nella cronologia:</translation> </message> <message> <source>Max. history size:</source> - <translation>Max. grandezza della cronologia:</translation> + <translation>Grandezza max. cronologia:</translation> </message> <message> <source>Use recycle bin</source> - <translation>Usa il cestino</translation> + <translation>Usa il Cestino</translation> </message> <message> <source>AES: 256 Bit (default)</source> @@ -488,7 +492,7 @@ Adesso puoi salvarlo.</translation> <name>DatabaseTabWidget</name> <message> <source>Root</source> - <translation>Root</translation> + <translation>Radice</translation> </message> <message> <source>KeePass 2 Database</source> @@ -520,21 +524,21 @@ Adesso puoi salvarlo.</translation> </message> <message> <source>Close?</source> - <translation>Chiudere?</translation> + <translation>Vuoi chiudere?</translation> </message> <message> <source>Save changes?</source> - <translation>Salvare modifiche?</translation> + <translation>Vuoi salvare modifiche?</translation> </message> <message> <source>"%1" was modified. Save changes?</source> <translation>"%1" è stata modificato. -Salvare le modifiche?</translation> +Vuoi salvare le modifiche?</translation> </message> <message> <source>Writing the database failed.</source> - <translation>Scrittura del database non riuscita.</translation> + <translation>Scrittura del database fallita.</translation> </message> <message> <source>Save database as</source> @@ -556,7 +560,7 @@ Salvare le modifiche?</translation> <source>Can't lock the database as you are currently editing it. Please press cancel to finish your changes or discard them.</source> <translation>Non è possibile bloccare il database dato che lo stai modificando. -Premere Annulla per completare le modifiche o scartarle.</translation> +Seleziona 'Annulla' per completare le modifiche o scartarle.</translation> </message> <message> <source>This database has never been saved. @@ -576,19 +580,19 @@ Altrimenti le modifiche verranno perse.</translation> <source>"%1" is in edit mode. Discard changes and close anyway?</source> <translation>"%1" è in modalità modifica. -Annullare le modifiche e chiudere comunque?</translation> +Vuoi annullare le modifiche e chiudere comunque?</translation> </message> <message> <source>Export database to CSV file</source> - <translation>Esporta il database come file CSV</translation> + <translation>Esporta database come file CSV</translation> </message> <message> <source>CSV file</source> - <translation>file CSV</translation> + <translation>File CSV</translation> </message> <message> <source>Writing the CSV file failed.</source> - <translation>Scrittura del file CSV non riuscita.</translation> + <translation>Scrittura file CSV fallita.</translation> </message> <message> <source>Unable to open the database.</source> @@ -610,18 +614,18 @@ Vuoi salvare comunque?</translation> </message> <message> <source>Database already opened</source> - <translation>Database già caricato</translation> + <translation>Database già aperto</translation> </message> <message> <source>The database you are trying to open is locked by another instance of KeePassXC. Do you want to open it anyway?</source> - <translation>Il database che stai provando ad aprire è bloccato da una altra instanza di KeePassXC. + <translation>Il database che stai cercando di aprire è bloccato da un'altra instanza di KeePassXC. Vuoi aprilo comunque?</translation> </message> <message> <source>Open read-only</source> - <translation>Aperto in sola lettura</translation> + <translation>Apri in sola lettura</translation> </message> <message> <source>File opened in read only mode.</source> @@ -629,42 +633,42 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Open CSV file</source> - <translation>Apri un file CSV</translation> + <translation>Apri file CSV</translation> </message> </context> <context> <name>DatabaseWidget</name> <message> <source>Change master key</source> - <translation>Cambia chiave principale</translation> + <translation>Modifica chiave principale</translation> </message> <message> <source>Delete entry?</source> - <translation>Eliminare voce?</translation> + <translation>Vuoi eliminare l'elemento?</translation> </message> <message> <source>Do you really want to delete the entry "%1" for good?</source> - <translation>Vuoi veramente eliminare la voce "%1"?</translation> + <translation>Vuoi veramente eliminare l'elemento "%1"?</translation> </message> <message> <source>Delete entries?</source> - <translation>Eliminare voci?</translation> + <translation>Vuoi eliminare gli elementi?</translation> </message> <message> <source>Do you really want to delete %1 entries for good?</source> - <translation>Vuoi veramente eliminare %1 voci?</translation> + <translation>Vuoi veramente eliminare %1 elementi?</translation> </message> <message> <source>Move entries to recycle bin?</source> - <translation>Muovere le voci nel cestino?</translation> + <translation>Vuoi spostare gli elementi nel Cestino?</translation> </message> <message numerus="yes"> <source>Do you really want to move %n entry(s) to the recycle bin?</source> - <translation><numerusform>Vuoi veramente spostare %n voce(i) nel cestino?</numerusform><numerusform>Vuoi veramente spostare %n voce(i) nel cestino?</numerusform></translation> + <translation><numerusform>Vuoi veramente spostare %n elemento nel Cestino?</numerusform><numerusform>Vuoi veramente spostare %n elementi nel Cestino?</numerusform></translation> </message> <message> <source>Delete group?</source> - <translation>Eliminare gruppo?</translation> + <translation>Vuoi eliminare il gruppo?</translation> </message> <message> <source>Do you really want to delete the group "%1" for good?</source> @@ -676,23 +680,23 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Move entry to recycle bin?</source> - <translation>Muovere la voce nel cestino?</translation> + <translation>Vuoi spostare l'elemento nel Cestino?</translation> </message> <message> <source>Do you really want to move entry "%1" to the recycle bin?</source> - <translation>Vuoi veramente spostare la voce "%1" nel cestino?</translation> + <translation>Vuoi veramente spostare l'elemento "%1" nel Cestino?</translation> </message> <message> <source>Searching...</source> - <translation>Ricerca in corso...</translation> + <translation>Ricerca...</translation> </message> <message> <source>No current database.</source> - <translation>Nessun database corrente.</translation> + <translation>Nessun database attuale.</translation> </message> <message> <source>No source database, nothing to do.</source> - <translation>Nessun database sorgente, niente da fare.</translation> + <translation>Nessun database sorgente. Nessuna operazione da fare.</translation> </message> <message> <source>Search Results (%1)</source> @@ -704,11 +708,11 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Execute command?</source> - <translation>Esegui comando?</translation> + <translation>Vuoi eseguire il comando?</translation> </message> <message> <source>Do you really want to execute the following command?<br><br>%1<br></source> - <translation>Sei sicuro di voler eseguire il comando seguente?<br><br>%1<br></translation> + <translation>Sei sicuro di voler eseguire il seguente comando?<br><br>%1<br></translation> </message> <message> <source>Remember my choice</source> @@ -716,19 +720,19 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Autoreload Request</source> - <translation>Auto ricarica le richieste</translation> + <translation>Ricaricamento automatico richieste</translation> </message> <message> <source>The database file has changed. Do you want to load the changes?</source> - <translation>Il file del database è cambiato. Vuoi caricare le modifiche?</translation> + <translation>Il file del database è stato modificato. Vuoi caricare le modifiche?</translation> </message> <message> <source>Merge Request</source> - <translation>Richiesta di fusione</translation> + <translation>Richiesta di unione</translation> </message> <message> <source>The database file has changed and you have unsaved changes.Do you want to merge your changes?</source> - <translation>Il file del database è cambiato e ci sono delle modifiche non salvate. Vuoi unire i tuoi cambiamenti.</translation> + <translation>Il file del database è stato modificato e ci sono delle modifiche non salvate. Vuoi unire i tuoi cambiamenti?</translation> </message> <message> <source>Could not open the new database file while attempting to autoreload this database.</source> @@ -736,18 +740,18 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Empty recycle bin?</source> - <translation>Svuotare il cestino?</translation> + <translation>Vuoi svuotare il Cestino?</translation> </message> <message> <source>Are you sure you want to permanently delete everything from your recycle bin?</source> - <translation>Sei sicuro di voler eliminare tutto definitivamente dal tuo Cestino?</translation> + <translation>Sei sicuro di voler eliminare tutto definitivamente dal Cestino?</translation> </message> </context> <context> <name>EditEntryWidget</name> <message> <source>Entry</source> - <translation>Voce</translation> + <translation>Elemento</translation> </message> <message> <source>Advanced</source> @@ -759,7 +763,7 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Auto-Type</source> - <translation>Auto-Type</translation> + <translation>Completamento automatico</translation> </message> <message> <source>Properties</source> @@ -771,19 +775,19 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Entry history</source> - <translation>Cronologia voce</translation> + <translation>Cronologia elemento</translation> </message> <message> <source>Add entry</source> - <translation>Aggiungere voce</translation> + <translation>Aggiungi elemento</translation> </message> <message> <source>Edit entry</source> - <translation>Modificare voce</translation> + <translation>Modifica elemento</translation> </message> <message> <source>Different passwords supplied.</source> - <translation>Sono state immesse password differenti.</translation> + <translation>Sono state inserite password differenti.</translation> </message> <message> <source>New attribute</source> @@ -799,7 +803,7 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Save attachment</source> - <translation>Salvare l'allegato</translation> + <translation>Salva allegato</translation> </message> <message> <source>Unable to save the attachment: @@ -825,7 +829,7 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Confirm Remove</source> - <translation>Conferma l'eliminazione</translation> + <translation>Conferma eliminazione</translation> </message> <message> <source>Are you sure you want to remove this attribute?</source> @@ -833,7 +837,7 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>[PROTECTED] Press reveal to view or edit</source> - <translation>[PROTETTO] Premere rivelare per visualizzare o modificare</translation> + <translation>[PROTETTO] Seleziona 'Rileva' per visualizzare o modificare</translation> </message> <message> <source>Are you sure you want to remove this attachment?</source> @@ -844,7 +848,7 @@ Vuoi aprilo comunque?</translation> <name>EditEntryWidgetAdvanced</name> <message> <source>Additional attributes</source> - <translation>Attributi addizionali</translation> + <translation>Attributi aggiuntivi</translation> </message> <message> <source>Add</source> @@ -868,22 +872,22 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Edit Name</source> - <translation>Modifica il nome</translation> + <translation>Modifica nome</translation> </message> <message> <source>Protect</source> - <translation>Proteggere</translation> + <translation>Proteggi</translation> </message> <message> <source>Reveal</source> - <translation>Rivelare</translation> + <translation>Rivela</translation> </message> </context> <context> <name>EditEntryWidgetAutoType</name> <message> <source>Enable Auto-Type for this entry</source> - <translation>Abilita Auto-Type per questa voce</translation> + <translation>Abilita completamento automatico per questo elemento</translation> </message> <message> <source>+</source> @@ -899,11 +903,11 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Inherit default Auto-Type sequence from the &group</source> - <translation>Eredita la sequenza per l'Auto-Completamento dal &gruppo</translation> + <translation>Eredita la sequenza per il completamento automatico dal &gruppo</translation> </message> <message> <source>&Use custom Auto-Type sequence:</source> - <translation>&Usa sequenza di Auto-Completamento personalizzata:</translation> + <translation>&Usa sequenza di compeltamento automatico personalizzata:</translation> </message> <message> <source>Use default se&quence</source> @@ -915,14 +919,14 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Window Associations</source> - <translation>Associazioni di finestra</translation> + <translation>Associazioni finestra</translation> </message> </context> <context> <name>EditEntryWidgetHistory</name> <message> <source>Show</source> - <translation>Mostra</translation> + <translation>Visualizza</translation> </message> <message> <source>Restore</source> @@ -961,7 +965,7 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Expires</source> - <translation>Scade:</translation> + <translation>Scade</translation> </message> <message> <source>Presets</source> @@ -1027,15 +1031,15 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Auto-Type</source> - <translation>Auto-Type</translation> + <translation>Completamento automatico</translation> </message> <message> <source>&Use default Auto-Type sequence of parent group</source> - <translation>&Usa la sequenza di auto-digitazione predefinita del gruppo genitore</translation> + <translation>&Usa la sequenza di completamento automatico predefinita del gruppo genitore</translation> </message> <message> <source>Set default Auto-Type se&quence</source> - <translation>Imposta la se&quenza predefinita di auto-digitazione</translation> + <translation>Imposta se&quenza predefinita di completamento automatico</translation> </message> </context> <context> @@ -1066,7 +1070,7 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Unable to fetch favicon.</source> - <translation>Impossibile scaricare la favicon.</translation> + <translation>Impossibile scaricare favicon.</translation> </message> <message> <source>Can't read icon</source> @@ -1082,19 +1086,19 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Confirm Delete</source> - <translation>Conferma la cancellazione</translation> + <translation>Conferma eliminazione</translation> </message> <message> <source>This icon is used by %1 entries, and will be replaced by the default icon. Are you sure you want to delete it?</source> - <translation>Questa icona viene utilizzata da %1 voci, e sarà sostituita dall'icona predefinita. Sei sicuro di volerla eliminare?</translation> + <translation>Questa icona viene usata da %1 elementi, e sarà sostituita dall'icona predefinita. Sei sicuro di volerla eliminare?</translation> </message> <message> <source>Hint: You can enable Google as a fallback under Tools>Settings>Security</source> - <translation>Suggerimento: è possibile abilitare Google come ripiego in Strumenti>Impostazioni>Sicurezza</translation> + <translation>Suggerimento: è possibile abilitare Google come alternativa in 'Strumenti'>'Impostazioni'>'Sicurezza'</translation> </message> <message> <source>Custom icon already exists</source> - <translation type="unfinished"/> + <translation>L'icona personalizzata esiste già</translation> </message> </context> <context> @@ -1120,7 +1124,7 @@ Vuoi aprilo comunque?</translation> <name>Entry</name> <message> <source> - Clone</source> - <translation>- Clona</translation> + <translation> - Clona</translation> </message> </context> <context> @@ -1188,11 +1192,11 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Character Types</source> - <translation>Tipi di carattere</translation> + <translation>Tipi carattere</translation> </message> <message> <source>Upper Case Letters</source> - <translation>Lettere Maiuscole</translation> + <translation>Lettere maiuscole</translation> </message> <message> <source>A-Z</source> @@ -1200,7 +1204,7 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Lower Case Letters</source> - <translation>Lettere Minuscole</translation> + <translation>Lettere minuscole</translation> </message> <message> <source>a-z</source> @@ -1273,7 +1277,7 @@ Vuoi aprilo comunque?</translation> </message> <message> <source>Root</source> - <translation>Root</translation> + <translation>Radice</translation> </message> <message> <source>Unable to calculate master key</source> @@ -1313,8 +1317,19 @@ 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.</source> <translation>Il file selezionato è un vecchio database di KeePass 1 (.kdb). -Puoi importarlo facendo clic su Database > 'Importa database KeePass 1...'. -Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il database importato con la vecchia versione di KeePassX 0.4.</translation> +È possibile importarlo facendo clic su 'Database' > 'Importa database KeePass 1...'. +Si tratta di una migrazione unidirezionale. Non sarà possibile aprire il database importato con la vecchia versione di KeePassX 0.4.</translation> + </message> +</context> +<context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>Non in grado dare la risposta di verifica.</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Impossibile calcolare la chiave principale</translation> </message> </context> <context> @@ -1333,11 +1348,11 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Another instance of KeePassXC is already running.</source> - <translation>Un'altra istanza di KeePassXC è già in esecuzione.</translation> + <translation>È già in esecuzione un'altra istanza di KeePassXC.</translation> </message> <message> <source>Existing single-instance lock file is invalid. Launching new instance.</source> - <translation type="unfinished"/> + <translation>Il file di blocco singola istanza non è valido. Esegui una nuova istanza.</translation> </message> </context> <context> @@ -1352,11 +1367,11 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Copy username to clipboard</source> - <translation>Copia nome utente negli appunti</translation> + <translation>Copia nome utente negli Appunti</translation> </message> <message> <source>Copy password to clipboard</source> - <translation>Copia password negli appunti</translation> + <translation>Copia password negli Appunti</translation> </message> <message> <source>Settings</source> @@ -1364,7 +1379,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Show toolbar</source> - <translation>Mostra barra degli strumenti</translation> + <translation>Visualizza barra strumenti</translation> </message> <message> <source>read-only</source> @@ -1372,7 +1387,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Toggle window</source> - <translation>Cambia finestra</translation> + <translation>Abilita/disabilita finestra</translation> </message> <message> <source>KeePass 2 Database</source> @@ -1384,11 +1399,11 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Save repaired database</source> - <translation>Salva il database riparato</translation> + <translation>Salva database riparato</translation> </message> <message> <source>Writing the database failed.</source> - <translation>Scrittura del database non riuscita.</translation> + <translation>Scrittura database fallita.</translation> </message> <message> <source>&Recent databases</source> @@ -1400,7 +1415,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Copy att&ribute to clipboard</source> - <translation>Copia gli att&ributi nella clipboard</translation> + <translation>Copia gli att&ributi negli Appunti</translation> </message> <message> <source>&Groups</source> @@ -1440,7 +1455,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>&View/Edit entry</source> - <translation>&Vedi/Modifica l'elemento</translation> + <translation>&Visualizza/modifica elemento</translation> </message> <message> <source>&Delete entry</source> @@ -1460,7 +1475,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>&Database settings</source> - <translation>Impostazioni &Database</translation> + <translation>Impostazioni &database</translation> </message> <message> <source>&Clone entry</source> @@ -1496,7 +1511,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>&Perform Auto-Type</source> - <translation>&Esegui Auto-Completamento</translation> + <translation>&Esegui completamento automatico</translation> </message> <message> <source>&Open URL</source> @@ -1520,11 +1535,11 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Password Generator</source> - <translation>Generatore Password</translation> + <translation>Genera password</translation> </message> <message> <source>Clear history</source> - <translation>Cancella cronologia</translation> + <translation>Azzera cronologia</translation> </message> <message> <source>&Database</source> @@ -1540,7 +1555,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Empty recycle bin</source> - <translation>Svuota il cestino</translation> + <translation>Svuota il Cestino</translation> </message> <message> <source>Access error for config file %1</source> @@ -1552,7 +1567,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Please touch the button on your YubiKey!</source> - <translation>Prego tocca il pulsante sulla tua YubiKey!</translation> + <translation>Seleziona il pulsante nelal YubiKey!</translation> </message> <message> <source>&Help</source> @@ -1564,27 +1579,27 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Sa&ve database as...</source> - <translation>Sal&va il database come...</translation> + <translation>Sal&va database come...</translation> </message> <message> <source>Change &master key...</source> - <translation>Ca&mbia la chiave principale...</translation> + <translation>&Modifica chiave principale...</translation> </message> <message> <source>&Export to CSV file...</source> - <translation>&Esporta su un file CSV...</translation> + <translation>&Esporta in file CSV...</translation> </message> <message> <source>Import KeePass 1 database...</source> - <translation>Importa un database di KeePass 1...</translation> + <translation>Importa database di KeePass 1...</translation> </message> <message> <source>Import CSV file...</source> - <translation>Importa un file CSV...</translation> + <translation>Importa file CSV...</translation> </message> <message> <source>Re&pair database...</source> - <translation>Ri&para il database...</translation> + <translation>Ri&para database...</translation> </message> <message> <source>Set up TOTP...</source> @@ -1595,7 +1610,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data <name>OptionDialog</name> <message> <source>Dialog</source> - <translation>Dialogo</translation> + <translation>Finestra</translation> </message> <message> <source>General</source> @@ -1603,15 +1618,15 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Sh&ow a notification when credentials are requested</source> - <translation>M&ostra una notifica quando sono richeste le credenziali</translation> + <translation>Visualizza una n&otifica quando sono richeste le credenziali</translation> </message> <message> <source>Sort matching entries by &username</source> - <translation>Ordina le voci trovate per &nome utente</translation> + <translation>Ordina elementi trovati per &nome utente</translation> </message> <message> <source>Re&move all stored permissions from entries in active database</source> - <translation>R&imuovi tutti i permessi presenti dalle voci nel database attivo</translation> + <translation>R&imuovi tutti i permessi presenti negli elementi nel database attivo</translation> </message> <message> <source>Advanced</source> @@ -1619,15 +1634,15 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Always allow &access to entries</source> - <translation>Permetti sempre di &accedere alle voci</translation> + <translation>Permetti sempre di &accedere agli elementi</translation> </message> <message> <source>Always allow &updating entries</source> - <translation>Permetti sempre di &aggiornare le voci</translation> + <translation>Permetti sempre di &aggiornare gli elementi</translation> </message> <message> <source>Searc&h in all opened databases for matching entries</source> - <translation>Cerc&a in tutti i database aperti per la ricerca delle voci</translation> + <translation>Cerc&a in tutti i database aperti gli elementi corrispondenti</translation> </message> <message> <source>HTTP Port:</source> @@ -1643,7 +1658,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data </message> <message> <source>Sort &matching entries by title</source> - <translation>Ordina le voci per &titolo</translation> + <translation>Ordina gli elementi per &titolo</translation> </message> <message> <source>KeePassXC will listen to this port on 127.0.0.1</source> @@ -1656,8 +1671,8 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data <message> <source>Cannot bind to privileged ports below 1024! Using default port 19455.</source> - <translation>Non è possibile collegarsi a porte sotto la 1024! -Utilizza la porta predefinita 19455.</translation> + <translation>Non è possibile usare porte sotto la 1024! +Usa la porta predefinita 19455.</translation> </message> <message> <source>R&emove all shared encryption keys from active database</source> @@ -1673,7 +1688,7 @@ Utilizza la porta predefinita 19455.</translation> </message> <message> <source>This is required for accessing your databases from ChromeIPass or PassIFox</source> - <translation>Questo è necessario per accedere ai tuoi database da ChromeIPass o PassIFox</translation> + <translation>Questo è necessario per accedere ai database da ChromeIPass o PassIFox</translation> </message> <message> <source>Enable KeePassHTTP server</source> @@ -1681,23 +1696,23 @@ Utilizza la porta predefinita 19455.</translation> </message> <message> <source>Only returns the best matches for a specific URL instead of all entries for the whole domain.</source> - <translation>Restituisce solo le corrispondenze migliori per un URL specifico invece di tutte le voci per l'intero dominio.</translation> + <translation>Restituisci solo le corrispondenze migliori per un'URL specifica invece di tutte gli elementi per l'intero dominio.</translation> </message> <message> <source>&Return only best matching entries</source> - <translation>&Restituisci solo le migliori voci corrispondenti</translation> + <translation>&Restituisci solo gli elementi corrispondenti migliori</translation> </message> <message> <source>Only entries with the same scheme (http://, https://, ftp://, ...) are returned.</source> - <translation>Solo le voci con lo stesso schema (http://, https://, ftp: //, ...) vengono restituite.</translation> + <translation>Solo gli elementi con lo stesso schema (http://, https://, ftp: //, ...) vengono restituite.</translation> </message> <message> <source>&Match URL schemes</source> - <translation>Co&mbina gli schemi URL</translation> + <translation>Sche&ma corrispndenza URL</translation> </message> <message> <source>Password Generator</source> - <translation>Generatore Password</translation> + <translation>Genera password</translation> </message> <message> <source>Only the selected database has to be connected with a client.</source> @@ -1718,7 +1733,7 @@ Modificale solo se sai quello che stai facendo.</translation> </message> <message> <source>Character Types</source> - <translation>Tipi di carattere</translation> + <translation>Tipi carattere</translation> </message> <message> <source>Upper Case Letters</source> @@ -1794,7 +1809,7 @@ Modificale solo se sai quello che stai facendo.</translation> </message> <message> <source>Good</source> - <translation>Sufficente</translation> + <translation>Buona</translation> </message> <message> <source>Excellent</source> @@ -1810,19 +1825,19 @@ Modificale solo se sai quello che stai facendo.</translation> </message> <message> <source>Passphrase</source> - <translation>Frase d'accesso</translation> + <translation>Frase accesso</translation> </message> <message> <source>Wordlist:</source> - <translation>Elenco di termini:</translation> + <translation>Elenco termini:</translation> </message> <message> <source>Word Count:</source> - <translation>Conteggio delle parole:</translation> + <translation>Conteggio parole:</translation> </message> <message> <source>Word Separator:</source> - <translation>Separatore delle parole:</translation> + <translation>Separatore parole:</translation> </message> <message> <source>Copy</source> @@ -1887,7 +1902,7 @@ Modificale solo se sai quello che stai facendo.</translation> </message> <message> <source>YubiKey[%1] Challenge Response - Slot %2 - %3</source> - <translation>YubiKey [%1] Risposta di verifica - Slot %2 - %3</translation> + <translation>YubiKey [%1] risposta di verifica - slot %2 - %3</translation> </message> <message> <source>Press</source> @@ -1895,7 +1910,7 @@ Modificale solo se sai quello che stai facendo.</translation> </message> <message> <source>Passive</source> - <translation>Passivo</translation> + <translation>Passiva</translation> </message> </context> <context> @@ -1936,7 +1951,7 @@ Modificale solo se sai quello che stai facendo.</translation> <name>SearchWidget</name> <message> <source>Case Sensitive</source> - <translation>Case sensitive</translation> + <translation>Sensibile maiuscole/minuscole</translation> </message> <message> <source>Search</source> @@ -1944,7 +1959,7 @@ Modificale solo se sai quello che stai facendo.</translation> </message> <message> <source>Clear</source> - <translation>Pulisci</translation> + <translation>Azzera</translation> </message> <message> <source>Search...</source> @@ -1960,7 +1975,7 @@ Modificale solo se sai quello che stai facendo.</translation> <message> <source>A shared encryption-key with the name "%1" already exists. Do you want to overwrite it?</source> - <translation>Una chiave di criptazione condivisa con il nome "%1" già esiste. + <translation>Una chiave di criptazione condivisa con il nome "%1" esiste già. Vuoi sovrascriverla?</translation> </message> <message> @@ -1971,11 +1986,11 @@ Vuoi sovrascriverla?</translation> <source>The active database is locked! Please unlock the selected database or choose another one which is unlocked.</source> <translation>Il database attivo è bloccato! -Sblocca il database selezionato o scegli un altro che è sbloccato</translation> +Sblocca il database selezionato o scegli un altro database sbloccato.</translation> </message> <message> <source>Successfully removed %1 encryption-%2 from KeePassX/Http Settings.</source> - <translation>Rimosso con successo %1 encryption-%2 dalle impostazioni KeePassX/Http.</translation> + <translation>Rimosso correttamente %1 encryption-%2 dalle impostazioni KeePassX/Http.</translation> </message> <message> <source>No shared encryption-keys found in KeePassHttp Settings.</source> @@ -1983,11 +1998,11 @@ Sblocca il database selezionato o scegli un altro che è sbloccato</translation> </message> <message> <source>The active database does not contain an entry of KeePassHttp Settings.</source> - <translation>Il database attivo non contiene nessuna voce delle impostazioni di KeePassHttp.</translation> + <translation>Il database attivo non contiene nessun elemento delle impostazioni di KeePassHttp.</translation> </message> <message> <source>Removing stored permissions...</source> - <translation>Rimuovi i permessi salvati...</translation> + <translation>Rimozione dei permessi salvati...</translation> </message> <message> <source>Abort</source> @@ -1995,11 +2010,11 @@ Sblocca il database selezionato o scegli un altro che è sbloccato</translation> </message> <message> <source>Successfully removed permissions from %1 %2.</source> - <translation>Permessi rimossi con successo da %1 %2.</translation> + <translation>Permessi rimossi correttamente da %1 %2.</translation> </message> <message> <source>The active database does not contain an entry with permissions.</source> - <translation>Il database attivo non contiene una voce con permessi.</translation> + <translation>Il database attivo non contiene un elemento con permessi.</translation> </message> <message> <source>KeePassXC: New key association request</source> @@ -2010,40 +2025,40 @@ Sblocca il database selezionato o scegli un altro che è sbloccato</translation> If you would like to allow it access to your KeePassXC database give it a unique name to identify and accept it.</source> <translation>Hai ricevuto una richiesta di associazione per la chiave sovrastante. -Se vuoi permetterle di accedere al tuo database KeePassXC +Se vuoi permetterle di accedere al database KeePassXC imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>KeePassXC: Overwrite existing key?</source> - <translation>KeePassXC: Sovrascrivere chiave esistente?</translation> + <translation>KeePassXC- Vuoi sovrascrivere la chiave esistente?</translation> </message> <message> <source>KeePassXC: Update Entry</source> - <translation>KeePassXC: Aggiorna voce</translation> + <translation>KeePassXC- Aggiorna elemento</translation> </message> <message> <source>KeePassXC: Database locked!</source> - <translation>KeePassXC: Database bloccato!</translation> + <translation>KeePassXC- Database bloccato!</translation> </message> <message> <source>KeePassXC: Removed keys from database</source> - <translation>KeePassXC: Rimuovi chiavi dal database</translation> + <translation>KeePassXC - Chiavi rimosse dal database</translation> </message> <message> <source>KeePassXC: No keys found</source> - <translation>KeePassXC: Nessuna chiave trovata</translation> + <translation>KeePassXC - Nessuna chiave trovata</translation> </message> <message> <source>KeePassXC: Settings not available!</source> - <translation>KeePassXC: Impostazioni non disponibili!</translation> + <translation>KeePassXC - Impostazioni non disponibili!</translation> </message> <message> <source>KeePassXC: Removed permissions</source> - <translation>KeePassXC: Rimossi permessi</translation> + <translation>KeePassXC - Permessi rimossi</translation> </message> <message> <source>KeePassXC: No entry with permissions found!</source> - <translation>KeePassXC: Nessuna voce con permessi trovata!</translation> + <translation>KeePassXC - Nessun elemento con permessi trovata!</translation> </message> </context> <context> @@ -2081,15 +2096,15 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Minimize when copying to clipboard</source> - <translation>Minimizza quando si copia negli appunti</translation> + <translation>Minimizza quando si copia negli Appunti</translation> </message> <message> <source>Use group icon on entry creation</source> - <translation>Usa l'icona del gruppo alla creazione di una voce</translation> + <translation>Usa icona del gruppo alla creazione di un elemento</translation> </message> <message> <source>Global Auto-Type shortcut</source> - <translation>Scorciatoia Auto-Type globale</translation> + <translation>Scorciatoia completamento automatico globale</translation> </message> <message> <source>Language</source> @@ -2097,7 +2112,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Show a system tray icon</source> - <translation>Mostra un'icona nell'area di notifica del sistema</translation> + <translation>Visualizza un'icona nell'area di notifica del sistema</translation> </message> <message> <source>Hide window to system tray when minimized</source> @@ -2105,7 +2120,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Load previous databases on startup</source> - <translation>Carica i database precedenti all'avvio</translation> + <translation>All'avvio carica i database precedenti</translation> </message> <message> <source>Automatically reload the database when modified externally</source> @@ -2129,23 +2144,23 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Don't mark database as modified for non-data changes (e.g., expanding groups)</source> - <translation>Non contrassegnare il database come modificato per modifiche non riguardanti i dati (ad es., espansione di gruppi)</translation> + <translation>Non contrassegnare il database come modificato per modifiche non riguardanti i dati (ad es. espansione dei gruppi)</translation> </message> <message> <source>Auto-Type</source> - <translation>Auto-Type</translation> + <translation>Completamento automatico</translation> </message> <message> <source>Use entry title and URL to match windows for global Auto-Type</source> - <translation>Usa il titolo della voce e l'URL per abbinare le finestre per l'auto-digitazione globale</translation> + <translation>Usa il titolo dell'elemento e l'URL per abbinare le finestre per il completamento automatico globale</translation> </message> <message> <source>Always ask before performing Auto-Type</source> - <translation>Chiedi sempre prima di effettuare l'auto-digitazione</translation> + <translation>Chiedi sempre prima di effettuare il completamento automatico</translation> </message> <message> <source>Auto-Type delay</source> - <translation>Ritardo dell'auto-digitazione</translation> + <translation>Ritardo completamento automatico</translation> </message> <message> <source> ms</source> @@ -2160,7 +2175,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> <name>SettingsWidgetSecurity</name> <message> <source>Clear clipboard after</source> - <translation>Pulisci appunti dopo</translation> + <translation>Svuota Appunti dopo</translation> </message> <message> <source> sec</source> @@ -2172,7 +2187,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Show passwords in cleartext by default</source> - <translation>Mostra la password in chiaro in maniera predefinita</translation> + <translation>Visualizza la password in chiaro in maniera predefinita</translation> </message> <message> <source>Lock databases after minimizing the window</source> @@ -2192,7 +2207,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Lock databases when session is locked or lid is closed</source> - <translation>Bloccare i database quando la sessione è bloccata o il coperchio è chiuso</translation> + <translation>Blocca i database quando la sessione è bloccata o il coperchio è chiuso</translation> </message> <message> <source>Privacy</source> @@ -2200,7 +2215,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Use Google as fallback for downloading website icons</source> - <translation>Utilizza Google come ripiego per scaricare le icone del sito web</translation> + <translation>Usa Google come alternativa per scaricare le icone dal sito web</translation> </message> </context> <context> @@ -2215,11 +2230,11 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Use custom settings</source> - <translation>Utilizza le impostazioni personalizzate</translation> + <translation>Usa le impostazioni personalizzate</translation> </message> <message> <source>Note: Change these settings only if you know what you are doing.</source> - <translation>Nota: modificare queste impostazioni solo se sai quello che stai facendo.</translation> + <translation>Nota: modifica queste impostazioni solo se sai quello che stai facendo.</translation> </message> <message> <source>Time step:</source> @@ -2235,7 +2250,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Code size:</source> - <translation>Dimensioni del codice:</translation> + <translation>Dimensioni codice:</translation> </message> <message> <source> sec</source> @@ -2258,7 +2273,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Expires in</source> - <translation>Scade in</translation> + <translation>Scade tra</translation> </message> <message> <source>seconds</source> @@ -2315,7 +2330,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>KeePassXC - cross-platform password manager</source> - <translation>KeePassXC - gestore password multipiattaforma</translation> + <translation>KeePassXC - Gestore password multipiattaforma</translation> </message> <message> <source>read password of the database from stdin</source> @@ -2335,11 +2350,11 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Use a GUI prompt unlocking the database.</source> - <translation>Utilizza un sollecito grafico per lo sblocco del database.</translation> + <translation>Usa una richiesta grafica per lo sblocco del database.</translation> </message> <message> <source>Name of the entry to clip.</source> - <translation>Nome della voce da troncare.</translation> + <translation>Nome dell'elemento da tagliare.</translation> </message> <message> <source>Extract and print the content of a database.</source> @@ -2355,7 +2370,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>List database entries.</source> - <translation>Elenco delle voci del database.</translation> + <translation>Elenco degli elementi del database.</translation> </message> <message> <source>Path of the group to list. Default is /</source> @@ -2363,7 +2378,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Print the UUIDs of the entries and groups.</source> - <translation>Stampa gli UUID delle voci e dei gruppi.</translation> + <translation>Stampa gli UUID degli elementi e dei gruppi.</translation> </message> <message> <source>Merge two databases.</source> @@ -2371,15 +2386,15 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Path of the database to merge into.</source> - <translation>Percorso del database di destinazione da unire</translation> + <translation>Percorso del database destinazione da unire.</translation> </message> <message> <source>Path of the database to merge from.</source> - <translation>Percorso del database di partenza da unire.</translation> + <translation>Percorso del database sorgente da unire.</translation> </message> <message> <source>Use the same password for both database files.</source> - <translation>Utilizza la stessa password per entrambi i file di database.</translation> + <translation>Usa la stessa password per entrambi i file dei database.</translation> </message> <message> <source>Show a password.</source> @@ -2387,7 +2402,7 @@ imposta un nome unico per identificarla ed accettarla.</translation> </message> <message> <source>Name of the entry to show.</source> - <translation>Nome della voce da mostrare.</translation> + <translation>Nome dell'elemento da visualizzare.</translation> </message> </context> </TS>
\ No newline at end of file diff --git a/share/translations/keepassx_ja.ts b/share/translations/keepassx_ja.ts index 4ac8b7ee7..28b7c5336 100644 --- a/share/translations/keepassx_ja.ts +++ b/share/translations/keepassx_ja.ts @@ -67,6 +67,10 @@ CPU アーキテクチャ: %2 <source>Include the following information whenever you report a bug:</source> <translation>バグを報告する際に下記の情報を含めてください:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1094,7 +1098,7 @@ Do you want to open it anyway?</source> </message> <message> <source>Custom icon already exists</source> - <translation type="unfinished"/> + <translation>カスタムアイコンは既に存在します</translation> </message> </context> <context> @@ -1318,6 +1322,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>チャレンジレスポンスを発行することができません。</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>マスターキーを計算できません</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> @@ -1337,7 +1352,7 @@ This is a one-way migration. You won't be able to open the imported databas </message> <message> <source>Existing single-instance lock file is invalid. Launching new instance.</source> - <translation type="unfinished"/> + <translation>既存のシングルインスタンスロックファイルは無効です。新しいインスタンスを起動します。</translation> </message> </context> <context> diff --git a/share/translations/keepassx_kk.ts b/share/translations/keepassx_kk.ts index 073052717..4531122bf 100644 --- a/share/translations/keepassx_kk.ts +++ b/share/translations/keepassx_kk.ts @@ -64,6 +64,10 @@ Kernel: %3 %4</source> <source>Include the following information whenever you report a bug:</source> <translation type="unfinished"/> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1308,6 +1312,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Басты парольді есептеу мүмкін емес</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_ko.ts b/share/translations/keepassx_ko.ts index ff6c208b8..0b528474d 100644 --- a/share/translations/keepassx_ko.ts +++ b/share/translations/keepassx_ko.ts @@ -67,6 +67,10 @@ CPU 아키텍처: %2 <source>Include the following information whenever you report a bug:</source> <translation>버그를 보고할 때 다음 정보를 포함하십시오:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1316,6 +1320,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>질의 응답을 실행할 수 없습니다.</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>마스터 키를 계산할 수 없습니다</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_lt.ts b/share/translations/keepassx_lt.ts index be7a82e09..a9a483836 100644 --- a/share/translations/keepassx_lt.ts +++ b/share/translations/keepassx_lt.ts @@ -67,6 +67,10 @@ Branduolys: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Pranešdami apie klaidą, visuomet pateikite ir šią informaciją:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation>Platinimas: %1</translation> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1094,7 +1098,7 @@ Ar vis tiek norite ją atverti?</translation> </message> <message> <source>Custom icon already exists</source> - <translation type="unfinished"/> + <translation>Tinkinta piktograma jau yra</translation> </message> </context> <context> @@ -1318,6 +1322,17 @@ Tai yra vienakryptis perkėlimas. Jūs negalėsite atverti importuotos duomenų </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>Nepavyko išduoti iššūkio atsakymo.</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Nepavyko apskaičiuoti pagrindinio rakto</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> @@ -1337,7 +1352,7 @@ Tai yra vienakryptis perkėlimas. Jūs negalėsite atverti importuotos duomenų </message> <message> <source>Existing single-instance lock file is invalid. Launching new instance.</source> - <translation type="unfinished"/> + <translation>Esamas vieno egzemplioriaus užrakto failas yra neteisingas. Paleidžiamas naujas egzempliorius.</translation> </message> </context> <context> diff --git a/share/translations/keepassx_nl_NL.ts b/share/translations/keepassx_nl_NL.ts index c8fd30dd6..e18f1a908 100644 --- a/share/translations/keepassx_nl_NL.ts +++ b/share/translations/keepassx_nl_NL.ts @@ -64,6 +64,10 @@ Kernel: %3 %4</source> <source>Include the following information whenever you report a bug:</source> <translation type="unfinished"/> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1311,6 +1315,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Niet mogelijk om hoofdsleutel te berekenen</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_pl.ts b/share/translations/keepassx_pl.ts index 1ed4ed058..66574202f 100644 --- a/share/translations/keepassx_pl.ts +++ b/share/translations/keepassx_pl.ts @@ -67,6 +67,10 @@ Jądro: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Uwzględnij następujące informacje, gdy zgłaszasz błąd:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation>Dystrybucja: %1</translation> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1095,7 +1099,7 @@ Czy chcesz ją otworzyć mimo to?</translation> </message> <message> <source>Custom icon already exists</source> - <translation type="unfinished"/> + <translation>Ikona niestandardowa już istnieje</translation> </message> </context> <context> @@ -1319,6 +1323,17 @@ Jest to migracja w jedną stronę. Nie będzie można otworzyć importowanej baz </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>Nie można wywołać wyzwania-odpowiedzi.</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Nie mogę wyliczyć głównego klucza</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> @@ -1338,7 +1353,7 @@ Jest to migracja w jedną stronę. Nie będzie można otworzyć importowanej baz </message> <message> <source>Existing single-instance lock file is invalid. Launching new instance.</source> - <translation type="unfinished"/> + <translation>Istniejący plik blokady pojedynczego wystąpienia jest nieprawidłowy. Uruchamianie nowego wystąpienia.</translation> </message> </context> <context> diff --git a/share/translations/keepassx_pt_BR.ts b/share/translations/keepassx_pt_BR.ts index b4f792605..1ea54d854 100644 --- a/share/translations/keepassx_pt_BR.ts +++ b/share/translations/keepassx_pt_BR.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Inclua as informações abaixo quando reportar um erro:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1315,6 +1319,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Não foi possível calcular a chave mestre</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_pt_PT.ts b/share/translations/keepassx_pt_PT.ts index cf9f124fe..0a671ed70 100644 --- a/share/translations/keepassx_pt_PT.ts +++ b/share/translations/keepassx_pt_PT.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</translation> <source>Include the following information whenever you report a bug:</source> <translation>Inclua as seguintes informações sempre que reportar um erro:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation>Distribuição: %1</translation> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1095,7 +1099,7 @@ Ainda assim deseja abrir a base de dados?</translation> </message> <message> <source>Custom icon already exists</source> - <translation type="unfinished"/> + <translation>Já existe um ícone personalizado</translation> </message> </context> <context> @@ -1319,6 +1323,17 @@ Esta é uma migração unidirecional. Não será possível abrir a base de dados </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>Incapaz de emitir a pergunta de segurança.</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Impossível de calcular a chave-mestre</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> @@ -1338,7 +1353,7 @@ Esta é uma migração unidirecional. Não será possível abrir a base de dados </message> <message> <source>Existing single-instance lock file is invalid. Launching new instance.</source> - <translation type="unfinished"/> + <translation>O ficheiro de bloqueio da instância única é inválido. A iniciar nova instância.</translation> </message> </context> <context> diff --git a/share/translations/keepassx_ru.ts b/share/translations/keepassx_ru.ts index c206b769f..938d5eefd 100644 --- a/share/translations/keepassx_ru.ts +++ b/share/translations/keepassx_ru.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</source> <source>Include the following information whenever you report a bug:</source> <translation>Включите следующую информацию, когда сообщаете об ошибке:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1319,6 +1323,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>Не удалось выполнить запрос ответа.</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Невозможно вычислить мастер-пароль</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_sl_SI.ts b/share/translations/keepassx_sl_SI.ts index f43dd17ab..cec9bd6ca 100644 --- a/share/translations/keepassx_sl_SI.ts +++ b/share/translations/keepassx_sl_SI.ts @@ -64,6 +64,10 @@ Kernel: %3 %4</source> <source>Include the following information whenever you report a bug:</source> <translation type="unfinished"/> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1306,6 +1310,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Izračun glavnega ključa ni uspel</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_sv.ts b/share/translations/keepassx_sv.ts index bc846e46c..a9e8a85d7 100644 --- a/share/translations/keepassx_sv.ts +++ b/share/translations/keepassx_sv.ts @@ -24,7 +24,8 @@ <message> <source>Version %1 </source> - <translation type="unfinished"/> + <translation>Version %1 +</translation> </message> <message> <source>Revision: %1</source> @@ -64,6 +65,10 @@ Kernel: %3 %4</source> <source>Include the following information whenever you report a bug:</source> <translation type="unfinished"/> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -196,7 +201,7 @@ Please select whether you want to allow access.</source> </message> <message> <source>Empty password</source> - <translation type="unfinished"/> + <translation>Tomt lösenord</translation> </message> <message> <source>Changing master key failed: no YubiKey inserted.</source> @@ -254,7 +259,7 @@ Please select whether you want to allow access.</source> </message> <message> <source>Comments start with</source> - <translation type="unfinished"/> + <translation>Kommentarer inleds med</translation> </message> <message> <source>First record has field names</source> @@ -282,7 +287,7 @@ Please select whether you want to allow access.</source> </message> <message> <source>Empty fieldname </source> - <translation type="unfinished"/> + <translation>Tomt fältnamn </translation> </message> <message> <source>column </source> @@ -337,7 +342,7 @@ Please select whether you want to allow access.</source> </message> <message> <source> rows, </source> - <translation type="unfinished"/> + <translation> rader, </translation> </message> <message> <source> columns</source> @@ -622,7 +627,7 @@ Do you want to open it anyway?</source> </message> <message> <source>Open CSV file</source> - <translation type="unfinished"/> + <translation>Öppna CSV fil</translation> </message> </context> <context> @@ -677,7 +682,7 @@ Do you want to open it anyway?</source> </message> <message> <source>Searching...</source> - <translation type="unfinished"/> + <translation>Söker...</translation> </message> <message> <source>No current database.</source> @@ -689,11 +694,11 @@ Do you want to open it anyway?</source> </message> <message> <source>Search Results (%1)</source> - <translation type="unfinished"/> + <translation>Sökresultat (%1)</translation> </message> <message> <source>No Results</source> - <translation type="unfinished"/> + <translation>Inget resultat</translation> </message> <message> <source>Execute command?</source> @@ -818,7 +823,7 @@ Do you want to open it anyway?</source> </message> <message> <source>Confirm Remove</source> - <translation type="unfinished"/> + <translation>Bekräfta borttagning</translation> </message> <message> <source>Are you sure you want to remove this attribute?</source> @@ -865,7 +870,7 @@ Do you want to open it anyway?</source> </message> <message> <source>Protect</source> - <translation type="unfinished"/> + <translation>Skydda</translation> </message> <message> <source>Reveal</source> @@ -1308,6 +1313,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Kunde inte räkna nu master-nyckeln</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_tr.ts b/share/translations/keepassx_tr.ts index 18639fc48..4514a4204 100644 --- a/share/translations/keepassx_tr.ts +++ b/share/translations/keepassx_tr.ts @@ -67,6 +67,10 @@ MİB mimarisi: %2 <source>Include the following information whenever you report a bug:</source> <translation>Bir hata bildirirken şu bilgileri ekleyin:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1314,6 +1318,17 @@ Bu tek yönlü bir yer değiştirmedir. İçe aktarılan veri tabanını eski Ke </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Ana anahtar hesaplanamıyor</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_uk.ts b/share/translations/keepassx_uk.ts index e1f98f86a..c8abb87fb 100644 --- a/share/translations/keepassx_uk.ts +++ b/share/translations/keepassx_uk.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</source> <source>Include the following information whenever you report a bug:</source> <translation>Коли Ви повідомляєте про ваду, завжди долучайте таку інформацію:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1319,6 +1323,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>Неможливо видати виклик-відповідь.</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>Неможливо вирахувати головний ключ</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_zh_CN.ts b/share/translations/keepassx_zh_CN.ts index db791625a..0d5e2806f 100644 --- a/share/translations/keepassx_zh_CN.ts +++ b/share/translations/keepassx_zh_CN.ts @@ -67,6 +67,10 @@ CPU 架构:%2 <source>Include the following information whenever you report a bug:</source> <translation>报告任何 bug 时,请包含以下信息:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1317,6 +1321,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation>无法发出挑战应答</translation> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>无法计算主密码</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/share/translations/keepassx_zh_TW.ts b/share/translations/keepassx_zh_TW.ts index af9c74b55..0dbabb3ab 100644 --- a/share/translations/keepassx_zh_TW.ts +++ b/share/translations/keepassx_zh_TW.ts @@ -67,6 +67,10 @@ Kernel: %3 %4</source> <source>Include the following information whenever you report a bug:</source> <translation>回報 Bug 時會包含以下資訊:</translation> </message> + <message> + <source>Distribution: %1</source> + <translation type="unfinished"/> + </message> </context> <context> <name>AccessControlDialog</name> @@ -1318,6 +1322,17 @@ This is a one-way migration. You won't be able to open the imported databas </message> </context> <context> + <name>KeePass2Writer</name> + <message> + <source>Unable to issue challenge-response.</source> + <translation type="unfinished"/> + </message> + <message> + <source>Unable to calculate master key</source> + <translation>無法計算主金鑰</translation> + </message> +</context> +<context> <name>Main</name> <message> <source>Fatal error while testing the cryptographic functions.</source> diff --git a/snapcraft.yaml b/snapcraft.yaml index edd2cf227..0d69941ac 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -1,18 +1,18 @@ name: keepassxc -version: 2.2.1 +version: 2.2.2 grade: stable -summary: community driven port of the windows application “Keepass Password Safe” +summary: Community-driven port of the Windows application “KeePass Password Safe” description: | KeePassXC is an application for people with extremely high demands on secure - personal data management. It has a light interface, is cross platform and - is published under the terms of the GNU General Public License. + personal data management. It has a light interface, is cross-platform and + published under the terms of the GNU General Public License. confinement: strict apps: keepassxc: command: desktop-launch keepassxc plugs: [unity7, x11, opengl, gsettings, home, network, network-bind, removable-media, raw-usb] - desktop: share/applications/keepassxc.desktop + desktop: usr/share/applications/org.keepassxc.desktop cli: command: keepassxc-cli plugs: [gsettings, home, removable-media, raw-usb] @@ -23,6 +23,8 @@ parts: plugin: cmake configflags: - -DCMAKE_BUILD_TYPE=Release + - -DCMAKE_INSTALL_PREFIX=/usr + - -DKEEPASSXC_DIST_TYPE=Snap - -DWITH_TESTS=OFF - -DWITH_XC_AUTOTYPE=ON - -DWITH_XC_HTTP=ON @@ -39,6 +41,8 @@ parts: - libxtst-dev - libyubikey-dev - libykpers-1-dev + install: | + sed -i 's|Icon=keepassxc|Icon=${SNAP}/usr/share/icons/hicolor/256x256/apps/keepassxc.png|g' $SNAPCRAFT_PART_INSTALL/usr/share/applications/org.keepassxc.desktop after: [desktop-qt5] # Redefine desktop-qt5 stage packages to work with Ubuntu 17.04 @@ -55,10 +59,12 @@ parts: - locales-all # Overcome limitation in snapd to support URL loading (CTRL+U) + # client needs to install "snapd-xdg-open" on their system snapd-xdg-open: source: https://github.com/ubuntu-core/snapd-xdg-open.git - plugin: dump - organize: - data/xdg-open: bin/xdg-open + source-depth: 1 + plugin: nil + install: | + install -D -t $SNAPCRAFT_PART_INSTALL/usr/bin/ data/xdg-open stage-packages: - dbus diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 791685576..5255186ea 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -59,6 +59,8 @@ set(keepassx_SOURCES core/Tools.cpp core/Translator.cpp core/Uuid.cpp + core/Base32.h + core/Base32.cpp cli/PasswordInput.cpp cli/PasswordInput.h crypto/Crypto.cpp @@ -138,8 +140,6 @@ set(keepassx_SOURCES streams/qtiocompressor.cpp streams/StoreDataStream.cpp streams/SymmetricCipherStream.cpp - totp/base32.h - totp/base32.cpp totp/totp.h totp/totp.cpp ) diff --git a/src/config-keepassx.h.cmake b/src/config-keepassx.h.cmake index 9ae5f4836..e06c69382 100644 --- a/src/config-keepassx.h.cmake +++ b/src/config-keepassx.h.cmake @@ -16,6 +16,11 @@ #cmakedefine WITH_XC_AUTOTYPE #cmakedefine WITH_XC_YUBIKEY +#cmakedefine KEEPASSXC_DIST +#cmakedefine KEEPASSXC_DIST_TYPE "@KEEPASSXC_DIST_TYPE@" +#cmakedefine KEEPASSXC_DIST_SNAP +#cmakedefine KEEPASSXC_DIST_APPIMAGE + #cmakedefine HAVE_PR_SET_DUMPABLE 1 #cmakedefine HAVE_RLIMIT_CORE 1 #cmakedefine HAVE_PT_DENY_ATTACH 1 diff --git a/src/core/Base32.cpp b/src/core/Base32.cpp new file mode 100644 index 000000000..13228a37f --- /dev/null +++ b/src/core/Base32.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Conforms to RFC 4648. For details, see: https://tools.ietf.org/html/rfc4648 + * Use the functions Base32::addPadding/1, Base32::removePadding/1 or + * Base32::sanitizeInput/1 to fix input or output for a particular + * applications (e.g. to use with Google Authenticator). + */ + +#include "Base32.h" + +constexpr quint64 MASK_40BIT = quint64(0xF8) << 32; +constexpr quint64 MASK_35BIT = quint64(0x7C0000000); +constexpr quint64 MASK_25BIT = quint64(0x1F00000); +constexpr quint64 MASK_20BIT = quint64(0xF8000); +constexpr quint64 MASK_10BIT = quint64(0x3E0); + +constexpr char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; +constexpr quint8 ALPH_POS_2 = 26; + +constexpr quint8 ASCII_2 = static_cast<quint8>('2'); +constexpr quint8 ASCII_7 = static_cast<quint8>('7'); +constexpr quint8 ASCII_A = static_cast<quint8>('A'); +constexpr quint8 ASCII_Z = static_cast<quint8>('Z'); +constexpr quint8 ASCII_a = static_cast<quint8>('a'); +constexpr quint8 ASCII_z = static_cast<quint8>('z'); +constexpr quint8 ASCII_EQ = static_cast<quint8>('='); + +QVariant Base32::decode(const QByteArray& encodedData) +{ + if (encodedData.size() <= 0) { + return QVariant::fromValue(QByteArray("")); + } + + if (encodedData.size() % 8 != 0) { + return QVariant(); + } + + int nPads = 0; + for (int i = -1; i > -7; --i) { + if ('=' == encodedData[encodedData.size() + i]) + ++nPads; + } + + int specialOffset; + int nSpecialBytes; + + switch (nPads) { // in {0, 1, 3, 4, 6} + case 1: + nSpecialBytes = 4; + specialOffset = 3; + break; + case 3: + nSpecialBytes = 3; + specialOffset = 1; + break; + case 4: + nSpecialBytes = 2; + specialOffset = 4; + break; + case 6: + nSpecialBytes = 1; + specialOffset = 2; + break; + default: + nSpecialBytes = 0; + specialOffset = 0; + } + + Q_ASSERT(encodedData.size() > 0); + const int nQuanta = encodedData.size() / 8; + const int nBytes = nSpecialBytes > 0 ? (nQuanta - 1) * 5 + nSpecialBytes : nQuanta * 5; + + QByteArray data(nBytes, Qt::Uninitialized); + + int i = 0; + int o = 0; + + while (i < encodedData.size()) { + quint64 quantum = 0; + int nQuantumBytes = 5; + + for (int n = 0; n < 8; ++n) { + quint8 ch = static_cast<quint8>(encodedData[i++]); + if ((ASCII_A <= ch && ch <= ASCII_Z) || (ASCII_a <= ch && ch <= ASCII_z)) { + ch -= ASCII_A; + if (ch >= ALPH_POS_2) + ch -= ASCII_a - ASCII_A; + } else { + if (ASCII_2 <= ch && ch <= ASCII_7) { + ch -= ASCII_2; + ch += ALPH_POS_2; + } else { + if (ASCII_EQ == ch) { + if (i == encodedData.size()) { + // finished with special quantum + quantum >>= specialOffset; + nQuantumBytes = nSpecialBytes; + } + continue; + } else { + // illegal character + return QVariant(); + } + } + } + + quantum <<= 5; + quantum |= ch; + } + + const int offset = (nQuantumBytes - 1) * 8; + quint64 mask = quint64(0xFF) << offset; + for (int n = offset; n >= 0 && o < nBytes; n -= 8) { + data[o++] = static_cast<char>((quantum & mask) >> n); + mask >>= 8; + } + } + + Q_ASSERT(encodedData.size() == i); + Q_ASSERT(nBytes == o); + + return QVariant::fromValue(data); +} + +QByteArray Base32::encode(const QByteArray& data) +{ + if (data.size() < 1) { + return QByteArray(); + } + + const int nBits = data.size() * 8; + const int rBits = nBits % 40; // in {0, 8, 16, 24, 32} + const int nQuanta = nBits / 40 + (rBits > 0 ? 1 : 0); + const int nBytes = nQuanta * 8; + QByteArray encodedData(nQuanta * 8, Qt::Uninitialized); + + int i = 0; + int o = 0; + int n; + quint64 mask; + quint64 quantum; + + // 40-bits of input per input group + while (i + 5 <= data.size()) { + quantum = 0; + for (n = 32; n >= 0; n -= 8) { + quantum |= (static_cast<quint64>(data[i++]) << n); + } + + mask = MASK_40BIT; + int index; + for (n = 35; n >= 0; n -= 5) { + index = (quantum & mask) >> n; + encodedData[o++] = alphabet[index]; + mask >>= 5; + } + } + + // < 40-bits of input at final input group + if (i < data.size()) { + Q_ASSERT(rBits > 0); + quantum = 0; + for (n = rBits - 8; n >= 0; n -= 8) + quantum |= static_cast<quint64>(data[i++]) << n; + + switch (rBits) { + case 8: // expand to 10 bits + quantum <<= 2; + mask = MASK_10BIT; + n = 5; + break; + case 16: // expand to 20 bits + quantum <<= 4; + mask = MASK_20BIT; + n = 15; + break; + case 24: // expand to 25 bits + quantum <<= 1; + mask = MASK_25BIT; + n = 20; + break; + default: // expand to 35 bits + Q_ASSERT(rBits == 32); + quantum <<= 3; + mask = MASK_35BIT; + n = 30; + } + + while (n >= 0) { + int index = (quantum & mask) >> n; + encodedData[o++] = alphabet[index]; + mask >>= 5; + n -= 5; + } + + // add pad characters + while (o < encodedData.size()) { + encodedData[o++] = '='; + } + } + + Q_ASSERT(data.size() == i); + Q_ASSERT(nBytes == o); + return encodedData; +} + +QByteArray Base32::addPadding(const QByteArray& encodedData) +{ + if (encodedData.size() <= 0 || encodedData.size() % 8 == 0) { + return encodedData; + } + + const int rBytes = encodedData.size() % 8; + // rBytes must be a member of {2, 4, 5, 7} + if (1 == rBytes || 3 == rBytes || 6 == rBytes) { + return encodedData; + } + + QByteArray newEncodedData(encodedData); + for (int nPads = 8 - rBytes; nPads > 0; --nPads) { + newEncodedData.append('='); + } + + return newEncodedData; +} + +QByteArray Base32::removePadding(const QByteArray& encodedData) +{ + if (encodedData.size() <= 0 || encodedData.size() % 8 != 0) { + return encodedData; // return same bad input + } + + int nPads = 0; + for (int i = -1; i > -7; --i) { + if ('=' == encodedData[encodedData.size() + i]) { + ++nPads; + } + } + + QByteArray newEncodedData(encodedData); + newEncodedData.remove(encodedData.size() - nPads, nPads); + newEncodedData.resize(encodedData.size() - nPads); + + return newEncodedData; +} + +QByteArray Base32::sanitizeInput(const QByteArray& encodedData) +{ + if (encodedData.size() <= 0) { + return encodedData; + } + + QByteArray newEncodedData(encodedData.size(), Qt::Uninitialized); + int i = 0; + for (auto ch : encodedData) { + switch (ch) { + case '0': + newEncodedData[i++] = 'O'; + break; + case '1': + newEncodedData[i++] = 'L'; + break; + case '8': + newEncodedData[i++] = 'B'; + break; + default: + if (('A' <= ch && ch <= 'Z') || ('a' <= ch && ch <= 'z') || ('2' <= ch && ch <= '7')) { + newEncodedData[i++] = ch; + } + } + } + newEncodedData.resize(i); + + return addPadding(newEncodedData); +} diff --git a/src/core/Base32.h b/src/core/Base32.h new file mode 100644 index 000000000..204368c52 --- /dev/null +++ b/src/core/Base32.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* Conforms to RFC 4648. For details, see: https://tools.ietf.org/html/rfc4648 + * Use the functions Base32::addPadding/1, Base32::removePadding/1 or + * Base32::sanitizeInput/1 to fix input or output for a particular + * applications (e.g. to use with Google Authenticator). + */ + +#ifndef BASE32_H +#define BASE32_H + +#include <QByteArray> +#include <QVariant> +#include <QtCore/qglobal.h> + +class Base32 +{ +public: + Base32() = default; + Q_REQUIRED_RESULT static QVariant decode(const QByteArray&); + Q_REQUIRED_RESULT static QByteArray encode(const QByteArray&); + Q_REQUIRED_RESULT static QByteArray addPadding(const QByteArray&); + Q_REQUIRED_RESULT static QByteArray removePadding(const QByteArray&); + Q_REQUIRED_RESULT static QByteArray sanitizeInput(const QByteArray&); +}; + +#endif // BASE32_H diff --git a/src/core/Database.cpp b/src/core/Database.cpp index d1c0fea4d..864dd758e 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -257,6 +257,25 @@ bool Database::hasKey() const return m_data.hasKey; } +bool Database::transformKeyWithSeed(const QByteArray& transformSeed) +{ + Q_ASSERT(hasKey()); + + bool ok; + QString errorString; + + QByteArray transformedMasterKey = + m_data.key.transform(transformSeed, transformRounds(), &ok, &errorString); + if (!ok) { + return false; + } + + m_data.transformSeed = transformSeed; + m_data.transformedMasterKey = transformedMasterKey; + + return true; +} + bool Database::verifyKey(const CompositeKey& key) const { Q_ASSERT(hasKey()); @@ -328,6 +347,15 @@ void Database::emptyRecycleBin() void Database::merge(const Database* other) { m_rootGroup->merge(other->rootGroup()); + + for (Uuid customIconId : other->metadata()->customIcons().keys()) { + QImage customIcon = other->metadata()->customIcon(customIconId); + if (!this->metadata()->containsCustomIcon(customIconId)) { + qDebug("Adding custom icon %s to database.", qPrintable(customIconId.toHex())); + this->metadata()->addCustomIcon(customIconId, customIcon); + } + } + emit modified(); } diff --git a/src/core/Database.h b/src/core/Database.h index a799e0b3b..b08233e57 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -106,6 +106,7 @@ public: */ bool setKey(const CompositeKey& key); bool hasKey() const; + bool transformKeyWithSeed(const QByteArray& transformSeed); bool verifyKey(const CompositeKey& key) const; void recycleEntry(Entry* entry); void recycleGroup(Group* group); diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 7388b429e..64ce5297c 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -801,28 +801,31 @@ QString Entry::resolvePlaceholder(const QString& str) const QString Entry::resolveUrl(const QString& url) const { -#ifdef WITH_XC_HTTP QString newUrl = url; - if (!url.contains("://")) { + if (!url.isEmpty() && !url.contains("://")) { // URL doesn't have a protocol, add https by default newUrl.prepend("https://"); } - QUrl tempUrl = QUrl(newUrl); - if (tempUrl.isValid()) { - if (tempUrl.scheme() == "cmd") { - // URL is a cmd, hopefully the second argument is an URL - QStringList cmd = newUrl.split(" "); - if (cmd.size() > 1) { - return resolveUrl(cmd[1].remove("'").remove("\"")); + if (newUrl.startsWith("cmd://")) { + QStringList cmdList = newUrl.split(" "); + for (int i=1; i < cmdList.size(); ++i) { + // Don't pass arguments to the resolveUrl function (they look like URL's) + if (!cmdList[i].startsWith("-") && !cmdList[i].startsWith("/")) { + return resolveUrl(cmdList[i].remove(QRegExp("'|\""))); } - } else if (tempUrl.scheme() == "http" || tempUrl.scheme() == "https") { - // URL is nice - return tempUrl.url(); } + + // No URL in this command + return QString(""); } -#else - Q_UNUSED(url); -#endif + + // Validate the URL + QUrl tempUrl = QUrl(newUrl); + if (tempUrl.isValid() && (tempUrl.scheme() == "http" || tempUrl.scheme() == "https")) { + return tempUrl.url(); + } + + // No valid http URL's found return QString(""); } diff --git a/src/core/FilePath.cpp b/src/core/FilePath.cpp index 132fdc007..b5c9d1020 100644 --- a/src/core/FilePath.cpp +++ b/src/core/FilePath.cpp @@ -91,17 +91,29 @@ QString FilePath::pluginPath(const QString& name) QIcon FilePath::applicationIcon() { +#ifdef KEEPASSXC_DIST_SNAP + return icon("apps", "keepassxc", false); +#else return icon("apps", "keepassxc"); +#endif } QIcon FilePath::trayIconLocked() { +#ifdef KEEPASSXC_DIST_SNAP + return icon("apps", "keepassxc-locked", false); +#else return icon("apps", "keepassxc-locked"); +#endif } QIcon FilePath::trayIconUnlocked() { +#ifdef KEEPASSXC_DIST_SNAP + return icon("apps", "keepassxc-unlocked", false); +#else return icon("apps", "keepassxc-unlocked"); +#endif } QIcon FilePath::icon(const QString& category, const QString& name, bool fromTheme) diff --git a/src/core/Metadata.cpp b/src/core/Metadata.cpp index eb976d0e5..6377c5846 100644 --- a/src/core/Metadata.cpp +++ b/src/core/Metadata.cpp @@ -454,7 +454,7 @@ void Metadata::copyCustomIcons(const QSet<Uuid>& iconList, const Metadata* other QByteArray Metadata::hashImage(const QImage& image) { - auto data = QByteArray((char*)image.bits(), image.byteCount()); + auto data = QByteArray(reinterpret_cast<const char*>(image.bits()), image.byteCount()); return QCryptographicHash::hash(data, QCryptographicHash::Md5); } diff --git a/src/crypto/SymmetricCipher.h b/src/crypto/SymmetricCipher.h index 0070ed7de..b85c58b7c 100644 --- a/src/crypto/SymmetricCipher.h +++ b/src/crypto/SymmetricCipher.h @@ -59,11 +59,11 @@ public: return m_backend->process(data, ok); } - inline bool processInPlace(QByteArray& data) Q_REQUIRED_RESULT { + Q_REQUIRED_RESULT inline bool processInPlace(QByteArray& data) { return m_backend->processInPlace(data); } - inline bool processInPlace(QByteArray& data, quint64 rounds) Q_REQUIRED_RESULT { + Q_REQUIRED_RESULT inline bool processInPlace(QByteArray& data, quint64 rounds) { Q_ASSERT(rounds > 0); return m_backend->processInPlace(data, rounds); } diff --git a/src/crypto/SymmetricCipherBackend.h b/src/crypto/SymmetricCipherBackend.h index 8f19b8ed0..78ec60c60 100644 --- a/src/crypto/SymmetricCipherBackend.h +++ b/src/crypto/SymmetricCipherBackend.h @@ -29,8 +29,8 @@ public: virtual bool setIv(const QByteArray& iv) = 0; virtual QByteArray process(const QByteArray& data, bool* ok) = 0; - virtual bool processInPlace(QByteArray& data) Q_REQUIRED_RESULT = 0; - virtual bool processInPlace(QByteArray& data, quint64 rounds) Q_REQUIRED_RESULT = 0; + Q_REQUIRED_RESULT virtual bool processInPlace(QByteArray& data) = 0; + Q_REQUIRED_RESULT virtual bool processInPlace(QByteArray& data, quint64 rounds) = 0; virtual bool reset() = 0; virtual int blockSize() const = 0; diff --git a/src/crypto/SymmetricCipherGcrypt.cpp b/src/crypto/SymmetricCipherGcrypt.cpp index cd4324065..e600a7edb 100644 --- a/src/crypto/SymmetricCipherGcrypt.cpp +++ b/src/crypto/SymmetricCipherGcrypt.cpp @@ -148,9 +148,10 @@ QByteArray SymmetricCipherGcrypt::process(const QByteArray& data, bool* ok) if (error != 0) { setErrorString(error); *ok = false; + } else { + *ok = true; } - *ok = true; return result; } diff --git a/src/crypto/SymmetricCipherGcrypt.h b/src/crypto/SymmetricCipherGcrypt.h index 367ee5b95..d3ad8d15b 100644 --- a/src/crypto/SymmetricCipherGcrypt.h +++ b/src/crypto/SymmetricCipherGcrypt.h @@ -35,8 +35,8 @@ public: bool setIv(const QByteArray& iv); QByteArray process(const QByteArray& data, bool* ok); - bool processInPlace(QByteArray& data) Q_REQUIRED_RESULT; - bool processInPlace(QByteArray& data, quint64 rounds) Q_REQUIRED_RESULT; + Q_REQUIRED_RESULT bool processInPlace(QByteArray& data); + Q_REQUIRED_RESULT bool processInPlace(QByteArray& data, quint64 rounds); bool reset(); int blockSize() const; diff --git a/src/format/KeePass2RandomStream.h b/src/format/KeePass2RandomStream.h index 022c8399f..584d738b3 100644 --- a/src/format/KeePass2RandomStream.h +++ b/src/format/KeePass2RandomStream.h @@ -29,7 +29,7 @@ public: bool init(const QByteArray& key); QByteArray randomBytes(int size, bool* ok); QByteArray process(const QByteArray& data, bool* ok); - bool processInPlace(QByteArray& data) Q_REQUIRED_RESULT; + Q_REQUIRED_RESULT bool processInPlace(QByteArray& data); QString errorString() const; private: diff --git a/src/format/KeePass2Writer.cpp b/src/format/KeePass2Writer.cpp index d63151c84..f8f60f11e 100644 --- a/src/format/KeePass2Writer.cpp +++ b/src/format/KeePass2Writer.cpp @@ -45,6 +45,7 @@ void KeePass2Writer::writeDatabase(QIODevice* device, Database* db) m_error = false; m_errorStr.clear(); + QByteArray transformSeed = randomGen()->randomArray(32); QByteArray masterSeed = randomGen()->randomArray(32); QByteArray encryptionIV = randomGen()->randomArray(16); QByteArray protectedStreamKey = randomGen()->randomArray(32); @@ -52,7 +53,12 @@ void KeePass2Writer::writeDatabase(QIODevice* device, Database* db) QByteArray endOfHeader = "\r\n\r\n"; if (db->challengeMasterSeed(masterSeed) == false) { - raiseError("Unable to issue challenge-response."); + raiseError(tr("Unable to issue challenge-response.")); + return; + } + + if (!db->transformKeyWithSeed(transformSeed)) { + raiseError(tr("Unable to calculate master key")); return; } diff --git a/src/format/KeePass2Writer.h b/src/format/KeePass2Writer.h index 1b3436dc6..184aa1a71 100644 --- a/src/format/KeePass2Writer.h +++ b/src/format/KeePass2Writer.h @@ -18,6 +18,8 @@ #ifndef KEEPASSX_KEEPASS2WRITER_H #define KEEPASSX_KEEPASS2WRITER_H +#include <QCoreApplication> + #include "format/KeePass2.h" #include "keys/CompositeKey.h" @@ -26,6 +28,8 @@ class QIODevice; class KeePass2Writer { + Q_DECLARE_TR_FUNCTIONS(KeePass2Writer) + public: KeePass2Writer(); void writeDatabase(QIODevice* device, Database* db); diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index 0e0f2960a..5978cd956 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -55,10 +55,14 @@ AboutDialog::AboutDialog(QWidget* parent) QString debugInfo = "KeePassXC - "; debugInfo.append(tr("Version %1\n").arg(KEEPASSX_VERSION)); if (!commitHash.isEmpty()) { - debugInfo.append(tr("Revision: %1").arg(commitHash).append("\n\n")); + debugInfo.append(tr("Revision: %1").arg(commitHash.left(7)).append("\n")); } - debugInfo.append(QString("%1\n- Qt %2\n- %3\n\n") +#ifdef KEEPASSXC_DIST + debugInfo.append(tr("Distribution: %1").arg(KEEPASSXC_DIST_TYPE).append("\n")); +#endif + + debugInfo.append("\n").append(QString("%1\n- Qt %2\n- %3\n\n") .arg(tr("Libraries:")) .arg(QString::fromLocal8Bit(qVersion())) .arg(Crypto::backendVersion())); diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index 7d59f16cf..ee0e9de26 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -70,9 +70,6 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) 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); @@ -98,10 +95,24 @@ void DatabaseOpenWidget::showEvent(QShowEvent* event) m_ui->editPassword->setFocus(); #ifdef WITH_XC_YUBIKEY + connect(YubiKey::instance(), SIGNAL(detected(int,bool)), SLOT(yubikeyDetected(int,bool)), Qt::QueuedConnection); + connect(YubiKey::instance(), SIGNAL(detectComplete()), SLOT(yubikeyDetectComplete()), Qt::QueuedConnection); + connect(YubiKey::instance(), SIGNAL(notFound()), SLOT(noYubikeyFound()), Qt::QueuedConnection); + pollYubikey(); #endif } +void DatabaseOpenWidget::hideEvent(QHideEvent* event) +{ + DialogyWidget::hideEvent(event); + +#ifdef WITH_XC_YUBIKEY + // Don't listen to any Yubikey events if we are hidden + disconnect(YubiKey::instance(), 0, this, 0); +#endif +} + void DatabaseOpenWidget::load(const QString& filename) { m_filename = filename; @@ -151,7 +162,10 @@ void DatabaseOpenWidget::enterKey(const QString& pw, const QString& keyFile) void DatabaseOpenWidget::openDatabase() { KeePass2Reader reader; - CompositeKey masterKey = databaseKey(); + QSharedPointer<CompositeKey> masterKey = databaseKey(); + if (masterKey.isNull()) { + return; + } QFile file(m_filename); if (!file.open(QIODevice::ReadOnly)) { @@ -163,7 +177,7 @@ void DatabaseOpenWidget::openDatabase() delete m_db; } QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); - m_db = reader.readDatabase(&file, masterKey); + m_db = reader.readDatabase(&file, *masterKey); QApplication::restoreOverrideCursor(); if (m_db) { @@ -171,20 +185,19 @@ void DatabaseOpenWidget::openDatabase() m_ui->messageWidget->animatedHide(); } emit editFinished(true); - } - else { - m_ui->messageWidget->showMessage(tr("Unable to open the database.") - .append("\n").append(reader.errorString()), MessageWidget::Error); + } else { + m_ui->messageWidget->showMessage(tr("Unable to open the database.").append("\n").append(reader.errorString()), + MessageWidget::Error); m_ui->editPassword->clear(); } } -CompositeKey DatabaseOpenWidget::databaseKey() +QSharedPointer<CompositeKey> DatabaseOpenWidget::databaseKey() { - CompositeKey masterKey; + auto masterKey = QSharedPointer<CompositeKey>::create(); if (m_ui->checkPassword->isChecked()) { - masterKey.addKey(PasswordKey(m_ui->editPassword->text())); + masterKey->addKey(PasswordKey(m_ui->editPassword->text())); } QHash<QString, QVariant> lastKeyFiles = config()->get("LastKeyFiles").toHash(); @@ -195,11 +208,11 @@ CompositeKey DatabaseOpenWidget::databaseKey() QString keyFilename = m_ui->comboKeyFile->currentText(); QString errorMsg; if (!key.load(keyFilename, &errorMsg)) { - m_ui->messageWidget->showMessage(tr("Can't open key file").append(":\n") - .append(errorMsg), MessageWidget::Error); - return CompositeKey(); + m_ui->messageWidget->showMessage(tr("Can't open key file").append(":\n").append(errorMsg), + MessageWidget::Error); + return QSharedPointer<CompositeKey>(); } - masterKey.addKey(key); + masterKey->addKey(key); lastKeyFiles[m_filename] = keyFilename; } else { lastKeyFiles.remove(m_filename); @@ -226,9 +239,9 @@ CompositeKey DatabaseOpenWidget::databaseKey() // read blocking mode from LSB and slot index number from second LSB bool blocking = comboPayload & 1; - int slot = comboPayload >> 1; - auto key = QSharedPointer<YkChallengeResponseKey>(new YkChallengeResponseKey(slot, blocking)); - masterKey.addChallengeResponseKey(key); + int slot = comboPayload >> 1; + auto key = QSharedPointer<YkChallengeResponseKey>(new YkChallengeResponseKey(slot, blocking)); + masterKey->addChallengeResponseKey(key); } #endif @@ -283,10 +296,6 @@ 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<QString, QVariant> lastChallengeResponse = config()->get("LastChallengeResponse").toHash(); @@ -296,6 +305,14 @@ void DatabaseOpenWidget::yubikeyDetected(int slot, bool blocking) } } +void DatabaseOpenWidget::yubikeyDetectComplete() +{ + m_ui->comboChallengeResponse->setEnabled(true); + m_ui->checkChallengeResponse->setEnabled(true); + m_ui->buttonRedetectYubikey->setEnabled(true); + m_ui->yubikeyProgress->setVisible(false); +} + void DatabaseOpenWidget::noYubikeyFound() { m_ui->buttonRedetectYubikey->setEnabled(true); diff --git a/src/gui/DatabaseOpenWidget.h b/src/gui/DatabaseOpenWidget.h index 441e6418c..a7691a91e 100644 --- a/src/gui/DatabaseOpenWidget.h +++ b/src/gui/DatabaseOpenWidget.h @@ -51,7 +51,8 @@ signals: protected: void showEvent(QShowEvent* event) override; - CompositeKey databaseKey(); + void hideEvent(QHideEvent* event) override; + QSharedPointer<CompositeKey> databaseKey(); protected slots: virtual void openDatabase(); @@ -63,6 +64,7 @@ private slots: void activateChallengeResponse(); void browseKeyFile(); void yubikeyDetected(int slot, bool blocking); + void yubikeyDetectComplete(); void noYubikeyFound(); protected: diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 9dca1ac06..4c9445ccc 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -129,7 +129,12 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, while (i.hasNext()) { i.next(); if (i.value().canonicalFilePath == canonicalFilePath) { - setCurrentIndex(databaseIndex(i.key())); + if (!i.value().dbWidget->dbHasKey() && !(pw.isNull() && keyFile.isEmpty())) { + // If the database is locked and a pw or keyfile is provided, unlock it + i.value().dbWidget->switchToOpenDatabase(i.value().filePath, pw, keyFile); + } else { + setCurrentIndex(databaseIndex(i.key())); + } return; } } @@ -181,6 +186,7 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, lockFile->tryLock(); } } else { + delete lockFile; return; } } @@ -203,7 +209,7 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, updateLastDatabases(dbStruct.filePath); - if (!pw.isNull() || !keyFile.isEmpty()) { + if (!(pw.isNull() && keyFile.isEmpty())) { dbStruct.dbWidget->switchToOpenDatabase(dbStruct.filePath, pw, keyFile); } else { diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index 691e93210..7c01b31f1 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -302,6 +302,7 @@ void EditWidgetIcons::addCustomIcon(const QImage &icon) } // Select the new or existing icon + updateRadioButtonCustomIcons(); QModelIndex index = m_customIconModel->indexFromUuid(uuid); m_ui->customIconsView->setCurrentIndex(index); } diff --git a/src/gui/SettingsWidget.cpp b/src/gui/SettingsWidget.cpp index e396f6043..420778be4 100644 --- a/src/gui/SettingsWidget.cpp +++ b/src/gui/SettingsWidget.cpp @@ -156,7 +156,7 @@ void SettingsWidget::loadSettings() 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->lockDatabaseOnScreenLockCheckBox->setChecked(config()->get("security/IconDownloadFallbackToGoogle").toBool()); + m_secUi->fallbackToGoogle->setChecked(config()->get("security/IconDownloadFallbackToGoogle").toBool()); m_secUi->passwordCleartextCheckBox->setChecked(config()->get("security/passwordscleartext").toBool()); m_secUi->passwordRepeatCheckBox->setChecked(config()->get("security/passwordsrepeat").toBool()); diff --git a/src/keys/drivers/YubiKey.cpp b/src/keys/drivers/YubiKey.cpp index b6f0d3098..4b98a6e48 100644 --- a/src/keys/drivers/YubiKey.cpp +++ b/src/keys/drivers/YubiKey.cpp @@ -25,6 +25,7 @@ #include <ykdef.h> #include <ykstatus.h> +#include "core/Tools.h" #include "core/Global.h" #include "crypto/Random.h" @@ -112,23 +113,36 @@ bool YubiKey::deinit() void YubiKey::detect() { + bool found = false; + if (init()) { - for (int i = 1; i < 3; i++) { - YubiKey::ChallengeResult result; - QByteArray rand = randomGen()->randomArray(1); - QByteArray resp; + YubiKey::ChallengeResult result; + QByteArray rand = randomGen()->randomArray(1); + QByteArray resp; + // Check slot 1 and 2 for Challenge-Response HMAC capability + for (int i = 1; i <= 2; ++i) { 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; + if (result == ALREADY_RUNNING) { + // Try this slot again after waiting + Tools::sleep(300); + result = challenge(i, false, rand, resp); + } + + if (result != ALREADY_RUNNING && result != ERROR) { + emit detected(i, result == WOULDBLOCK); + found = true; } + // Wait between slots to let the yubikey settle + Tools::sleep(150); } } - emit notFound(); + + if (!found) { + emit notFound(); + } else { + emit detectComplete(); + } } bool YubiKey::getSerial(unsigned int& serial) @@ -160,6 +174,7 @@ YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByte } // yk_challenge_response() insists on 64 byte response buffer */ + response.clear(); response.resize(64); /* The challenge sent to the yubikey should always be 64 bytes for diff --git a/src/keys/drivers/YubiKey.h b/src/keys/drivers/YubiKey.h index 1467b9fd1..328688f08 100644 --- a/src/keys/drivers/YubiKey.h +++ b/src/keys/drivers/YubiKey.h @@ -88,6 +88,11 @@ signals: void detected(int slot, bool blocking); /** + * Emitted when detection is complete + */ + void detectComplete(); + + /** * Emitted when the YubiKey was challenged and has returned a response. */ void challenged(); diff --git a/src/totp/base32.cpp b/src/totp/base32.cpp deleted file mode 100644 index 4c81cb491..000000000 --- a/src/totp/base32.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// 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 <team@keepassxc.org> -// -// 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<char> (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 deleted file mode 100644 index 75343fa43..000000000 --- a/src/totp/base32.h +++ /dev/null @@ -1,34 +0,0 @@ -// 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 <team@keepassxc.org> -// -// 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 <QtCore/qglobal.h> -#include <QByteArray> - -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 index 51af0e086..7a584def2 100644 --- a/src/totp/totp.cpp +++ b/src/totp/totp.cpp @@ -17,16 +17,16 @@ */ #include "totp.h" -#include "base32.h" -#include <cmath> -#include <QtEndian> -#include <QRegExp> -#include <QDateTime> +#include "core/Base32.h" #include <QCryptographicHash> +#include <QDateTime> #include <QMessageAuthenticationCode> +#include <QRegExp> #include <QUrl> #include <QUrlQuery> - +#include <QVariant> +#include <QtEndian> +#include <cmath> const quint8 QTotp::defaultStep = 30; const quint8 QTotp::defaultDigits = 6; @@ -35,7 +35,7 @@ QTotp::QTotp() { } -QString QTotp::parseOtpString(QString key, quint8 &digits, quint8 &step) +QString QTotp::parseOtpString(QString key, quint8& digits, quint8& step) { QUrl url(key); @@ -58,7 +58,6 @@ QString QTotp::parseOtpString(QString key, quint8 &digits, quint8 &step) step = q_step; } - } else { // Compatibility with "KeeOtp" plugin string format QRegExp rx("key=(.+)", Qt::CaseInsensitive, QRegExp::RegExp); @@ -93,30 +92,59 @@ QString QTotp::parseOtpString(QString key, quint8 &digits, quint8 &step) return seed; } -QString QTotp::generateTotp(const QByteArray key, quint64 time, - const quint8 numDigits = defaultDigits, const quint8 step = defaultStep) +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()) { + QVariant secret = Base32::decode(Base32::sanitizeInput(key)); + if (secret.isNull()) { return "Invalid TOTP secret key"; } QMessageAuthenticationCode code(QCryptographicHash::Sha1); - code.setKey(secret); + code.setKey(secret.toByteArray()); code.addData(QByteArray(reinterpret_cast<char*>(¤t), sizeof(current))); QByteArray hmac = code.result(); int offset = (hmac[hmac.length() - 1] & 0xf); + + // clang-format off int binary = ((hmac[offset] & 0x7f) << 24) | ((hmac[offset + 1] & 0xff) << 16) | ((hmac[offset + 2] & 0xff) << 8) | (hmac[offset + 3] & 0xff); + // clang-format on quint32 digitsPower = pow(10, numDigits); quint64 password = binary % digitsPower; return QString("%1").arg(password, numDigits, 10, QChar('0')); } + +// See: https://github.com/google/google-authenticator/wiki/Key-Uri-Format +QUrl QTotp::generateOtpString(const QString& secret, + const QString& type, + const QString& issuer, + const QString& username, + const QString& algorithm, + const quint8& digits, + const quint8& step) +{ + QUrl keyUri; + keyUri.setScheme("otpauth"); + keyUri.setHost(type); + keyUri.setPath(QString("/%1:%2").arg(issuer).arg(username)); + QUrlQuery parameters; + parameters.addQueryItem("secret", secret); + parameters.addQueryItem("issuer", issuer); + parameters.addQueryItem("algorithm", algorithm); + parameters.addQueryItem("digits", QString::number(digits)); + parameters.addQueryItem("period", QString::number(step)); + keyUri.setQuery(parameters); + + return keyUri; +} diff --git a/src/totp/totp.h b/src/totp/totp.h index 642b4f9a3..d5d8aa679 100644 --- a/src/totp/totp.h +++ b/src/totp/totp.h @@ -21,12 +21,21 @@ #include <QtCore/qglobal.h> +class QUrl; + class QTotp { public: QTotp(); - static QString parseOtpString(QString rawSecret, quint8 &digits, quint8 &step); + static QString parseOtpString(QString rawSecret, quint8& digits, quint8& step); static QString generateTotp(const QByteArray key, quint64 time, const quint8 numDigits, const quint8 step); + static QUrl generateOtpString(const QString& secret, + const QString& type, + const QString& issuer, + const QString& username, + const QString& algorithm, + const quint8& digits, + const quint8& step); static const quint8 defaultStep; static const quint8 defaultDigits; }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2a420270a..3f003f01c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -161,6 +161,9 @@ add_unit_test(NAME testentry SOURCES TestEntry.cpp add_unit_test(NAME testtotp SOURCES TestTotp.cpp LIBS ${TEST_LIBRARIES}) +add_unit_test(NAME testbase32 SOURCES TestBase32.cpp + LIBS ${TEST_LIBRARIES}) + add_unit_test(NAME testcsvparser SOURCES TestCsvParser.cpp LIBS ${TEST_LIBRARIES}) diff --git a/tests/TestBase32.cpp b/tests/TestBase32.cpp new file mode 100644 index 000000000..1d30e7817 --- /dev/null +++ b/tests/TestBase32.cpp @@ -0,0 +1,330 @@ +/* + * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "TestBase32.h" +#include "core/Base32.h" +#include <QTest> + +QTEST_GUILESS_MAIN(TestBase32) + +void TestBase32::testDecode() +{ + // 3 quanta, all upper case + padding + QByteArray encodedData = "JBSWY3DPEB3W64TMMQXC4LQ="; + QVariant data = Base32::decode(encodedData); + QString expectedData = "Hello world..."; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + // 4 quanta, all upper case + encodedData = "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ"; + data = Base32::decode(encodedData); + expectedData = "12345678901234567890"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + // 4 quanta, all lower case + encodedData = "gezdgnbvgy3tqojqgezdgnbvgy3tqojq"; + data = Base32::decode(encodedData); + expectedData = "12345678901234567890"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + // 4 quanta, mixed upper and lower case + encodedData = "Gezdgnbvgy3tQojqgezdGnbvgy3tQojQ"; + data = Base32::decode(encodedData); + expectedData = "12345678901234567890"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + // 1 pad characters + encodedData = "ORSXG5A="; + data = Base32::decode(encodedData); + expectedData = "test"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + // 3 pad characters + encodedData = "L5PV6==="; + data = Base32::decode(encodedData); + expectedData = "___"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + // 4 pad characters + encodedData = "MZXW6IDCMFZA===="; + data = Base32::decode(encodedData); + expectedData = "foo bar"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + // six pad characters + encodedData = "MZXW6YTBOI======"; + data = Base32::decode(encodedData); + expectedData = "foobar"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + encodedData = "IA======"; + data = Base32::decode(encodedData); + expectedData = "@"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + // error: illegal character + encodedData = "1MZXW6YTBOI====="; + data = Base32::decode(encodedData); + QVERIFY(data.isNull()); + + // error: missing pad character + encodedData = "MZXW6YTBOI====="; + data = Base32::decode(encodedData); + QVERIFY(data.isNull()); + + // RFC 4648 test vectors + encodedData = ""; + data = Base32::decode(encodedData); + expectedData = ""; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + encodedData = "MY======"; + data = Base32::decode(encodedData); + expectedData = "f"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + encodedData = "MZXQ===="; + data = Base32::decode(encodedData); + expectedData = "fo"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + encodedData = "MZXW6==="; + data = Base32::decode(encodedData); + QVERIFY(!data.isNull()); + expectedData = "foo"; + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + encodedData = "MZXW6YQ="; + data = Base32::decode(encodedData); + expectedData = "foob"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + encodedData = "MZXW6YTB"; + expectedData = "fooba"; + data = Base32::decode(encodedData); + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); + + encodedData = "MZXW6YTBOI======"; + data = Base32::decode(encodedData); + expectedData = "foobar"; + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), expectedData); + QVERIFY(data.value<QByteArray>().size() == expectedData.size()); +} + +void TestBase32::testEncode() +{ + QByteArray data = "Hello world..."; + QByteArray encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("JBSWY3DPEB3W64TMMQXC4LQ=")); + + data = "12345678901234567890"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ")); + + data = "012345678901234567890"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("GAYTEMZUGU3DOOBZGAYTEMZUGU3DOOBZGA======")); + + data = "test"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("ORSXG5A=")); + + data = "___"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("L5PV6===")); + + data = "foo bar"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("MZXW6IDCMFZA====")); + + data = "@"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("IA======")); + + // RFC 4648 test vectors + data = ""; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("")); + + data = "f"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("MY======")); + + data = "fo"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("MZXQ====")); + + data = "foo"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("MZXW6===")); + + data = "foob"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("MZXW6YQ=")); + + data = "fooba"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("MZXW6YTB")); + + data = "foobar"; + encodedData = Base32::encode(data); + QCOMPARE(encodedData, QByteArray("MZXW6YTBOI======")); +} + +void TestBase32::testAddPadding() +{ + // Empty. Invalid, returns input. + QByteArray data = ""; + QByteArray paddedData = Base32::addPadding(data); + QCOMPARE(paddedData, data); + + // One byte of encoded data. Invalid, returns input. + data = "B"; + paddedData = Base32::addPadding(data); + QCOMPARE(paddedData, data); + + // Two bytes of encoded data. + data = "BB"; + paddedData = Base32::addPadding(data); + QCOMPARE(paddedData, QByteArray("BB======")); + + // Three bytes of encoded data. Invalid, returns input. + data = "BBB"; + paddedData = Base32::addPadding(data); + QCOMPARE(paddedData, data); + + // Four bytes of encoded data. + data = "BBBB"; + paddedData = Base32::addPadding(data); + QCOMPARE(paddedData, QByteArray("BBBB====")); + + // Five bytes of encoded data. + data = "BBBBB"; + paddedData = Base32::addPadding(data); + QCOMPARE(paddedData, QByteArray("BBBBB===")); + + // Six bytes of encoded data. Invalid, returns input. + data = "BBBBBB"; + paddedData = Base32::addPadding(data); + QCOMPARE(paddedData, data); + + // Seven bytes of encoded data. + data = "BBBBBBB"; + paddedData = Base32::addPadding(data); + QCOMPARE(paddedData, QByteArray("BBBBBBB=")); + + // Eight bytes of encoded data. Valid, but returns same as input. + data = "BBBBBBBB"; + paddedData = Base32::addPadding(data); + QCOMPARE(paddedData, data); + + // More than eight bytes (8+5). + data = "AAAAAAAABBBBB"; + paddedData = Base32::addPadding(data); + QCOMPARE(paddedData, QByteArray("AAAAAAAABBBBB===")); +} + +void TestBase32::testRemovePadding() +{ + QByteArray data = ""; + QByteArray unpaddedData = Base32::removePadding(data); + QCOMPARE(unpaddedData, data); + + data = "AAAAAAAABB======"; + unpaddedData = Base32::removePadding(data); + QCOMPARE(unpaddedData, QByteArray("AAAAAAAABB")); + + data = "BBBB===="; + unpaddedData = Base32::removePadding(data); + QCOMPARE(unpaddedData, QByteArray("BBBB")); + + data = "AAAAAAAABBBBB==="; + unpaddedData = Base32::removePadding(data); + QCOMPARE(unpaddedData, QByteArray("AAAAAAAABBBBB")); + + data = "BBBBBBB="; + unpaddedData = Base32::removePadding(data); + QCOMPARE(unpaddedData, QByteArray("BBBBBBB")); + + // Invalid: 7 bytes of data. Returns same as input. + data = "IIIIIII"; + unpaddedData = Base32::removePadding(data); + QCOMPARE(unpaddedData, data); + + // Invalid: more padding than necessary. Returns same as input. + data = "AAAAAAAABBBB====="; + unpaddedData = Base32::removePadding(data); + QCOMPARE(unpaddedData, data); +} + +void TestBase32::testSanitizeInput() +{ + // sanitize input (white space + missing padding) + QByteArray encodedData = "JBSW Y3DP EB3W 64TM MQXC 4LQA"; + auto data = Base32::decode(Base32::sanitizeInput(encodedData)); + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), QString("Hello world...")); + + // sanitize input (typo + missing padding) + encodedData = "J8SWY3DPE83W64TMMQXC4LQA"; + data = Base32::decode(Base32::sanitizeInput(encodedData)); + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), QString("Hello world...")); + + // sanitize input (other illegal characters) + encodedData = "J8SWY3D[PE83W64TMMQ]XC!4LQA"; + data = Base32::decode(Base32::sanitizeInput(encodedData)); + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), QString("Hello world...")); + + // sanitize input (NUL character) + encodedData = "J8SWY3DPE83W64TMMQXC4LQA"; + encodedData.insert(3, '\0'); + data = Base32::decode(Base32::sanitizeInput(encodedData)); + QVERIFY(!data.isNull()); + QCOMPARE(data.toString(), QString("Hello world...")); +} diff --git a/tests/TestBase32.h b/tests/TestBase32.h new file mode 100644 index 000000000..cf7cf092c --- /dev/null +++ b/tests/TestBase32.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef KEEPASSX_TESTBASE32_H +#define KEEPASSX_TESTBASE32_H + +#include <QObject> + +class Base32; + +class TestBase32 : public QObject +{ + Q_OBJECT + +private slots: + void testEncode(); + void testDecode(); + void testAddPadding(); + void testRemovePadding(); + void testSanitizeInput(); +}; + +#endif // KEEPASSX_TESTBASE32_H diff --git a/tests/TestEntry.cpp b/tests/TestEntry.cpp index 4d34cf31b..84ad03181 100644 --- a/tests/TestEntry.cpp +++ b/tests/TestEntry.cpp @@ -16,6 +16,7 @@ */ #include "TestEntry.h" +#include "config-keepassx-tests.h" #include <QTest> @@ -130,3 +131,30 @@ void TestEntry::testClone() delete entryOrg; } + +void TestEntry::testResolveUrl() +{ + Entry* entry = new Entry(); + QString testUrl("www.google.com"); + QString testCmd("cmd://firefox " + testUrl); + QString testComplexCmd("cmd://firefox --start-now --url 'http://" + testUrl + "' --quit"); + QString nonHttpUrl("ftp://google.com"); + QString noUrl("random text inserted here"); + + // Test standard URL's + QCOMPARE(entry->resolveUrl(""), QString("")); + QCOMPARE(entry->resolveUrl(testUrl), "https://" + testUrl); + QCOMPARE(entry->resolveUrl("http://" + testUrl), "http://" + testUrl); + // Test cmd:// with no URL + QCOMPARE(entry->resolveUrl("cmd://firefox"), QString("")); + QCOMPARE(entry->resolveUrl("cmd://firefox --no-url"), QString("")); + // Test cmd:// with URL's + QCOMPARE(entry->resolveUrl(testCmd), "https://" + testUrl); + QCOMPARE(entry->resolveUrl(testComplexCmd), "http://" + testUrl); + // Test non-http URL + QCOMPARE(entry->resolveUrl(nonHttpUrl), QString("")); + // Test no URL + QCOMPARE(entry->resolveUrl(noUrl), QString("")); + + delete entry; +} diff --git a/tests/TestEntry.h b/tests/TestEntry.h index 0c97c0b9d..3f6d20ee3 100644 --- a/tests/TestEntry.h +++ b/tests/TestEntry.h @@ -31,6 +31,7 @@ private slots: void testHistoryItemDeletion(); void testCopyDataFrom(); void testClone(); + void testResolveUrl(); }; #endif // KEEPASSX_TESTENTRY_H diff --git a/tests/TestTotp.cpp b/tests/TestTotp.cpp index e22c2567e..48ff88144 100644 --- a/tests/TestTotp.cpp +++ b/tests/TestTotp.cpp @@ -18,15 +18,14 @@ #include "TestTotp.h" +#include <QDateTime> #include <QTest> +#include <QTextCodec> #include <QTime> -#include <QDateTime> #include <QtEndian> -#include <QTextCodec> #include "crypto/Crypto.h" #include "totp/totp.h" -#include "totp/base32.h" QTEST_GUILESS_MAIN(TestTotp) @@ -35,12 +34,13 @@ 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"; + 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)); @@ -60,25 +60,6 @@ void TestTotp::testParseSecret() 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 diff --git a/tests/TestTotp.h b/tests/TestTotp.h index d197294dd..785a9f522 100644 --- a/tests/TestTotp.h +++ b/tests/TestTotp.h @@ -30,7 +30,6 @@ class TestTotp : public QObject private slots: void initTestCase(); void testParseSecret(); - void testBase32(); void testTotpCode(); }; |