Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanek Bevendorff <janek@jbev.net>2017-10-22 01:28:08 +0300
committerJanek Bevendorff <janek@jbev.net>2017-10-22 01:28:08 +0300
commit6d46717cfc2d61bfc6a5335b02e95c6b1d9bf482 (patch)
tree6582a28ee275e7852c1cf6251d89e477a423e274
parent2bce9c8add07226e9a05e9e0fd0e5e66b236d5b6 (diff)
parent3088371631cf8a57a1431f170fb9a54dce6f65ba (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]
-rw-r--r--.gitignore1
-rwxr-xr-xAppImage-Recipe.sh21
-rw-r--r--CHANGELOG17
-rw-r--r--CMakeLists.txt14
-rw-r--r--COPYING9
-rw-r--r--Dockerfile81
-rw-r--r--LICENSE.APACHE-2.0201
-rw-r--r--README.md2
-rwxr-xr-xrelease-tool82
-rw-r--r--share/CMakeLists.txt3
-rw-r--r--share/linux/keepassxc.xml2
-rw-r--r--share/linux/org.keepassxc.appdata.xml218
-rw-r--r--share/linux/org.keepassxc.desktop (renamed from share/linux/keepassxc.desktop)7
-rw-r--r--share/translations/keepassx_cs.ts19
-rw-r--r--share/translations/keepassx_da.ts15
-rw-r--r--share/translations/keepassx_de.ts19
-rw-r--r--share/translations/keepassx_el.ts15
-rw-r--r--share/translations/keepassx_en.ts15
-rw-r--r--share/translations/keepassx_es.ts15
-rw-r--r--share/translations/keepassx_eu.ts15
-rw-r--r--share/translations/keepassx_fi.ts15
-rw-r--r--share/translations/keepassx_fr.ts15
-rw-r--r--share/translations/keepassx_hu.ts19
-rw-r--r--share/translations/keepassx_id.ts15
-rw-r--r--share/translations/keepassx_it.ts415
-rw-r--r--share/translations/keepassx_ja.ts19
-rw-r--r--share/translations/keepassx_kk.ts15
-rw-r--r--share/translations/keepassx_ko.ts15
-rw-r--r--share/translations/keepassx_lt.ts19
-rw-r--r--share/translations/keepassx_nl_NL.ts15
-rw-r--r--share/translations/keepassx_pl.ts19
-rw-r--r--share/translations/keepassx_pt_BR.ts15
-rw-r--r--share/translations/keepassx_pt_PT.ts19
-rw-r--r--share/translations/keepassx_ru.ts15
-rw-r--r--share/translations/keepassx_sl_SI.ts15
-rw-r--r--share/translations/keepassx_sv.ts38
-rw-r--r--share/translations/keepassx_tr.ts15
-rw-r--r--share/translations/keepassx_uk.ts15
-rw-r--r--share/translations/keepassx_zh_CN.ts15
-rw-r--r--share/translations/keepassx_zh_TW.ts15
-rw-r--r--snapcraft.yaml22
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/config-keepassx.h.cmake5
-rw-r--r--src/core/Base32.cpp290
-rw-r--r--src/core/Base32.h42
-rw-r--r--src/core/Database.cpp28
-rw-r--r--src/core/Database.h1
-rw-r--r--src/core/Entry.cpp33
-rw-r--r--src/core/FilePath.cpp12
-rw-r--r--src/core/Metadata.cpp2
-rw-r--r--src/crypto/SymmetricCipher.h4
-rw-r--r--src/crypto/SymmetricCipherBackend.h4
-rw-r--r--src/crypto/SymmetricCipherGcrypt.cpp3
-rw-r--r--src/crypto/SymmetricCipherGcrypt.h4
-rw-r--r--src/format/KeePass2RandomStream.h2
-rw-r--r--src/format/KeePass2Writer.cpp8
-rw-r--r--src/format/KeePass2Writer.h4
-rw-r--r--src/gui/AboutDialog.cpp8
-rw-r--r--src/gui/DatabaseOpenWidget.cpp63
-rw-r--r--src/gui/DatabaseOpenWidget.h4
-rw-r--r--src/gui/DatabaseTabWidget.cpp10
-rw-r--r--src/gui/EditWidgetIcons.cpp1
-rw-r--r--src/gui/SettingsWidget.cpp2
-rw-r--r--src/keys/drivers/YubiKey.cpp37
-rw-r--r--src/keys/drivers/YubiKey.h5
-rw-r--r--src/totp/base32.cpp68
-rw-r--r--src/totp/base32.h34
-rw-r--r--src/totp/totp.cpp54
-rw-r--r--src/totp/totp.h11
-rw-r--r--tests/CMakeLists.txt3
-rw-r--r--tests/TestBase32.cpp330
-rw-r--r--tests/TestBase32.h37
-rw-r--r--tests/TestEntry.cpp28
-rw-r--r--tests/TestEntry.h1
-rw-r--r--tests/TestTotp.cpp29
-rw-r--r--tests/TestTotp.h1
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
diff --git a/CHANGELOG b/CHANGELOG
index cc976c138..3719f8e4c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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()
diff --git a/COPYING b/COPYING
index 481aaf726..403e4564b 100644
--- a/COPYING
+++ b/COPYING
@@ -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
diff --git a/README.md b/README.md
index bf214d3c1..5588e3222 100644
--- a/README.md
+++ b/README.md
@@ -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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;agit d&apos;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: &lt;a href=&quot;https://github.com/keepassxreboot/keepassxc/issues&quot; style=&quot;text-decoration: underline;&quot;&gt;https://github.com&lt;/a&gt;</source>
- <translation>Segnala eventuali problemi su: &lt;a href=&quot;https://github.com/keepassxreboot/keepassxc/issues&quot; style=&quot;text-decoration: underline;&quot;&gt;https://github.com&lt;/a&gt;</translation>
+ <translation>Segnala eventuali problemi in: &lt;a href=&quot;https://github.com/keepassxreboot/keepassxc/issues&quot; style=&quot;text-decoration: underline;&quot;&gt;https://github.com&lt;/a&gt;</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>&lt;a href=&quot;https://github.com/keepassxreboot/keepassxc/graphs/contributors&quot;&gt;See Contributions on GitHub&lt;/a&gt;</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&apos;accesso.</translation>
+ <translation>%1 ha richiesto accesso alle passwords per il seguente elemento/i.
+Seleziona se vuoi consentire l&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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 &apos;\&apos; an escape character</source>
@@ -278,7 +282,7 @@ Perfavore seleziona se vuoi consentire l&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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>&quot;%1&quot; was modified.
Save changes?</source>
<translation>&quot;%1&quot; è 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 &apos;Annulla&apos; 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>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;%1&quot; è 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&apos;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&apos;elemento?</translation>
</message>
<message>
<source>Do you really want to delete the entry &quot;%1&quot; for good?</source>
- <translation>Vuoi veramente eliminare la voce &quot;%1&quot;?</translation>
+ <translation>Vuoi veramente eliminare l&apos;elemento &quot;%1&quot;?</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 &quot;%1&quot; 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&apos;elemento nel Cestino?</translation>
</message>
<message>
<source>Do you really want to move entry &quot;%1&quot; to the recycle bin?</source>
- <translation>Vuoi veramente spostare la voce &quot;%1&quot; nel cestino?</translation>
+ <translation>Vuoi veramente spostare l&apos;elemento &quot;%1&quot; 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?&lt;br&gt;&lt;br&gt;%1&lt;br&gt;</source>
- <translation>Sei sicuro di voler eseguire il comando seguente?&lt;br&gt;&lt;br&gt;%1&lt;br&gt;</translation>
+ <translation>Sei sicuro di voler eseguire il seguente comando?&lt;br&gt;&lt;br&gt;%1&lt;br&gt;</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&apos;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&apos;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 &apos;Rileva&apos; 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 &amp;group</source>
- <translation>Eredita la sequenza per l&apos;Auto-Completamento dal &amp;gruppo</translation>
+ <translation>Eredita la sequenza per il completamento automatico dal &amp;gruppo</translation>
</message>
<message>
<source>&amp;Use custom Auto-Type sequence:</source>
- <translation>&amp;Usa sequenza di Auto-Completamento personalizzata:</translation>
+ <translation>&amp;Usa sequenza di compeltamento automatico personalizzata:</translation>
</message>
<message>
<source>Use default se&amp;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>&amp;Use default Auto-Type sequence of parent group</source>
- <translation>&amp;Usa la sequenza di auto-digitazione predefinita del gruppo genitore</translation>
+ <translation>&amp;Usa la sequenza di completamento automatico predefinita del gruppo genitore</translation>
</message>
<message>
<source>Set default Auto-Type se&amp;quence</source>
- <translation>Imposta la se&amp;quenza predefinita di auto-digitazione</translation>
+ <translation>Imposta se&amp;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&apos;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&apos;icona predefinita. Sei sicuro di volerla eliminare?</translation>
+ <translation>Questa icona viene usata da %1 elementi, e sarà sostituita dall&apos;icona predefinita. Sei sicuro di volerla eliminare?</translation>
</message>
<message>
<source>Hint: You can enable Google as a fallback under Tools&gt;Settings&gt;Security</source>
- <translation>Suggerimento: è possibile abilitare Google come ripiego in Strumenti&gt;Impostazioni&gt;Sicurezza</translation>
+ <translation>Suggerimento: è possibile abilitare Google come alternativa in &apos;Strumenti&apos;&gt;&apos;Impostazioni&apos;&gt;&apos;Sicurezza&apos;</translation>
</message>
<message>
<source>Custom icon already exists</source>
- <translation type="unfinished"/>
+ <translation>L&apos;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 &gt; 'Import KeePass 1 database...'.
This is a one-way migration. You won&apos;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 &gt; &apos;Importa database KeePass 1...&apos;.
-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 &apos;Database&apos; &gt; &apos;Importa database KeePass 1...&apos;.
+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&apos;altra istanza di KeePassXC è già in esecuzione.</translation>
+ <translation>È già in esecuzione un&apos;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>&amp;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&amp;ribute to clipboard</source>
- <translation>Copia gli att&amp;ributi nella clipboard</translation>
+ <translation>Copia gli att&amp;ributi negli Appunti</translation>
</message>
<message>
<source>&amp;Groups</source>
@@ -1440,7 +1455,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data
</message>
<message>
<source>&amp;View/Edit entry</source>
- <translation>&amp;Vedi/Modifica l&apos;elemento</translation>
+ <translation>&amp;Visualizza/modifica elemento</translation>
</message>
<message>
<source>&amp;Delete entry</source>
@@ -1460,7 +1475,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data
</message>
<message>
<source>&amp;Database settings</source>
- <translation>Impostazioni &amp;Database</translation>
+ <translation>Impostazioni &amp;database</translation>
</message>
<message>
<source>&amp;Clone entry</source>
@@ -1496,7 +1511,7 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data
</message>
<message>
<source>&amp;Perform Auto-Type</source>
- <translation>&amp;Esegui Auto-Completamento</translation>
+ <translation>&amp;Esegui completamento automatico</translation>
</message>
<message>
<source>&amp;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>&amp;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>&amp;Help</source>
@@ -1564,27 +1579,27 @@ Si tratta di una migrazione unidirezionale. Non sarai in grado di aprire il data
</message>
<message>
<source>Sa&amp;ve database as...</source>
- <translation>Sal&amp;va il database come...</translation>
+ <translation>Sal&amp;va database come...</translation>
</message>
<message>
<source>Change &amp;master key...</source>
- <translation>Ca&amp;mbia la chiave principale...</translation>
+ <translation>&amp;Modifica chiave principale...</translation>
</message>
<message>
<source>&amp;Export to CSV file...</source>
- <translation>&amp;Esporta su un file CSV...</translation>
+ <translation>&amp;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&amp;pair database...</source>
- <translation>Ri&amp;para il database...</translation>
+ <translation>Ri&amp;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&amp;ow a notification when credentials are requested</source>
- <translation>M&amp;ostra una notifica quando sono richeste le credenziali</translation>
+ <translation>Visualizza una n&amp;otifica quando sono richeste le credenziali</translation>
</message>
<message>
<source>Sort matching entries by &amp;username</source>
- <translation>Ordina le voci trovate per &amp;nome utente</translation>
+ <translation>Ordina elementi trovati per &amp;nome utente</translation>
</message>
<message>
<source>Re&amp;move all stored permissions from entries in active database</source>
- <translation>R&amp;imuovi tutti i permessi presenti dalle voci nel database attivo</translation>
+ <translation>R&amp;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 &amp;access to entries</source>
- <translation>Permetti sempre di &amp;accedere alle voci</translation>
+ <translation>Permetti sempre di &amp;accedere agli elementi</translation>
</message>
<message>
<source>Always allow &amp;updating entries</source>
- <translation>Permetti sempre di &amp;aggiornare le voci</translation>
+ <translation>Permetti sempre di &amp;aggiornare gli elementi</translation>
</message>
<message>
<source>Searc&amp;h in all opened databases for matching entries</source>
- <translation>Cerc&amp;a in tutti i database aperti per la ricerca delle voci</translation>
+ <translation>Cerc&amp;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 &amp;matching entries by title</source>
- <translation>Ordina le voci per &amp;titolo</translation>
+ <translation>Ordina gli elementi per &amp;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&amp;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&apos;intero dominio.</translation>
+ <translation>Restituisci solo le corrispondenze migliori per un&apos;URL specifica invece di tutte gli elementi per l&apos;intero dominio.</translation>
</message>
<message>
<source>&amp;Return only best matching entries</source>
- <translation>&amp;Restituisci solo le migliori voci corrispondenti</translation>
+ <translation>&amp;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>&amp;Match URL schemes</source>
- <translation>Co&amp;mbina gli schemi URL</translation>
+ <translation>Sche&amp;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&apos;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 &quot;%1&quot; already exists.
Do you want to overwrite it?</source>
- <translation>Una chiave di criptazione condivisa con il nome &quot;%1&quot; già esiste.
+ <translation>Una chiave di criptazione condivisa con il nome &quot;%1&quot; 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&apos;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&apos;icona nell&apos;area di notifica del sistema</translation>
+ <translation>Visualizza un&apos;icona nell&apos;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&apos;avvio</translation>
+ <translation>All&apos;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&apos;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&apos;URL per abbinare le finestre per l&apos;auto-digitazione globale</translation>
+ <translation>Usa il titolo dell&apos;elemento e l&apos;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&apos;auto-digitazione</translation>
+ <translation>Chiedi sempre prima di effettuare il completamento automatico</translation>
</message>
<message>
<source>Auto-Type delay</source>
- <translation>Ritardo dell&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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&apos;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*>(&current), 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();
};