diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..baae16c8 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +src/version.h.cmake export-subst diff --git a/.travis.yml b/.travis.yml index 6e26860f..550518aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,15 +5,21 @@ compiler: - gcc - clang language: cpp +sudo: required +dist: trusty install: - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq update; fi - - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake libqt4-dev libgcrypt11-dev zlib1g-dev libxtst-dev; fi + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake qtbase5-dev libqt5x11extras5-dev qttools5-dev qttools5-dev-tools libgcrypt20-dev zlib1g-dev libxtst-dev xvfb; fi - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; fi - - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install cmake qt libgcrypt; fi -before_script: mkdir build && pushd build + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq cmake || brew install cmake; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq qt5 || brew install qt5; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq libgcrypt || brew install libgcrypt; fi +before_script: + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then CMAKE_ARGS="-DCMAKE_PREFIX_PATH=/usr/local/opt/qt5"; fi + - mkdir build && pushd build script: - - cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_GUI_TESTS=ON .. + - cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_GUI_TESTS=ON $CMAKE_ARGS .. - make - if [ "$TRAVIS_OS_NAME" = "linux" ]; then make test ARGS+="-E testgui --output-on-failure"; fi - if [ "$TRAVIS_OS_NAME" = "linux" ]; then xvfb-run -a --server-args="-screen 0 800x600x24" make test ARGS+="-R testgui --output-on-failure"; fi - - if [ "$TRAVIS_OS_NAME" = "osx" ]; then make test; fi + - if [ "$TRAVIS_OS_NAME" = "osx" ]; then make test ARGS+="--output-on-failure"; fi diff --git a/CHANGELOG b/CHANGELOG index b61597b7..14d19357 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,55 @@ +2.0.2 (2016-02-02) +========================= + +- Fix regression in database writer that caused it to strip certain special + characters (characters from Unicode plane > 0). +- Fix bug in repair function that caused it to strip non-ASCII characters. + +2.0.1 (2016-01-31) +========================= + +- Flush temporary file before opening attachment. [#390] +- Disable password generator when showing entry in history mode. [#422] +- Strip invalid XML chars when writing databases. [#392] +- Add repair function to fix databases with invalid XML chars. [#392] +- Display custom icons scaled. [#322] +- Allow opening databases that have no password and keyfile. [#391] +- Fix crash when importing .kdb files with invalid icon ids. [#425] +- Update translations. + +2.0 (2015-12-06) +========================= + +- Improve UI of the search edit. +- Clear clipboard when locking databases. [#342] +- Enable Ctrl+M shortcut to minimize the window on all platforms. [#329] +- Show a better message when trying to open an old database format. [#338] +- Fix global auto-type behavior with some window managers. +- Show global auto-type window on the active desktop. [#359] +- Disable systray on OS X. [#326] +- Restore main window when clicking on the OS X docker icon. [#326] + +2.0 Beta 2 (2015-09-06) +========================= + +- Fix crash when locking with search UI open [#309] +- Fix file locking on Mac OS X [#327] +- Set default extension when saving a database [#79, #308] + +2.0 Beta 1 (2015-07-18) +========================= + +- Remember entry column sizes [#159] +- Add translations +- Support opening attachments directly +- Support cmd:// URLs [#244] +- Protect opened databases with a file lock [#18] +- Export to csv files [#57] +- Add optional tray icon [#153] +- Allow setting the default auto-type sequence for groups [#175] +- Make the kdbx parser more lenient +- Remove --password command line option [#285] + 2.0 Alpha 6 (2014-04-12) ========================= diff --git a/CMakeLists.txt b/CMakeLists.txt index 13b7b10f..8403ea9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ endif() project(KeePassX) -cmake_minimum_required(VERSION 2.6.4) +cmake_minimum_required(VERSION 2.8.12) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) @@ -31,11 +31,10 @@ include(CheckCXXSourceCompiles) option(WITH_TESTS "Enable building of unit tests" ON) option(WITH_GUI_TESTS "Enable building of GUI tests" OFF) -option(WITH_LTO "Enable Link Time Optimization (LTO)" OFF) -option(WITH_CXX11 "Build with the C++ 11 standard" ON) +option(WITH_DEV_BUILD "Use only for development. Disables/warns about deprecated methods." OFF) -set(KEEPASSX_VERSION "2.0 alpha 6") -set(KEEPASSX_VERSION_NUM "1.9.85") +set(KEEPASSX_VERSION "2.0.2") +set(KEEPASSX_VERSION_NUM "2.0.2") if("${CMAKE_C_COMPILER}" MATCHES "clang$" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_COMPILER_IS_CLANG 1) @@ -62,7 +61,7 @@ macro(add_gcc_compiler_flags FLAGS) add_gcc_compiler_cflags("${FLAGS}") endmacro(add_gcc_compiler_flags) -add_definitions(-DQT_NO_KEYWORDS -DQT_NO_EXCEPTIONS -DQT_NO_STL -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII) +add_definitions(-DQT_NO_KEYWORDS -DQT_NO_EXCEPTIONS -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII) add_gcc_compiler_flags("-fno-common -fstack-protector --param=ssp-buffer-size=4") add_gcc_compiler_flags("-Wall -Wextra -Wundef -Wpointer-arith -Wno-long-long") @@ -101,25 +100,16 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro") endif() -if(WITH_LTO) - if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_COMPILER_IS_GNUCXX) - check_cxx_compiler_flag("-flto -fuse-linker-plugin" LTO_AVAILABLE) +add_gcc_compiler_cxxflags("-std=c++11") - if(LTO_AVAILABLE) - add_gcc_compiler_flags("-flto -fuse-linker-plugin") - else() - message(FATAL_ERROR "This version of gcc doesn't support LTO") - endif(LTO_AVAILABLE) - else() - message(FATAL_ERROR "LTO is only supported with gcc") - endif() +if(APPLE) + add_gcc_compiler_cxxflags("-stdlib=libc++") endif() -if (WITH_CXX11) - add_gcc_compiler_cxxflags("-std=c++0x") - add_gcc_compiler_cflags("-ansi") -else() - add_gcc_compiler_flags("-ansi") +add_gcc_compiler_cflags("-ansi") + +if(WITH_DEV_BUILD) + add_definitions(-DQT_DEPRECATED_WARNINGS -DGCRYPT_NO_DEPRECATED) endif() if(MINGW) @@ -158,22 +148,18 @@ if(WITH_TESTS) enable_testing() endif(WITH_TESTS) -set(QT_REQUIRED_MODULES QtCore QtGui QtTest) -if(UNIX AND NOT APPLE) - set(QT_REQUIRED_MODULES ${QT_REQUIRED_MODULES} QtDBus) -endif() +find_package(Qt5Core 5.2 REQUIRED) +find_package(Qt5Concurrent 5.2 REQUIRED) +find_package(Qt5Widgets 5.2 REQUIRED) +find_package(Qt5Test 5.2 REQUIRED) +find_package(Qt5LinguistTools 5.2 REQUIRED) +set(CMAKE_AUTOMOC ON) -find_package(Qt4 4.6.0 REQUIRED ${QT_REQUIRED_MODULES}) -include(${QT_USE_FILE}) # Debian sets the the build type to None for package builds. # Make sure we don't enable asserts there. set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG) -find_package(Gcrypt REQUIRED) -if(NOT (${GCRYPT_VERSION_STRING} VERSION_LESS "1.6.0")) - message(STATUS "Gcrypt ${GCRYPT_VERSION_STRING} supports the SALSA20 cipher") - set(GCRYPT_HAS_SALSA20 1) -endif() +find_package(Gcrypt 1.6.0 REQUIRED) find_package(LibMicroHTTPD REQUIRED) @@ -218,10 +204,7 @@ endif() include_directories(SYSTEM ${GCRYPT_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) -if(NOT (${CMAKE_VERSION} VERSION_LESS 2.8.3)) - set(PRINT_SUMMARY ON) - include(FeatureSummary) -endif() +include(FeatureSummary) add_subdirectory(src) add_subdirectory(share) diff --git a/COPYING b/COPYING index 7042fa11..e350b79a 100644 --- a/COPYING +++ b/COPYING @@ -139,10 +139,10 @@ Files: share/icons/application/*/actions/application-exit.png share/icons/application/*/actions/password-copy.png share/icons/application/*/actions/password-show-*.png share/icons/application/*/actions/system-search.png + share/icons/application/*/actions/username-copy.png share/icons/application/*/status/dialog-error.png share/icons/application/*/status/dialog-information.png share/icons/application/*/status/dialog-warning.png - share/icons/application/*/status/username-copy.png share/icons/svg/*.svgz Copyright: 2007, Nuno Pinheiro 2007, David Vignoni @@ -183,3 +183,7 @@ Files: src/streams/qtiocompressor.* tests/modeltest.* Copyright: 2009-2012, Nokia Corporation and/or its subsidiary(-ies) License: LGPL-2.1 or GPL-3 + +Files: cmake/GetGitRevisionDescription.cmake* +Copyright: 2009-2010, Iowa State University +License: Boost-1.0 diff --git a/LICENSE.BOOST-1.0 b/LICENSE.BOOST-1.0 new file mode 100644 index 00000000..36b7cd93 --- /dev/null +++ b/LICENSE.BOOST-1.0 @@ -0,0 +1,23 @@ +Boost Software License - Version 1.0 - August 17th, 2003 + +Permission is hereby granted, free of charge, to any person or organization +obtaining a copy of the software and accompanying documentation covered by +this license (the "Software") to use, reproduce, display, distribute, +execute, and transmit the Software, and to prepare derivative works of the +Software, and to permit third-parties to whom the Software is furnished to +do so, all subject to the following: + +The copyright notices in the Software and this entire statement, including +the above license grant, this restriction and the following disclaimer, +must be included in all copies of the Software, in whole or in part, and +all derivative works of the Software, unless such copies or derivative +works are solely in the form of machine-executable object code generated by +a source language processor. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index d15ddcca..c53d98eb 100644 --- a/README.md +++ b/README.md @@ -13,22 +13,23 @@ My intention is to keep this repository as up-to-date with the main keePassX rep The following tools must exist within your PATH: * make -* cmake (>= 2.6.4) -* g++ or clang++ +* cmake (>= 2.8.12) +* g++ (>= 4.7) or clang++ (>= 3.0) The following libraries are required: -* Qt 4 (>= 4.6) -* libgcrypt +* Qt 5 (>= 5.2): qtbase and qttools5 +* libgcrypt (>= 1.6) * zlib * libmicrohttpd * QJSON * libxtst (optional for auto-type on X11) +* libxtst, qtx11extras (optional for auto-type on X11) On Debian you can install them with: ```bash -sudo apt-get install build-essential cmake libqt4-dev libgcrypt11-dev zlib1g-dev +sudo apt-get install build-essential cmake qtbase5-dev libqt5x11extras5-dev qttools5-dev qttools5-dev-tools libgcrypt20-dev zlib1g-dev ``` #### Build Steps @@ -51,3 +52,45 @@ sudo make install ``` More detailed instructions available in the INSTALL file. + +## Contribute + +Coordination of work between developers is handled through the [KeePassX development](https://www.keepassx.org/dev/) site. +Requests for enhancements, or reports of bugs encountered, can also be reported through the KeePassX development site. +However, members of the open-source community are encouraged to submit pull requests directly through GitHub. + +### Clone Repository + +Clone the repository to a suitable location where you can extend and build this project. + +```bash +git clone https://github.com/keepassx/keepassx.git +``` + +**Note:** This will clone the entire contents of the repository at the HEAD revision. + +To update the project from within the project's folder you can run the following command: + +```bash +git pull +``` + +### Feature Requests + +We're always looking for suggestions to improve our application. If you have a suggestion for improving an existing feature, +or would like to suggest a completely new feature for KeePassX, please file a ticket on the [KeePassX development](https://www.keepassx.org/dev/) site. + +### Bug Reports + +Our software isn't always perfect, but we strive to always improve our work. You may file bug reports on the [KeePassX development](https://www.keepassx.org/dev/) site. + +### Pull Requests + +Along with our desire to hear your feedback and suggestions, we're also interested in accepting direct assistance in the form of code. + +Issue merge requests against our [GitHub repository](https://github.com/keepassx/keepassx). + +### Translations + +Translations are managed on [Transifex](https://www.transifex.com/projects/p/keepassx/) which offers a web interface. +Please join an existing language team or request a new one if there is none. diff --git a/cmake/GetGitRevisionDescription.cmake b/cmake/GetGitRevisionDescription.cmake new file mode 100644 index 00000000..d39671cd --- /dev/null +++ b/cmake/GetGitRevisionDescription.cmake @@ -0,0 +1,130 @@ +# - Returns a version string from Git +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# get_git_head_revision( [ ...]) +# +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.BOOST-1.0 or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +function(get_git_head_revision _refspecvar _hashvar) + set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories + set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") + get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) + if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) + # We have reached the root directory, we are not in git + set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + return() + endif() + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + endwhile() + # check if this is a submodule + if(NOT IS_DIRECTORY ${GIT_DIR}) + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${GIT_DIR}/HEAD") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" + @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) + set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) +endfunction() + +function(git_describe _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() + + #message(STATUS "Arguments to execute_process: ${ARGN}") + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + describe + ${hash} + ${ARGN} + WORKING_DIRECTORY + "${CMAKE_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +function(git_get_exact_tag _var) + git_describe(out --exact-match ${ARGN}) + set(${_var} "${out}" PARENT_SCOPE) +endfunction() diff --git a/cmake/GetGitRevisionDescription.cmake.in b/cmake/GetGitRevisionDescription.cmake.in new file mode 100644 index 00000000..353c0252 --- /dev/null +++ b/cmake/GetGitRevisionDescription.cmake.in @@ -0,0 +1,41 @@ +# +# Internal file for GetGitRevisionDescription.cmake +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE.BOOST-1.0 or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() diff --git a/share/linux/keepassx.desktop b/share/linux/keepassx.desktop index c4fb0ccc..41213bbe 100644 --- a/share/linux/keepassx.desktop +++ b/share/linux/keepassx.desktop @@ -1,9 +1,10 @@ [Desktop Entry] Name=KeePassX -GenericName=Cross Platform Password Manager +GenericName=Password Manager GenericName[de]=Passwortverwaltung -GenericName[es]=Gestor de contraseñas multiplataforma +GenericName[es]=Gestor de contraseñas GenericName[fr]=Gestionnaire de mot de passe +GenericName[ru]=менеджер паролей Exec=keepassx %f Icon=keepassx Terminal=false diff --git a/share/translations/CMakeLists.txt b/share/translations/CMakeLists.txt index b1aa8785..7380750e 100644 --- a/share/translations/CMakeLists.txt +++ b/share/translations/CMakeLists.txt @@ -17,9 +17,9 @@ file(GLOB TRANSLATION_FILES *.ts) get_filename_component(TRANSLATION_EN_ABS keepassx_en.ts ABSOLUTE) list(REMOVE_ITEM TRANSLATION_FILES keepassx_en.ts) list(REMOVE_ITEM TRANSLATION_FILES ${TRANSLATION_EN_ABS}) -message(STATUS ${TRANSLATION_FILES}) +message(STATUS "${TRANSLATION_FILES}") -qt4_add_translation(QM_FILES ${TRANSLATION_FILES}) +qt5_add_translation(QM_FILES ${TRANSLATION_FILES}) install(FILES ${QM_FILES} DESTINATION ${DATA_INSTALL_DIR}/translations) add_custom_target(translations DEPENDS ${QM_FILES}) diff --git a/share/translations/keepassx_cs.ts b/share/translations/keepassx_cs.ts index 0ac580fe..dc59db55 100644 --- a/share/translations/keepassx_cs.ts +++ b/share/translations/keepassx_cs.ts @@ -3,22 +3,26 @@ AboutDialog About KeePassX - O aplikaci KeePassX + O KeePassX KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. KeePassX je šířeno za podmínek licence GNU General Public License (GPL) verze 2 a (případně) 3. + + Revision + Revize + AutoType Auto-Type - KeePassX - Samočinné vyplňování – KeePassX + Automatické vyplňování – KeePassX Couldn't find an entry that matches the window title: - Nelze nalézt položku, která by se shodovala s titulkem okna: + Nedaří se nalézt položku, která by se shodovala s titulkem okna: @@ -40,11 +44,11 @@ AutoTypeSelectDialog Auto-Type - KeePassX - Samočinné vyplňování – KeePassX + Automatické vyplňování – KeePassX Select entry to Auto-Type: - Vyberte položku pro samočinné vyplňování: + Vyberte položku, kterou se bude automaticky vyplňovat: @@ -91,7 +95,7 @@ Unable to create Key File : - Nelze vytvořit soubor s klíčem : + Nedaří se vytvořit soubor s klíčem : Select a key file @@ -103,11 +107,21 @@ Do you really want to use an empty string as password? - Opravdu chcete heslo ponechat nevyplněné? + Opravdu chcete ponechat bez hesla, tedy nechráněné? Different passwords supplied. - Zadání hesla nejsou shodná. + Nepodařilo se vám zadat heslo do obou kolonek stejně. + + + Failed to set key file + Nezdařilo se nastavit soubor s klíčem + + + Failed to set %1 as the Key file: +%2 + Nezdařilo se nastavit %1 jako soubor s klíčem: +%2 @@ -134,11 +148,11 @@ Unable to open the database. - Databázi nebylo možné otevřít. + Databázi se nepodařilo otevřít. Can't open key file - Soubor s klíčem nelze otevřít. + Soubor s klíčem se nedaří otevřít All files @@ -165,7 +179,7 @@ Transform rounds: - Počet průchodů: + Počet průchodů algoritmu: Default username: @@ -173,7 +187,7 @@ Use recycle bin: - Použít Koš: + Namísto mazání přesouvat do Koše: MiB @@ -185,11 +199,11 @@ Max. history items: - Nejvyšší umožněný položek historie: + Nejvyšší umožněný počet položek historie: Max. history size: - Nejvyšší umožněná velikost historie: + Nejvyšší umožněný objem dat historie záznamů: @@ -200,7 +214,7 @@ KeePass 2 Database - Databáze aplikace KeePass 2 + Databáze aplikace KeePass verze 2 All files @@ -220,11 +234,11 @@ Open KeePass 1 database - Otevřít databázi aplikace KeePass 1 + Otevřít databázi aplikace KeePass verze 1 KeePass 1 database - Databáze aplikace KeePass 1 + Databáze aplikace KeePass verze 1 All files (*) @@ -234,12 +248,6 @@ Close? Zavřít? - - "%1" is in edit mode. -Close anyway? - %1 je upravováno. -Přesto zavřít? - Save changes? Uložit změny? @@ -270,6 +278,64 @@ Uložit změny? locked zamčeno + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Pro databázi, kterou se pokoušíte otevřít, existuje zámek úprav (stejnojmenný +.lock soubor). To znamená, že je nejspíš již otevřená v jiném okně KeePassX +(v případě sdíleného úložiště, třeba i na jiném počítači). Pokud tomu tak není, +je zámek nejspíš pozůstatkem předchozího neočekávaného ukončení aplikace +a je možné ho smazat. V každém případě, dotčenou databázi je možné otevřít + i tak, ale pouze pro čtení. Chcete? + + + Lock database + Uzamknout databázi + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Nelze uzamknout databázi, protože ji v tuto chvíli upravujete. +Pokud chcete změny dokončit, klikněte na Zrušit. V opačném případě změny zahodíte. + + + This database has never been saved. +You can save the database or stop locking it. + Tato databáze doposud ještě nebyla uložena. +Buď ji můžete uložit, nebo neuzamykat. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Tato databáze byla upravena. +Chcete ji před uzamčením uložit? +Pokud ne, provedené změny budou ztraceny. + + + "%1" is in edit mode. +Discard changes and close anyway? + %1 je právě upravováno. +Přesto zavřít a zahodit změny? + + + Export database to CSV file + Exportovat databázi do CSV souboru + + + CSV file + CSV soubor + + + Writing the CSV file failed. + Zápis do CSV souboru se nezdařil. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + Databáze, kterou se pokoušíte uložit, je uzamčena jinou instancí KeePassX. +Přesto uložit? + DatabaseWidget @@ -283,7 +349,7 @@ Uložit změny? Do you really want to delete the entry "%1" for good? - Opravdu chcete smazat položku %1? + Opravdu chcete nenávratně smazat položku %1? Delete entries? @@ -291,7 +357,7 @@ Uložit změny? Do you really want to delete %1 entries for good? - Opravdu chcete smazat %1 položek? + Opravdu chcete nenávratně smazat %1 položek? Move entries to recycle bin? @@ -299,7 +365,7 @@ Uložit změny? Do you really want to move %n entry(s) to the recycle bin? - + Opravdu chcete přesunout %n položku do Koše?Opravdu chcete přesunout %n položky do Koše?Opravdu chcete přesunout %n položek do Koše? Delete group? @@ -307,12 +373,20 @@ Uložit změny? Do you really want to delete the group "%1" for good? - Opravdu chcete smazat skupinu %1? + Opravdu chcete nenávratně smazat skupinu %1? Current group Stávající skupina + + Error + Chyba + + + Unable to calculate master key + Nepodařilo se spočítat hlavní klíč + EditEntryWidget @@ -330,7 +404,7 @@ Uložit změny? Auto-Type - Samočinné vyplňování + Automatické vyplňování Properties @@ -370,7 +444,7 @@ Uložit změny? Unable to open file - Soubor nelze otevřít + Soubor se nedaří otevřít Save attachment @@ -379,7 +453,7 @@ Uložit změny? Unable to save the attachment: - Přílohu nelze uložit: + Přílohu se nedaří uložit: @@ -388,11 +462,11 @@ Uložit změny? %n week(s) - + %n týden%n týdny%n týdnů %n month(s) - + %n měsíc%n měsíce%n měsíců 1 year @@ -425,20 +499,24 @@ Uložit změny? Save Uložit + + Open + Otevřít + EditEntryWidgetAutoType Enable Auto-Type for this entry - Zapnout samočinné vyplňování u této položky + Zapnout automatické vyplňování této položky Inherit default Auto-Type sequence from the group - Převzít výchozí posloupnost samočinného vyplňování ze skupiny + Převzít výchozí posloupnost automatického vyplňování od skupiny Use custom Auto-Type sequence: - Použít vlastní posloupnost samočinného vyplňování: + Použít vlastní posloupnost automatického vyplňování: + @@ -500,7 +578,7 @@ Uložit změny? Gen. - Obec. + Tvoř URL: @@ -551,7 +629,7 @@ Uložit změny? Inherit from parent group (%1) - Převzít z nadřazené skupiny (%1) + Převzít od nadřazené skupiny (%1) @@ -574,7 +652,15 @@ Uložit změny? Auto-type - Samočinné vyplňování + Automatické vyplňování + + + Use default auto-type sequence of parent group + Použít výchozí posloupnost automatického vyplňování z nadřazené skupiny + + + Set default auto-type sequence + Nastavit výchozí posloupnost automatického vyplňování @@ -585,15 +671,15 @@ Uložit změny? Use custom icon - Použít vlastní ikonu + Použít svou vlastní ikonu Add custom icon - Přidat vlastní ikonu + Přidat svou vlastní ikonu Delete custom icon - Smazat vlastní ikonu + Smazat svou vlastní ikonu Images @@ -613,26 +699,26 @@ Uložit změny? Can't delete icon. Still used by %n item(s). - + Ikonu není možné smazat. Je používána %n položkou.Ikonu není možné smazat. Je používána %n položkami.Ikonu není možné smazat. Používá ji %n položek EditWidgetProperties Created: - Vytvořeno: + Okamžik vytvoření: Modified: - Čas poslední změny: + Okamžik minulé úpravy: Accessed: - Čas posledního přístupu: + Okamžik minulého přístupu: Uuid: - Uuid identifikátor: + Univerzálně jedinečný identifikátor: @@ -646,7 +732,7 @@ Uložit změny? EntryHistoryModel Last modified - Čas poslední změny + Okamžik minulé změny Title @@ -691,7 +777,7 @@ Uložit změny? KeePass1OpenWidget Import KeePass1 database - Importovat databázi aplikace KeePass 1 + Importovat databázi aplikace KeePass verze 1 Error @@ -724,6 +810,10 @@ Uložit změny? Root Kořen + + Unable to calculate master key + Nedaří se spočítat hlavní klíč + KeePass2Reader @@ -739,12 +829,16 @@ Uložit změny? Wrong key or database file is corrupt. Chybný klíč nebo je databáze poškozená. + + Unable to calculate master key + Nedaří se spočítat hlavní klíč + Main Fatal error while testing the cryptographic functions. - Při testování šifrovacích funkcí došlo k fatální chybě. + Při ověřování šifrovacích funkcí byl zjištěn fatální nedostatek. KeePassX - Error @@ -777,10 +871,6 @@ Uložit změny? Groups Skupiny - - Extras - Doplňující - View Zobrazit @@ -847,7 +937,7 @@ Uložit změny? Import KeePass 1 database - Importovat databázi aplikace KeePass 1 + Importovat databázi aplikace KeePass verze 1 Clone entry @@ -857,18 +947,10 @@ Uložit změny? Find Najít - - Username - Uživatelské jméno - Copy username to clipboard Zkopírovat uživatelské jméno do schránky - - Password - Heslo - Copy password to clipboard Zkopírovat heslo do schránky @@ -879,7 +961,7 @@ Uložit změny? Perform Auto-Type - Provést samočinné vyplnění + Provést automatické vyplnění Open URL @@ -913,6 +995,22 @@ Uložit změny? Toggle window Přepnout okno + + Tools + Nástroje + + + Copy username + Zkopírovat uživatelské jméno + + + Copy password + Zkopírovat heslo + + + Export to CSV file + Exportovat do CSV souboru + PasswordGeneratorWidget @@ -942,15 +1040,15 @@ Uložit změny? Special Characters - Speciální znaky + Zvláštní znaky Exclude look-alike characters - Vynechat podobně vypadající znaky + Vynechat podobně vypadající znaky (předejití záměně) Ensure that the password contains characters from every group - Zajistit, aby heslo obsahovalo znaky ze všech zvolených skupin + Zajistit, aby heslo obsahovalo znaky ze všech zvolených skupin znaků Accept @@ -969,11 +1067,11 @@ Uložit změny? Unknown option '%1'. - Neznámá volba %1. + Neznámá předvolba %1. Unknown options: %1. - Neznámé volby: %1. + Neznámé předvolby: %1. Missing value after '%1'. @@ -985,7 +1083,7 @@ Uložit změny? [options] - [volby] + [předvolby] Usage: %1 @@ -993,7 +1091,7 @@ Uložit změny? Options: - Volby: + Předvolby: Arguments: @@ -1004,7 +1102,7 @@ Uložit změny? QSaveFile Existing file %1 is not writable - Existující soubor %1 není zapisovatelný + Do stávajícího souboru %1 nelze zapisovat Writing canceled by application @@ -1012,7 +1110,7 @@ Uložit změny? Partial write. Partition full? - Zápis nebylo možné dokončit zcela. Nedostatek volného místa? + Zápis nebylo možné zcela dokončit. Nedostatek volného místa? @@ -1023,15 +1121,15 @@ Uložit změny? Error writing to underlying device: - Chyba při zápisu na zařízení: + Došlo k chybě při zápisu na zařízení, na kterém se nachází: Error opening underlying device: - Chyba při otevírání zařízení: + Došlo k chybě při otevírání zařízení, na kterém se nachází: Error reading data from underlying device: - Chyba při čtení dat ze zařízení: + Došlo k chybě při čtení dat ze zařízení, na kterém se nachází: Internal zlib error when decompressing: @@ -1042,7 +1140,7 @@ Uložit změny? QtIOCompressor::open The gzip format not supported in this version of zlib. - Formát tohoto gzip archivu není podporován touto verzí knihovny zlib. + Použitý formát gzip komprese není podporován verzí knihovny zlib, která je právě používána na tomto systému. Internal zlib error: @@ -1087,39 +1185,35 @@ Uložit změny? SettingsWidgetGeneral Remember last databases - Pamatovat si nedávno otevírané databáze + Pamatovat si nedávno otevřené databáze Open previous databases on startup - Při startu otevřít minule otevřenou databázi - - - Mark as modified on expanded state changes - Při změnách rozšířeného stavu označit jako změněné + Při spuštění aplikace otevřít minule otevřené databáze Automatically save on exit - Při ukončování samočinně uložit + Před ukončením aplikace automaticky uložit případné změny Automatically save after every change - Po každé změně okamžitě samočinně uložit + Po každé změně hned automaticky uložit Minimize when copying to clipboard - Po zkopírování do schránky samočinně zminimalizovat aplikaci + Po zkopírování údaje do schránky automaticky minimalizovat okno KeePassX (do popředí se tak dostane okno, do kterého se zkopírovaný údaj bude vkládat) Use group icon on entry creation - Při vytváření položky použít ikonu skupiny + Pro vytvářenou položku použít ikonu skupiny, do které spadá Global Auto-Type shortcut - Všeobecná klávesová zkratka pro samočinné vyplňování + Klávesová zkratka pro všeobecné automatické vyplňování Use entry title to match windows for global auto-type - Použít titulek položky pro porovnání s okny pro všeobecné samočinné vyplňování + Všeobecné automatické vyplňování provádět na základě shody titulku položky s titulkem okna. Language @@ -1127,22 +1221,26 @@ Uložit změny? Show a system tray icon - Zobrazit ikonu v oznamovací oblasti + Zobrazit ikonu v oznamovací oblasti systémového panelu Hide window to system tray when minimized - Minimalizovat do oznamovací oblasti + Minimalizovat okno aplikace do oznamovací oblasti systémového panelu + + + Remember last key files + Pamatovat si nedávno otevřené soubory s klíči SettingsWidgetSecurity Clear clipboard after - Vyčistit schránku po uplynutí + Vymazat obsah schránky po uplynutí sec - sek + sek. Lock databases after inactivity of @@ -1150,11 +1248,11 @@ Uložit změny? Show passwords in cleartext by default - Vždy zobrazovat hesla + Hesla vždy viditelná (nezakrývat hvězdičkami) Always ask before performing auto-type - Před provedením samočinného vyplnění se vždy dotázat + Před provedením automatického vyplnění se vždy dotázat @@ -1163,14 +1261,6 @@ Uložit změny? Unlock database Odemknout databázi - - Error - Chyba - - - Wrong key. - Chybný klíč. - WelcomeWidget @@ -1183,20 +1273,16 @@ Uložit změny? main KeePassX - cross-platform password manager - KeePassX – multiplatformní správce hesel + KeePassX – správce hesel, fungující napříč rozličnými operačními systémy filename of the password database to open (*.kdbx) - Soubor s databází hesel (*.kdbx), který otevřít + který soubor s databází hesel (*.kdbx) otevřít path to a custom config file umístění souboru s vlastními nastaveními - - password of the database (DANGEROUS!) - heslo databáze (NEBEZPEČNÉ!) - key file of the database soubor s klíčem k databázi diff --git a/share/translations/keepassx_da.ts b/share/translations/keepassx_da.ts index 25bdd2c1..0ee8cc33 100644 --- a/share/translations/keepassx_da.ts +++ b/share/translations/keepassx_da.ts @@ -9,12 +9,20 @@ KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. KeePassX distribueres under betingelserne i GNU General Public License (GPL) version 2 eller (efter eget valg) version 3. + + Revision + Revision + + + Using: + Bruger: + AutoType Auto-Type - KeePassX - + Auto-indsæt - KeePassX Couldn't find an entry that matches the window title: @@ -40,26 +48,26 @@ AutoTypeSelectDialog Auto-Type - KeePassX - + Auto-indsæt - KeePassX Select entry to Auto-Type: - + Vælg post til Auto-Indsæt: ChangeMasterKeyWidget Password - Adgangskode + Kodeord Enter password: - Indtast adgangskode + Indtast kodeord Repeat password: - Gentag adgangskode + Gentag kodeord Key file @@ -103,18 +111,28 @@ Do you really want to use an empty string as password? - Vil du virkelig bruge en tom streng som adgangskode? + Vil du virkelig bruge en tom streng som kodeord? Different passwords supplied. - Andre adgangskoder leveret. + Andre kodeord leveret. + + + Failed to set key file + Kan ikke sætte nøglefil + + + Failed to set %1 as the Key file: +%2 + Kunne ikke sætte %1 som Nøglefil: +%2 DatabaseOpenWidget Enter master key - Indtast primærnøgle + Indtast hovednøgle Key File: @@ -122,7 +140,7 @@ Password: - Adgangskode: + Kodeord: Browse @@ -165,7 +183,7 @@ Transform rounds: - + Transformationsrunder: Default username: @@ -185,18 +203,18 @@ Max. history items: - + Maks. posthistorik: Max. history size: - + Maks. historikstørrelse: DatabaseTabWidget Root - + Rod KeePass 2 Database @@ -234,11 +252,6 @@ Close? Luk? - - "%1" is in edit mode. -Close anyway? - - Save changes? Gem ændringer? @@ -246,7 +259,8 @@ Close anyway? "%1" was modified. Save changes? - + "%1" blev ændret. +Gem disse ændringer? Error @@ -268,12 +282,66 @@ Save changes? locked låst + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Den database, du prøver at åbne er låst af en anden forekomst af KeePassX. +Vil du åbne den alligevel? Alternativt åbnes databasen skrivebeskyttet. + + + Lock database + Lås database + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Kan ikke låse databasen, mens du redigerer i den. +Tryk på Afbryd for at afslutte dine ændringer eller kassere dem. + + + This database has never been saved. +You can save the database or stop locking it. + Denne database er aldrig blevet gemt. +Du kan gemme databasen eller stop låsning. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Denne database er blevet ændret. +Vil du gemme databasen før låsning? +Ellers mister du dine ændringer. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" er i redigeringstilstand. +Kassér ændringer og luk alligevel? + + + Export database to CSV file + Eksportér databasen til CSV-fil + + + CSV file + CSV-fil + + + Writing the CSV file failed. + Kan ikke skrive til CSV-fil. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + Databasen som du prøver at gemme er låst af en anden instans af KeePassX. +Vil du alligevel gemme? + DatabaseWidget Change master key - Skift primærnøgle + Skift hovednøgle Delete entry? @@ -281,7 +349,7 @@ Save changes? Do you really want to delete the entry "%1" for good? - + Vil du virkelig slette posten "%1" permanent? Delete entries? @@ -289,7 +357,7 @@ Save changes? Do you really want to delete %1 entries for good? - + Vil du virkelig slette %1 poster permanent? Move entries to recycle bin? @@ -297,7 +365,7 @@ Save changes? Do you really want to move %n entry(s) to the recycle bin? - + Ønsker du virkelig at flytte %n post over i papirkurven?Ønsker du virkelig at flytte %n poster over i papirkurven? Delete group? @@ -305,12 +373,20 @@ Save changes? Do you really want to delete the group "%1" for good? - + Ønsker du at slette gruppen "%1" permanent? Current group Nuværende gruppe + + Error + Fejl + + + Unable to calculate master key + Kan ikke beregne hovednøgle + EditEntryWidget @@ -328,7 +404,7 @@ Save changes? Auto-Type - + Auto-Indsæt Properties @@ -340,7 +416,7 @@ Save changes? Entry history - + Indtastningshistorik Add entry @@ -356,7 +432,7 @@ Save changes? Different passwords supplied. - Andre adgangskoder leveret. + Andre kodeord leveret. New attribute @@ -377,7 +453,7 @@ Save changes? Unable to save the attachment: - + Kan ikke gemme vedhæftningen: Tomorrow @@ -422,20 +498,24 @@ Save changes? Save Gem + + Open + Åben + EditEntryWidgetAutoType Enable Auto-Type for this entry - + Aktivér Auto-Indsæt for denne post Inherit default Auto-Type sequence from the group - + Nedarv standard Auto-Indsæt sekvens fra gruppe Use custom Auto-Type sequence: - + Brug brugerdefineret Auto-indsæt sekvens: + @@ -451,11 +531,11 @@ Save changes? Use default sequence - + Brug standardsekvens Set custom sequence: - + Definér brugervalgt sekvens: @@ -489,7 +569,7 @@ Save changes? Password: - Adgangskode: + Kodeord: Repeat: @@ -497,7 +577,7 @@ Save changes? Gen. - + Generer URL: @@ -509,7 +589,7 @@ Save changes? Presets - + Predefinerede Notes: @@ -571,7 +651,15 @@ Save changes? Auto-type - + Auto-indsæt + + + Use default auto-type sequence of parent group + Brug standard Auto-Indsæt sekvens fra forældregruppe + + + Set default auto-type sequence + Definér standard auto-indsæt sekvens @@ -610,7 +698,7 @@ Save changes? Can't delete icon. Still used by %n item(s). - + Kan ikke slette ikonet. Det anvendes stadig af %n element.Kan ikke slette ikonet. Det anvendes stadig af %n elementer. @@ -719,14 +807,18 @@ Save changes? Root - + Rod + + + Unable to calculate master key + Kan ikke beregne hovednøgle KeePass2Reader Not a KeePass database. - Det er ikke en KeePass database. + Dette er ikke en KeePass database. Unsupported KeePass database version. @@ -736,6 +828,20 @@ Save changes? Wrong key or database file is corrupt. Forkert nøgle eller databasefil er korrupt. + + Unable to calculate master key + Kan ikke beregne hovednøgle + + + The selected file is an old KeePass 1 database (.kdb). + +You can import it by clicking on Database > 'Import KeePass 1 database'. +This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + Den valgte fil er en gammel KeePass 1 databasefil (.kdb). + +Du kan importere den ved at klikke på Database > 'Importér KeePass 1 database'. +Dette er en envejs konvertering. Du vil ikke være i stand til at åbne den importerede database med den gamle KeePassX 0.4 version. + Main @@ -774,10 +880,6 @@ Save changes? Groups Grupper - - Extras - - View Vis @@ -836,7 +938,7 @@ Save changes? Change master key - Skift primærnøgle + Skift hovednøgle Database settings @@ -854,21 +956,13 @@ Save changes? Find Find - - Username - Brugernavn - Copy username to clipboard Kopiér brugernavn til udklipsholder - - Password - Adgangskode - Copy password to clipboard - Kopiér adgangskode til udklipsholder + Kopiér kodeord til udklipsholder Settings @@ -876,7 +970,7 @@ Save changes? Perform Auto-Type - + Udfør Auto-indsæt Open URL @@ -910,12 +1004,28 @@ Save changes? Toggle window Skift vindue + + Tools + Værktøj + + + Copy username + Kopiér brugernavn + + + Copy password + Kopiér kodeord + + + Export to CSV file + Eksportér til CSV-fil + PasswordGeneratorWidget Password: - Adgangskode: + Kodeord: Length: @@ -923,7 +1033,7 @@ Save changes? Character Types - + Tegntyper Upper Case Letters @@ -931,7 +1041,7 @@ Save changes? Lower Case Letters - + Små Bogstaver Numbers @@ -939,15 +1049,15 @@ Save changes? Special Characters - + Specialtegn Exclude look-alike characters - + Udeluk lool-alike tegn Ensure that the password contains characters from every group - + Vær sikker på at dit kodeord indeholder tegn fra alle grupper Accept @@ -1020,11 +1130,11 @@ Save changes? Error writing to underlying device: - + Fejl ved skrivning til enhed: Error opening underlying device: - + Fejl ved åbning fra enhed: Error reading data from underlying device: @@ -1032,7 +1142,7 @@ Save changes? Internal zlib error when decompressing: - + Intern zlib-fejl ved dekomprimering: @@ -1054,7 +1164,7 @@ Save changes? Case sensitive - + Versalfølsom Current group @@ -1062,7 +1172,7 @@ Save changes? Root group - + Rodgruppe @@ -1073,7 +1183,7 @@ Save changes? General - + Generelt Security @@ -1084,15 +1194,11 @@ Save changes? SettingsWidgetGeneral Remember last databases - + Husk seneste databaser Open previous databases on startup - - - - Mark as modified on expanded state changes - + Åben foregående databaser ved opstart Automatically save on exit @@ -1108,15 +1214,15 @@ Save changes? Use group icon on entry creation - + Brug gruppeikon ved oprettelse af post Global Auto-Type shortcut - + Global Auto-Indsæt genvej Use entry title to match windows for global auto-type - + Brug titel på post til at matche global aito-indsæt Language @@ -1130,6 +1236,10 @@ Save changes? Hide window to system tray when minimized Skjul vindue i systembakken når det er minimeret + + Remember last key files + Husk de sidste nøglefiler + SettingsWidgetSecurity @@ -1143,15 +1253,15 @@ Save changes? Lock databases after inactivity of - + Lås databaserne efter inaktivitet i Show passwords in cleartext by default - + Vis kodeord i klartekst som standard Always ask before performing auto-type - + Spørg altid før auto-indsæt @@ -1160,14 +1270,6 @@ Save changes? Unlock database Lås database op - - Error - Fejl - - - Wrong key. - Forkert nøgle. - WelcomeWidget @@ -1180,7 +1282,7 @@ Save changes? main KeePassX - cross-platform password manager - + KeePassX - cross-platform password manager filename of the password database to open (*.kdbx) @@ -1188,11 +1290,7 @@ Save changes? path to a custom config file - - - - password of the database (DANGEROUS!) - adgangskode til databasen (FAARLIGT!) + sti til brugerdefineret indstillingsfil key file of the database diff --git a/share/translations/keepassx_de.ts b/share/translations/keepassx_de.ts index 8c582803..e85586bd 100644 --- a/share/translations/keepassx_de.ts +++ b/share/translations/keepassx_de.ts @@ -7,7 +7,11 @@ KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassX ist unter der GNU General Public License (GPL) version 2 (version 3) veröffentlicht. + KeePassX steht unter der GNU General Public License (GPL) version 2 (version 3). + + + Revision + Überarbeitung @@ -109,6 +113,15 @@ Different passwords supplied. Unterschiedliche Passwörter eingegeben. + + Failed to set key file + Festlegen der Schlüsseldatei nicht möglich. + + + Failed to set %1 as the Key file: +%2 + Festlegen von %1 als Schlüsseldatei nicht möglich: %2 + DatabaseOpenWidget @@ -234,12 +247,6 @@ Close? Schließen? - - "%1" is in edit mode. -Close anyway? - "%1" wird bearbeitet. -Trotzdem schließen? - Save changes? Änderungen speichern? @@ -270,6 +277,59 @@ Save changes? locked gesperrt + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Die Datenbank, die geöffnet werden soll, ist aktuell von einer anderen Instanz von KeePassX blockiert. Soll sie dennoch geöffnet werden? Andererseits wird die Datenbank schreibgeschützt geöffnet. + + + Lock database + Datenbank sperren + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Datenbank kann nicht gesperrt werden, da sie gerade bearbeitet wird. +Wählen sie "cancel", um die Änderungen zu speichern oder sie zurückzunehmen. + + + This database has never been saved. +You can save the database or stop locking it. + Diese Datenbank wurde noch nicht gespeichert. +Sie können sie speichern oder Sperre freigeben. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Dieses Datenbank wurde geändert. +Soll sie gespeichert werden bevor sie gesperrt wirt? +Anderenfalls gehen Ihre Änderungen verloren. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" wird bearbeitet. +Änderungen verwerfen und trotzdem schließen? + + + Export database to CSV file + Datenbank als CSV Datei exportieren. + + + CSV file + CSV Datei + + + Writing the CSV file failed. + Die CSV Datei konnte nicht gespeichert werden. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + Die Datenbank, die gespeichert werden soll, ist von einer anderen Instanz von KeePassX blockiert. +Soll sie dennoch gespeichert werden? + DatabaseWidget @@ -313,6 +373,14 @@ Save changes? Current group Aktuelle Gruppe + + Error + Fehler + + + Unable to calculate master key + Berechnung des "master keys" gescheitert + EditEntryWidget @@ -424,6 +492,10 @@ Save changes? Save Speichern + + Open + Offen + EditEntryWidgetAutoType @@ -575,6 +647,14 @@ Save changes? Auto-type Auto-type + + Use default auto-type sequence of parent group + Auto-Type-Sequenz der übergeordneten Gruppe anwenden. + + + Set default auto-type sequence + Standard Auto-Type-Sequenz setzen + EditWidgetIcons @@ -723,6 +803,10 @@ Save changes? Root Root + + Unable to calculate master key + Berechnung des "master keys" gescheitert + KeePass2Reader @@ -738,6 +822,10 @@ Save changes? Wrong key or database file is corrupt. Falscher Schlüssel oder die Datei ist beschädigt. + + Unable to calculate master key + Berechnung des "master keys" gescheitert + Main @@ -776,10 +864,6 @@ Save changes? Groups Gruppen - - Extras - Extras - View Ansicht @@ -856,18 +940,10 @@ Save changes? Find Suchen - - Username - Benutzername - Copy username to clipboard Benutzername in die Zwischenablage kopieren - - Password - Passwort - Copy password to clipboard Passwort in die Zwischenablage kopieren @@ -912,6 +988,22 @@ Save changes? Toggle window Fenster zeigen/verstecken + + Tools + Tools + + + Copy username + Benutzername kopieren + + + Copy password + Passwort kopieren + + + Export to CSV file + Als CSV Datei exportieren + PasswordGeneratorWidget @@ -1092,10 +1184,6 @@ Save changes? Open previous databases on startup Letzte Datenbank beim Starten öffnen - - Mark as modified on expanded state changes - Als erweiterte Zustandsänderungen makieren - Automatically save on exit Automatisch speichern beim Schließen @@ -1140,6 +1228,10 @@ Save changes? Hide window to system tray on App start Fenster zu Taskleistensymbol minimieren wenn Programm started + + Remember last key files + Letzte Schlüsseldateien merken + SettingsWidgetSecurity @@ -1157,7 +1249,7 @@ Save changes? Show passwords in cleartext by default - Passwort standartmäßig in Klartext anzeigen + Passwörter standardmäßig in Klartext anzeigen Always ask before performing auto-type @@ -1170,14 +1262,6 @@ Save changes? Unlock database Datenbank entsperren - - Error - Fehler - - - Wrong key. - Falscher Schlüssel. - WelcomeWidget @@ -1200,10 +1284,6 @@ Save changes? path to a custom config file Pfad zu einer benutzerdefinierten Konfigurationsdatei - - password of the database (DANGEROUS!) - Passwort der Datenbank (GEFÄHRLICH!) - key file of the database Schlüsseldatei der Datenbank diff --git a/share/translations/keepassx_el.ts b/share/translations/keepassx_el.ts new file mode 100644 index 00000000..be7ff16f --- /dev/null +++ b/share/translations/keepassx_el.ts @@ -0,0 +1,1286 @@ + + + AboutDialog + + About KeePassX + Σχετικά με το KeepPassX + + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + + + + Revision + Αναθεώρηση + + + + AutoType + + Auto-Type - KeePassX + Αυτόματη-Γραφή - KeePassX + + + Couldn't find an entry that matches the window title: + Αποτυχία να βρεθεί μια καταχώρηση που να ταιριάζει με τον τίτλο του παραθύρου: + + + + AutoTypeAssociationsModel + + Window + Παράθυρο + + + Sequence + Ακολουθεία + + + Default sequence + Προεπιλεγμένη ακολουθεία + + + + AutoTypeSelectDialog + + Auto-Type - KeePassX + Αυτόματη-Γραφή - KeePassX + + + Select entry to Auto-Type: + Επιλέξτε καταχώρηση για αυτόματη γραφή: + + + + ChangeMasterKeyWidget + + Password + Κωδικός + + + Enter password: + Εισάγετε κωδικό: + + + Repeat password: + Επαναλάβετε τον κωδικό: + + + Key file + Αρχείο κλειδί + + + Browse + Αναζήτηση + + + Create + Δημιουργία + + + Key files + Αρχεία κλειδιά + + + All files + Όλα τα αρχεία + + + Create Key File... + Δημιουργεία αρχείου κλειδιού... + + + Error + Σφάλμα + + + Unable to create Key File : + Αποτυχία δημιουργεία αρχείου κλειδιού: + + + Select a key file + Επιλέξτε ένα αρχείο κλειδί + + + Question + Ερώτηση + + + Do you really want to use an empty string as password? + Θέλετε στα αλήθεια να χρησιμοποιήσετε μια άδεια σειρά σαν κωδικό; + + + Different passwords supplied. + Έχετε εισάγει διαφορετικούς κωδικούς. + + + Failed to set key file + Αποτυχία ορισμού αρχείου κλειδιού + + + Failed to set %1 as the Key file: +%2 + Αποτυχία ορισμού του %1 ως αρχείου κλειδιού + + + + DatabaseOpenWidget + + Enter master key + + + + Key File: + Αρχείο κλειδί: + + + Password: + Κωδικός: + + + Browse + Αναζήτηση + + + Error + Σφάλμα + + + Unable to open the database. + Αδύνατο να ανοιχτεί η βάση δεδομένων. + + + Can't open key file + Αποτυχία ανοίγματος αρχείο κλειδιού + + + All files + Όλα τα αρχεία + + + Key files + Αρχεία κλειδιά + + + Select key file + Επιλέξτε αρχείο κλειδί + + + + DatabaseSettingsWidget + + Database name: + Όνομα βάσης δεδομένων: + + + Database description: + Περιγραφή βάσης δεδομένων: + + + Transform rounds: + Μετατρεπόμενοι γύροι: + + + Default username: + Προεπιλεγμένο όνομα χρήστη: + + + Use recycle bin: + Χρήση καλαθιού αχρήστων: + + + MiB + MiB + + + Benchmark + + + + Max. history items: + Μέγιστα αντικείμενα ιστορικού: + + + Max. history size: + Μέγιστο μέγεθος ιστορικού: + + + + DatabaseTabWidget + + Root + + + + KeePass 2 Database + Βάση Δεδομένων KeePass 2 + + + All files + Όλα τα αρχεία + + + Open database + Άνοιγμα βάσης δεδομένων + + + Warning + Προειδοποίηση + + + File not found! + Αρχείο δεν βρέθηκε! + + + Open KeePass 1 database + Άνοιγμα βάσης δεδομένων KeePass 1 + + + KeePass 1 database + Βάση δεδομένων KeePass 1 + + + All files (*) + Όλα τα αρχεία (*) + + + Close? + Κλείσιμο; + + + Save changes? + Αποθήκευση αλλαγών; + + + "%1" was modified. +Save changes? + "%1" έχει τροποποιηθή. +Αποθήκευση αλλαγών; + + + Error + Σφάλμα + + + Writing the database failed. + + + + Save database as + Αποθήκευση βάσης δεδομένων σαν + + + New database + Νέα βάση δεδομένων + + + locked + κλειδωμένο + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Η βάση δεδομένω που προσπαθείται να ανοίξετε ειναι κλειδωμένη από μια άλλη διεργασία του KeePassX. +Θέλετε να την ανοίξετε ούτως η άλλως; Αλλίως η βαση δεδομένων θα ανοιχτή μόνο για ανάγνωση. + + + Lock database + Κλείδωμα βάσης δεδομένων + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Η βάση δεδομένων δεν μπορεί να κλειδωθεί γιατί την επεξεργάζεται αυτην την στιγμή. +Παρακαλώ πατήστε άκυρο για να αποθηκεύσετε τις αλλαγές σας η να τις απορρίψετε. + + + This database has never been saved. +You can save the database or stop locking it. + Αυτή η βάση δεδομένων δεν έχει αποθηκευτεί ποτέ. +Μπορείται να την αποθηκεύσετε ή να σταματήσετε να την κλειδώνετε. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Αυτή η βάση δεδομένων έχει αλλάξει. +Θέλετε να αποθηκεύσετε τις αλλαγές σας πρίν την κλειδώσετε: +Αλλιώς οι αλλαγές σας θα χαθούν. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" είναι σε λειτουργεία επεξεργασίας. +Απόρριψη αλλαγών και κλείσιμο ούτως η άλλως; + + + Export database to CSV file + Εξαγωγή βάσης δεδομένων σε αρχείο CSV + + + CSV file + αρχείο CSV + + + Writing the CSV file failed. + Γράψιμο στο αρχείο CSV απέτυχε. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + Η βάση δεδομένων που πρασπαθείται να αποθηκεύσετε είναι κλειδωμένη από μία άλλη διεργασία KeePassX. +Θέλετε να την αποθηκεύσετε ούτως η άλλως; + + + + DatabaseWidget + + Change master key + + + + Delete entry? + Διαγραφή καταχώρησης; + + + Do you really want to delete the entry "%1" for good? + Θέλετε πραγματικά να διαγράψετε την καταχώρηση "%1" μόνιμα; + + + Delete entries? + Διαγραφή καταχωρήσεων; + + + Do you really want to delete %1 entries for good? + Θέλετε πραγματικά να διαγράψετε %1 καταχωρήσεις για πάντα; + + + Move entries to recycle bin? + Μετακίνηση καταχωρήσεων στο καλάθι των αχρήστων; + + + Do you really want to move %n entry(s) to the recycle bin? + + + + Delete group? + Διαγραφή ομάδας; + + + Do you really want to delete the group "%1" for good? + Θέλετε στα αλήθεια να διαγράψετε την ομάδα "%1" μόνιμα; + + + Current group + Τρέχων ομάδα + + + Error + Σφάλμα + + + Unable to calculate master key + + + + + EditEntryWidget + + Entry + Καταχώρηση + + + Advanced + Για προχωρημένους + + + Icon + Εικονίδιο + + + Auto-Type + Αυτόματη-Γραφή + + + Properties + Ιδιότητες + + + History + Ιστορικό + + + Entry history + Ιστορικό καταχωρήσεων + + + Add entry + Πρόσθεση καταχώρησης + + + Edit entry + Επεξεργασία καταχώρησης + + + Error + Σφάλμα + + + Different passwords supplied. + Παρέχονται διαφορετικοί κωδικοί. + + + New attribute + Νέο χαρακτηριστικό + + + Select file + Επιλογή αρχείου + + + Unable to open file + Αποτυχία ανοίγματος αρχείου + + + Save attachment + Αποθήκευση συνημμένου + + + Unable to save the attachment: + + Αποτυχία αποθήκευσης συνημμένου. + + + + Tomorrow + Αύριο + + + %n week(s) + + + + %n month(s) + + + + 1 year + 1 χρόνο + + + + EditEntryWidgetAdvanced + + Additional attributes + Πρόσθετα χαρακτηριστικά + + + Add + Πρόσθεση + + + Edit + Επεξεργασία + + + Remove + Αφαίρεση + + + Attachments + Συνημμένα + + + Save + Αποθήκευση + + + Open + Άνοιγμα + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + Ενεργοποίηση Αυτόματης-Γραφής για αυτήν την καταχώρηση + + + Inherit default Auto-Type sequence from the group + Χρησιμοποίηση προεπιλεγμένης ακολουθείας Αυτόματης-Γραφής απο την ομάδα + + + Use custom Auto-Type sequence: + Χρησιμοποίηση προσαρμοσμένης ακολουθείας Αυτόματης Γραφής: + + + + + + + + + - + - + + + Window title: + Τίτλος Παραθύρου: + + + Use default sequence + Χρησιμοποίηση προεπιλεγμένης ακολουθείας + + + Set custom sequence: + Ορισμός προσαρμοσμένης ακολουθείας: + + + + EditEntryWidgetHistory + + Show + Εμφάνιση + + + Restore + Επαναφορά + + + Delete + Διαγραφή + + + Delete all + Διαγραφή όλων + + + + EditEntryWidgetMain + + Title: + Τίτλος: + + + Username: + Όνομα χρήστη: + + + Password: + Κωδικός: + + + Repeat: + Επαναλάβετε: + + + Gen. + + + + URL: + URL: + + + Expires + Λήγει + + + Presets + Προεπιλογές + + + Notes: + Σημειώσεις: + + + + EditGroupWidget + + Group + Όμαδα + + + Icon + Εικονίδιο + + + Properties + Ιδιότητες + + + Add group + Πρόσθεση Ομάδας + + + Edit group + Επεξεργασία ομάδας + + + Enable + Ενεργοποίηση + + + Disable + Απενεργοποίηση + + + Inherit from parent group (%1) + + + + + EditGroupWidgetMain + + Name + Όνομα + + + Notes + Σημειώσεις + + + Expires + Λήγει + + + Search + Αναζήτηση + + + Auto-type + Αυτόματη-γραφή + + + Use default auto-type sequence of parent group + Χρησιμοποίηση προεπιλεγμένης ακολουθείας αυτόματης γραφής της μητρικής ομάδας + + + Set default auto-type sequence + Ορισμός προεπιλεγμένης ακολουθείας αυτόματης-γραφής + + + + EditWidgetIcons + + Use default icon + Χρήση προεπιλεγμένου εικονιδίου + + + Use custom icon + Χρήση προσαρμοσμένου εικονιδίου + + + Add custom icon + Πρόσθεση προσαρμοσμένου εικονιδίου + + + Delete custom icon + Διαγραφή προσαρμοσμένου εικονιδίου + + + Images + Εικόνες + + + All files + Όλα τα αρχεία + + + Select Image + Επιλογή εικόνας + + + Can't delete icon! + Αποτυχία διαγραφής εικονίδιου! + + + Can't delete icon. Still used by %n item(s). + + + + + EditWidgetProperties + + Created: + Δημιουργήθηκε: + + + Modified: + Τροποποιήθηκε: + + + Accessed: + Προσπελάστηκε: + + + Uuid: + + + + + EntryAttributesModel + + Name + Όνομα + + + + EntryHistoryModel + + Last modified + Τελευταία τροποποίηση + + + Title + Τίτλος + + + Username + Όνομα χρήστη + + + URL + URL + + + + EntryModel + + Group + Όμαδα + + + Title + Τίτλος + + + Username + Όνομα χρήστη + + + URL + URL + + + + Group + + Recycle Bin + Καλάθι ανακύκλωσης + + + + KeePass1OpenWidget + + Import KeePass1 database + Εισαγωγή βάσης δεδομένων KeePass1 + + + Error + Σφάλμα + + + Unable to open the database. + Αποτυχία ανοίγματος βάσης δεδομένων. + + + + KeePass1Reader + + Unable to read keyfile. + Αποτυχία διαβάσματος αρχείου κλειδιού. + + + Not a KeePass database. + Δεν ειναι βάση δεδομένων KeePass. + + + Unsupported encryption algorithm. + Μη υποστηριζόμενος αλογόριθμος κρυπτογράφησης. + + + Unsupported KeePass database version. + Μη υποστηριζόμενη έκδοση βάσης δεδομένων KeePass. + + + Root + + + + Unable to calculate master key + + + + + KeePass2Reader + + Not a KeePass database. + Δεν είναι βάση δεδομένων KeePass. + + + Unsupported KeePass database version. + Μη υποστηριζόμενη έκδοση βάσης δεδομένων KeePass. + + + Wrong key or database file is corrupt. + Λάθος κλειδί ή το άρχειο της βάσης δεδομένων είναι κατεστραμένο. + + + Unable to calculate master key + + + + + Main + + Fatal error while testing the cryptographic functions. + + + + KeePassX - Error + KeePassX - Σφάλμα + + + + MainWindow + + Database + Βάση Δεδομένων + + + Recent databases + Πρόσφατες βάσεις δεδομένων + + + Help + Βοήθεια + + + Entries + Καταχωρήσεις + + + Copy attribute to clipboard + Αντιγραφή χαρακτηριστικού στο πρόχειρο + + + Groups + Ομάδες + + + View + Προβολή + + + Quit + Έξοδος + + + About + Σχετικά + + + Open database + Άνοιγμα Βάσης Δεδομένων + + + Save database + Αποθήκευση Βάσης Δεδομένων + + + Close database + Κλείσιμο Βάσης Δεδομένων + + + New database + Νέα Βάση Δεδομένων + + + Add new entry + Πρόσθεση νέα καταχώρησης + + + View/Edit entry + Προβολή/επεξεργασία καταχώρησης + + + Delete entry + Διαγραφή Καταχώρησης + + + Add new group + Πρόσθεση νέας ομάδας + + + Edit group + Επεξεργασία Ομάδας + + + Delete group + Διαγραφή ομάδας + + + Save database as + Αποθήκευση βάσης δεδομένων ως + + + Change master key + + + + Database settings + Ρυθμίσεις βάσης δεδομένων + + + Import KeePass 1 database + Εισαγωγή βάσης δεδομένων KeePass1 + + + Clone entry + Κλωνοποίηση Καταχώρησης + + + Find + Εύρεση + + + Copy username to clipboard + Αντιγραφή όνομα χρήστη στο πρόχειρο + + + Copy password to clipboard + Αντιγραφή κωδικού στο πρόχειρο + + + Settings + Ρύθμίσεις + + + Perform Auto-Type + Εκτέλεση Αυτόματης-Γραφής + + + Open URL + Άνοιγμα ιστοσελίδας + + + Lock databases + Κλείδωμα βάσεων δεδομένων + + + Title + Τίτλος + + + URL + URL + + + Notes + Σημειώσεις + + + Show toolbar + Εμφάνιση γραμμής εργαλείων + + + read-only + Μόνο για ανάγνωση + + + Toggle window + Εναλλαγή παραθύρων + + + Tools + Εργαλεία + + + Copy username + Αντιγραφή όνομα χρήστη + + + Copy password + Αντιγραφή κωδικού + + + Export to CSV file + Εξαγωγή σε αρχείο CSV + + + + PasswordGeneratorWidget + + Password: + Κωδικός: + + + Length: + Μήκος: + + + Character Types + Τύποι χαρακτήρων + + + Upper Case Letters + Κεφαλαία γράμματα + + + Lower Case Letters + Πεζά γράμματα + + + Numbers + Αριθμοί + + + Special Characters + Ειδικοί χαρακτήρες + + + Exclude look-alike characters + Εξαίρεση χαρακτήρων που μοίαζουν + + + Ensure that the password contains characters from every group + Βεβαιωθείται οτι ο κωδικός περιέχει χαρακτήρες απο κάθε ομάδα + + + Accept + Αποδοχή + + + + QCommandLineParser + + Displays version information. + Προβολή πληροφοριών έκδοσης. + + + Displays this help. + Δείχνει αυτήν την βοήθεια. + + + Unknown option '%1'. + + + + Unknown options: %1. + + + + Missing value after '%1'. + + + + Unexpected value after '%1'. + + + + [options] + [επιλογές] + + + Usage: %1 + Χρήση: %1 + + + Options: + Επιλογές: + + + Arguments: + Επιχειρήματα: + + + + QSaveFile + + Existing file %1 is not writable + + + + Writing canceled by application + + + + Partial write. Partition full? + + + + + QtIOCompressor + + Internal zlib error when compressing: + + + + Error writing to underlying device: + + + + Error opening underlying device: + + + + Error reading data from underlying device: + + + + Internal zlib error when decompressing: + + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + + + + Internal zlib error: + + + + + SearchWidget + + Find: + Εύρεση + + + Case sensitive + + + + Current group + Τρέχων ομάδα + + + Root group + + + + + SettingsWidget + + Application Settings + Ρυθμίσεις Εφαρμογής + + + General + + + + Security + Ασφάλεια + + + + SettingsWidgetGeneral + + Remember last databases + + + + Open previous databases on startup + Άνοιγμα προηγούμενων βάσεω δεδομένων κατα την εκκίνηση + + + Automatically save on exit + Αυτόματη αποθήκευση κατα την έξοδο + + + Automatically save after every change + Αυτόματη Αποθήκευση μετά απο κάθε αλλαγή + + + Minimize when copying to clipboard + Ελαχιστοποίηση οταν αντιγράφετε στο πρόχειρο + + + Use group icon on entry creation + Χρησιμοποίηση εικονιδίου ομάδας κατα την δημιουργία καταχώρησης + + + Global Auto-Type shortcut + + + + Use entry title to match windows for global auto-type + + + + Language + Γλώσσα + + + Show a system tray icon + + + + Hide window to system tray when minimized + + + + Remember last key files + + + + + SettingsWidgetSecurity + + Clear clipboard after + Εκκαθάριση πρόχειρου μετά από + + + sec + δευτερόλεπτα + + + Lock databases after inactivity of + Κλείδωμα βάσης δεδομένων μετα απο ανενεργεία + + + Show passwords in cleartext by default + + + + Always ask before performing auto-type + Πάντα να ρωτάτε πριν να εκτελείται η αυτόματη γραφή + + + + UnlockDatabaseWidget + + Unlock database + Ξεκλείδωμα βάσης δεδομένων + + + + WelcomeWidget + + Welcome! + Καλως ήρθατε! + + + + main + + KeePassX - cross-platform password manager + + + + filename of the password database to open (*.kdbx) + Όνομα της βάσης δεδομένων κωδικών για άνοιγμα (*.kdbx) + + + path to a custom config file + + + + key file of the database + Αρχείο κλειδί της βάσεως δεδομένων + + + \ No newline at end of file diff --git a/share/translations/keepassx_en.ts b/share/translations/keepassx_en.ts index 5eb8eca0..13343c8b 100644 --- a/share/translations/keepassx_en.ts +++ b/share/translations/keepassx_en.ts @@ -11,6 +11,14 @@ KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + + Revision + + + + Using: + + AutoType @@ -164,6 +172,42 @@ + + DatabaseRepairWidget + + Repair database + + + + Error + + + + Can't open key file + + + + Database opened fine. Nothing to do. + + + + Unable to open the database. + + + + Success + + + + The database has been successfully repaired +You can now save it. + + + + Unable to repair the database. + + + DatabaseSettingsWidget @@ -245,11 +289,6 @@ Close? - - "%1" is in edit mode. -Close anyway? - - Save changes? @@ -304,6 +343,28 @@ Do you want to save the database before locking it? Otherwise your changes are lost. + + "%1" is in edit mode. +Discard changes and close anyway? + + + + Export database to CSV file + + + + CSV file + + + + Writing the CSV file failed. + + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + + DatabaseWidget @@ -812,6 +873,13 @@ Otherwise your changes are lost. Unable to calculate master key + + The selected file is an old KeePass 1 database (.kdb). + +You can import it by clicking on Database > 'Import KeePass 1 database'. +This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + + Main @@ -926,18 +994,10 @@ Otherwise your changes are lost. Find - - Username - - Copy username to clipboard - - Password - - Copy password to clipboard @@ -986,6 +1046,42 @@ Otherwise your changes are lost. Tools + + Copy username + + + + Copy password + + + + Export to CSV file + + + + Repair database + + + + KeePass 2 Database + + + + All files + + + + Save repaired database + + + + Error + + + + Writing the database failed. + + PasswordGeneratorWidget @@ -1266,10 +1362,6 @@ Otherwise your changes are lost. path to a custom config file - - password of the database (DANGEROUS!) - - key file of the database diff --git a/share/translations/keepassx_es.ts b/share/translations/keepassx_es.ts index b3f6b6ff..c9a7df8b 100644 --- a/share/translations/keepassx_es.ts +++ b/share/translations/keepassx_es.ts @@ -75,7 +75,7 @@ Key files - Archivos de llaves + Archivos llave All files @@ -109,6 +109,16 @@ Different passwords supplied. Las contraseñas ingresadas son distintas. + + Failed to set key file + No se pudo establecer el archivo llave + + + Failed to set %1 as the Key file: +%2 + No se pudo establecer %1 como el Archivo llave: +%2 + DatabaseOpenWidget @@ -118,7 +128,7 @@ Key File: - Archivo clave: + Archivo llave: Password: @@ -196,7 +206,7 @@ DatabaseTabWidget Root - + Raíz KeePass 2 Database @@ -234,12 +244,6 @@ Close? ¿Cerrar? - - "%1" is in edit mode. -Close anyway? - "%1" está en modo de edición. -¿Cerrar de todas formas? - Save changes? ¿Guardar cambios? @@ -270,12 +274,60 @@ Save changes? locked bloqueado + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + La base de datos que está intentando abrir está bloqueada por otra instancia de KeePassX. +¿Quiere abrirla de todos modos? Alternativamente, la base de datos se abre como sólo lectura. + + + Lock database + Bloquear base de datos + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + No se puede bloquear la base de datos porque actualmente está editándola. +Por favor, pulse cancelar para terminar sus cambios o descartarlos. + + + This database has never been saved. +You can save the database or stop locking it. + Esta base de datos nunca ha sido guardada. +Puede guardar la base de datos o dejar de bloquearla. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Esta base de datos ha sido modificada. +¿Desea guardar la base de datos antes de bloquearla? +De lo contrario se perderán los cambios. + + + "%1" is in edit mode. +Discard changes and close anyway? + "% 1" está en el modo de edición. +¿Descartar cambios y cerrar de todos modos? + + + Export database to CSV file + Exportar base de datos a un archivo CSV + + + CSV file + Archivo CSV + + + Writing the CSV file failed. + La escritura del archivo CSV falló. + DatabaseWidget Change master key - Cambiar la llave maestra + Cambiar la clave maestra Delete entry? @@ -313,6 +365,14 @@ Save changes? Current group Grupo actual + + Error + Error + + + Unable to calculate master key + No se puede calcular la llave maestra + EditEntryWidget @@ -425,6 +485,10 @@ Save changes? Save Guardar + + Open + Abrir + EditEntryWidgetAutoType @@ -576,6 +640,14 @@ Save changes? Auto-type Auto-escritura + + Use default auto-type sequence of parent group + Usar escritura automática por defecto del grupo padre + + + Set default auto-type sequence + Establecer escritura automática por defecto + EditWidgetIcons @@ -722,7 +794,11 @@ Save changes? Root - + Raíz + + + Unable to calculate master key + No se puede calcular la clave maestra @@ -739,6 +815,10 @@ Save changes? Wrong key or database file is corrupt. La contraseña es incorrecta o el archivo está dañado + + Unable to calculate master key + No se puede calcular la clave maestra + Main @@ -777,10 +857,6 @@ Save changes? Groups Grupos - - Extras - Extras - View Ver @@ -839,7 +915,7 @@ Save changes? Change master key - Cambiar la llave maestra + Cambiar la clave maestra Database settings @@ -857,18 +933,10 @@ Save changes? Find Buscar - - Username - Usuario - Copy username to clipboard Copiar nombre de usuario al portapapeles - - Password - Contraseña - Copy password to clipboard Copiar contraseña al portapapeles @@ -913,6 +981,22 @@ Save changes? Toggle window Cambiar a ventana + + Tools + Herramientas + + + Copy username + Copiar nombre de usuario + + + Copy password + Copiar contraseña + + + Export to CSV file + Exportar a un archivo CSV + PasswordGeneratorWidget @@ -1065,7 +1149,7 @@ Save changes? Root group - + Grupo raíz @@ -1093,10 +1177,6 @@ Save changes? Open previous databases on startup Abrir base de datos anterior al inicio - - Mark as modified on expanded state changes - Marcar como modificado en los cambios de estado ampliados - Automatically save on exit Guardar automáticamente al salir @@ -1133,6 +1213,10 @@ Save changes? Hide window to system tray when minimized Ocultar la ventana a la bandeja del sistema cuando se minimiza + + Remember last key files + Recordar últimos archivos clave + SettingsWidgetSecurity @@ -1163,14 +1247,6 @@ Save changes? Unlock database Desbloquear base de datos - - Error - Error - - - Wrong key. - Clave incorrecta. - WelcomeWidget diff --git a/share/translations/keepassx_fr.ts b/share/translations/keepassx_fr.ts index cf575025..31944bbe 100644 --- a/share/translations/keepassx_fr.ts +++ b/share/translations/keepassx_fr.ts @@ -9,6 +9,14 @@ KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. KeePassX est distribué selon les conditions de la GNU General Public License (GPL) version 2 ou (à votre choix) version 3. + + Revision + Version + + + Using: + Utilise : + AutoType @@ -25,7 +33,7 @@ AutoTypeAssociationsModel Window - Fenêtre + Fenêtre Sequence @@ -63,7 +71,7 @@ Key file - Fichier de clé + Fichier-clé Browse @@ -75,7 +83,7 @@ Key files - Fichiers de clé + Fichiers-clés All files @@ -83,7 +91,7 @@ Create Key File... - Créer un fichier de clé... + Créer un fichier-clé... Error @@ -91,11 +99,11 @@ Unable to create Key File : - Incapable de créer un fichier de clé : + Impossible de créer un fichier-clé : Select a key file - Choisir un fichier de clé + Choisir un fichier-clé Question @@ -109,16 +117,26 @@ Different passwords supplied. Les mots de passe ne sont pas identiques. + + Failed to set key file + Échec de définition du fichier-clé + + + Failed to set %1 as the Key file: +%2 + Impossible de définir %1 comme fichier-clé : +%2 + DatabaseOpenWidget Enter master key - Entrez la clé maîtresse + Entrez la clé maître Key File: - Fichier de clé : + Fichier-clé : Password: @@ -138,7 +156,7 @@ Can't open key file - Impossible d'ouvrir le fichier de clé + Impossible d'ouvrir le fichier-clé All files @@ -146,11 +164,11 @@ Key files - Fichiers de clé + Fichiers-clés Select key file - Choisissez un fichier de clé + Choisissez un fichier-clé @@ -177,7 +195,7 @@ MiB - MiB + MiB Benchmark @@ -208,7 +226,7 @@ Open database - Ovrire la base de données + Ouvrir la base de données Warning @@ -216,7 +234,7 @@ File not found! - Fichier introuvable! + Fichier introuvable ! Open KeePass 1 database @@ -232,13 +250,7 @@ Close? - Fermer? - - - "%1" is in edit mode. -Close anyway? - "%1" est en cours de modification. -Fermer quand même ? + Fermer ? Save changes? @@ -256,7 +268,7 @@ Enregistrer les modifications ? Writing the database failed. - Une erreur s'est produite lors de l'écriture de la base de données. + Une erreur s'est produite lors de l'écriture de la base de données. Save database as @@ -270,12 +282,66 @@ Enregistrer les modifications ? locked verrouillée + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + La base de données que vous essayez d'ouvrir est verrouillée par une autre instance de KeePassX. +Voulez-vous quand même l'ouvrir ? Dans ce cas, elle sera ouverte en lecture seule. + + + Lock database + Verrouiller la base de données + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Impossible de verrouiller la base de données lors de modifications. +Cliquez sur Annuler pour finir vos modifications ou abandonnez-les. + + + This database has never been saved. +You can save the database or stop locking it. + Cette base de données n'a pas encore été sauvegardée. +Vous devez la sauvegarder ou annuler son verrouillage. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + La base de données a été modifiée. +Voulez-vous l'enregistrer avant de la verrouiller ? +Autrement, vos modifications seront perdues. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" est en mode édition. +Ignorer les changements et fermer ? + + + Export database to CSV file + Exporter la base de données au format CSV + + + CSV file + Fichier CSV + + + Writing the CSV file failed. + Échec de l'écriture du fichier CSV. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + La base de données que vous essayez de sauvegarder a été verrouillée par une autre instance de KeePassX. +Voulez-vous quand même la sauvegarder ? + DatabaseWidget Change master key - Changer la clé maîtresse + Changer la clé maître Delete entry? @@ -311,7 +377,15 @@ Enregistrer les modifications ? Current group - Group actif + Groupe actif + + + Error + Erreur + + + Unable to calculate master key + Impossible de calculer la clé maître @@ -322,7 +396,7 @@ Enregistrer les modifications ? Advanced - Avancées + Avancé Icon @@ -330,11 +404,11 @@ Enregistrer les modifications ? Auto-Type - Auto-Type + Remplissage automatique Properties - Propriétés + Propriétés History @@ -379,7 +453,7 @@ Enregistrer les modifications ? Unable to save the attachment: - Impossible de enregistrer le fichier attaché: + Impossible d'enregistrer le fichier attaché : @@ -396,14 +470,14 @@ Enregistrer les modifications ? 1 year - Une année + 1 an EditEntryWidgetAdvanced Additional attributes - Attributs additionnel + Attributs supplémentaires Add @@ -423,22 +497,26 @@ Enregistrer les modifications ? Save - Enregistrer le fichier + Enregistrer le fichier + + + Open + Ouvrir EditEntryWidgetAutoType Enable Auto-Type for this entry - Activer l'Auto-Type pour cette entrée + Activer le remplissage automatique pour cette entrée Inherit default Auto-Type sequence from the group - + Utiliser la séquence de remplissage automatique par défaut du groupe Use custom Auto-Type sequence: - Utiliser une séquence d'Auto-Type personnalisée : + Utiliser une séquence de remplissage automatique personnalisée : + @@ -450,7 +528,7 @@ Enregistrer les modifications ? Window title: - Titre de la fenêtre: + Titre de la fenêtre : Use default sequence @@ -458,14 +536,14 @@ Enregistrer les modifications ? Set custom sequence: - + Définir une séquence personnalisée : EditEntryWidgetHistory Show - Exposer + Afficher Restore @@ -484,19 +562,19 @@ Enregistrer les modifications ? EditEntryWidgetMain Title: - Titre: + Titre : Username: - Non d'utilisateur: + Nom d'utilisateur : Password: - Mot de passe: + Mot de passe : Repeat: - Confirme: + Confirmation : Gen. @@ -504,7 +582,7 @@ Enregistrer les modifications ? URL: - URL: + URL : Expires @@ -516,7 +594,7 @@ Enregistrer les modifications ? Notes: - Notes: + Notes : @@ -531,15 +609,15 @@ Enregistrer les modifications ? Properties - Propriétés + Propriétés Add group - Ajouter un groupe. + Ajouter un groupe Edit group - Modifie le groupe + Modifier le groupe Enable @@ -566,7 +644,7 @@ Enregistrer les modifications ? Expires - Expires + Expiration Search @@ -574,7 +652,15 @@ Enregistrer les modifications ? Auto-type - Auto-type + Remplissage automatique + + + Use default auto-type sequence of parent group + Utiliser la séquence de remplissage automatique par défaut du groupe parent + + + Set default auto-type sequence + Définir une séquence de remplissage automatique par défaut @@ -605,7 +691,7 @@ Enregistrer les modifications ? Select Image - Choisis un image. + Choisir une image Can't delete icon! @@ -632,7 +718,7 @@ Enregistrer les modifications ? Uuid: - Uuid: + Uuid : @@ -673,7 +759,7 @@ Enregistrer les modifications ? Username - Non d'utilisateur + Nom d'utilisateur URL @@ -684,14 +770,14 @@ Enregistrer les modifications ? Group Recycle Bin - Bac de Recyclage + Corbeille KeePass1OpenWidget Import KeePass1 database - Importe un KeePass1 bas de données + Importer une base de données au format KeePass1 Error @@ -699,18 +785,18 @@ Enregistrer les modifications ? Unable to open the database. - Impossible d'ouvrir la bas de données. + Impossible d'ouvrir la base de données. KeePass1Reader Unable to read keyfile. - Impossible de lire le fichier de clé. + Impossible de lire le fichier-clé. Not a KeePass database. - Ce n'est pas une base de donnée KeePass. + Ce n'est pas une base de données KeePass. Unsupported encryption algorithm. @@ -718,26 +804,44 @@ Enregistrer les modifications ? Unsupported KeePass database version. - Version de base de donnée KeePass non supportée. + Version de base de données KeePass non supportée. Root Racine + + Unable to calculate master key + Impossible de calculer la clé maître + KeePass2Reader Not a KeePass database. - Ce n'est pas une base de donnée KeePass. + Ce n'est pas une base de données KeePass. Unsupported KeePass database version. - Version de base de donnée KeePass non supportée. + Version de base de données KeePass non supportée. Wrong key or database file is corrupt. - Mauvaise clé ou fichier de base de donnée corrompu. + Mauvaise clé ou fichier de base de données corrompu. + + + Unable to calculate master key + Impossible de calculer la clé maître + + + The selected file is an old KeePass 1 database (.kdb). + +You can import it by clicking on Database > 'Import KeePass 1 database'. +This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + Le fichier sélectionné est une ancienne base de données pour KeePass 1 (.kdb). + +Vous pouvez l'importer en cliquant sur "Base de données" > "Importer une base de données KeePass 1". +Ceci est une migration à sens unique. Vous ne serez plus en mesure d'ouvrir la base de données importée avec l'ancienne version KeePassX version 0.4. @@ -771,16 +875,12 @@ Enregistrer les modifications ? Copy attribute to clipboard - Copier l'attribut dans le presse-papiers + Copier l'attribut dans le presse-papier Groups Groupes - - Extras - Extras - View Vue @@ -795,19 +895,19 @@ Enregistrer les modifications ? Open database - Ouvrir une base de donnée + Ouvrir une base de données Save database - Enregistrer la base de donnée + Enregistrer la base de données Close database - Fermer la base de donnée + Fermer la base de données New database - Nouvelle base de donnée + Nouvelle base de données Add new entry @@ -835,7 +935,7 @@ Enregistrer les modifications ? Save database as - Enregistrer la base de donnée sous + Enregistrer la base de données sous Change master key @@ -843,11 +943,11 @@ Enregistrer les modifications ? Database settings - Paramètre de la base de donnée + Paramètres de la base de données Import KeePass 1 database - Importer une base de donnée KeePass 1 + Importer une base de données KeePass 1 Clone entry @@ -857,21 +957,13 @@ Enregistrer les modifications ? Find Chercher - - Username - Nom d'utilisateur - Copy username to clipboard - Copier le nom d'utilisateur dans le presse-papiers - - - Password - Mot de passe + Copier le nom d'utilisateur dans le presse-papier Copy password to clipboard - Copier le mot de passe dans le presse-papiers + Copier le mot de passe dans le presse-papier Settings @@ -879,7 +971,7 @@ Enregistrer les modifications ? Perform Auto-Type - Effectuer un Auto-Type + Effectuer un remplissage automatique Open URL @@ -913,12 +1005,28 @@ Enregistrer les modifications ? Toggle window Basculer de fenêtre + + Tools + Outils + + + Copy username + Copier le nom d'utilisateur + + + Copy password + Copier le mot de passe + + + Export to CSV file + Exporter au format CSV + PasswordGeneratorWidget Password: - Mot de passe: + Mot de passe : Length: @@ -926,7 +1034,7 @@ Enregistrer les modifications ? Character Types - Types de caractère + Types de caractères Upper Case Letters @@ -961,7 +1069,7 @@ Enregistrer les modifications ? QCommandLineParser Displays version information. - Afficher les informations de version + Afficher les informations de version. Displays this help. @@ -1023,15 +1131,15 @@ Enregistrer les modifications ? Error writing to underlying device: - + Erreur d'écriture sur le périphérique concerné : Error opening underlying device: - + Erreur d'ouverture du périphérique concerné : Error reading data from underlying device: - + Erreur de lecture sur le périphérique concerné : Internal zlib error when decompressing: @@ -1072,7 +1180,7 @@ Enregistrer les modifications ? SettingsWidget Application Settings - Paramètre de l'application + Paramètres de l'application General @@ -1091,23 +1199,19 @@ Enregistrer les modifications ? Open previous databases on startup - Ouvrir les base de données précédentes au démarrage - - - Mark as modified on expanded state changes - + Ouvrir les bases de données précédentes au démarrage Automatically save on exit - Sauvegarde automatiquement à la sortie + Sauvegarder automatiquement à la sortie Automatically save after every change - Sauvegarde automatiquement après chaque modification + Sauvegarder automatiquement après chaque modification Minimize when copying to clipboard - + Réduire lors de la copie dans le presse-papier Use group icon on entry creation @@ -1115,11 +1219,11 @@ Enregistrer les modifications ? Global Auto-Type shortcut - Raccourci d'Auto-Type global + Raccourci de remplissage automatique global Use entry title to match windows for global auto-type - Utiliser la correspondance entre le titre de l'entrée et de la fenêtre pour l'Auto-Type global + Utiliser la correspondance entre le titre de l'entrée et de la fenêtre pour le remplissage automatique global Language @@ -1127,26 +1231,30 @@ Enregistrer les modifications ? Show a system tray icon - + Afficher une icône dans la zone de notification Hide window to system tray when minimized - + Réduire la fenêtre vers la zone de notification lors de sa réduction + + + Remember last key files + Se rappeler les derniers fichiers-clés ouverts SettingsWidgetSecurity Clear clipboard after - Vider le presse-papiers après + Vider le presse-papier après sec - s + s Lock databases after inactivity of - Verrouiller les bases de donnée après une inactivité de + Verrouiller les bases de données après une inactivité de Show passwords in cleartext by default @@ -1154,22 +1262,14 @@ Enregistrer les modifications ? Always ask before performing auto-type - Toujours demander avant d'effectuer un auto-type + Toujours demander avant d'effectuer un remplissage automatique UnlockDatabaseWidget Unlock database - Déverrouiller la base de donnée - - - Error - Erreur - - - Wrong key. - Mauvaise clé. + Déverrouiller la base de données @@ -1187,19 +1287,15 @@ Enregistrer les modifications ? filename of the password database to open (*.kdbx) - Nom de fichier de la base de donnée de mot de pass à ouvrir (*.kdbx) + Nom de fichier de la base de données de mot de passe à ouvrir (*.kdbx) path to a custom config file Chemin vers un fichier de configuration personnalisé - - password of the database (DANGEROUS!) - Mot de passe de la base de donnée (DANGEREUX !) - key file of the database - Fichier de clé de la base de donnée + Fichier-clé de la base de données \ No newline at end of file diff --git a/share/translations/keepassx_id.ts b/share/translations/keepassx_id.ts index d71e981e..9b210f60 100644 --- a/share/translations/keepassx_id.ts +++ b/share/translations/keepassx_id.ts @@ -7,7 +7,15 @@ KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - + KeePassX disebarluaskan dibawah ketentuan dari Lisensi Publik Umum GNU (GPL) versi 2 atau (sesuai pilihan Anda) versi 3. + + + Revision + Revisi + + + Using: + Menggunakan: @@ -18,7 +26,7 @@ Couldn't find an entry that matches the window title: - Tidak dapat menemukan entri yang cocok dengan judul jendela + Tidak bisa menemukan entri yang cocok dengan judul jendela: @@ -51,15 +59,15 @@ ChangeMasterKeyWidget Password - Kata Sandi + Sandi Enter password: - Masukan kata sandi: + Masukkan sandi: Repeat password: - Ulangi kata sandi: + Ulangi sandi: Key file @@ -75,7 +83,7 @@ Key files - Berkas Kunci + Berkas kunci All files @@ -91,11 +99,11 @@ Unable to create Key File : - Tidak dapat membuat Berkas Kunci : + Tidak bisa membuat Berkas Kunci : Select a key file - Pilih sebuah berkas kunci + Pilih berkas kunci Question @@ -103,18 +111,28 @@ Do you really want to use an empty string as password? - Apakah anda ingin menggunakan string kosong sebagai kata sandi? + Apakah Anda benar-benar ingin menggunakan lema kosong sebagai sandi? Different passwords supplied. - Kata sandi yang berbeda diberikan. + Sandi berbeda. + + + Failed to set key file + Gagal menetapkan berkas kunci + + + Failed to set %1 as the Key file: +%2 + Gagal menetapkan %1 sebagai berkas Kunci: +%2 DatabaseOpenWidget Enter master key - Masukan kunci utama + Masukkan kunci utama Key File: @@ -122,7 +140,7 @@ Password: - Kata sandi: + Sandi: Browse @@ -134,11 +152,11 @@ Unable to open the database. - Tidak dapat membuka basis data + Tidak bisa membuka basis data. Can't open key file - Tidak dapat membuka berkas kunci + Tidak bisa membuka berkas kunci All files @@ -173,7 +191,7 @@ Use recycle bin: - + Gunakan tong sampah: MiB @@ -196,7 +214,7 @@ DatabaseTabWidget Root - + Root KeePass 2 Database @@ -234,12 +252,6 @@ Close? Tutup? - - "%1" is in edit mode. -Close anyway? - "%1" dalam berada mode sunting. -Tetap tutup? - Save changes? Simpan perubahan? @@ -256,7 +268,7 @@ Simpan perubahan? Writing the database failed. - Menulis basis data gagal. + Gagal membuat basis data. Save database as @@ -270,6 +282,60 @@ Simpan perubahan? locked terkunci + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Basis data yang Anda coba buka terkunci oleh KeePassX lain yang sedang berjalan. +Apakah Anda tetap ingin membukanya? Alternatif lain buka basis data baca-saja. + + + Lock database + Kunci basis data + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Tidak bisa mengunci basis data karena Anda sedang menyuntingnya. +Harap tekan batal untuk menyelesaikan ubahan Anda atau membuangnya. + + + This database has never been saved. +You can save the database or stop locking it. + Basis data ini belum pernah disimpan. +Anda bisa menyimpan basis data atau berhenti menguncinya. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Basis data ini telah dimodifikasi. +Apakah Anda ingin menyimpan basis data sebelum menguncinya? +Kalau tidak, ubahan Anda akan hilang. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" dalam mode penyuntingan. +Tetap buang ubahan dan tutup? + + + Export database to CSV file + Ekspor basis data ke berkas CSV + + + CSV file + Berkas CSV + + + Writing the CSV file failed. + Gagal membuat berkas CSV. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + Basis data yang Anda coba buka terkunci oleh KeePassX lain yang sedang berjalan. +Apakah Anda tetap ingin menyimpannya? + DatabaseWidget @@ -283,7 +349,7 @@ Simpan perubahan? Do you really want to delete the entry "%1" for good? - Apakah anda ingin menghapus entri "%1" untuk selamanya? + Apakah Anda benar-benar ingin menghapus entri "%1" untuk selamanya? Delete entries? @@ -291,15 +357,15 @@ Simpan perubahan? Do you really want to delete %1 entries for good? - Apakah anda ingin menghapus entri %1 untuk selamanya? + Apakah Anda benar-benar ingin menghapus entri %1 untuk selamanya? Move entries to recycle bin? - + Pindah entri ke tong sampah? Do you really want to move %n entry(s) to the recycle bin? - + Apakah Anda benar-benar ingin memindahkan %n entri ke tong sampah? Delete group? @@ -307,12 +373,20 @@ Simpan perubahan? Do you really want to delete the group "%1" for good? - Apakah anda ingin menghapus grup "%1" untuk selamanya? + Apakah Anda benar-benar ingin menghapus grup "%1" untuk selamanya? Current group Grup saat ini + + Error + Galat + + + Unable to calculate master key + Tidak bisa mengkalkulasi kunci utama + EditEntryWidget @@ -342,7 +416,7 @@ Simpan perubahan? Entry history - Entri riwayat + Riwayat entri Add entry @@ -358,7 +432,7 @@ Simpan perubahan? Different passwords supplied. - Kata sandi yang berbeda diberikan. + Sandi berbeda. New attribute @@ -370,7 +444,7 @@ Simpan perubahan? Unable to open file - Tidak dapat membuka berkas + Tidak bisa membuka berkas Save attachment @@ -379,7 +453,7 @@ Simpan perubahan? Unable to save the attachment: - Tidak dapat menyimpan lampiran: + Tidak bisa menyimpan lampiran: @@ -388,11 +462,11 @@ Simpan perubahan? %n week(s) - %n minggu(s) + %n minggu %n month(s) - %n bulan(s) + %n bulan 1 year @@ -415,7 +489,7 @@ Simpan perubahan? Remove - Hapus + Buang Attachments @@ -425,6 +499,10 @@ Simpan perubahan? Save Simpan + + Open + Buka + EditEntryWidgetAutoType @@ -434,11 +512,11 @@ Simpan perubahan? Inherit default Auto-Type sequence from the group - + Mengikuti urutan Ketik-Otomatis baku grup Use custom Auto-Type sequence: - + Gunakan urutan Ketik-Otomatis ubahsuai: + @@ -458,7 +536,7 @@ Simpan perubahan? Set custom sequence: - Tetapkan urutan kustom: + Tetapkan urutan ubahsuai: @@ -492,7 +570,7 @@ Simpan perubahan? Password: - Kata sandi: + Sandi: Repeat: @@ -508,11 +586,11 @@ Simpan perubahan? Expires - Kadaluarsa + Kedaluwarsa Presets - + Prasetel Notes: @@ -551,7 +629,7 @@ Simpan perubahan? Inherit from parent group (%1) - + Mengikuti grup induk (%1) @@ -566,7 +644,7 @@ Simpan perubahan? Expires - Kadaluarsa + Kedaluwarsa Search @@ -576,6 +654,14 @@ Simpan perubahan? Auto-type Ketik-otomatis + + Use default auto-type sequence of parent group + Gunakan urutan ketik-otomatis baku grup induk + + + Set default auto-type sequence + Tetapkan urutan ketik-otomatis baku + EditWidgetIcons @@ -585,15 +671,15 @@ Simpan perubahan? Use custom icon - Gunakan ikon kustom + Gunakan ikon ubahsuai Add custom icon - Tambah ikon kustom + Tambah ikon ubahsuai Delete custom icon - Hapus ikon kustom + Hapus ikon ubahsuai Images @@ -609,11 +695,11 @@ Simpan perubahan? Can't delete icon! - Tidak dapat menghapus ikon! + Tidak bisa menghapus ikon! Can't delete icon. Still used by %n item(s). - Can't delete icon. Still used by %n item(s). + Tidak bisa menghapus ikon. Masih digunakan oleh %n item. @@ -684,7 +770,7 @@ Simpan perubahan? Group Recycle Bin - + Tong Sampah @@ -699,52 +785,70 @@ Simpan perubahan? Unable to open the database. - Tidak dapat membuka basis data + Tidak bisa membuka basis data. KeePass1Reader Unable to read keyfile. - Tidak dapat membaca berkas kunci. + Tidak bisa membaca berkas kunci. Not a KeePass database. - Bukan basis data KeePass + Bukan basis data KeePass. Unsupported encryption algorithm. - Algoritma enkripsi tidak didukung + Algoritma enkripsi tidak didukung. Unsupported KeePass database version. - Versi Basis data KeePass tidak didukung + Versi basis data KeePass tidak didukung. Root - + Root + + + Unable to calculate master key + Tidak bisa mengkalkulasi kunci utama KeePass2Reader Not a KeePass database. - Bukan basis data KeePass + Bukan basis data KeePass. Unsupported KeePass database version. - Versi basis data KeePass tidak didukung + Versi basis data KeePass tidak didukung. Wrong key or database file is corrupt. - Kunci salah atau berkas basis data korup. + Kunci salah atau berkas basis data rusak. + + + Unable to calculate master key + Tidak bisa mengkalkulasi kunci utama + + + The selected file is an old KeePass 1 database (.kdb). + +You can import it by clicking on Database > 'Import KeePass 1 database'. +This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + Berkas yang dipilih adalah basis data KeePass 1 yang lama (.kdb). + +Anda bisa mengimpornya dengan mengklik Basis Data > 'Impor basis data KeePass 1'. +Ini adalah migrasi satu arah. Anda tidak akan bisa lagi membuka basis data yang diimpor dengan versi lama KeePassX 0.4. Main Fatal error while testing the cryptographic functions. - + Galat saat menguji fungsi kriptografi. KeePassX - Error @@ -759,7 +863,7 @@ Simpan perubahan? Recent databases - + Basis data baru-baru ini Help @@ -777,13 +881,9 @@ Simpan perubahan? Groups Grup - - Extras - Ekstra - View - + Lihat Quit @@ -815,7 +915,7 @@ Simpan perubahan? View/Edit entry - Tampil/Sunting entri + Lihat/Sunting entri Delete entry @@ -851,27 +951,19 @@ Simpan perubahan? Clone entry - + Duplikat entri Find Temukan - - Username - Nama pengguna - Copy username to clipboard Salin nama pengguna ke papan klip - - Password - Kata sandi - Copy password to clipboard - Salin kata sandi ke papan klip + Salin sandi ke papan klip Settings @@ -879,7 +971,7 @@ Simpan perubahan? Perform Auto-Type - Melakukan Ketik-Otomatis + Lakukan Ketik-Otomatis Open URL @@ -907,18 +999,34 @@ Simpan perubahan? read-only - hanya-baca + baca-saja Toggle window - + Jungkit jendela + + + Tools + Perkakas + + + Copy username + Salin nama pengguna + + + Copy password + Salin sandi + + + Export to CSV file + Ekspor ke berkas CSV PasswordGeneratorWidget Password: - Kata sandi: + Sandi: Length: @@ -926,15 +1034,15 @@ Simpan perubahan? Character Types - Tipe karakter + Tipe Karakter Upper Case Letters - + Huruf Besar Lower Case Letters - + Huruf Kecil Numbers @@ -946,11 +1054,11 @@ Simpan perubahan? Exclude look-alike characters - + Kecualikan karakter mirip Ensure that the password contains characters from every group - Pastikan kata sandi berisi karakter dari setiap grup + Pastikan sandi berisi karakter dari setiap grup Accept @@ -961,11 +1069,11 @@ Simpan perubahan? QCommandLineParser Displays version information. - Tampilkan informasi versi + Tampilkan informasi versi. Displays this help. - Tampilkan bantuan ini + Tampilkan bantuan ini. Unknown option '%1'. @@ -997,29 +1105,29 @@ Simpan perubahan? Arguments: - Argumen + Argumen: QSaveFile Existing file %1 is not writable - Berkas yang ada %1 tidak dapat ditulis + Berkas yang ada %1 tidak bisa ditulis Writing canceled by application - Menulis dibatalkan oleh aplikasi + Penulisan dibatalkan oleh aplikasi Partial write. Partition full? - + Penulisan parsial. Partisi penuh? QtIOCompressor Internal zlib error when compressing: - Galat zlib internal ketika mengkompress: + Galat zlib internal ketika memampatkan: Error writing to underlying device: @@ -1035,7 +1143,7 @@ Simpan perubahan? Internal zlib error when decompressing: - Galat zlib internal ketika dekompress + Galat zlib internal ketika dekompres: @@ -1057,15 +1165,15 @@ Simpan perubahan? Case sensitive - + Sensitif besar kecil huruf Current group - + Grup saat ini Root group - + Grup root @@ -1093,10 +1201,6 @@ Simpan perubahan? Open previous databases on startup Buka basis data sebelumnya saat mulai - - Mark as modified on expanded state changes - - Automatically save on exit Otomatis simpan ketika keluar @@ -1107,7 +1211,7 @@ Simpan perubahan? Minimize when copying to clipboard - Kecilkan ketika menyalin ke papan klip + Minimalkan ketika menyalin ke papan klip Use group icon on entry creation @@ -1115,11 +1219,11 @@ Simpan perubahan? Global Auto-Type shortcut - Jalan pintas global Ketik-Otomatis + Pintasan global Ketik-Otomatis Use entry title to match windows for global auto-type - + Gunakan judul entri untuk mencocokkan jendela untuk ketik-otomatis global Language @@ -1127,18 +1231,22 @@ Simpan perubahan? Show a system tray icon - Tampilkan sebuah ikon baki sistem + Tampilkan ikon baki sistem Hide window to system tray when minimized - Sembunyikan jendela ke baki sistem ketika dikecilkan + Sembunyikan jendela ke baki sistem ketika diminimalkan + + + Remember last key files + Ingat berkas kunci terakhir SettingsWidgetSecurity Clear clipboard after - Bersihkan papan klip setelaj + Kosongkan papan klip setelah sec @@ -1146,56 +1254,44 @@ Simpan perubahan? Lock databases after inactivity of - + Kunci basis data setelah tidak aktif selama Show passwords in cleartext by default - + Tampilkan teks sandi secara baku Always ask before performing auto-type - + Selalu tanya sebelum melakukan ketik-otomatis UnlockDatabaseWidget Unlock database - - - - Error - Galat - - - Wrong key. - Kunci salah. + Buka kunci basis data WelcomeWidget Welcome! - Selamat Datang. + Selamat datang! main KeePassX - cross-platform password manager - KeePassX - manajer kata sandi cross-platform + KeePassX - pengelola sandi lintas platform filename of the password database to open (*.kdbx) - nama berkasi dari basis data kata sandi untuk dibuka (*.kdbx) + nama berkas dari basis data sandi untuk dibuka (*.kdbx) path to a custom config file - - - - password of the database (DANGEROUS!) - kata sandi dari basis data (BERBAHAYA!) + jalur ke berkas konfig ubahsuai key file of the database diff --git a/share/translations/keepassx_it.ts b/share/translations/keepassx_it.ts index 4f91b75a..ad9af908 100644 --- a/share/translations/keepassx_it.ts +++ b/share/translations/keepassx_it.ts @@ -3,12 +3,19 @@ AboutDialog About KeePassX - A proposito di KeePassX + Informazioni su KeePassX KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. - KeePassX è distribuito sotto i termini della licenza -GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. + KeePassX è distribuito sotto i termini della licenza GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. + + + Revision + Revisione + + + Using: + In uso: @@ -18,7 +25,7 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3.Auto-Type - KeePassX - Couldn't find an entry that matches the window title. + Couldn't find an entry that matches the window title: Impossibile trovare una voce che corrisponda al titolo della finestra @@ -45,7 +52,7 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Select entry to Auto-Type: - Selezionare una voce per Auto-Type: + Seleziona una voce per Auto-Type: @@ -56,11 +63,11 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Enter password: - Inserire password: + Inserisci password: Repeat password: - Ripetere password: + Ripeti password: Key file @@ -68,11 +75,11 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Browse - Sfogliare + Sfoglia Create - Creare + Crea Key files @@ -84,7 +91,7 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Create Key File... - Creare file chiave... + Crea file chiave... Error @@ -96,7 +103,7 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Select a key file - Selezionare file chiave + Seleziona il file chiave Question @@ -110,16 +117,26 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3.Different passwords supplied. Sono state fornite password differenti. + + Failed to set key file + Impossibile impostare il file chiave + + + Failed to set %1 as the Key file: +%2 + Impossibile impostare %1 come file chiave: +%2 + DatabaseOpenWidget Enter master key - Inserire password + Inserisci la chiave principale Key File: - File Chiave: + File chiave: Password: @@ -127,7 +144,7 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Browse - Sfogliare + Sfoglia Error @@ -151,18 +168,18 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Select key file - Selezionare file chiave + Seleziona file chiave DatabaseSettingsWidget Database name: - Nome database: + Nome del database: Database description: - Descrizione database: + Descrizione del database: Transform rounds: @@ -174,7 +191,7 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Use recycle bin: - Utilizzare cestino: + Utilizza cestino: MiB @@ -182,7 +199,7 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Benchmark - Benchmark + Prestazione Max. history items: @@ -209,7 +226,7 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Open database - Aprire database + Apri database Warning @@ -221,7 +238,7 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3. Open KeePass 1 database - Aprire database KeePass 1 + Apri database KeePass 1 KeePass 1 database @@ -235,12 +252,6 @@ GNU General Public License (GPL) versione 2 o, a tua scelta, della versione 3.Close? Chiudere? - - "%1" is in edit mode. -Close anyway? - "%1" è in modalità modifica. -Chiudere comunque? - Save changes? Salvare modifiche? @@ -248,7 +259,7 @@ Chiudere comunque? "%1" was modified. Save changes? - "%1" è stata modificata. + "%1" è stata modificato. Salvare le modifiche? @@ -257,11 +268,11 @@ Salvare le modifiche? Writing the database failed. - Scrittura del database fallita. + Scrittura del database non riuscita. Save database as - Salvare database come + Salva database come New database @@ -271,12 +282,66 @@ Salvare le modifiche? locked bloccato + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Il database che stai tentando di aprire è bloccato da un'altra istanza di KeePassX. +Vuoi aprirlo comunque? Altrimenti il database verrà aperto in sola lettura. + + + Lock database + Blocca database + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Non è possibile bloccare il database dato che lo stai modificando. +Premere Annulla per completare le modifiche o scartarle. + + + This database has never been saved. +You can save the database or stop locking it. + Questo database non è mai stato salvato. +È possibile salvare il database o interrompere il blocco. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Questo database è stato modificato. +Vuoi salvare il database prima di bloccarlo? +Altrimenti le modifiche verranno perse. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" è in modalità modifica. +Annullare le modifiche e chiudere comunque? + + + Export database to CSV file + Esporta il database come file CSV + + + CSV file + file CSV + + + Writing the CSV file failed. + Scrittura del file CSV non riuscita. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + Il database che stai tentando di salvare è bloccato da un'altra istanza di KeePassX. +Vuoi salvare comunque? + DatabaseWidget Change master key - Cambiare password principale + Cambia chiave principale Delete entry? @@ -314,6 +379,14 @@ Salvare le modifiche? Current group Gruppo corrente + + Error + Errore + + + Unable to calculate master key + Impossibile calcolare la chiave principale + EditEntryWidget @@ -367,7 +440,7 @@ Salvare le modifiche? Select file - Selezionare file + Seleziona file Unable to open file @@ -380,7 +453,7 @@ Salvare le modifiche? Unable to save the attachment: - Impossibile salvare l'allegato + Impossibile salvare l'allegato: @@ -389,15 +462,15 @@ Salvare le modifiche? %n week(s) - %n settimana(e)%n settimana(e) + %n settimana%n settimane %n month(s) - %n mese(i)%n mese(i) + %n mese%n mesi 1 year - 1 anno + Un anno @@ -408,15 +481,15 @@ Salvare le modifiche? Add - Aggiungere + Aggiungi Edit - Modificare + Modifica Remove - Rimuovere + Rimuovi Attachments @@ -424,22 +497,26 @@ Salvare le modifiche? Save - Salvare + Salva + + + Open + Apri EditEntryWidgetAutoType Enable Auto-Type for this entry - Abilitare Auto-Type per questa voce + Abilita Auto-Type per questa voce Inherit default Auto-Type sequence from the group - Ereditare la sequenza predefinita di Auto-Type dal gruppo + Eredita la sequenza predefinita di Auto-Type dal gruppo Use custom Auto-Type sequence: - Usare sequenza personalizzata di Auto-Type: + Usa sequenza personalizzata di Auto-Type: + @@ -455,30 +532,30 @@ Salvare le modifiche? Use default sequence - Usare sequenza predefinita + Usa sequenza predefinita Set custom sequence: - Impostare sequenza personalizzata: + Imposta sequenza personalizzata: EditEntryWidgetHistory Show - Mostrare + Mostra Restore - Ripristinare + Ripristina Delete - Eliminare + Elimina Delete all - Eliminare tutti + Elimina tutti @@ -497,7 +574,7 @@ Salvare le modifiche? Repeat: - Ripetere: + Ripeti: Gen. @@ -513,7 +590,7 @@ Salvare le modifiche? Presets - Programmare + Preimpostazioni Notes: @@ -536,23 +613,23 @@ Salvare le modifiche? Add group - Aggiungere gruppo + Aggiungi gruppo Edit group - Modificare gruppo + Modifica gruppo Enable - Abilitare + Abilita Disable - Disabilitare + Disabilita Inherit from parent group (%1) - Ereditare dal gruppo genitore (%1) + Eredita dal gruppo genitore (%1) @@ -571,30 +648,38 @@ Salvare le modifiche? Search - Cercare + Cerca Auto-type Auto-Type + + Use default auto-type sequence of parent group + Eredita la sequenza predefinita di auto-type dal gruppo + + + Set default auto-type sequence + Usa sequenza di auto-type predefinita + EditWidgetIcons Use default icon - Usare icona predefinita + Usa icona predefinita Use custom icon - Usare icona personalizzata + Usa icona personalizzata Add custom icon - Aggiungere icona personalizzata + Aggiungi icona personalizzata Delete custom icon - Rimuovere icona personalizzata + Rimuovi icona personalizzata Images @@ -606,26 +691,26 @@ Salvare le modifiche? Select Image - Selezionare Immagine + Seleziona immagine Can't delete icon! - Impossibile eliminare icona! + Impossibile eliminare l'icona! Can't delete icon. Still used by %n item(s). - Impossibile eliminare l'icona in quanto è in uso da %n voce(i).Impossibile eliminare l'icona in quanto è in uso da %n voce(i). + Impossibile eliminare l'icona in quanto è in uso da %n voce.Impossibile eliminare l'icona in quanto è in uso da %n voci. EditWidgetProperties Created: - Creato: + Creazione: Modified: - Modificato: + Modifica: Accessed: @@ -633,7 +718,7 @@ Salvare le modifiche? Uuid: - Uuid: + UUID: @@ -674,7 +759,7 @@ Salvare le modifiche? Username - Nome Utente + Nome utente URL @@ -685,14 +770,14 @@ Salvare le modifiche? Group Recycle Bin - Cestino (Gruppo) + Cestino KeePass1OpenWidget Import KeePass1 database - Importare database KeePass1 + Importa database KeePass1 Error @@ -707,7 +792,7 @@ Salvare le modifiche? KeePass1Reader Unable to read keyfile. - Impossibile leggere il file chiave. + Impossibile leggere il file della chiave. Not a KeePass database. @@ -719,11 +804,15 @@ Salvare le modifiche? Unsupported KeePass database version. - Versione database non supportata + Versione database KeePass non supportata. Root - Root (KeePass1Reader) + Root + + + Unable to calculate master key + Impossibile calcolare la chiave principale @@ -734,11 +823,36 @@ Salvare le modifiche? Unsupported KeePass database version. - Versione database non supportata + Versione database KeePass non supportata. Wrong key or database file is corrupt. - Password errata o database corrotto. + Chiave errata o file del database danneggiato. + + + Unable to calculate master key + Impossibile calcolare la chiave principale + + + The selected file is an old KeePass 1 database (.kdb). + +You can import it by clicking on Database > 'Import KeePass 1 database'. +This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + Il file selezionato è un vecchio database KeePass 1 (.kdb). + +Puoi importarlo facendo clic su Database > 'Importa database KeePass 1'. +Questa è una migrazione in una sola direzione. Non potrai aprire il database importato con la vecchia versione 0.4 di KeePassX. + + + + Main + + Fatal error while testing the cryptographic functions. + Errore fatale durante il test delle funzioni di crittografia. + + + KeePassX - Error + KeePassx - Errore @@ -761,39 +875,35 @@ Salvare le modifiche? Copy attribute to clipboard - Copiare attributi negli appunti + Copia attributi negli appunti Groups Gruppi - - Extras - Extra - View - Visualizzare + Visualizza Quit - Uscire + Esci About - A Proposito + Informazioni Open database - Aprire database + Apri database Save database - Salvare database + Salva database Close database - Chiudere database + Chiudi database New database @@ -801,35 +911,35 @@ Salvare le modifiche? Add new entry - Aggiungere nuova voce + Aggiungi nuova voce View/Edit entry - Visualizzare/Modificare voce + Visualizza/modifica voce Delete entry - Eliminare voce + Elimina voce Add new group - Aggiungere nuovo gruppo + Aggiungi nuovo gruppo Edit group - Modificare gruppo + Modifica gruppo Delete group - Eliminare gruppo + Elimina gruppo Save database as - Salvare database come + Salva database come Change master key - Cambiare password principale + Cambia chiave principale Database settings @@ -837,7 +947,7 @@ Salvare le modifiche? Import KeePass 1 database - Importare database KeePass 1 + Importa database KeePass 1 Clone entry @@ -845,23 +955,15 @@ Salvare le modifiche? Find - Trovare - - - Username - Nome Utente + Trova Copy username to clipboard - Copiare nome utente negli appunti - - - Password - Password + Copia nome utente negli appunti Copy password to clipboard - Copiare password negli appunti + Copia password negli appunti Settings @@ -869,15 +971,15 @@ Salvare le modifiche? Perform Auto-Type - Eseguire Auto-Type + Esegui Auto-Type Open URL - Aprire URL + Apri URL Lock databases - Bloccare database + Blocca database Title @@ -893,12 +995,32 @@ Salvare le modifiche? Show toolbar - Mostrare barra degli strumenti + Mostra barra degli strumenti read-only sola lettura + + Toggle window + Cambia finestra + + + Tools + Strumenti + + + Copy username + Copia nome utente + + + Copy password + Copia password + + + Export to CSV file + Esporta in un file CSV + PasswordGeneratorWidget @@ -932,26 +1054,26 @@ Salvare le modifiche? Exclude look-alike characters - Escludere caratteri simili + Escludi caratteri simili Ensure that the password contains characters from every group - Assicurare che la password contenga caratteri di ogni gruppo + Verifica che la password contenga caratteri di ogni gruppo Accept - Accettare + Accetta QCommandLineParser Displays version information. - Mostrare informazioni sulla versione. + Mostra informazioni sulla versione. Displays this help. - Mostrare questo aiuto. + Mostra questo aiuto. Unknown option '%1'. @@ -994,7 +1116,7 @@ Salvare le modifiche? Writing canceled by application - Scrittura cancellata dall'applicazione + Scrittura annullata dall'applicazione Partial write. Partition full? @@ -1039,11 +1161,11 @@ Salvare le modifiche? SearchWidget Find: - Trovare: + Trova: Case sensitive - Case sensitive + Riconoscimento di maiuscole e minuscole Current group @@ -1073,31 +1195,27 @@ Salvare le modifiche? SettingsWidgetGeneral Remember last databases - Ricordare ultimo database + Ricorda ultimo database Open previous databases on startup - Aprire precedente database all'avvio - - - Mark as modified on expanded state changes - Marcare come modificata quando la voce viene espansa + Apri il database precedente all'avvio Automatically save on exit - Salvare automaticamente all'uscita + Salva automaticamente all'uscita Automatically save after every change - Salvare automaticamente dopo ogni modifica + Salva automaticamente dopo ogni modifica Minimize when copying to clipboard - Minimizzare quando si copia negli appunti + Minimizza quando si copia negli appunti Use group icon on entry creation - Usare l'icona del gruppo alla creazione di una voce + Usa l'icona del gruppo alla creazione di una voce Global Auto-Type shortcut @@ -1105,14 +1223,30 @@ Salvare le modifiche? Use entry title to match windows for global auto-type - Utilizzare il titolo della voce per abbinare la finestra per auto-type globale + Utilizza il titolo della voce per abbinare la finestra per auto-type globale + + + Language + Lingua + + + Show a system tray icon + Mostra un'icona nell'area di notifica del sistema + + + Hide window to system tray when minimized + Nascondi la finestra nell'area di notifica del sistema quando viene minimizzata + + + Remember last key files + Ricorda gli ultimi file di chiavi SettingsWidgetSecurity Clear clipboard after - Pulire appunti dopo + Pulisci appunti dopo sec @@ -1120,57 +1254,45 @@ Salvare le modifiche? Lock databases after inactivity of - Bloccare database dopo un'inattività di + Blocca i database dopo un'inattività di Show passwords in cleartext by default - Mostrare la password in chiaro in maniera predefinita + Mostra la password in chiaro in maniera predefinita Always ask before performing auto-type - Chiedere sempre prima di eseguire auto-type + Chiedi sempre prima di eseguire auto-type UnlockDatabaseWidget Unlock database - Sbloccare database - - - Error - Errore - - - Wrong key. - Password errata. + Sblocca database WelcomeWidget Welcome! - Benvenuto/a! + Benvenuto! main KeePassX - cross-platform password manager - KeePassX - gestore di password cross-platform + KeePassX - gestore di password multipiattafroma filename of the password database to open (*.kdbx) - nome del file del database da aprire (*.kdbx) + nome del file di database da aprire (*.kdbx) path to a custom config file percorso ad un file di configurazione personalizzato - - password of the database (DANGEROUS!) - password del database (PERICOLOSO!) - key file of the database file chiave del database diff --git a/share/translations/keepassx_ja.ts b/share/translations/keepassx_ja.ts new file mode 100644 index 00000000..0b468c98 --- /dev/null +++ b/share/translations/keepassx_ja.ts @@ -0,0 +1,1275 @@ + + + AboutDialog + + About KeePassX + KeePassX について + + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + KeePassXはGNU General Public License (GPL) version 2 または version 3 (どちらかを選択)の条件で配布されます。 + + + + AutoType + + Auto-Type - KeePassX + 自動入力 - KeePassX + + + Couldn't find an entry that matches the window title: + + + + + AutoTypeAssociationsModel + + Window + ウインドウ + + + Sequence + + + + Default sequence + + + + + AutoTypeSelectDialog + + Auto-Type - KeePassX + 自動入力 - KeePassX + + + Select entry to Auto-Type: + + + + + ChangeMasterKeyWidget + + Password + パスワード + + + Enter password: + パスワードを入力: + + + Repeat password: + パスワードを再入力: + + + Key file + キーファイル + + + Browse + 参照 + + + Create + 作成 + + + Key files + キーファイル + + + All files + 全てのファイル + + + Create Key File... + キーファイルを作成... + + + Error + エラー + + + Unable to create Key File : + キーファイルを作成できませんでした: + + + Select a key file + キーファイルを選択 + + + Question + 質問 + + + Do you really want to use an empty string as password? + 本当に空のパスワード文字列で使いますか? + + + Different passwords supplied. + + + + Failed to set key file + + + + Failed to set %1 as the Key file: +%2 + + + + + DatabaseOpenWidget + + Enter master key + マスターキーの入力 + + + Key File: + キーファイル: + + + Password: + パスワード: + + + Browse + 参照 + + + Error + エラー + + + Unable to open the database. + データベースを開けませんでした。 + + + Can't open key file + キーファイルを開けませんでした。 + + + All files + 全てのファイル + + + Key files + キーファイル + + + Select key file + キーファイルを選択 + + + + DatabaseSettingsWidget + + Database name: + データベース名: + + + Database description: + データベースの概要: + + + Transform rounds: + 変換回数: + + + Default username: + ユーザー名の初期値: + + + Use recycle bin: + ゴミ箱を使う: + + + MiB + MiB + + + Benchmark + ベンチマーク + + + Max. history items: + 最大履歴数: + + + Max. history size: + 最大履歴データサイズ: + + + + DatabaseTabWidget + + Root + + + + KeePass 2 Database + KeePass 2 データベース + + + All files + 全てのファイル + + + Open database + データベースを開く + + + Warning + 警告 + + + File not found! + ファイルが見つかりません! + + + Open KeePass 1 database + KeePass 1 データベースを開く + + + KeePass 1 database + KeePass 1 データベース + + + All files (*) + 全てのファイル (*) + + + Close? + 閉じますか? + + + Save changes? + 変更を保存しますか? + + + "%1" was modified. +Save changes? + "%1" は編集されています。 +変更を保存しますか? + + + Error + エラー + + + Writing the database failed. + データベースが保存できませんでした。 + + + Save database as + データベースを別名で保存 + + + New database + 新しいデータベース + + + locked + ロック済み + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + 開こうとしたデータベースは別のKeePassXプログラムからロックされています。 +とにかく開きますか? データベースを読み取り専用で開きます。 + + + Lock database + データベースをロックする + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + + + + This database has never been saved. +You can save the database or stop locking it. + + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + + + + "%1" is in edit mode. +Discard changes and close anyway? + + + + Export database to CSV file + + + + CSV file + + + + Writing the CSV file failed. + + + + + DatabaseWidget + + Change master key + マスターキーを変更する + + + Delete entry? + エントリーを削除してよいですか? + + + Do you really want to delete the entry "%1" for good? + + + + Delete entries? + 複数のエントリーを削除してよいですか? + + + Do you really want to delete %1 entries for good? + + + + Move entries to recycle bin? + エントリーをゴミ箱に移しますか? + + + Do you really want to move %n entry(s) to the recycle bin? + %n個()のエントリーをゴミ箱に移してもよいですか? + + + Delete group? + グループを削除してよいですか? + + + Do you really want to delete the group "%1" for good? + グループ "%1" を完全に削除しますがよろしいですか? + + + Current group + 現在のグループ + + + Error + エラー + + + Unable to calculate master key + マスターキーを計算できませんでした + + + + EditEntryWidget + + Entry + エントリー + + + Advanced + 詳細設定 + + + Icon + アイコン + + + Auto-Type + 自動入力 + + + Properties + プロパティ + + + History + 履歴 + + + Entry history + エントリーの履歴 + + + Add entry + エントリーを追加 + + + Edit entry + エントリーを編集 + + + Error + エラー + + + Different passwords supplied. + + + + New attribute + 新しい属性 + + + Select file + ファイルを選択 + + + Unable to open file + ファイルを開けませんでした + + + Save attachment + 添付を保存する + + + Unable to save the attachment: + + 添付を保存できませんでした: + + + + Tomorrow + 明日 + + + %n week(s) + %s週間() + + + %n month(s) + %nヶ月() + + + 1 year + 1年 + + + + EditEntryWidgetAdvanced + + Additional attributes + 追加属性 + + + Add + 追加 + + + Edit + 編集 + + + Remove + 削除 + + + Attachments + 添付ファイル + + + Save + 保存 + + + Open + 開く + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + エントリーの自動入力を有効にする + + + Inherit default Auto-Type sequence from the group + 自動入力手順をグループから引き継ぐ + + + Use custom Auto-Type sequence: + カスタムの自動入力手順を使う + + + + + + + + + - + - + + + Window title: + ウインドウタイトル: + + + Use default sequence + デフォルトの手順を使う + + + Set custom sequence: + カスタムの手順を入力: + + + + EditEntryWidgetHistory + + Show + 表示 + + + Restore + 復元 + + + Delete + 削除 + + + Delete all + 全て削除 + + + + EditEntryWidgetMain + + Title: + タイトル: + + + Username: + ユーザ名 + + + Password: + パスワード: + + + Repeat: + パスワード確認: + + + Gen. + 生成 + + + URL: + URL: + + + Expires + 期限 + + + Presets + プリセット + + + Notes: + メモ: + + + + EditGroupWidget + + Group + グループ + + + Icon + アイコン + + + Properties + プロパティ + + + Add group + グループの追加 + + + Edit group + グループの編集 + + + Enable + 有効 + + + Disable + 無効 + + + Inherit from parent group (%1) + 親グループ "(%1)" から引き継ぐ + + + + EditGroupWidgetMain + + Name + グループ名 + + + Notes + メモ + + + Expires + 期限 + + + Search + 検索 + + + Auto-type + 自動入力 + + + Use default auto-type sequence of parent group + 親グループのデフォルトの自動入力手順を使う + + + Set default auto-type sequence + デフォルトの自動入力手順をセット + + + + EditWidgetIcons + + Use default icon + デフォルトアイコンから選択 + + + Use custom icon + カスタムアイコンから選択 + + + Add custom icon + カスタムアイコンを追加 + + + Delete custom icon + カスタムアイコンを削除 + + + Images + 画像 + + + All files + 全てのファイル + + + Select Image + 画像を選択 + + + Can't delete icon! + アイコンを削除できません! + + + Can't delete icon. Still used by %n item(s). + %s個のアイテム()から使われているので、アイコンを削除できません。 + + + + EditWidgetProperties + + Created: + 作成日時: + + + Modified: + 編集日時: + + + Accessed: + アクセス日時: + + + Uuid: + UUID: + + + + EntryAttributesModel + + Name + + + + + EntryHistoryModel + + Last modified + 最終更新日時 + + + Title + タイトル + + + Username + ユーザー名 + + + URL + URL + + + + EntryModel + + Group + グループ + + + Title + タイトル + + + Username + ユーザー名 + + + URL + URL + + + + Group + + Recycle Bin + ゴミ箱 + + + + KeePass1OpenWidget + + Import KeePass1 database + KeePass1 データベースをインポートする + + + Error + エラー + + + Unable to open the database. + データベースを開けませんでした。 + + + + KeePass1Reader + + Unable to read keyfile. + キーファイルを読み込めませんでした。 + + + Not a KeePass database. + KeePassデータベースではありません。 + + + Unsupported encryption algorithm. + サポートしていない暗号化アルゴリズムです。 + + + Unsupported KeePass database version. + サポートしていないバージョンのKeePassデータベースです。 + + + Root + Root + + + Unable to calculate master key + マスターキーを計算できませんでした + + + + KeePass2Reader + + Not a KeePass database. + KeePassデータベースではありません。 + + + Unsupported KeePass database version. + サポートしていないバージョンのKeePassデータベースです。 + + + Wrong key or database file is corrupt. + キーが間違っているかデータベースファイルが破損しています。 + + + Unable to calculate master key + マスターキーを計算できません + + + + Main + + Fatal error while testing the cryptographic functions. + 暗号化機能のテスト中に致命的なエラーが発生しました。 + + + KeePassX - Error + KeePassX - エラー + + + + MainWindow + + Database + データベース + + + Recent databases + 最近使ったデータベース + + + Help + ヘルプ + + + Entries + エントリー + + + Copy attribute to clipboard + クリップボードにコピーする + + + Groups + グループ + + + View + 表示 + + + Quit + 終了 + + + About + このソフトウェアについて + + + Open database + データベースを開く + + + Save database + データベースを保存 + + + Close database + データベースを閉じる + + + New database + 新規データベース + + + Add new entry + 新規エントリーの追加 + + + View/Edit entry + エントリーの表示/編集 + + + Delete entry + エントリーの削除 + + + Add new group + 新規グループの追加 + + + Edit group + グループの編集 + + + Delete group + グループの削除 + + + Save database as + ファイル名をつけてデータベースを保存 + + + Change master key + マスターキーを変更 + + + Database settings + データベースの設定 + + + Import KeePass 1 database + KeePass1 データベースをインポートする + + + Clone entry + エントリーの複製 + + + Find + 検索 + + + Copy username to clipboard + ユーザー名をコピー + + + Copy password to clipboard + パスワードをコピー + + + Settings + 設定 + + + Perform Auto-Type + 自動入力の実行 + + + Open URL + URLを開く + + + Lock databases + データベースをロック + + + Title + タイトル + + + URL + URL + + + Notes + メモ + + + Show toolbar + ツールバーを表示 + + + read-only + 読み取り専用 + + + Toggle window + + + + Tools + ツール + + + Copy username + + + + Copy password + + + + Export to CSV file + + + + + PasswordGeneratorWidget + + Password: + パスワード: + + + Length: + 文字数: + + + Character Types + 文字種 + + + Upper Case Letters + 大文字 + + + Lower Case Letters + 小文字 + + + Numbers + 数字 + + + Special Characters + 特殊な文字 + + + Exclude look-alike characters + よく似た文字を除外する + + + Ensure that the password contains characters from every group + 使用する文字種の文字が必ず含まれるようにする + + + Accept + 適用 + + + + QCommandLineParser + + Displays version information. + バージョン情報を表示する + + + Displays this help. + このヘルプを表示する + + + Unknown option '%1'. + '%1' は不明なオプションです。 + + + Unknown options: %1. + %1 は不明なオプションです。 + + + Missing value after '%1'. + '%1' の後に値が見つかりません。 + + + Unexpected value after '%1'. + '%1' の後に予期しない値があります。 + + + [options] + [オプション] + + + Usage: %1 + 使い方: %1 + + + Options: + オプション: + + + Arguments: + 引数: + + + + QSaveFile + + Existing file %1 is not writable + 存在するファイル %1 は書き込みできません。 + + + Writing canceled by application + アプリケーションにより書き込みがキャンセルされました + + + Partial write. Partition full? + + + + + QtIOCompressor + + Internal zlib error when compressing: + 圧縮時に内部zlibエラーが発生しました + + + Error writing to underlying device: + 基本デバイスへの書き込み時にエラーが発生しました: + + + Error opening underlying device: + 基本デバイスを開く時にエラーが発生しました: + + + Error reading data from underlying device: + 基本デバイスから読み込み時にエラーが発生しました: + + + Internal zlib error when decompressing: + 解凍時に内部zlibエラーが発生しました + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + zlibの現在のバージョンがgzip形式をサポートしていません。 + + + Internal zlib error: + 内部のzlibエラー: + + + + SearchWidget + + Find: + 検索: + + + Case sensitive + 大文字と小文字を区別 + + + Current group + 現在のグループ + + + Root group + 全て + + + + SettingsWidget + + Application Settings + アプリケーション設定 + + + General + 一般 + + + Security + セキュリティ + + + + SettingsWidgetGeneral + + Remember last databases + 最近使用したデータベースを記憶する + + + Open previous databases on startup + KeePassX起動時に前回使用したデータベースを開く + + + Automatically save on exit + 終了時に自動的に保存する + + + Automatically save after every change + 変更するごとに自動的に保存 + + + Minimize when copying to clipboard + クリップボードにコピーしたら最小化 + + + Use group icon on entry creation + エントリーを作成したらグループのアイコンを使う + + + Global Auto-Type shortcut + 全体の自動入力ショートカット + + + Use entry title to match windows for global auto-type + + + + Language + 言語 + + + Show a system tray icon + システムトレイアイコンを表示 + + + Hide window to system tray when minimized + + + + Remember last key files + 最後のキーファイルを記憶 + + + + SettingsWidgetSecurity + + Clear clipboard after + 次の時間が過ぎたらクリップボードを消去 + + + sec + + + + Lock databases after inactivity of + 未操作の時間が続いたらデータベースをロック + + + Show passwords in cleartext by default + パスワードはデフォルトで平文表示にする + + + Always ask before performing auto-type + 自動入力の実行前に常に確認する + + + + UnlockDatabaseWidget + + Unlock database + データベースのロックを解除 + + + + WelcomeWidget + + Welcome! + ようこそ! + + + + main + + KeePassX - cross-platform password manager + KeePassX - クロスプラットフォーム パスワードマネージャー + + + filename of the password database to open (*.kdbx) + 開くパスワードデータベースのファイル名 (*.kdbx) + + + path to a custom config file + + + + password of the database (DANGEROUS!) + データベースのパスワード (危険!) + + + key file of the database + データベースのキーファイル + + + \ No newline at end of file diff --git a/share/translations/keepassx_ko.ts b/share/translations/keepassx_ko.ts new file mode 100644 index 00000000..23911868 --- /dev/null +++ b/share/translations/keepassx_ko.ts @@ -0,0 +1,1284 @@ + + + AboutDialog + + About KeePassX + KeePassX 정보 + + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + KeePassX는 GNU General Public License(GPL) 버전 2 혹은 버전 3(선택적)으로 배포됩니다. + + + Revision + 리비전 + + + + AutoType + + Auto-Type - KeePassX + 자동 입력 - KeePassX + + + Couldn't find an entry that matches the window title: + 창 제목과 일치하는 항목을 찾을 수 없습니다: + + + + AutoTypeAssociationsModel + + Window + + + + Sequence + 시퀀스 + + + Default sequence + 기본 시퀀스 + + + + AutoTypeSelectDialog + + Auto-Type - KeePassX + 자동 입력 - KeePassX + + + Select entry to Auto-Type: + 자동으로 입력할 항목 선택: + + + + ChangeMasterKeyWidget + + Password + 암호 + + + Enter password: + 암호 입력: + + + Repeat password: + 암호 확인: + + + Key file + 키 파일 + + + Browse + 찾아보기 + + + Create + 만들기 + + + Key files + 키 파일 + + + All files + 모든 파일 + + + Create Key File... + 키 파일 만들기... + + + Error + 오류 + + + Unable to create Key File : + 키 파일을 만들 수 없습니다: + + + Select a key file + 키 파일 선택 + + + Question + 질문 + + + Do you really want to use an empty string as password? + 빈 문자열을 암호로 사용하시겠습니까? + + + Different passwords supplied. + 다른 암호를 입력하였습니다. + + + Failed to set key file + 키 파일을 설정할 수 없음 + + + Failed to set %1 as the Key file: +%2 + %1을(를) 키 파일로 설정할 수 없습니다: %2 + + + + DatabaseOpenWidget + + Enter master key + 마스터 키 입력 + + + Key File: + 키 파일: + + + Password: + 암호: + + + Browse + 찾아보기 + + + Error + 오류 + + + Unable to open the database. + 데이터베이스를 열 수 없습니다. + + + Can't open key file + 키 파일을 열 수 없음 + + + All files + 모든 파일 + + + Key files + 키 파일 + + + Select key file + 키 파일 선택 + + + + DatabaseSettingsWidget + + Database name: + 데이터베이스 이름: + + + Database description: + 데이터베이스 설명: + + + Transform rounds: + 변환 횟수: + + + Default username: + 기본 사용자 이름: + + + Use recycle bin: + 휴지통 사용: + + + MiB + MiB + + + Benchmark + 벤치마크 + + + Max. history items: + 최대 과거 항목 수: + + + Max. history size: + 최대 과거 항목 크기: + + + + DatabaseTabWidget + + Root + 루트 + + + KeePass 2 Database + KeePass 2 데이터베이스 + + + All files + 모든 파일 + + + Open database + 데이터베이스 열기 + + + Warning + 경고 + + + File not found! + 파일을 찾을 수 없습니다! + + + Open KeePass 1 database + KeePass 1 데이터베이스 열기 + + + KeePass 1 database + KeePass 1 데이터베이스 + + + All files (*) + 모든 파일 (*) + + + Close? + 닫기 확인? + + + Save changes? + 변경 사항 저장 확인? + + + "%1" was modified. +Save changes? + "%1"이(가) 변경되었습니다. 저장하시겠습니까? + + + Error + 오류 + + + Writing the database failed. + 데이터베이스에 쓸 수 없습니다. + + + Save database as + 다른 이름으로 데이터베이스 저장 + + + New database + 새 데이터베이스 + + + locked + 잠김 + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + 열려고 하는 데이터베이스를 다른 KeePassX 인스턴스에서 잠갔습니다. +그래도 여시겠습니까? 읽기 전용으로 열 수도 있습니다. + + + Lock database + 데이터베이스 잠금 + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + 데이터베이스를 편집하고 있어서 잠글 수 없습니다. +취소를 눌러서 변경 사항을 저장하거나 무시하십시오. + + + This database has never been saved. +You can save the database or stop locking it. + 이 데이터베이스가 저장되지 않았습니다. +데이터베이스를 저장하거나 잠금을 풀 수 있습니다. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + 데이터베이스가 수정되었습니다. +잠그기 전에 데이터베이스를 저장하시겠습니까? +저장하지 않은 변경 사항은 손실됩니다. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1"이(가) 현재 편집 모드입니다. +변경 사항을 무시하고 닫으시겠습니까? + + + Export database to CSV file + 데이터베이스를 CSV 파일로 내보내기 + + + CSV file + CSV 파일 + + + Writing the CSV file failed. + CSV 파일에 기록할 수 없습니다. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + 저장하려고 하는 데이터베이스를 다른 KeePassX 인스턴스에서 잠갔습니다. +그래도 저장하시겠습니까? + + + + DatabaseWidget + + Change master key + 마스터 키 변경 + + + Delete entry? + 항목을 삭제하시겠습니까? + + + Do you really want to delete the entry "%1" for good? + 정말 항목 "%1"을(를) 삭제하시겠습니까? + + + Delete entries? + 항목을 삭제하시겠습니까? + + + Do you really want to delete %1 entries for good? + 정말 항목 %1개를 삭제하시겠습니까? + + + Move entries to recycle bin? + 항목을 휴지통으로 이동하시겠습니까? + + + Do you really want to move %n entry(s) to the recycle bin? + 항목 %n개를 휴지통으로 이동하시겠습니까? + + + Delete group? + 그룹을 삭제하시겠습니까? + + + Do you really want to delete the group "%1" for good? + 정말 그룹 "%1"을(를) 삭제하시겠습니까? + + + Current group + 현재 그룹 + + + Error + 오류 + + + Unable to calculate master key + 마스터 키를 계산할 수 없음 + + + + EditEntryWidget + + Entry + 항목 + + + Advanced + 고급 + + + Icon + 아이콘 + + + Auto-Type + 자동 입력 + + + Properties + 속성 + + + History + 과거 기록 + + + Entry history + 항목 과거 기록 + + + Add entry + 항목 추가 + + + Edit entry + 항목 편집 + + + Error + 오류 + + + Different passwords supplied. + 다른 암호를 입력하였습니다. + + + New attribute + 새 속성 + + + Select file + 파일 선택 + + + Unable to open file + 파일을 열 수 없습니다 + + + Save attachment + 첨부 항목 저장 + + + Unable to save the attachment: + + 첨부 항목을 저장할 수 없습니다: + + + Tomorrow + 내일 + + + %n week(s) + %n주 + + + %n month(s) + %n개월 + + + 1 year + 1년 + + + + EditEntryWidgetAdvanced + + Additional attributes + 추가 속성 + + + Add + 추가 + + + Edit + 편집 + + + Remove + 삭제 + + + Attachments + 첨부 + + + Save + 저장 + + + Open + 열기 + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + 이 항목 자동 입력 사용 + + + Inherit default Auto-Type sequence from the group + 그룹의 기본 자동 입력 시퀀스 사용 + + + Use custom Auto-Type sequence: + 사용자 정의 자동 입력 시퀀스 사용: + + + + + + + + + - + - + + + Window title: + 창 제목: + + + Use default sequence + 기본 시퀀스 사용 + + + Set custom sequence: + 사용자 정의 시퀀스 설정: + + + + EditEntryWidgetHistory + + Show + 보이기 + + + Restore + 복원 + + + Delete + 삭제 + + + Delete all + 모두 삭제 + + + + EditEntryWidgetMain + + Title: + 제목: + + + Username: + 사용자 이름: + + + Password: + 암호: + + + Repeat: + 암호 확인: + + + Gen. + 생성 + + + URL: + URL: + + + Expires + 만료 기간 + + + Presets + 사전 설정 + + + Notes: + 메모: + + + + EditGroupWidget + + Group + 그룹 + + + Icon + 아이콘 + + + Properties + 속성 + + + Add group + 그룹 추가 + + + Edit group + 그룹 편집 + + + Enable + 활성화 + + + Disable + 비활성화 + + + Inherit from parent group (%1) + 부모 그룹에서 상속(%1) + + + + EditGroupWidgetMain + + Name + 이름 + + + Notes + 메모 + + + Expires + 만료 기간 + + + Search + 찾기 + + + Auto-type + 자동 입력 + + + Use default auto-type sequence of parent group + 부모 그룹의 기본 자동 입력 시퀀스 사용 + + + Set default auto-type sequence + 기본 자동 입력 시퀀스 설정 + + + + EditWidgetIcons + + Use default icon + 기본 아이콘 사용 + + + Use custom icon + 사용자 정의 아이콘 사용 + + + Add custom icon + 사용자 정의 아이콘 추가 + + + Delete custom icon + 사용자 정의 아이콘 삭제 + + + Images + 그림 + + + All files + 모든 파일 + + + Select Image + 그림 선택 + + + Can't delete icon! + 아이콘을 삭제할 수 없습니다! + + + Can't delete icon. Still used by %n item(s). + 아이콘을 삭제할 수 없습니다. 항목 %n개에서 사용 중입니다. + + + + EditWidgetProperties + + Created: + 만든 날짜: + + + Modified: + 수정한 날짜: + + + Accessed: + 접근한 날짜: + + + Uuid: + UUID: + + + + EntryAttributesModel + + Name + 이름 + + + + EntryHistoryModel + + Last modified + 마지막 수정 + + + Title + 제목 + + + Username + 사용자 이름 + + + URL + URL + + + + EntryModel + + Group + 그룹 + + + Title + 제목 + + + Username + 사용자 이름 + + + URL + URL + + + + Group + + Recycle Bin + 휴지통 + + + + KeePass1OpenWidget + + Import KeePass1 database + KeePass1 데이터베이스 가져오기 + + + Error + 오류 + + + Unable to open the database. + 데이터베이스를 열 수 없습니다. + + + + KeePass1Reader + + Unable to read keyfile. + 키 파일을 읽을 수 없습니다. + + + Not a KeePass database. + KeePass 데이터베이스가 아닙니다. + + + Unsupported encryption algorithm. + 지원하지 않는 암호화 알고리즘입니다. + + + Unsupported KeePass database version. + 지원하지 않는 KeePass 데이터베이스 버전입니다. + + + Root + 루트 + + + Unable to calculate master key + 마스터 키를 계산할 수 없음 + + + + KeePass2Reader + + Not a KeePass database. + KeePass 데이터베이스가 아닙니다. + + + Unsupported KeePass database version. + 지원하지 않는 KeePass 데이터베이스 버전입니다. + + + Wrong key or database file is corrupt. + 키가 잘못되었거나 데이터베이스가 손상되었습니다. + + + Unable to calculate master key + 마스터 키를 계산할 수 없습니다 + + + + Main + + Fatal error while testing the cryptographic functions. + 암호화 함수를 시험하는 중 오류가 발생하였습니다. + + + KeePassX - Error + KeePassX - 오류 + + + + MainWindow + + Database + 데이터베이스 + + + Recent databases + 최근 데이터베이스 + + + Help + 도움말 + + + Entries + 항목 + + + Copy attribute to clipboard + 클립보드에 속성 복사 + + + Groups + 그룹 + + + View + 보기 + + + Quit + 끝내기 + + + About + 정보 + + + Open database + 데이터베이스 열기 + + + Save database + 데이터베이스 저장 + + + Close database + 데이터베이스 닫기 + + + New database + 새 데이터베이스 + + + Add new entry + 새 항목 추가 + + + View/Edit entry + 항목 보기/편집 + + + Delete entry + 항목 삭제 + + + Add new group + 새 그룹 추가 + + + Edit group + 그룹 편집 + + + Delete group + 그룹 삭제 + + + Save database as + 다른 이름으로 데이터베이스 저장 + + + Change master key + 마스터 키 변경 + + + Database settings + 데이터베이스 설정 + + + Import KeePass 1 database + KeePass 1 데이터베이스 가져오기 + + + Clone entry + 항목 복제 + + + Find + 찾기 + + + Copy username to clipboard + 클립보드에 사용자 이름 복사 + + + Copy password to clipboard + 클립보드에 암호 복사 + + + Settings + 설정 + + + Perform Auto-Type + 자동 입력 실행 + + + Open URL + URL 열기 + + + Lock databases + 데이터베이스 잠금 + + + Title + 제목 + + + URL + URL + + + Notes + 메모 + + + Show toolbar + 도구 모음 보이기 + + + read-only + 읽기 전용 + + + Toggle window + 창 전환 + + + Tools + 도구 + + + Copy username + 사용자 이름 복사 + + + Copy password + 암호 복사 + + + Export to CSV file + CSV 파일로 내보내기 + + + + PasswordGeneratorWidget + + Password: + 암호: + + + Length: + 길이: + + + Character Types + 문자 종류 + + + Upper Case Letters + 대문자 + + + Lower Case Letters + 소문자 + + + Numbers + 숫자 + + + Special Characters + 특수 문자 + + + Exclude look-alike characters + 비슷하게 생긴 문자 제외 + + + Ensure that the password contains characters from every group + 모든 그룹에서 최소 1글자 이상 포함 + + + Accept + 사용 + + + + QCommandLineParser + + Displays version information. + 버전 정보를 표시합니다. + + + Displays this help. + 이 도움말을 표시합니다. + + + Unknown option '%1'. + 알 수 없는 옵션 '%1'. + + + Unknown options: %1. + 알 수 없는 옵션 '%1'. + + + Missing value after '%1'. + '%1' 다음에 값이 없습니다. + + + Unexpected value after '%1'. + '%1' 다음에 예상하지 못한 값이 왔습니다. + + + [options] + [옵션] + + + Usage: %1 + 사용 방법: %1 + + + Options: + 옵션: + + + Arguments: + 인자: + + + + QSaveFile + + Existing file %1 is not writable + 존재하는 파일 %1에 기록할 수 없음 + + + Writing canceled by application + 프로그램에서 쓰기 작업 취소함 + + + Partial write. Partition full? + 일부분만 기록되었습니다. 파티션이 가득 찼습니까? + + + + QtIOCompressor + + Internal zlib error when compressing: + 압축 중 내부 zlib 오류 발생: + + + Error writing to underlying device: + 장치에 기록하는 중 오류 발생: + + + Error opening underlying device: + 장치를 여는 중 오류 발생: + + + Error reading data from underlying device: + 장치에서 읽는 중 오류 발생: + + + Internal zlib error when decompressing: + 압축 푸는 중 내부 zlib 오류 발생: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + 이 버전의 zlib에서 gzip 형식을 지원하지 않습니다. + + + Internal zlib error: + 내부 zlib 오류: + + + + SearchWidget + + Find: + 찾기: + + + Case sensitive + 대소문자 구분 + + + Current group + 현재 그룹 + + + Root group + 루트 그룹 + + + + SettingsWidget + + Application Settings + 프로그램 설정 + + + General + 일반 + + + Security + 보안 + + + + SettingsWidgetGeneral + + Remember last databases + 마지막 데이터베이스 기억 + + + Open previous databases on startup + 시작할 때 이전 데이터베이스 열기 + + + Automatically save on exit + 끝낼 때 자동 저장 + + + Automatically save after every change + 항목을 변경할 때 자동 저장 + + + Minimize when copying to clipboard + 클립보드에 복사할 때 최소화 + + + Use group icon on entry creation + 항목을 만들 때 그룹 아이콘 사용 + + + Global Auto-Type shortcut + 전역 자동 입력 단축키 + + + Use entry title to match windows for global auto-type + 전역 자동 입력 시 항목 제목과 일치하는 창 찾기 + + + Language + 언어 + + + Show a system tray icon + 시스템 트레이 아이콘 표시 + + + Hide window to system tray when minimized + 시스템 트레이로 최소화 + + + Remember last key files + 마지막 키 파일 기억 + + + + SettingsWidgetSecurity + + Clear clipboard after + 다음 시간 이후 클립보드 비우기 + + + sec + + + + Lock databases after inactivity of + 다음 시간 동안 활동이 없을 때 데이터베이스 잠금 + + + Show passwords in cleartext by default + 기본값으로 암호를 평문으로 표시 + + + Always ask before performing auto-type + 자동으로 입력하기 전에 항상 묻기 + + + + UnlockDatabaseWidget + + Unlock database + 데이터베이스 잠금 해제 + + + + WelcomeWidget + + Welcome! + 환영합니다! + + + + main + + KeePassX - cross-platform password manager + KeePassX - 크로스 플랫폼 암호 관리자 + + + filename of the password database to open (*.kdbx) + 열 암호 데이터베이스 파일 이름 (*.kdbx) + + + path to a custom config file + 사용자 정의 설정 파일 경로 + + + key file of the database + 데이터베이스 키 파일 + + + \ No newline at end of file diff --git a/share/translations/keepassx_lt.ts b/share/translations/keepassx_lt.ts new file mode 100644 index 00000000..63b46655 --- /dev/null +++ b/share/translations/keepassx_lt.ts @@ -0,0 +1,1287 @@ + + + AboutDialog + + About KeePassX + Apie KeePassX + + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + KeePassX yra platinama GNU Bendrosios Viešosios Licencijos (GPL) versijos 2 arba (jūsų pasirinkimu) versijos 3 sąlygomis. + + + Revision + Poversijis + + + + AutoType + + Auto-Type - KeePassX + Automatinis Rinkimas - KeePassX + + + Couldn't find an entry that matches the window title: + Nepavyko rasti įrašo, kuris atitiktų lango antraštę: + + + + AutoTypeAssociationsModel + + Window + Langas + + + Sequence + Seka + + + Default sequence + Numatytoji seka + + + + AutoTypeSelectDialog + + Auto-Type - KeePassX + Automatinis Rinkimas - KeePassX + + + Select entry to Auto-Type: + Pasirinkite įrašą Automatiniam Rinkimui: + + + + ChangeMasterKeyWidget + + Password + Slaptažodis + + + Enter password: + Įveskite slaptažodį: + + + Repeat password: + Pakartokite slaptažodį: + + + Key file + Rakto failas + + + Browse + Naršyti + + + Create + Kurti + + + Key files + Rakto failai + + + All files + Visi failai + + + Create Key File... + Sukurti Rakto Failą... + + + Error + Klaida + + + Unable to create Key File : + Nepavyko sukurti Rakto Failo : + + + Select a key file + Pasirinkite rakto failą + + + Question + Klausimas + + + Do you really want to use an empty string as password? + Ar tikrai norite naudoti tuščią eilutę kaip slaptažodį? + + + Different passwords supplied. + Pateikti skirtingi slaptažodžiai. + + + Failed to set key file + Nepavyko nustatyti rakto failo + + + Failed to set %1 as the Key file: +%2 + Nepavyko nustatyti %1 kaip Rakto failą: +%2 + + + + DatabaseOpenWidget + + Enter master key + Įveskite pagrindinį raktą + + + Key File: + Rakto Failas: + + + Password: + Slaptažodis: + + + Browse + Naršyti + + + Error + Klaida + + + Unable to open the database. + Nepavyko atverti duomenų bazės. + + + Can't open key file + Nepavyksta atverti rakto failo + + + All files + Visi failai + + + Key files + Rakto failai + + + Select key file + Pasirinkite rakto failą + + + + DatabaseSettingsWidget + + Database name: + Duomenų bazės pavadinimas: + + + Database description: + Duomenų bazės aprašas: + + + Transform rounds: + Pasikeitimo ciklų: + + + Default username: + Numatytasis naudotojo vardas: + + + Use recycle bin: + Naudoti šiukšlinę: + + + MiB + MiB + + + Benchmark + Našumo testas + + + Max. history items: + Daugiausia istorijos elementų: + + + Max. history size: + Didžiausias istorijos dydis: + + + + DatabaseTabWidget + + Root + Šaknis + + + KeePass 2 Database + KeePass 2 Duomenų Bazė + + + All files + Visi failai + + + Open database + Atverti duomenų bazę + + + Warning + Įspėjimas + + + File not found! + Failas nerastas! + + + Open KeePass 1 database + Atverkite KeePass 1 duomenų bazę + + + KeePass 1 database + KeePass 1 duomenų bazė + + + All files (*) + Visi failai (*) + + + Close? + Užverti? + + + Save changes? + Įrašyti pakeitimus? + + + "%1" was modified. +Save changes? + "%1" buvo pakeista. +Įrašyti pakeitimus? + + + Error + Klaida + + + Writing the database failed. + Duomenų bazės rašymas nepavyko. + + + Save database as + Įrašyti duomenų bazę kaip + + + New database + Nauja duomenų bazė + + + locked + užrakinta + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Duomenų bazė, kurią bandote atverti, yra užrakinta kito KeePassX egzemplioriaus. +Ar vis tiek norite ją atverti? Kitu atveju duomenų bazė bus atverta tik skaitymui. + + + Lock database + Užrakinti duomenų bazę + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Nepavyksta užrakinti duomenų bazės, kadangi šiuo metu ją redaguojate. +Spauskite atšaukti, kad užbaigtumėte savo pakeitimus arba juos atmestumėte. + + + This database has never been saved. +You can save the database or stop locking it. + Ši duomenų bazė niekada nebuvo įrašyta. +Galite duomenų bazę įrašyti arba atsisakyti ją užrakinti. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Ši duomenų bazė buvo modifikuota. +Ar prieš užrakinant, norite įrašyti duomenų bazę? +Kitu atveju jūsų pakeitimai bus prarasti. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" yra redagavimo veiksenoje. +Vis tiek atmesti pakeitimus ir užverti? + + + Export database to CSV file + Eksportuoti duomenų bazę į CSV failą + + + CSV file + CSV failas + + + Writing the CSV file failed. + CSV failo įrašymas nepavyko. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + Duomenų bazė, kurią bandote įrašyti yra užrakinta kito KeePassX programos egzemplioriaus. +Ar vis tiek norite ją įrašyti? + + + + DatabaseWidget + + Change master key + Pakeisti pagrindinį raktą + + + Delete entry? + Ištrinti įrašą? + + + Do you really want to delete the entry "%1" for good? + Ar tikrai norite ištrinti įrašą "%1"? + + + Delete entries? + Ištrinti įrašus? + + + Do you really want to delete %1 entries for good? + Ar tikrai norite ištrinti %1 įrašų? + + + Move entries to recycle bin? + Perkelti įrašus į šiukšlinę? + + + Do you really want to move %n entry(s) to the recycle bin? + Ar tikrai norite perkelti %n įrašą į šiukšlinę?Ar tikrai norite perkelti %n įrašus į šiukšlinę?Ar tikrai norite perkelti %n įrašų į šiukšlinę? + + + Delete group? + Ištrinti grupę? + + + Do you really want to delete the group "%1" for good? + Ar tikrai norite ištrinti grupę "%1"? + + + Current group + Esama grupė + + + Error + Klaida + + + Unable to calculate master key + Nepavyko apskaičiuoti pagrindinio rakto + + + + EditEntryWidget + + Entry + Įrašas + + + Advanced + Išplėstiniai + + + Icon + Piktograma + + + Auto-Type + Automatinis Rinkimas + + + Properties + Savybės + + + History + Istorija + + + Entry history + Įrašo istorija + + + Add entry + Pridėti įrašą + + + Edit entry + Keisti įrašą + + + Error + Klaida + + + Different passwords supplied. + Pateikti skirtingi slaptažodžiai. + + + New attribute + Naujas požymis + + + Select file + Pasirinkite failą + + + Unable to open file + Nepavyko atverti failo + + + Save attachment + Įrašyti priedą + + + Unable to save the attachment: + + Nepavyko įrašyti priedo: + + + + Tomorrow + Rytoj + + + %n week(s) + %n savaitė%n savaitės%n savaičių + + + %n month(s) + %n mėnesis%n mėnesiai%n mėnesių + + + 1 year + 1 metai + + + + EditEntryWidgetAdvanced + + Additional attributes + Papildomi požymiai + + + Add + Pridėti + + + Edit + Keisti + + + Remove + Šalinti + + + Attachments + Priedai + + + Save + Įrašyti + + + Open + Atverti + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + Įjungti šiam įrašui Automatinį Rinkimą + + + Inherit default Auto-Type sequence from the group + Paveldėti numatytąją Automatinio Rinkimo seką iš grupės + + + Use custom Auto-Type sequence: + Naudoti tinkintą Automatinio Rinkimo seka: + + + + + + + + + - + - + + + Window title: + Lango antraštė: + + + Use default sequence + Naudoti numatytąją seką + + + Set custom sequence: + Nustatyti tinkintą seką: + + + + EditEntryWidgetHistory + + Show + Rodyti + + + Restore + Atkurti + + + Delete + Ištrinti + + + Delete all + Ištrinti visus + + + + EditEntryWidgetMain + + Title: + Antraštė: + + + Username: + Naudotojo vardas: + + + Password: + Slaptažodis: + + + Repeat: + Pakartokite: + + + Gen. + Kurti + + + URL: + URL: + + + Expires + Baigia galioti + + + Presets + Parinktys + + + Notes: + Pastabos: + + + + EditGroupWidget + + Group + Grupė + + + Icon + Piktograma + + + Properties + Savybės + + + Add group + Pridėti grupę + + + Edit group + Keisti grupę + + + Enable + Įjungti + + + Disable + Išjungti + + + Inherit from parent group (%1) + Paveldėti iš pirminės grupės (%1) + + + + EditGroupWidgetMain + + Name + Pavadinimas + + + Notes + Pastabos + + + Expires + Baigia galioti + + + Search + Paieška + + + Auto-type + Automatinis rinkimas + + + Use default auto-type sequence of parent group + Naudoti numatytąją pirminės grupės automatinio rinkimo seką + + + Set default auto-type sequence + Nustatyti numatytąją automatinio rinkimo seką + + + + EditWidgetIcons + + Use default icon + Naudoti numatytąją piktogramą + + + Use custom icon + Naudoti tinkintą piktogramą + + + Add custom icon + Pridėti tinkintą piktogramą + + + Delete custom icon + Ištrinti tinkintą piktogramą + + + Images + Paveikslai + + + All files + Visi failai + + + Select Image + Pasirinkite Paveikslą + + + Can't delete icon! + Nepavyksta ištrinti piktogramos! + + + Can't delete icon. Still used by %n item(s). + Nepavyksta ištrinti piktogramos. Vis dar naudojama %n elemento.Nepavyksta ištrinti piktogramos. Vis dar naudojama %n elementų.Nepavyksta ištrinti piktogramos. Vis dar naudojama %n elementų. + + + + EditWidgetProperties + + Created: + Sukurta: + + + Modified: + Keista: + + + Accessed: + Prieiga: + + + Uuid: + Uuid: + + + + EntryAttributesModel + + Name + Pavadinimas + + + + EntryHistoryModel + + Last modified + Paskutinis keitimas + + + Title + Antraštė + + + Username + Naudotojo vardas + + + URL + URL + + + + EntryModel + + Group + Grupė + + + Title + Antraštė + + + Username + Naudotojo vardas + + + URL + URL + + + + Group + + Recycle Bin + Šiukšlinė + + + + KeePass1OpenWidget + + Import KeePass1 database + Importuoti KeePass1 duomenų bazę + + + Error + Klaida + + + Unable to open the database. + Nepavyko atverti duomenų bazės. + + + + KeePass1Reader + + Unable to read keyfile. + Nepavyko perskaityti rakto failo. + + + Not a KeePass database. + Ne KeePass duomenų bazė. + + + Unsupported encryption algorithm. + Nepalaikomas šifravimo algoritmas. + + + Unsupported KeePass database version. + Nepalaikoma KeePass duomenų bazės versija. + + + Root + Šaknis + + + Unable to calculate master key + Nepavyko apskaičiuoti pagrindinio rakto + + + + KeePass2Reader + + Not a KeePass database. + Ne KeePass duomenų bazė. + + + Unsupported KeePass database version. + Nepalaikoma KeePass duomenų bazės versija. + + + Wrong key or database file is corrupt. + Neteisingas raktas arba duomenų bazės failas yra pažeistas. + + + Unable to calculate master key + Nepavyko apskaičiuoti pagrindinio rakto + + + + Main + + Fatal error while testing the cryptographic functions. + Lemtingoji klaida, testuojant šifravimo funkcijas. + + + KeePassX - Error + KeePassX - Klaida + + + + MainWindow + + Database + Duomenų bazė + + + Recent databases + Paskiausios duomenų bazės + + + Help + Pagalba + + + Entries + Įrašai + + + Copy attribute to clipboard + Kopijuoti požymį į iškarpinę + + + Groups + Grupės + + + View + Rodinys + + + Quit + Baigti + + + About + Apie + + + Open database + Atverti duomenų bazę + + + Save database + Įrašyti duomenų bazę + + + Close database + Užverti duomenų bazę + + + New database + Nauja duomenų bazė + + + Add new entry + Pridėti naują įrašą + + + View/Edit entry + Žiūrėti/Keisti įrašą + + + Delete entry + Ištrinti įrašą + + + Add new group + Pridėti naują grupę + + + Edit group + Keisti grupę + + + Delete group + Ištrinti grupę + + + Save database as + Įrašyti duomenų bazę kaip + + + Change master key + Pakeisti pagrindinį raktą + + + Database settings + Duomenų bazės nustatymai + + + Import KeePass 1 database + Importuoti KeePass 1 duomenų bazę + + + Clone entry + Dublikuoti įrašą + + + Find + Rasti + + + Copy username to clipboard + Kopijuoti naudotojo vardą į iškarpinę + + + Copy password to clipboard + Kopijuoti slaptažodį į iškarpinę + + + Settings + Nustatymai + + + Perform Auto-Type + Atlikti Automatinį Rinkimą + + + Open URL + Atverti URL + + + Lock databases + Užrakinti duomenų bazes + + + Title + Antraštė + + + URL + URL + + + Notes + Pastabos + + + Show toolbar + Rodyti įrankių juostą + + + read-only + tik skaitymui + + + Toggle window + Perjungti langą + + + Tools + Įrankiai + + + Copy username + Kopijuoti naudotojo vardą + + + Copy password + Kopijuoti slaptažodį + + + Export to CSV file + Eksportuoti į CSV failą + + + + PasswordGeneratorWidget + + Password: + Slaptažodis: + + + Length: + Ilgis: + + + Character Types + Simbolių Tipai + + + Upper Case Letters + Viršutinio Registro Raidės + + + Lower Case Letters + Apatinio Registro Raidės + + + Numbers + Skaičiai + + + Special Characters + Specialūs Simboliai + + + Exclude look-alike characters + Pašalinti panašiai atrodančius simbolius + + + Ensure that the password contains characters from every group + Užtikrinti, kad slaptažodyje yra simboliai iš kiekvienos grupės + + + Accept + Priimti + + + + QCommandLineParser + + Displays version information. + Rodo versijos informaciją. + + + Displays this help. + Rodo šią pagalbą. + + + Unknown option '%1'. + Nežinoma parinktis "%1". + + + Unknown options: %1. + Nežinomos parinktys: %1. + + + Missing value after '%1'. + Trūksta reikšmės po "%1". + + + Unexpected value after '%1'. + Netikėta reikšmė po "%1". + + + [options] + [parinktys] + + + Usage: %1 + Naudojimas: %1 + + + Options: + Parinktys: + + + Arguments: + Argumentai: + + + + QSaveFile + + Existing file %1 is not writable + Esamas failas %1 nėra įrašomas + + + Writing canceled by application + Programa atšaukė įrašymą + + + Partial write. Partition full? + Dalinis įrašymas. Pilnas skaidinys? + + + + QtIOCompressor + + Internal zlib error when compressing: + Vidinė zlib klaida, glaudinant: + + + Error writing to underlying device: + Klaida, įrašant į bazinį įrenginį: + + + Error opening underlying device: + Klaida, atveriant bazinį įrenginį: + + + Error reading data from underlying device: + Klaida, skaitant iš bazinio įrenginio: + + + Internal zlib error when decompressing: + Vidinė zlib klaida, išskleidžiant: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + Šioje zlib versijoje gzip formatas yra nepalaikomas. + + + Internal zlib error: + Vidinė zlib klaida: + + + + SearchWidget + + Find: + Rasti: + + + Case sensitive + Skiriant raidžių registrą + + + Current group + Esama grupė + + + Root group + Šakninė grupė + + + + SettingsWidget + + Application Settings + Programos Nustatymai + + + General + Bendra + + + Security + Saugumas + + + + SettingsWidgetGeneral + + Remember last databases + Prisiminti paskutines duomenų bazes + + + Open previous databases on startup + Paleidžiant programą, atverti ankstesnes duomenų bazes + + + Automatically save on exit + Išeinant, automatiškai įrašyti + + + Automatically save after every change + Automatiškai įrašyti po kiekvieno pakeitimo + + + Minimize when copying to clipboard + Kopijuojant į iškarpinę, suskleisti langą + + + Use group icon on entry creation + Kuriant įrašus, naudoti grupės piktogramą + + + Global Auto-Type shortcut + Visuotinis Automatinio Rinkimo spartusis klavišas + + + Use entry title to match windows for global auto-type + Naudoti įrašo antraštę, norint sutapatinti langus visuotiniam automatiniam rinkimui + + + Language + Kalba + + + Show a system tray icon + Rodyti sistemos dėklo piktogramą + + + Hide window to system tray when minimized + Suskleidus langą, slėpti jį į sistemos dėklą + + + Remember last key files + Prisiminti paskutinius rakto failus + + + + SettingsWidgetSecurity + + Clear clipboard after + Išvalyti iškarpinę po + + + sec + sek. + + + Lock databases after inactivity of + Užrakinti duomenų bazes, kai kompiuteris neaktyvus + + + Show passwords in cleartext by default + Pagal numatymą, rodyti slaptažodžius atviruoju tekstu + + + Always ask before performing auto-type + Visuomet klausti prieš atliekant automatinį rinkimą + + + + UnlockDatabaseWidget + + Unlock database + Atrakinti duomenų bazę + + + + WelcomeWidget + + Welcome! + Sveiki atvykę! + + + + main + + KeePassX - cross-platform password manager + KeePassX - daugiaplatformė slaptažodžių tvarkytuvė + + + filename of the password database to open (*.kdbx) + norimos atverti slaptažodžių duomenų bazės failo pavadinimas (*.kdbx) + + + path to a custom config file + kelias į tinkintą konfigūracijos failą + + + key file of the database + duomenų bazės rakto failas + + + \ No newline at end of file diff --git a/share/translations/keepassx_nl_NL.ts b/share/translations/keepassx_nl_NL.ts index da376921..86613116 100644 --- a/share/translations/keepassx_nl_NL.ts +++ b/share/translations/keepassx_nl_NL.ts @@ -9,6 +9,10 @@ KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. KeePassX wordt verspreid onder de bepalingen van de GNU General Public License (GPL) versie 2 of (als u wenst) versie 3. + + Revision + Revisie + AutoType @@ -109,6 +113,16 @@ Different passwords supplied. Verschillende wachtwoorden opgegeven. + + Failed to set key file + Niet gelukt het sleutelbestand in te stellen + + + Failed to set %1 as the Key file: +%2 + Niet gelukt %1 als sleutelbestand in te stellen: +%2 + DatabaseOpenWidget @@ -234,12 +248,6 @@ Close? Sluiten? - - "%1" is in edit mode. -Close anyway? - "%1" is in bewerkmodus. -Toch sluiten? - Save changes? Wijzigingen opslaan? @@ -270,6 +278,60 @@ Opslaan? locked vergrendeld + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + De database die u probeert te openen is vergrendeld door een andere instantie van KeePassX. +Wilt u toch doorgaan met openen? U kunt de database ook alleen-lezen openen. + + + Lock database + Database vergrendelen + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Kan de database niet vergrendelen omdat u deze momenteel aan het bewerken bent. +Druk op annuleren om uw wijzigingen aan te passen of gooi de wijzigingen weg. + + + This database has never been saved. +You can save the database or stop locking it. + Deze database is nog niet opgeslagen. +U kunt de database opslaan of het vergrendelen annuleren. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Deze database is gewijzigd. +Wilt u de database opslaan voordat u deze vergrendelt? +Zo nee, dan gaan de wijzigingen verloren. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" is gewijzigd. +Wijzigingen ongedaan maken en doorgaan met sluiten? + + + Export database to CSV file + Database exporteren naar CSV-bestand + + + CSV file + CSV-bestand + + + Writing the CSV file failed. + Schrijven van het CSV-bestand mislukt. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + De database die u op probeert te slaan is vergrendeld door een andere instantie van KeePassX. +Wilt u toch doorgaan met opslaan? + DatabaseWidget @@ -313,6 +375,14 @@ Opslaan? Current group Huidige groep + + Error + Fout + + + Unable to calculate master key + Niet mogelijk om hoofdsleutel te berekenen + EditEntryWidget @@ -425,6 +495,10 @@ Opslaan? Save Opslaan + + Open + Open + EditEntryWidgetAutoType @@ -576,6 +650,14 @@ Opslaan? Auto-type Auto-typen + + Use default auto-type sequence of parent group + Gebruik standaard auto-typevolgorde van bovenliggende groep + + + Set default auto-type sequence + Stel standaard auto-typevolgorde in + EditWidgetIcons @@ -724,6 +806,10 @@ Opslaan? Root Alles + + Unable to calculate master key + Niet mogelijk om hoofdsleutel te berekenen + KeePass2Reader @@ -739,6 +825,10 @@ Opslaan? Wrong key or database file is corrupt. Verkeerde sleutel of corrupte database. + + Unable to calculate master key + Niet mogelijk om hoofdsleutel te berekenen + Main @@ -777,10 +867,6 @@ Opslaan? Groups Groepen - - Extras - Extra's - View Beeld @@ -857,18 +943,10 @@ Opslaan? Find Vind - - Username - Gebruikersnaam - Copy username to clipboard Kopieer gebruikersnaam naar klembord - - Password - Wachtwoord - Copy password to clipboard Kopieer wachtwoord naar klembord @@ -913,6 +991,22 @@ Opslaan? Toggle window Wissel venster + + Tools + Hulpmiddelen + + + Copy username + Gebruikersnaam kopieren + + + Copy password + Wachtwoord kopiëren + + + Export to CSV file + Naar CSV-bestand exporteren + PasswordGeneratorWidget @@ -1093,10 +1187,6 @@ Opslaan? Open previous databases on startup Open vorige databases bij starten - - Mark as modified on expanded state changes - Markeer database als gewijzigd bij wijzigen van de status - Automatically save on exit Automatisch opslaan bij afsluiten @@ -1133,6 +1223,10 @@ Opslaan? Hide window to system tray when minimized Bij minimaliseren enkel icoon in systray tonen + + Remember last key files + Onthoud laatste sleutelbestanden + SettingsWidgetSecurity @@ -1163,14 +1257,6 @@ Opslaan? Unlock database Database ontgrendelen - - Error - Fout - - - Wrong key. - Verkeerd wachtwoord - WelcomeWidget @@ -1193,10 +1279,6 @@ Opslaan? path to a custom config file pad naar een configuratiebestand - - password of the database (DANGEROUS!) - wachtwoord van de database (GEVAARLIJK!) - key file of the database sleutelbestand van de database diff --git a/share/translations/keepassx_pl.ts b/share/translations/keepassx_pl.ts new file mode 100644 index 00000000..ab471029 --- /dev/null +++ b/share/translations/keepassx_pl.ts @@ -0,0 +1,1278 @@ + + + AboutDialog + + About KeePassX + O KeePassX + + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + + + + Revision + Rewizja + + + + AutoType + + Auto-Type - KeePassX + Auto-uzupełnianie - KeePassX + + + Couldn't find an entry that matches the window title: + + + + + AutoTypeAssociationsModel + + Window + Okno + + + Sequence + Swkwencja + + + Default sequence + Domyślna sekwencja + + + + AutoTypeSelectDialog + + Auto-Type - KeePassX + Auto-uzupełnianie - KeePassX + + + Select entry to Auto-Type: + Wybierz wpis do auto-uzupełniania: + + + + ChangeMasterKeyWidget + + Password + Hasło + + + Enter password: + Wprowadź hasło: + + + Repeat password: + Wprowadź ponownie hasło: + + + Key file + Plik klucza + + + Browse + Przeglądaj + + + Create + Stwórz + + + Key files + Pliki kluczy + + + All files + Wszystkie pliki + + + Create Key File... + Utwórz plik klucza + + + Error + Błąd + + + Unable to create Key File : + Nie można utworzyć pliku klucza + + + Select a key file + Wybierz plik z kluczem + + + Question + Pytanie + + + Do you really want to use an empty string as password? + Czy naprawdę chcesz użyć pusty ciąg znaków jako hasło ? + + + Different passwords supplied. + + + + Failed to set key file + + + + Failed to set %1 as the Key file: +%2 + + + + + DatabaseOpenWidget + + Enter master key + Wprowadź klucz główny + + + Key File: + Plik klucza: + + + Password: + Hasło: + + + Browse + Przeglądaj + + + Error + Błąd + + + Unable to open the database. + Nie można otworzyć bazy kluczy. + + + Can't open key file + Nie mogę otworzyć pliku z kluczem + + + All files + Wszystkie pliki + + + Key files + Pliki kluczy + + + Select key file + Wybierz plik z kluczem + + + + DatabaseSettingsWidget + + Database name: + Nazwa bazy danych: + + + Database description: + Opis bazy danych + + + Transform rounds: + Liczba rund szyfrowania: + + + Default username: + Domyślny użytkownik: + + + Use recycle bin: + Korzystaj z kosza: + + + MiB + MiB + + + Benchmark + Test sprawności + + + Max. history items: + + + + Max. history size: + + + + + DatabaseTabWidget + + Root + Root + + + KeePass 2 Database + Baza danych KeePass 2 + + + All files + Wszystkie pliki + + + Open database + Otwórz bazę danych + + + Warning + Ostrzeżenie + + + File not found! + Nie znaleziono pliku! + + + Open KeePass 1 database + Otwórz bazę danych KeePass 1 + + + KeePass 1 database + Baza danych KeePass1 + + + All files (*) + Wszystkie pliki(*) + + + Close? + Zamknąć ? + + + Save changes? + Zapisać zmiany ? + + + "%1" was modified. +Save changes? + "%1" został zmieniony. Zapisać zmiany ? + + + Error + Błąd + + + Writing the database failed. + Błąd w zapisywaniu bazy kluczy. + + + Save database as + Zapisz bazę danych jako + + + New database + Nowa baza danych + + + locked + plik CSV + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + + + + Lock database + Zablokuj bazę + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + + + + This database has never been saved. +You can save the database or stop locking it. + + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + + + + "%1" is in edit mode. +Discard changes and close anyway? + + + + Export database to CSV file + Eksport bazy danych do pliku CSV + + + CSV file + plik CSV + + + Writing the CSV file failed. + Błąd przy zapisywaniu pliku CSV. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + + + + + DatabaseWidget + + Change master key + Zmień główne hasło + + + Delete entry? + Skasować wpis? + + + Do you really want to delete the entry "%1" for good? + Czy na pewno całkowicie usunąć wpis "%1" ? + + + Delete entries? + Usunąć wpisy? + + + Do you really want to delete %1 entries for good? + Czy na prawdę chcesz usunąć %1 wpisów na dobre? + + + Move entries to recycle bin? + Przenieść wpisy do kosza? + + + Do you really want to move %n entry(s) to the recycle bin? + + + + Delete group? + Usunąć grupę? + + + Do you really want to delete the group "%1" for good? + Czy na pewno całkowicie usunąć grupę "%1"? + + + Current group + Bieżąca grupa + + + Error + Błąd + + + Unable to calculate master key + Nie mogę wyliczyć głównego klucza + + + + EditEntryWidget + + Entry + Wpis + + + Advanced + Zaawansowane + + + Icon + Ikona + + + Auto-Type + Auto-uzupełnianie + + + Properties + Właściwości + + + History + Historia + + + Entry history + Historia wpisu + + + Add entry + Nowy wpis + + + Edit entry + Edycja wpisu + + + Error + Błąd + + + Different passwords supplied. + + + + New attribute + Nowy atrybut + + + Select file + Wybierz plik + + + Unable to open file + Nie można otworzyć pliku + + + Save attachment + Zapisz załącznik + + + Unable to save the attachment: + + Nie można zapisać załącznika: + + + + Tomorrow + Jutro + + + %n week(s) + %n tydzień%n tygodni(e)%n tygodni(e) + + + %n month(s) + %n miesiąc%n miesiąc(e)%n miesiąc(e) + + + 1 year + 1 rok + + + + EditEntryWidgetAdvanced + + Additional attributes + Dodatkowe atrybuty + + + Add + Dodaj + + + Edit + Edytuj + + + Remove + Usuń + + + Attachments + Załączniki + + + Save + Zapisz + + + Open + Otwórz + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + Włącz auto-uzupełnianie dla tego wpisu + + + Inherit default Auto-Type sequence from the group + Dziedzicz domyślną sekwencję auto-uzupełniania z grupy + + + Use custom Auto-Type sequence: + Używaj niestandardowej sekwencji auto-uzupełniania: + + + + + + + + + - + - + + + Window title: + Tytuł okna: + + + Use default sequence + Korzystaj z domyślnej sekwencji + + + Set custom sequence: + Ustaw niestandardową sekwencję: + + + + EditEntryWidgetHistory + + Show + Pokaż + + + Restore + Przywróć + + + Delete + Usuń + + + Delete all + Usuń wszystkie + + + + EditEntryWidgetMain + + Title: + Tytuł: + + + Username: + Użytkownik: + + + Password: + Hasło: + + + Repeat: + Powtórz: + + + Gen. + + + + URL: + URL: + + + Expires + Wygasa + + + Presets + + + + Notes: + Notatki: + + + + EditGroupWidget + + Group + Grupa + + + Icon + Ikona + + + Properties + Właściwości + + + Add group + Dodaj grupę + + + Edit group + Edytuj grupę + + + Enable + Włącz + + + Disable + Wyłącz + + + Inherit from parent group (%1) + Dziedzicz z nadrzędnej grupy (%1) + + + + EditGroupWidgetMain + + Name + Nazwa + + + Notes + Notatki + + + Expires + Wygasa + + + Search + Szukaj + + + Auto-type + Auto-uzupełnianie + + + Use default auto-type sequence of parent group + Korzystaj z domyślnej sekwencji auto-uzupełniania z nadrzędnej grupy + + + Set default auto-type sequence + Ustaw domyślną sekwencję auto-uzupełniania + + + + EditWidgetIcons + + Use default icon + Ustaw domyślną ikonę + + + Use custom icon + Ustaw niestandardową ikonę + + + Add custom icon + Dodaj niestandardową ikonę + + + Delete custom icon + Usuń niestandardową ikonę + + + Images + Obrazy + + + All files + Wszystkie pliki + + + Select Image + Wybierz obraz + + + Can't delete icon! + Nie można usunąć ikony! + + + Can't delete icon. Still used by %n item(s). + + + + + EditWidgetProperties + + Created: + Stworzone: + + + Modified: + Modyfikowane: + + + Accessed: + + + + Uuid: + Uuid: + + + + EntryAttributesModel + + Name + Nazwa + + + + EntryHistoryModel + + Last modified + Ostatnia modyfikacja + + + Title + Tytuł + + + Username + Użytkownik + + + URL + URL + + + + EntryModel + + Group + Grupa + + + Title + Tytuł + + + Username + Użytkownik + + + URL + URL + + + + Group + + Recycle Bin + Kosz + + + + KeePass1OpenWidget + + Import KeePass1 database + Importuj bazę danych KeePass1 + + + Error + Błąd + + + Unable to open the database. + Nie można otworzyć bazy kluczy. + + + + KeePass1Reader + + Unable to read keyfile. + Nie można otworzyć pliku z kluczem. + + + Not a KeePass database. + To nie baza KeePass. + + + Unsupported encryption algorithm. + Niewspierany algorytm szyfrowania. + + + Unsupported KeePass database version. + Niewspierana wersja bazy KeePass. + + + Root + Root + + + Unable to calculate master key + Nie mogę wyliczyć głównego klucza + + + + KeePass2Reader + + Not a KeePass database. + To nie baza KeePass. + + + Unsupported KeePass database version. + Niewspierana wersja bazy KeePass. + + + Wrong key or database file is corrupt. + Błędny klucz lub baza jest uszkodzona. + + + Unable to calculate master key + Nie mogę wyliczyć głównego klucza + + + + Main + + Fatal error while testing the cryptographic functions. + Błąd krytyczny podczas testowania funkcji kryptograficznych. + + + KeePassX - Error + KeePassX - Błąd + + + + MainWindow + + Database + Baza danych + + + Recent databases + Niedawne bazy danych + + + Help + Pomoc + + + Entries + Wpisy + + + Copy attribute to clipboard + Skopiuj atrybut do schowka + + + Groups + Grupy + + + View + Widok + + + Quit + Zakończ + + + About + O + + + Open database + Otwórz bazę danych + + + Save database + Zapisz bazę danych + + + Close database + Zamknij bazę danych + + + New database + Nowa baza danych + + + Add new entry + Dodaj nowy wpis + + + View/Edit entry + Podgląd/edycja wpisu + + + Delete entry + Usuń wpis + + + Add new group + Dodaj nową grupę + + + Edit group + Edytuj grupę + + + Delete group + Usuń grupę + + + Save database as + Zapisz bazę danych jako + + + Change master key + Zmień główne hasło + + + Database settings + Ustawienia bazy danych + + + Import KeePass 1 database + Importuj bazę danych KeePass 1 + + + Clone entry + Sklonuj wpis + + + Find + Znajdź + + + Copy username to clipboard + Skopiuj użytkownika do schowka + + + Copy password to clipboard + Skopiuj hasło do schowka + + + Settings + Ustawienia + + + Perform Auto-Type + Wykonaj auto-uzupełnianie + + + Open URL + Otwórz URL + + + Lock databases + Zablokuj bazy + + + Title + Tytuł + + + URL + URL + + + Notes + Notatki + + + Show toolbar + Pokaż pasek narzędziowy + + + read-only + Tylko do odczytu + + + Toggle window + + + + Tools + Narzędzia + + + Copy username + Skopiuj użytkownika + + + Copy password + Skopiuj hasło + + + Export to CSV file + Eksport do pliku CSV + + + + PasswordGeneratorWidget + + Password: + Hasło: + + + Length: + Długość + + + Character Types + + + + Upper Case Letters + Duże litery + + + Lower Case Letters + Małe litery + + + Numbers + Liczby + + + Special Characters + Znaki specjalne + + + Exclude look-alike characters + Wyklucz podobnie wyglądające znaki + + + Ensure that the password contains characters from every group + + + + Accept + Zaakceptuj + + + + QCommandLineParser + + Displays version information. + Wyświetl informację o wersji. + + + Displays this help. + Wyświetla ten dialog. + + + Unknown option '%1'. + Nie znana opcja '%1': + + + Unknown options: %1. + Nie znana opcja: %1. + + + Missing value after '%1'. + Brakująca wartość po '%1'. + + + Unexpected value after '%1'. + Nieoczekiwana wartość po '%1'. + + + [options] + [options] + + + Usage: %1 + + + + Options: + Opcje: + + + Arguments: + Argumenty: + + + + QSaveFile + + Existing file %1 is not writable + + + + Writing canceled by application + Zapisywanie anulowane przez aplikację + + + Partial write. Partition full? + + + + + QtIOCompressor + + Internal zlib error when compressing: + Błąd wewnętrzny zlib podczas kompresowania: + + + Error writing to underlying device: + + + + Error opening underlying device: + + + + Error reading data from underlying device: + + + + Internal zlib error when decompressing: + Błąd wewnętrzny zlib podczas dekompresowania: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + Format gzip nie wspierany przez tą wersję zlib. + + + Internal zlib error: + Błąd wewnętrzny zlib: + + + + SearchWidget + + Find: + Znajdź: + + + Case sensitive + Rozróżniaj wielkość znaków + + + Current group + Bieżąca grupa + + + Root group + + + + + SettingsWidget + + Application Settings + Ustawienia aplikacji + + + General + Główne + + + Security + Bezpieczeństwo + + + + SettingsWidgetGeneral + + Remember last databases + Pamiętaj ostatnią bazę + + + Open previous databases on startup + Otwórz poprzednią bazę podczas startu + + + Automatically save on exit + Automatycznie zapisz przy wyjściu + + + Automatically save after every change + Automatycznie zapisz po każdej zmianie + + + Minimize when copying to clipboard + Zminimalizuj po skopiowaniu do schowka + + + Use group icon on entry creation + Użyj ikony grupy podczas tworzenia wpisu + + + Global Auto-Type shortcut + Globalny skrót auto-uzupełnianie + + + Use entry title to match windows for global auto-type + + + + Language + Język + + + Show a system tray icon + Pokaż ikonę w zasobniku systemowym + + + Hide window to system tray when minimized + Schowaj okno do zasobnika podczas minimalizacji + + + Remember last key files + Zapamiętaj ostatni plik klucza + + + + SettingsWidgetSecurity + + Clear clipboard after + Wyczyść schowek po + + + sec + + + + Lock databases after inactivity of + Zablokuj bazę po nieaktywności + + + Show passwords in cleartext by default + Domyślnie pokazuj hasła + + + Always ask before performing auto-type + Zawsze pytaj przed wykonaniem auto-uzupełninia + + + + UnlockDatabaseWidget + + Unlock database + Odblokuj bazę + + + + WelcomeWidget + + Welcome! + Witaj! + + + + main + + KeePassX - cross-platform password manager + + + + filename of the password database to open (*.kdbx) + + + + path to a custom config file + + + + key file of the database + plik klucza bazy + + + \ No newline at end of file diff --git a/share/translations/keepassx_pt_BR.ts b/share/translations/keepassx_pt_BR.ts new file mode 100644 index 00000000..fc1128d5 --- /dev/null +++ b/share/translations/keepassx_pt_BR.ts @@ -0,0 +1,1282 @@ + + + AboutDialog + + About KeePassX + Sobre KeePassX + + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + KeePassX é distribuído nos termos da Licença Pública Geral (GPL), versão 2 ou (à sua escolha) versão 3, do GNU. + + + Revision + + + + + AutoType + + Auto-Type - KeePassX + Auto-Digitação - KeePassX + + + Couldn't find an entry that matches the window title: + Não foi possível encontrar uma entrada que corresponda ao título da janela: + + + + AutoTypeAssociationsModel + + Window + Janela + + + Sequence + Sequência + + + Default sequence + Sequência pré-definida + + + + AutoTypeSelectDialog + + Auto-Type - KeePassX + Auto-Digitação - KeePassX + + + Select entry to Auto-Type: + Escolha uma entrada para Auto-Digitar: + + + + ChangeMasterKeyWidget + + Password + Senha + + + Enter password: + Insira senha: + + + Repeat password: + Repita senha: + + + Key file + Arquivo-Chave + + + Browse + Navegar + + + Create + Criar + + + Key files + Arquivos-Chave + + + All files + Todos os Arquivos + + + Create Key File... + Criar Arquivo-Chave... + + + Error + Erro + + + Unable to create Key File : + Não foi possível criar o Arquivo-Chave : + + + Select a key file + Escolha um arquivo-chave + + + Question + Pergunta + + + Do you really want to use an empty string as password? + Você realmente quer usar uma sequência vazia como senha? + + + Different passwords supplied. + Senhas diferentes fornecidas. + + + Failed to set key file + Falha ao definir arquivo-chave + + + Failed to set %1 as the Key file: +%2 + Falha ao definir %1 como o Arquivo-Chave: +%2 + + + + DatabaseOpenWidget + + Enter master key + Insira a chave-mestra + + + Key File: + Arquivo-Chave: + + + Password: + Senha: + + + Browse + Navegar + + + Error + Erro + + + Unable to open the database. + Não foi possível abrir o banco de dados. + + + Can't open key file + Não foi possível abrir o arquivo-chave + + + All files + Todos os arquivos + + + Key files + Arquivos-chave + + + Select key file + Escolha o arquivo-chave + + + + DatabaseSettingsWidget + + Database name: + Nome do Banco de Dados: + + + Database description: + Descrição do Banco de Dados: + + + Transform rounds: + Rodadas de transformação: + + + Default username: + Usuário padrão: + + + Use recycle bin: + Usar lixeira: + + + MiB + MB + + + Benchmark + Benchmark + + + Max. history items: + Máx. Itens no histórico: + + + Max. history size: + Tamanho Máx. do histórico: + + + + DatabaseTabWidget + + Root + Raíz + + + KeePass 2 Database + Banco de Dados KeePass 2 + + + All files + Todos os arquivos + + + Open database + Abrir banco de dados + + + Warning + Aviso + + + File not found! + Arquivo não encontrado! + + + Open KeePass 1 database + Abrir banco de dados KeePass 1 + + + KeePass 1 database + banco de dados KeePass 1 + + + All files (*) + Todos os arquivos (*) + + + Close? + Fechar? + + + Save changes? + Salvar alterações? + + + "%1" was modified. +Save changes? + "%1" foi modificado. +Salvar alterações? + + + Error + Erro + + + Writing the database failed. + Escrever no banco de dados falhou. + + + Save database as + Salvar banco de dados como + + + New database + Novo banco de dados + + + locked + Trancado + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + O banco de dados que você está tentando abrir está bloqueado por outra instância do KeePassX. +Você quer abri-lo de qualquer forma? Alternativamente o banco de dados é aberto como somente leitura. + + + Lock database + Trancar Banco de Dados + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Não é possível trancar o banco de dados uma vez que você o está editando. +Por favor aperte cancelar para finalizar suas alterações ou descartá-las. + + + This database has never been saved. +You can save the database or stop locking it. + + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + + + + "%1" is in edit mode. +Discard changes and close anyway? + + + + Export database to CSV file + Exportar banco de dados para arquivo CSV + + + CSV file + Arquivo CSV + + + Writing the CSV file failed. + Falha ao gravar arquivo CSV. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + + + + + DatabaseWidget + + Change master key + Alterar chave mestra + + + Delete entry? + Apagar entrada? + + + Do you really want to delete the entry "%1" for good? + Você realmente quer apagar a entrada "%1" para sempre? + + + Delete entries? + Apagar entradas? + + + Do you really want to delete %1 entries for good? + Você realmente quer apagar %1 entradas para sempre? + + + Move entries to recycle bin? + Mover entradas para lixeira? + + + Do you really want to move %n entry(s) to the recycle bin? + + + + Delete group? + Apagar grupo? + + + Do you really want to delete the group "%1" for good? + Você realmente quer apagar o grupo "%1" para sempre? + + + Current group + Grupo atual + + + Error + Erro + + + Unable to calculate master key + Não foi possível calcular chave mestra + + + + EditEntryWidget + + Entry + Entrada + + + Advanced + Avançado + + + Icon + Ícone + + + Auto-Type + Auto-Digitação + + + Properties + Propriedades + + + History + Histórico + + + Entry history + Histórico de Entradas + + + Add entry + Adicionar entrada + + + Edit entry + Editar entrada + + + Error + Erro + + + Different passwords supplied. + Senhas diferentes fornecidas. + + + New attribute + Novo atributo + + + Select file + Selecionar arquivo + + + Unable to open file + Não foi possível abrir o arquivo + + + Save attachment + Salvar anexo + + + Unable to save the attachment: + + Não foi possível salvar o anexo: + + + + Tomorrow + Amanhã + + + %n week(s) + %n semana(s)%n semana(s) + + + %n month(s) + %n mês%n mese(s) + + + 1 year + 1 ano + + + + EditEntryWidgetAdvanced + + Additional attributes + Atributos extras + + + Add + Adicionar + + + Edit + Editar + + + Remove + Remover + + + Attachments + Anexos + + + Save + Salvar + + + Open + Abrir + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + Habilitar Auto-Digitação para esta entrada + + + Inherit default Auto-Type sequence from the group + Herdar sequência pré-definida de Auto-Digitação do grupo + + + Use custom Auto-Type sequence: + Usar sequência de Auto-Digitação personalizada: + + + + + + + + + - + - + + + Window title: + Título da Janela: + + + Use default sequence + Usar sequência pré-definida + + + Set custom sequence: + Definir sequência personalizada: + + + + EditEntryWidgetHistory + + Show + Mostrar + + + Restore + Restaurar + + + Delete + Excluir + + + Delete all + Excluir todos + + + + EditEntryWidgetMain + + Title: + Título: + + + Username: + Nome de Usuário: + + + Password: + Senha: + + + Repeat: + Repetir + + + Gen. + Gerar + + + URL: + URL: + + + Expires + Expira em: + + + Presets + Pré-definidos + + + Notes: + Notas: + + + + EditGroupWidget + + Group + Grupo + + + Icon + Ícone + + + Properties + Propriedades + + + Add group + Adicionar grupo + + + Edit group + Editar grupo + + + Enable + Habilitar + + + Disable + Desabilitar + + + Inherit from parent group (%1) + Herdar do grupo pai (%1) + + + + EditGroupWidgetMain + + Name + Nom + + + Notes + Notas + + + Expires + Expira em + + + Search + Buscar + + + Auto-type + Auto-digitar + + + Use default auto-type sequence of parent group + + + + Set default auto-type sequence + + + + + EditWidgetIcons + + Use default icon + Usar Ícone padrão + + + Use custom icon + Usar ícone personalizado + + + Add custom icon + Adicionar ícone personalizado + + + Delete custom icon + Excluir ícone personalizado + + + Images + Imagens + + + All files + Todos os arquivos + + + Select Image + Selecionar imagem + + + Can't delete icon! + Não é possível apagar o ícone! + + + Can't delete icon. Still used by %n item(s). + Não é possível apagar o ícone. Ainda usado por %n item.Não é possível apagar o ícone. Ainda usado por %n item(s). + + + + EditWidgetProperties + + Created: + Criado em: + + + Modified: + Modificado em: + + + Accessed: + Acessado em: + + + Uuid: + Uuid: + + + + EntryAttributesModel + + Name + Nome + + + + EntryHistoryModel + + Last modified + Modificado pela última vez em + + + Title + Título + + + Username + Nome de usuário + + + URL + URL + + + + EntryModel + + Group + Grupo + + + Title + Título + + + Username + Nome de usuário + + + URL + URL + + + + Group + + Recycle Bin + Lixeira + + + + KeePass1OpenWidget + + Import KeePass1 database + Importar banco de dados KeePass1 + + + Error + Erro + + + Unable to open the database. + Não foi possível abrir o banco de dados. + + + + KeePass1Reader + + Unable to read keyfile. + Não foi possível ler o arquivo-chave. + + + Not a KeePass database. + Não é um banco de dados KeePass. + + + Unsupported encryption algorithm. + Algoritmo de encriptação não suportado. + + + Unsupported KeePass database version. + Versão do banco de dados KeePass não suportada. + + + Root + Raíz + + + Unable to calculate master key + Não foi possível calcular a chave mestra + + + + KeePass2Reader + + Not a KeePass database. + Não é um banco de dados KeePass. + + + Unsupported KeePass database version. + Versão não suportada do banco de dados KeePass. + + + Wrong key or database file is corrupt. + + + + Unable to calculate master key + + + + + Main + + Fatal error while testing the cryptographic functions. + + + + KeePassX - Error + KeePassX - Erro + + + + MainWindow + + Database + Banco de Dados + + + Recent databases + Bancos de dados recentes + + + Help + Ajuda + + + Entries + Entradas + + + Copy attribute to clipboard + Copiar atributo para a área de transferência + + + Groups + Grupos + + + View + Ver + + + Quit + Sair + + + About + Sobre + + + Open database + Abrir banco de dados + + + Save database + Salvar banco de dados + + + Close database + Fechar banco de dados + + + New database + Novo banco de dados + + + Add new entry + Adicionar nova entrada + + + View/Edit entry + Ver/Editar entrada + + + Delete entry + Excluir entrada + + + Add new group + Adicionar novo grupo + + + Edit group + Editar grupo + + + Delete group + Excluir grupo + + + Save database as + Salvar banco de dados como + + + Change master key + Alterar chave-mestra + + + Database settings + Configurações do Banco de Dados + + + Import KeePass 1 database + Importar banco de dados KeePass1 + + + Clone entry + Clonar entrada + + + Find + Encontrar + + + Copy username to clipboard + Copiar nome de usuário para área de transferência + + + Copy password to clipboard + Copiar senha para área de transferência + + + Settings + Configurações + + + Perform Auto-Type + Realizar Auto-Digitação + + + Open URL + Abrir URL + + + Lock databases + Trancar bancos de dados + + + Title + Título + + + URL + URL + + + Notes + Notas + + + Show toolbar + Mostrar barra de ferramentas + + + read-only + somente leitura + + + Toggle window + Alternar Janela + + + Tools + Ferramentas + + + Copy username + Copiar nome de usuário + + + Copy password + Copiar senha + + + Export to CSV file + Exportar para arquivo CSV + + + + PasswordGeneratorWidget + + Password: + Senha: + + + Length: + Tamanho: + + + Character Types + Tipos de Caracteres + + + Upper Case Letters + Letras Maiúsculas + + + Lower Case Letters + Letras Minúsculas + + + Numbers + Números + + + Special Characters + Caracteres Especiais + + + Exclude look-alike characters + Excluir caracteres similares + + + Ensure that the password contains characters from every group + Assegurar que a senha contenha caracteres de todos os grupos + + + Accept + Aceitar + + + + QCommandLineParser + + Displays version information. + Mostrar informações da versão. + + + Displays this help. + Mostrar esta ajuda. + + + Unknown option '%1'. + Opção desconhecida '%1'. + + + Unknown options: %1. + Opções desconhecidas: %1. + + + Missing value after '%1'. + Falta valor após '%1'. + + + Unexpected value after '%1'. + Valor inesperado após '%1'. + + + [options] + [opções] + + + Usage: %1 + Utilização: %1 + + + Options: + Opções: + + + Arguments: + Argumentos: + + + + QSaveFile + + Existing file %1 is not writable + O arquivo existente %1 não é gravável + + + Writing canceled by application + Escrita cancelada pelo aplicativo + + + Partial write. Partition full? + Escrita parcial. Partição cheia? + + + + QtIOCompressor + + Internal zlib error when compressing: + Erro interno do zlib ao compactar: + + + Error writing to underlying device: + Erro ao gravar no dispositivo subjacente: + + + Error opening underlying device: + Erro ao abrir dispositivo subjacente: + + + Error reading data from underlying device: + + + + Internal zlib error when decompressing: + + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + + + + Internal zlib error: + Erro interno do zlib: + + + + SearchWidget + + Find: + Encontrar: + + + Case sensitive + diferenciar maiúsculas e minúsculas + + + Current group + Grupo atual + + + Root group + Grupo Raíz + + + + SettingsWidget + + Application Settings + Configurações do Aplicativo + + + General + Geral + + + Security + Segurança + + + + SettingsWidgetGeneral + + Remember last databases + Lembrar dos últimos bancos de dados + + + Open previous databases on startup + Abrir bancos de dados anteriores na inicialização + + + Automatically save on exit + Salvar automaticamente ao sair + + + Automatically save after every change + Salvar automaticamente depois de cada alteração + + + Minimize when copying to clipboard + Minimizar ao copiar para área de transferência + + + Use group icon on entry creation + + + + Global Auto-Type shortcut + + + + Use entry title to match windows for global auto-type + + + + Language + Idioma + + + Show a system tray icon + Mostrar um ícone da bandeja do sistema + + + Hide window to system tray when minimized + + + + Remember last key files + + + + + SettingsWidgetSecurity + + Clear clipboard after + + + + sec + + + + Lock databases after inactivity of + + + + Show passwords in cleartext by default + + + + Always ask before performing auto-type + + + + + UnlockDatabaseWidget + + Unlock database + Destrancar banco de dados + + + + WelcomeWidget + + Welcome! + Bemvindo! + + + + main + + KeePassX - cross-platform password manager + KeePassX - gerenciador de senhas Multiplataforma + + + filename of the password database to open (*.kdbx) + + + + path to a custom config file + + + + key file of the database + + + + \ No newline at end of file diff --git a/share/translations/keepassx_pt_PT.ts b/share/translations/keepassx_pt_PT.ts new file mode 100644 index 00000000..daaf7356 --- /dev/null +++ b/share/translations/keepassx_pt_PT.ts @@ -0,0 +1,1280 @@ + + + AboutDialog + + About KeePassX + Sobre o KeePassX + + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + KeePassX é distribuído sob os termos GNU de licença pública geral (GPL) versão 2 ou (á sua escolha) versão 3. + + + + AutoType + + Auto-Type - KeePassX + Escrever automáticamente - KeePassX + + + Couldn't find an entry that matches the window title: + Não foi possível encontrar uma entrada que coincida com o titulo da janela: + + + + AutoTypeAssociationsModel + + Window + Janela + + + Sequence + Sequência + + + Default sequence + Sequência padrão + + + + AutoTypeSelectDialog + + Auto-Type - KeePassX + Escrever automáticamente - KeePassX + + + Select entry to Auto-Type: + Seleccionar entrada para auto escrever: + + + + ChangeMasterKeyWidget + + Password + Senha + + + Enter password: + Inserir a senha: + + + Repeat password: + Reinserir a senha + + + Key file + Ficheiro chave + + + Browse + Procurar + + + Create + Criar + + + Key files + Ficheiros chave + + + All files + Todos os ficheiros + + + Create Key File... + Criar ficheiro chave + + + Error + Erro + + + Unable to create Key File : + Impossível criar ficheiro chave: + + + Select a key file + Seleccionar ficheiro chave + + + Question + Questão + + + Do you really want to use an empty string as password? + Pretende utilizar um valor sem conteúdo como senha ? + + + Different passwords supplied. + As senhas inseridas não coincidem. + + + Failed to set key file + Falha ao definir o ficheiro chave + + + Failed to set %1 as the Key file: +%2 + Falha ao especificar %1 como ficheiro chave: +%2 + + + + DatabaseOpenWidget + + Enter master key + Inserir chave mestra + + + Key File: + Ficheiro chave: + + + Password: + Senha: + + + Browse + Procurar + + + Error + Erro + + + Unable to open the database. + Impossível abrir a base de dados. + + + Can't open key file + Não é possível abrir ao ficheiro chave + + + All files + Todos os ficheiros + + + Key files + Ficheiros chave + + + Select key file + Seleccionar o ficheiro chave + + + + DatabaseSettingsWidget + + Database name: + Nome da base de dados: + + + Database description: + Descrição da base de dados: + + + Transform rounds: + Ciclos de transformação: + + + Default username: + Utilizador padrão: + + + Use recycle bin: + Utilizar reciclagem: + + + MiB + MiB + + + Benchmark + Teste de desempenho + + + Max. history items: + Número máximo de items no histórico: + + + Max. history size: + Tamanho máximo para o histórico: + + + + DatabaseTabWidget + + Root + Raiz + + + KeePass 2 Database + Base de dados KeePass 2 + + + All files + Todos os ficheiros + + + Open database + Abrir base de dados + + + Warning + Aviso + + + File not found! + Ficheiro não encontrado ! + + + Open KeePass 1 database + Abrir base de dados KeePass 1 + + + KeePass 1 database + Base de dados KeePass 1 + + + All files (*) + Todos os ficheiros (*) + + + Close? + Fechar ? + + + Save changes? + Guardar alterações ? + + + "%1" was modified. +Save changes? + "%1" foi modificado. +Guardar alterações ? + + + Error + Erro + + + Writing the database failed. + Falha na escrita da base de dados. + + + Save database as + Guardar base de dados como + + + New database + Nova base de dados + + + locked + Trancado + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + A base de dados que está a tentar abrir encontra-se trancada por outra utilização do KeePassX. +Pretende abri-la de qualquer forma ? Alternativamente será apenas para leitura. + + + Lock database + Trancar base de dados + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Não é possível trancar a base de dados pois encontra-se em edição. +Por favor cancele para finalizar as alterações ou descarte-as. + + + This database has never been saved. +You can save the database or stop locking it. + Esta base de dados nunca foi guardada. +Pode guarda-la ou pare de a tentar trancar. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Esta base de dados foi modificada. +Pretende guardar a base de dados antes de a trancar ? +Caso contrário as alterações serão perdidas. + + + "%1" is in edit mode. +Discard changes and close anyway? + %1 está em modo de edição. +Fechar e Ignorar alterações ? + + + Export database to CSV file + Exportar base de dados para ficheiro CSV + + + CSV file + Ficheiro CSV + + + Writing the CSV file failed. + Falha na escrita do ficheiro CSV + + + + DatabaseWidget + + Change master key + Alterar a chave mestra + + + Delete entry? + Apagar entrada ? + + + Do you really want to delete the entry "%1" for good? + Pretender realmente apagar a entrada "%1" para sempre ? + + + Delete entries? + Apagar entradas ? + + + Do you really want to delete %1 entries for good? + Pretender realmente apagar as entradas "%1" para sempre ? + + + Move entries to recycle bin? + Mover entradas para a reciclagem ? + + + Do you really want to move %n entry(s) to the recycle bin? + Pretende realmente mover a entrada(s) %n para a reciclagem ?Pretende realmente mover a entrada(s) %n para a reciclagem ? + + + Delete group? + Apagar grupo ? + + + Do you really want to delete the group "%1" for good? + Pretender realmente apagar o grupo "%1" para sempre ? + + + Current group + Grupo actual + + + Error + Erro + + + Unable to calculate master key + Impossível calcular ficheiro chave + + + + EditEntryWidget + + Entry + Entrada + + + Advanced + Avançado + + + Icon + Icon + + + Auto-Type + Auto escrita + + + Properties + Propriedades + + + History + Histórico + + + Entry history + Entrada do histórico + + + Add entry + Adicionar entrada + + + Edit entry + Editar entrada + + + Error + Erro + + + Different passwords supplied. + As senhas inseridas não coincidem. + + + New attribute + Novo atributo + + + Select file + Seleccionar ficheiro + + + Unable to open file + Incapaz de abrir o ficheiro + + + Save attachment + Guardar anexo + + + Unable to save the attachment: + + Incapaz de guardar o anexo: + + + Tomorrow + Amanhã + + + %n week(s) + %n semana(s)%n semana(s) + + + %n month(s) + %n mês%n mês(es) + + + 1 year + 1 ano + + + + EditEntryWidgetAdvanced + + Additional attributes + Atributos adicionais + + + Add + Adicionar + + + Edit + Editar + + + Remove + Remover + + + Attachments + Anexos + + + Save + Guardar + + + Open + Abrir + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + Activar auto escrita para esta entrada + + + Inherit default Auto-Type sequence from the group + Herdar sequência de auto escrita padrão deste grupo + + + Use custom Auto-Type sequence: + Utilizar sequência de auto escrita personalizada: + + + + + + + + + - + - + + + Window title: + Título da janela: + + + Use default sequence + Utilizar sequência padrão + + + Set custom sequence: + Especificar sequência padrão: + + + + EditEntryWidgetHistory + + Show + Mostrar + + + Restore + Restaurar + + + Delete + Apagar + + + Delete all + Apagar tudo + + + + EditEntryWidgetMain + + Title: + Título: + + + Username: + Nome de utilizador: + + + Password: + Senha: + + + Repeat: + Repetir: + + + Gen. + Gerar. + + + URL: + URL: + + + Expires + Expira + + + Presets + Definições + + + Notes: + Notas: + + + + EditGroupWidget + + Group + Grupo + + + Icon + Icon + + + Properties + Propriedades + + + Add group + Adicionar grupo + + + Edit group + Editar grupo + + + Enable + Activar + + + Disable + Desactivar + + + Inherit from parent group (%1) + Herdar a partir do grupo (%1) + + + + EditGroupWidgetMain + + Name + Nome + + + Notes + Notas + + + Expires + Expira + + + Search + Procurar + + + Auto-type + Auto escrita + + + Use default auto-type sequence of parent group + Herdar sequência de auto escrita padrão do grupo relacionado + + + Set default auto-type sequence + Especificar sequência padrão de auto escrita + + + + EditWidgetIcons + + Use default icon + Utilizar icon padrão + + + Use custom icon + Utilizar icon padrão + + + Add custom icon + Adicionar icon personalizado + + + Delete custom icon + Apagar icon personalizado + + + Images + Imagens + + + All files + Todos os ficheiros + + + Select Image + Seleccionar imagem + + + Can't delete icon! + Impossível apagar o icon + + + Can't delete icon. Still used by %n item(s). + Impossível apagar icon. Ainda em uso por %n item(s).Impossível apagar icon. Ainda em uso por %n item(s). + + + + EditWidgetProperties + + Created: + Criado: + + + Modified: + Modificado: + + + Accessed: + Acedido: + + + Uuid: + Uuid: + + + + EntryAttributesModel + + Name + Nome + + + + EntryHistoryModel + + Last modified + Última modificação + + + Title + Título + + + Username + Nome de utilizador + + + URL + URL + + + + EntryModel + + Group + Grupo + + + Title + Título: + + + Username + Nome de utilizador + + + URL + URL + + + + Group + + Recycle Bin + Reciclagem + + + + KeePass1OpenWidget + + Import KeePass1 database + Importar de dados KeePass 1 + + + Error + Erro + + + Unable to open the database. + Impossível abrir a base de dados. + + + + KeePass1Reader + + Unable to read keyfile. + Impossível ler o ficheiro chave: + + + Not a KeePass database. + Não é uma base de dados KeePass + + + Unsupported encryption algorithm. + Algoritmo de criptografia não suportado. + + + Unsupported KeePass database version. + Versão de base de dados KeePass não suportada. + + + Root + Raiz + + + Unable to calculate master key + Impossível calcular chave mestra: + + + + KeePass2Reader + + Not a KeePass database. + Não é uma base de dados KeePass. + + + Unsupported KeePass database version. + Versão de base de dados KeePass não suportada. + + + Wrong key or database file is corrupt. + Chave errada ou base de dados corrompida. + + + Unable to calculate master key + Impossível calcular chave mestra: + + + + Main + + Fatal error while testing the cryptographic functions. + Erro fatal durante teste de funções criptográficas. + + + KeePassX - Error + Erro - KeePassX + + + + MainWindow + + Database + Base de dados + + + Recent databases + Base de dados recentes + + + Help + Ajuda + + + Entries + Entradas + + + Copy attribute to clipboard + Copiar atributo para inserção + + + Groups + Grupos + + + View + Vista + + + Quit + Terminar + + + About + Sobre + + + Open database + Abrir base de dados + + + Save database + Guardar base de dados + + + Close database + Fechar base de dados + + + New database + Nova base de dados + + + Add new entry + Adicionar nova entrada + + + View/Edit entry + Ver/Editar entrada + + + Delete entry + Apagar entrada + + + Add new group + Adicionar novo grupo + + + Edit group + Editar grupo + + + Delete group + Apagar grupo + + + Save database as + Guardar base de dados como + + + Change master key + Alterar a chave mestra + + + Database settings + Definições da base de dados: + + + Import KeePass 1 database + Importar base de dados KeePass 1 + + + Clone entry + Clonar entrada + + + Find + Encontrar + + + Copy username to clipboard + Copiar nome de utilizador para inserção + + + Copy password to clipboard + Copiar senha para inserção + + + Settings + Definições + + + Perform Auto-Type + Utilizar auto escrita + + + Open URL + Abrir URL + + + Lock databases + Trancar base de dados + + + Title + Título + + + URL + URL + + + Notes + Notas + + + Show toolbar + Mostrar barra de ferramentas + + + read-only + apenas leitura + + + Toggle window + Alternar janela + + + Tools + Ferramentas + + + Copy username + Copiar nome de utilizador + + + Copy password + Copiar senha + + + Export to CSV file + Exportar para ficheiro CSV + + + + PasswordGeneratorWidget + + Password: + Senha: + + + Length: + Tamanho: + + + Character Types + Tipo de caracteres + + + Upper Case Letters + Letras maiúsculas + + + Lower Case Letters + Letras minúsculas + + + Numbers + Números + + + Special Characters + Caracteres especiais + + + Exclude look-alike characters + Excluir caracteres semelhantes + + + Ensure that the password contains characters from every group + Assegurar que a senha contém caracteres de todos os grupos + + + Accept + Aceitar + + + + QCommandLineParser + + Displays version information. + Mostrar informação da versão. + + + Displays this help. + Mostrar esta ajuda. + + + Unknown option '%1'. + Opção '%1' desconhecida. + + + Unknown options: %1. + Opções desconhecidas: %1. + + + Missing value after '%1'. + Valor em falta após '%1'. + + + Unexpected value after '%1'. + Valor inesperado após '%1'. + + + [options] + [opções] + + + Usage: %1 + Utilização: %1 + + + Options: + Opções: + + + Arguments: + Argumentos: + + + + QSaveFile + + Existing file %1 is not writable + O ficheiro %1 existente não permite escrita + + + Writing canceled by application + Escrita cancelada pela aplicação + + + Partial write. Partition full? + Escrita parcial. Armazenamento cheio ? + + + + QtIOCompressor + + Internal zlib error when compressing: + Erro interno zlib durante compressão: + + + Error writing to underlying device: + Erro de escrita no dispositivo subjacente: + + + Error opening underlying device: + Erro ao abrir dispositivo subjacente: + + + Error reading data from underlying device: + Erro de leitura no dispositivo subjacente: + + + Internal zlib error when decompressing: + Erro interno zlib durante descompressão: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + O formato gzip não é suportado pela versão zlib utilizada. + + + Internal zlib error: + Erro interno zlib: + + + + SearchWidget + + Find: + Procurar: + + + Case sensitive + Sensível ao tipo + + + Current group + Grupo actual + + + Root group + Grupo de raiz + + + + SettingsWidget + + Application Settings + Definições da aplicação + + + General + Geral + + + Security + Segurança + + + + SettingsWidgetGeneral + + Remember last databases + Lembrar últimas bases de dados + + + Open previous databases on startup + Abrir última base da dados ao iniciar + + + Automatically save on exit + Guardar automáticamente ao terminar + + + Automatically save after every change + Guardar automáticamente a cada alteração + + + Minimize when copying to clipboard + Minimizar quando copiar para inserção + + + Use group icon on entry creation + Utilizar icon de grupo na criação de entrada + + + Global Auto-Type shortcut + Atalho global de auto escrita + + + Use entry title to match windows for global auto-type + Utilizar titulo de entrada para coincidir com janela de entrada de auto escrita global + + + Language + Língua + + + Show a system tray icon + Mostrar icon na barra de sistema + + + Hide window to system tray when minimized + Esconder janela na barra de sistema quando minimizada + + + Remember last key files + Lembrar os últimos ficheiro chave + + + + SettingsWidgetSecurity + + Clear clipboard after + Limpar dados de inserção no final + + + sec + seg + + + Lock databases after inactivity of + Trancar bases de dados após inatividade de + + + Show passwords in cleartext by default + Revelar senhas em texto por padrão + + + Always ask before performing auto-type + Confirmar antes de executar auto escrita + + + + UnlockDatabaseWidget + + Unlock database + Destrancar base de dados + + + + WelcomeWidget + + Welcome! + Bem vindo/a ! + + + + main + + KeePassX - cross-platform password manager + KeePassX - Administrador de senhas multi plataforma + + + filename of the password database to open (*.kdbx) + ficheiro chave para abrir a base de dados (*.kdbx) + + + path to a custom config file + caminho para um ficheiro de configuração personalizado + + + password of the database (DANGEROUS!) + senha da base de dados (PERIGOSO !) + + + key file of the database + ficheiro chave da base de dados + + + \ No newline at end of file diff --git a/share/translations/keepassx_ru.ts b/share/translations/keepassx_ru.ts index 6b8092ef..2400dfc1 100644 --- a/share/translations/keepassx_ru.ts +++ b/share/translations/keepassx_ru.ts @@ -9,6 +9,10 @@ KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. KeePassX распространяется на условиях Стандартной общественной лицензии GNU (GPL) версии 2 или (на ваше усмотрение) версии 3. + + Revision + Ревизия + AutoType @@ -44,7 +48,7 @@ Select entry to Auto-Type: - Выберете запись для автоввода: + Выберите запись для автоввода: @@ -103,12 +107,22 @@ Do you really want to use an empty string as password? - Вы действительно хотите использовать пустую строку как пароль? + Вы действительно хотите использовать в качестве пароля пустую строку? Different passwords supplied. Пароли не совпадают. + + Failed to set key file + Не удалось установить файл-ключ + + + Failed to set %1 as the Key file: +%2 + Не удалось установить %1 как файл-ключ: +%2 + DatabaseOpenWidget @@ -150,7 +164,7 @@ Select key file - Выберете файл-ключ + Выберите файл-ключ @@ -169,7 +183,7 @@ Default username: - Имя пользователя по-умолчанию: + Имя пользователя по умолчанию: Use recycle bin: @@ -234,12 +248,6 @@ Close? Закрыть? - - "%1" is in edit mode. -Close anyway? - «%1» в режиме редактирования. -Всё равно закрыть? - Save changes? Сохранить изменения? @@ -268,14 +276,65 @@ Save changes? locked - заблокированно + заблокировано + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Хранилище, которое Вы хотите открыть, заблокировано другой запущенной копией KeePassX. Всё равно открыть? В качестве альтернативы хранилище будет открыто в режиме для чтения. + + + Lock database + Заблокировать хранилище + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + + + + This database has never been saved. +You can save the database or stop locking it. + + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Хранилище было изменено. +Вы хотите сохранить его перед тем, как заблокировать? +В противном случае все изменения будут потеряны. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" в режиме редактирования. +Отменить изменения и всё равно закрыть? + + + Export database to CSV file + Экспортировать хранилище в файл CSV + + + CSV file + Файл CSV + + + Writing the CSV file failed. + Не удалось записать CSV файл. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + Данное хранилище заблокировано другой запущенной копией KeePassX. +Вы уверены, что хотите продолжить сохранение? DatabaseWidget Change master key - Сменить мастер-пароль + Изменить мастер-пароль Delete entry? @@ -313,6 +372,14 @@ Save changes? Current group Текущая группа + + Error + Ошибка + + + Unable to calculate master key + Невозможно вычислить мастер-пароль + EditEntryWidget @@ -326,7 +393,7 @@ Save changes? Icon - Иконка + Значок Auto-Type @@ -425,6 +492,10 @@ Save changes? Save Сохранить + + Open + Открыть + EditEntryWidgetAutoType @@ -527,7 +598,7 @@ Save changes? Icon - Иконка + Значок Properties @@ -574,26 +645,34 @@ Save changes? Auto-type - автоввод + Автоввод + + + Use default auto-type sequence of parent group + + + + Set default auto-type sequence + EditWidgetIcons Use default icon - Использовать стандартную иконку + Использовать стандартный значок Use custom icon - Использовать свою иконку + Использовать свой значок Add custom icon - Добавить свою иконку + Добавить свой значок Delete custom icon - Удалить свою иконку + Удалить свой значок Images @@ -609,11 +688,11 @@ Save changes? Can't delete icon! - Не могу удалить иконку! + Не могу удалить значок! Can't delete icon. Still used by %n item(s). - Не могу удалить иконку, %n запись всё ещё использует её.Не могу удалить иконку, %n записи всё ещё использует её.Не могу удалить иконку, %n записей всё ещё использует её.Не могу удалить иконку, %n записей всё ещё использует её. + Не могу удалить иконку, %n запись всё ещё использует её.Не могу удалить иконку, %n записи всё ещё использует её.Не могу удалить иконку, %n записей всё ещё использует её.Не могу удалить значок, %n записей всё ещё использует его. @@ -724,6 +803,10 @@ Save changes? Root Корень + + Unable to calculate master key + Невозможно вычислить мастер-пароль + KeePass2Reader @@ -739,6 +822,10 @@ Save changes? Wrong key or database file is corrupt. Неверный ключ или файл хранилища повреждён. + + Unable to calculate master key + Невозможно вычислить мастер-пароль + Main @@ -777,10 +864,6 @@ Save changes? Groups Группы - - Extras - Дополнительно - View Вид @@ -857,18 +940,10 @@ Save changes? Find Найти - - Username - Имя пользователя - Copy username to clipboard Скопировать имя пользователя в буфер обмена - - Password - Пароль - Copy password to clipboard Скопировать пароль в буфер обмена @@ -913,6 +988,22 @@ Save changes? Toggle window Переключить окно + + Tools + Инструменты + + + Copy username + Скопировать имя пользователя + + + Copy password + Скопировать пароль + + + Export to CSV file + Экспортировать в файл CSV + PasswordGeneratorWidget @@ -950,7 +1041,7 @@ Save changes? Ensure that the password contains characters from every group - Пожалуйста, пусть пароль будет содержать символы всех видов + Убедитесь, что пароль содержит символы всех видов Accept @@ -1023,19 +1114,19 @@ Save changes? Error writing to underlying device: - Ошибка записи на нижлежащее устройство: + Ошибка записи на низлежащее устройство: Error opening underlying device: - Ошибка открытия нижлежащего устройства: + Ошибка открытия низлежащего устройства: Error reading data from underlying device: - Ошибка чтения с нижлежащего устройства: + Ошибка чтения с низлежащего устройства: Internal zlib error when decompressing: - Внутренняя ошибка zlib при расжатии: + Внутренняя ошибка zlib при распаковке: @@ -1093,10 +1184,6 @@ Save changes? Open previous databases on startup Открывать предыдущее хранилище при запуске - - Mark as modified on expanded state changes - - Automatically save on exit Автоматически сохранять при выходе @@ -1133,12 +1220,16 @@ Save changes? Hide window to system tray when minimized При сворачивании прятать окно в область системных уведомлений + + Remember last key files + Запоминать последние файл-ключи + SettingsWidgetSecurity Clear clipboard after - Потом почтистить буфер обмена + Очищать буфер обмена через sec @@ -1150,7 +1241,7 @@ Save changes? Show passwords in cleartext by default - Показывать пароль в открытую по-умолчанию + По умолчанию показывать пароль в открытую Always ask before performing auto-type @@ -1163,14 +1254,6 @@ Save changes? Unlock database Разблокировать хранилище - - Error - Ошибка - - - Wrong key. - Неверный ключ. - WelcomeWidget @@ -1193,10 +1276,6 @@ Save changes? path to a custom config file путь к своему файлу настроек - - password of the database (DANGEROUS!) - пароль от хранилища (ОПАСНО!) - key file of the database файл-ключ хранилища diff --git a/share/translations/keepassx_sl_SI.ts b/share/translations/keepassx_sl_SI.ts new file mode 100644 index 00000000..c2a93c25 --- /dev/null +++ b/share/translations/keepassx_sl_SI.ts @@ -0,0 +1,1285 @@ + + + AboutDialog + + About KeePassX + O KeePassX + + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + KeePassX se razširja pod GNU General Public License (GPL) licenco verzija 2 ali (po želji) verzija 3. + + + Revision + + + + + AutoType + + Auto-Type - KeePassX + Samodejno tipkanje - KeePassX + + + Couldn't find an entry that matches the window title: + Ne najdem vnosa, ki bi ustrezal: + + + + AutoTypeAssociationsModel + + Window + Okno + + + Sequence + Sekvenca + + + Default sequence + Privzeta sekvenca + + + + AutoTypeSelectDialog + + Auto-Type - KeePassX + Samodejno tipkanje - KeePassX + + + Select entry to Auto-Type: + Izberi vnos za samodejno tipkanje: + + + + ChangeMasterKeyWidget + + Password + Geslo + + + Enter password: + Vnesi geslo: + + + Repeat password: + Ponovi geslo: + + + Key file + Datoteka s ključi + + + Browse + Prebrskaj + + + Create + Ustvari novo + + + Key files + Datoteke s ključi + + + All files + Vse datoteke + + + Create Key File... + Ustvari datoteko s ključi... + + + Error + Napaka + + + Unable to create Key File : + Ustvarjanje datoteke s ključi ni uspelo: + + + Select a key file + Izberi datoteko s kljući + + + Question + Vprašanje + + + Do you really want to use an empty string as password? + Ali res želite uporabiti prazen niz kot geslo? + + + Different passwords supplied. + Vnešeni gesli sta različni. + + + Failed to set key file + Nastavljanje datoteke s ključi ni uspelo + + + Failed to set %1 as the Key file: +%2 + Nastavljanje %1 kot datoteko s ključi ni uspelo: +%2 + + + + DatabaseOpenWidget + + Enter master key + Vnesi glavno geslo + + + Key File: + Datoteka s ključi: + + + Password: + Geslo: + + + Browse + Prebrskaj + + + Error + Napaka + + + Unable to open the database. + Odpiranje podatkovne baze ni uspelo. + + + Can't open key file + Odpiranje datoteke s ključi ni uspelo + + + All files + Vse datoteke + + + Key files + Datoteke s ključi + + + Select key file + Izberi datoteko s ključi + + + + DatabaseSettingsWidget + + Database name: + Ime podatkovne baze: + + + Database description: + Opis podatkovne baze: + + + Transform rounds: + Transform rounds: + + + Default username: + Privzeto uporabniško ime: + + + Use recycle bin: + Uporaba koša: + + + MiB + MiB + + + Benchmark + Primerjalni preizkus (benchmark) + + + Max. history items: + Max. vnosov zgodovine: + + + Max. history size: + Max. velikost zgodovine: + + + + DatabaseTabWidget + + Root + Koren + + + KeePass 2 Database + KeePass 2 podatkovna baza + + + All files + Vse datoteke + + + Open database + Odpri podatkovno bazo + + + Warning + Opozorilo + + + File not found! + Datoteke ni mogoče najti! + + + Open KeePass 1 database + Odpri KeePass 1 podatkovno bazo + + + KeePass 1 database + KeePass 1 podatkovna baza + + + All files (*) + Vse datoteke (*) + + + Close? + Zapri? + + + Save changes? + Shrani spremembe? + + + "%1" was modified. +Save changes? + "%1" spremenjeno. +Shrani spremembe? + + + Error + Napaka + + + Writing the database failed. + Zapis podatkovne baze ni uspel. + + + Save database as + Shrani podatkovno bazo kot + + + New database + Nova podatkovna baza + + + locked + zaklenjeno + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Podatkovna baza ki jo želite odpreti je že odprta v drugem KeePassX. +Ali jo vseeno želite odpreti? Lahko jo odprete tudi samo za branje. + + + Lock database + Zakleni podatkovno bazo + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Podatkovna baza je trenutno v urejanju, zato je ni mogoče zakleniti. +Dokončajte spremembe in poskusite znova. + + + This database has never been saved. +You can save the database or stop locking it. + Podatkovna baza še ni bila shranjena. +Lahko jo shranite ali prekinete z zaklepanjem. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Podatkovna baza je bila spremenjena. +Ali jo želite shraniti? +V nasprotnem primeru bodo spremembe izgubljene. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" je v urejanju. +Zavrži spremembe in zapri? + + + Export database to CSV file + Izvozi podatkovno bazo v CSV datoteko + + + CSV file + CSV datoteka + + + Writing the CSV file failed. + Pisanje v CSV datoteko ni uspelo + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + + + + + DatabaseWidget + + Change master key + Spremeni glavni ključ + + + Delete entry? + Izbris vnosa? + + + Do you really want to delete the entry "%1" for good? + Ali res želite izbrisati "%1"? + + + Delete entries? + Izbris vnosov? + + + Do you really want to delete %1 entries for good? + Ali res želite izbrisati %1 vnosov? + + + Move entries to recycle bin? + Premik vnosov v koš? + + + Do you really want to move %n entry(s) to the recycle bin? + Ali res želite premakniti %n vnos v koš?Ali res želite premakniti %n vnosa v koš?Ali res želite premakniti %n vnose v koš?Ali res želite premakniti %n - vnosov v koš? + + + Delete group? + Izbris skupine? + + + Do you really want to delete the group "%1" for good? + Ali res želite izbrisati skupino "%1"? + + + Current group + Trenutna skupina + + + Error + Napaka + + + Unable to calculate master key + Izračun glavnega ključa ni uspel + + + + EditEntryWidget + + Entry + Vnos + + + Advanced + Napredno + + + Icon + Ikona + + + Auto-Type + Samodejno tipkanje + + + Properties + Lastnosti + + + History + Zgodovina + + + Entry history + Zgodovina vnosov + + + Add entry + Dodaj vnos + + + Edit entry + Uredi vnos + + + Error + Napaka + + + Different passwords supplied. + Gesli se ne ujemata. + + + New attribute + Nov atribut + + + Select file + Izberi datoteko + + + Unable to open file + Datoteke ni mogoče odpreti + + + Save attachment + Shrani priponko + + + Unable to save the attachment: + + Priponke ni bilo mogoče shraniti: + + + Tomorrow + Jutri + + + %n week(s) + %n teden%n tedna%n tedni%n tednov + + + %n month(s) + %n mesec%n meseca%n meseci%n mesecev + + + 1 year + 1 leto + + + + EditEntryWidgetAdvanced + + Additional attributes + Dodatni atributi + + + Add + Dodaj + + + Edit + Uredi + + + Remove + Odstrani + + + Attachments + Priponke + + + Save + Shrani + + + Open + Odpri + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + Omogoči samodejno tipkanje za ta vnos + + + Inherit default Auto-Type sequence from the group + Dedovanje privzete sekvence za samodejno tipkanje iz skupine + + + Use custom Auto-Type sequence: + Uporabi poljubno sekvenco za samodejno tipkanje: + + + + + + + + + - + - + + + Window title: + Naslov okna: + + + Use default sequence + Uporabi privzeto sekvenco + + + Set custom sequence: + Nastavi privzeto sekvenco: + + + + EditEntryWidgetHistory + + Show + Prikaži + + + Restore + Obnovi + + + Delete + Izbriši + + + Delete all + Izbriši vse + + + + EditEntryWidgetMain + + Title: + Naslov: + + + Username: + Uporabniško ime: + + + Password: + Geslo: + + + Repeat: + Ponovi geslo: + + + Gen. + Samodejno generiraj + + + URL: + URL: + + + Expires + Poteče + + + Presets + Prednastavljeno + + + Notes: + Opombe: + + + + EditGroupWidget + + Group + Skupina + + + Icon + Ikona + + + Properties + Lastnosti + + + Add group + Dodaj skupino + + + Edit group + Uredi skupino + + + Enable + Omogoči + + + Disable + Onemogoči + + + Inherit from parent group (%1) + Podeduj iz nadrejene skupine (%1) + + + + EditGroupWidgetMain + + Name + Ime + + + Notes + Opombe + + + Expires + Poteče + + + Search + Išči + + + Auto-type + Samodejno tipkanje + + + Use default auto-type sequence of parent group + Za samodejno tipkanje uporabi privzeto sekvenco nadrejene skupine + + + Set default auto-type sequence + Nastavi privzeto sekvenco za samodejno tipkanje + + + + EditWidgetIcons + + Use default icon + Uporabi privzeto ikono + + + Use custom icon + Uporabi ikono po meri + + + Add custom icon + Dodaj poljubno ikono + + + Delete custom icon + Izbriši ikono + + + Images + Slike + + + All files + Vse datoteke + + + Select Image + Izberi sliko + + + Can't delete icon! + Ikone ni mogoče izbrisati! + + + Can't delete icon. Still used by %n item(s). + Ikone ni mogoče izbrisati. Uporablja jo še %n vnos.Ikone ni mogoče izbrisati. Uporabljata jo še %n vnosa.Ikone ni mogoče izbrisati. Uporabljajo jo še %n vnosi.Ikone ni mogoče izbrisati. Uporablja jo še %n vnosov. + + + + EditWidgetProperties + + Created: + Ustvarjeno: + + + Modified: + Spremenjeno: + + + Accessed: + Zadnji dostop: + + + Uuid: + Uuid: + + + + EntryAttributesModel + + Name + Ime + + + + EntryHistoryModel + + Last modified + Zadnja sprememba + + + Title + Naslov + + + Username + Uporabniško ime + + + URL + URL + + + + EntryModel + + Group + Skupina + + + Title + Naslov + + + Username + Uporabniško ime + + + URL + URL + + + + Group + + Recycle Bin + Koš + + + + KeePass1OpenWidget + + Import KeePass1 database + Uvozi KeePass1 podatkovno bazo + + + Error + Napaka + + + Unable to open the database. + Odpiranje podatkovne baze ni uspelo. + + + + KeePass1Reader + + Unable to read keyfile. + Branje datoteke s ključi ni uspelo. + + + Not a KeePass database. + Datoteka ni KeePass podatkovna baza. + + + Unsupported encryption algorithm. + Algoritem za enkripcijo ni podprt. + + + Unsupported KeePass database version. + Različica KeePass podatkovne baze ni podprta. + + + Root + Koren + + + Unable to calculate master key + Izračun glavnega ključa ni uspel + + + + KeePass2Reader + + Not a KeePass database. + Datoteka ni KeePass podatkovna baza. + + + Unsupported KeePass database version. + Različica KeePass podatkovne baze ni podprta. + + + Wrong key or database file is corrupt. + Napačno geslo ali pa je podatkovna baza poškodovana. + + + Unable to calculate master key + Izračun glavnega ključa ni uspel + + + + Main + + Fatal error while testing the cryptographic functions. + Napaka pri testiranju kriptografskih funkcij. + + + KeePassX - Error + KeePassX - Napaka + + + + MainWindow + + Database + Podatkovna baza + + + Recent databases + Nedavne podatkovne baze + + + Help + Pomoč + + + Entries + Vnosi + + + Copy attribute to clipboard + Kopiraj atribut v odložišče + + + Groups + Skupine + + + View + Pogled + + + Quit + Izhod + + + About + O programu + + + Open database + Odpri podatkovno bazo + + + Save database + Shrani podatkovno bazo + + + Close database + Zapri podatkovno bazo + + + New database + Nova podatkovna baza + + + Add new entry + Dodaj vnos + + + View/Edit entry + Uredi vnos + + + Delete entry + Izbriši vnos + + + Add new group + Dodaj novo skupino + + + Edit group + Uredi skupino + + + Delete group + Izbriši skupino + + + Save database as + Shrani podatkovno bazo kot + + + Change master key + Spremeni glavni ključ + + + Database settings + Nastavitve podatkovne baze + + + Import KeePass 1 database + Uvozi KeePass 1 podatkovno bazo + + + Clone entry + Kloniraj vnos + + + Find + Išči + + + Copy username to clipboard + Kopiraj uporabniško ime v odložišče + + + Copy password to clipboard + Kopiraj geslo v odložišče + + + Settings + Nastavitve + + + Perform Auto-Type + Izvedi samodejno tipkanje + + + Open URL + Odpri URL + + + Lock databases + Zakleni podatkovne baze + + + Title + Naslov + + + URL + URL + + + Notes + Opombe + + + Show toolbar + Prikaži orodno vrstico + + + read-only + samo za branje + + + Toggle window + Preklopi okno + + + Tools + Orodja + + + Copy username + Kopiraj uporabniško ime + + + Copy password + Kopiraj geslo + + + Export to CSV file + Izvozi v CSV datoteko + + + + PasswordGeneratorWidget + + Password: + Geslo: + + + Length: + Dolžina: + + + Character Types + Tipi znakov + + + Upper Case Letters + Velike črke + + + Lower Case Letters + Male črke + + + Numbers + Številke + + + Special Characters + Posebni znaki + + + Exclude look-alike characters + Izključi podobne znake + + + Ensure that the password contains characters from every group + Geslo naj vsebuje znake iz vsake skupine + + + Accept + Sprejmi + + + + QCommandLineParser + + Displays version information. + Prikaže informacije o različici. + + + Displays this help. + Prikaže pomoč. + + + Unknown option '%1'. + Neznana izbrira %1. + + + Unknown options: %1. + Neznane izbire: %1. + + + Missing value after '%1'. + Manjkajoča vrednost po '%1'. + + + Unexpected value after '%1'. + Nepričakovana vrednost po '%1'. + + + [options] + [možnosti] + + + Usage: %1 + Uporaba: %1 + + + Options: + Možnosti: + + + Arguments: + Argumenti: + + + + QSaveFile + + Existing file %1 is not writable + Obstoječa datoteka %1 ni zapisljiva + + + Writing canceled by application + Aplikacija je prekinila pisanje + + + Partial write. Partition full? + Delno pisanje. Polna particija? + + + + QtIOCompressor + + Internal zlib error when compressing: + Notranja zlib napaka pri stiskanju: + + + Error writing to underlying device: + Napaka pri pisanju na napravo: + + + Error opening underlying device: + Napaka pri odpiranju naprave: + + + Error reading data from underlying device: + Napak pri branju iz naprave: + + + Internal zlib error when decompressing: + Notranja zlib napaka pri dekompresiranju: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + Ta različica zlib ne podpira gzip formata. + + + Internal zlib error: + Notranja zlib napaka: + + + + SearchWidget + + Find: + Išči: + + + Case sensitive + Razlikuj med velikimi in malimi črkami + + + Current group + Trenutna skupina + + + Root group + Korenska skupina + + + + SettingsWidget + + Application Settings + Nastavitve aplikacije + + + General + Splošno + + + Security + Varnost + + + + SettingsWidgetGeneral + + Remember last databases + Zapomni si zadnje podatkovne baze + + + Open previous databases on startup + Odpri prejšnje podatkovne baze ob zagonu programa + + + Automatically save on exit + Samodejno shrani ob izhodu + + + Automatically save after every change + Samodejno shrani po vsaki spremembi + + + Minimize when copying to clipboard + Minimiziraj pri kopiranju v odložišče + + + Use group icon on entry creation + Za nove vnose uporabi ikono skupine + + + Global Auto-Type shortcut + Globalna bližnjica za samodejno tipkanje + + + Use entry title to match windows for global auto-type + Uporabi ujemanje naslova vnosa in naslova okna pri samodejnem tipkanju + + + Language + Jezik + + + Show a system tray icon + Pokaži ikono v sistemski vrstici + + + Hide window to system tray when minimized + Minimiziraj v sistemsko vrstico + + + Remember last key files + Zapomni si zadnje datoteke s ključi + + + + SettingsWidgetSecurity + + Clear clipboard after + Pobriši odložišče po + + + sec + sekundah + + + Lock databases after inactivity of + Zakleni podatkovne baze po neaktivnosti + + + Show passwords in cleartext by default + Gesla privzeto v čistopisu + + + Always ask before performing auto-type + Pred izvedbo samodejnega tipkanja vprašaj za potrditev + + + + UnlockDatabaseWidget + + Unlock database + Odkleni podatkovno bazo + + + + WelcomeWidget + + Welcome! + Dobrodošli! + + + + main + + KeePassX - cross-platform password manager + KeePassX - urejevalnik gesel za različne platforme + + + filename of the password database to open (*.kdbx) + končnica podatkovne baze (*.kdbx) + + + path to a custom config file + pot do konfiguracijske datoteke po meri + + + key file of the database + datoteka s ključi podatkovne baze + + + \ No newline at end of file diff --git a/share/translations/keepassx_sv.ts b/share/translations/keepassx_sv.ts index c18a3102..ff8126c5 100644 --- a/share/translations/keepassx_sv.ts +++ b/share/translations/keepassx_sv.ts @@ -9,6 +9,14 @@ KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. Keepassx distribueras enligt villkoren i GNU General Public License (GPL) version 2 eller (om du vill) version 3. + + Revision + Revision + + + Using: + Använder: + AutoType @@ -109,6 +117,16 @@ Different passwords supplied. Olika lösenord angivna + + Failed to set key file + Kunde inte sätta nyckel-fil + + + Failed to set %1 as the Key file: +%2 + Kunde inte sätta %1 som nyckel-fil: +%2 + DatabaseOpenWidget @@ -234,12 +252,6 @@ Close? Stäng? - - "%1" is in edit mode. -Close anyway? - "%1" är i redigerar-läge. -Stäng ändå? - Save changes? Spara ändringar? @@ -270,6 +282,60 @@ Spara ändringarna? locked låst + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Databasen som du försöker öppna är låst av en annan instans av KeePassX. +Vill du öppna den ändå? Databasen kommer då att öppnas skrivskyddad. + + + Lock database + Lås databasen + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Kan inte låsa databasen eftersom du håller på att redigera den. +Tryck avbryt för att ansluta dina ändringar alternativt kasta dem. + + + This database has never been saved. +You can save the database or stop locking it. + Databasen has aldrig sparats. +Spara databasen eller sluta lås den. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + Databasen har ändrats. +Vill du spara databasen innen du låser den? +I annat fall försvinner ändringarna. + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" är i redigeringsläge. +Kasta ändringarna och stäng endå? + + + Export database to CSV file + Exportera databasen till en CSV-fil + + + CSV file + CSV-fil + + + Writing the CSV file failed. + Kunde inte skriva till CSV-filen + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + Databasen du försöker spara som är låst av en annan instans av KeePassX. +Vill du spara endå? + DatabaseWidget @@ -313,6 +379,14 @@ Spara ändringarna? Current group Nuvarande grupp + + Error + Fel + + + Unable to calculate master key + Kunde inte räkna nu master-nyckeln + EditEntryWidget @@ -425,6 +499,10 @@ Spara ändringarna? Save Spara + + Open + Öppna + EditEntryWidgetAutoType @@ -576,6 +654,14 @@ Spara ändringarna? Auto-type Auto-skriv + + Use default auto-type sequence of parent group + Använd standard auto-skriv sekvensen från föräldergruppen + + + Set default auto-type sequence + Ange standard auto-skriv sekvens + EditWidgetIcons @@ -724,6 +810,10 @@ Spara ändringarna? Root Root + + Unable to calculate master key + Kunde inte räkna nu master-nyckeln + KeePass2Reader @@ -739,6 +829,17 @@ Spara ändringarna? Wrong key or database file is corrupt. Fel lösenord eller korrupt databas-fil + + Unable to calculate master key + Kunde inte räkna nu master-nyckeln + + + The selected file is an old KeePass 1 database (.kdb). + +You can import it by clicking on Database > 'Import KeePass 1 database'. +This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + + Main @@ -759,7 +860,7 @@ Spara ändringarna? Recent databases - Senast använda databser + Senast använda databaser Help @@ -777,10 +878,6 @@ Spara ändringarna? Groups Grupper - - Extras - Extra - View Vy @@ -857,18 +954,10 @@ Spara ändringarna? Find Sök - - Username - Användarnamn - Copy username to clipboard Kopiera användarnamn - - Password - Lösenord - Copy password to clipboard Kopiera lösenord @@ -913,6 +1002,22 @@ Spara ändringarna? Toggle window Visa/dölj fönster + + Tools + Verktyg + + + Copy username + Kopiera användarnamn + + + Copy password + Kopiera lösenord + + + Export to CSV file + Exportera till CSV-fil + PasswordGeneratorWidget @@ -1091,15 +1196,11 @@ Spara ändringarna? Open previous databases on startup - Öppna senaste databasen är programmet startar - - - Mark as modified on expanded state changes - Markera som ändrad när utökat läge ändras + Öppna senaste databasen när programmet startar Automatically save on exit - Spara automatiskt är applikationen anslutas + Spara automatiskt när applikationen anslutas Automatically save after every change @@ -1133,6 +1234,10 @@ Spara ändringarna? Hide window to system tray when minimized Vid minimering, minimera fönstret till systemfältet + + Remember last key files + Komihåg senaste nyckel-filen + SettingsWidgetSecurity @@ -1163,14 +1268,6 @@ Spara ändringarna? Unlock database Lås upp databas - - Error - Fel - - - Wrong key. - Fel lösenord - WelcomeWidget @@ -1193,10 +1290,6 @@ Spara ändringarna? path to a custom config file Sökväg till egen konfigurations-fil - - password of the database (DANGEROUS!) - lösenord för databasen (FARLIGT!) - key file of the database nyckel-fil för databas diff --git a/share/translations/keepassx_uk.ts b/share/translations/keepassx_uk.ts new file mode 100644 index 00000000..18d124a1 --- /dev/null +++ b/share/translations/keepassx_uk.ts @@ -0,0 +1,1300 @@ + + + AboutDialog + + About KeePassX + Про KeePassX + + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + KeePassX розповсюджується на умовах Загальної публічної ліцензії GNU (GPL) версії 2 або (на ваш вибір) версії 3. + + + Revision + Ревізія + + + Using: + Використання: + + + + AutoType + + Auto-Type - KeePassX + Автозаповнення — KeePassX + + + Couldn't find an entry that matches the window title: + Не знайдено запис, що відповідає заголовку вікна: + + + + AutoTypeAssociationsModel + + Window + Вікно + + + Sequence + Послідовність + + + Default sequence + Типова послідовність + + + + AutoTypeSelectDialog + + Auto-Type - KeePassX + Автозаповнення — KeePassX + + + Select entry to Auto-Type: + Оберіть запис для автозаповнення: + + + + ChangeMasterKeyWidget + + Password + Пароль + + + Enter password: + Введіть пароль: + + + Repeat password: + Повторіть пароль: + + + Key file + Файл-ключ + + + Browse + Огляд + + + Create + Створити + + + Key files + Файли-ключі + + + All files + Всі файли + + + Create Key File... + Створити файл-ключ... + + + Error + Помилка + + + Unable to create Key File : + Неможливо створити файл-ключ: + + + Select a key file + Обрати файл-ключ + + + Question + Питання + + + Do you really want to use an empty string as password? + Ви дійсно хочете використати порожній рядок в якості пароля? + + + Different passwords supplied. + Паролі не співпадають. + + + Failed to set key file + Не вдалося встановити файл-ключ + + + Failed to set %1 as the Key file: +%2 + Не вдалося встановити %1 в якості файл-ключа: +%2 + + + + DatabaseOpenWidget + + Enter master key + Введіть майстер-пароль + + + Key File: + Файл-ключ: + + + Password: + Пароль: + + + Browse + Огляд + + + Error + Помилка + + + Unable to open the database. + Неможливо відкрити сховище. + + + Can't open key file + Не вдається відкрити файл-ключ + + + All files + Всі файли + + + Key files + Файли-ключі + + + Select key file + Оберіть файл-ключ + + + + DatabaseSettingsWidget + + Database name: + Назва сховища: + + + Database description: + Опис сховища: + + + Transform rounds: + Раундів перетворень: + + + Default username: + Типове ім’я користувача: + + + Use recycle bin: + Використати смітник: + + + MiB + MiB + + + Benchmark + Перевірка + + + Max. history items: + Максимум записів історії: + + + Max. history size: + Максимальний розмір історії: + + + + DatabaseTabWidget + + Root + Корінь + + + KeePass 2 Database + Сховище KeePass 2 + + + All files + Всі файли + + + Open database + Відкрити сховище + + + Warning + Увага + + + File not found! + Файл не знайдено! + + + Open KeePass 1 database + Відкрити сховище KeePass 1 + + + KeePass 1 database + Сховище KeePass 1 + + + All files (*) + Всі файли (*) + + + Close? + Закрити? + + + Save changes? + Зберегти зміни? + + + "%1" was modified. +Save changes? + "%1" змінено. +Зберегти зміни? + + + Error + Помилка + + + Writing the database failed. + Записати сховище не вдалося. + + + Save database as + Зберегти сховище як + + + New database + Нове сховище + + + locked + заблоковано + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + Сховище, яке ви хочете відкрити, заблоковано іншою запущеною копією KeePassX. Все одно відкрити? Сховище буде відкрито тільки для читання. + + + Lock database + Заблокувати сховище + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + Не можливо заблокувати базу даних, яку ви в даний час редагуєте. +Натисніть Скасувати, щоб завершити зміни або скасувати їх. + + + This database has never been saved. +You can save the database or stop locking it. + Це сховище не було збережено. +Ви можете зберегти сховище або зупинити його блокування. + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + В сховище було внесено зміни. +Ви хочете зберегти його перед блокуванням? +Інакше внесені зміни буде втрачено. + + + "%1" is in edit mode. +Discard changes and close anyway? + «%1» в режимі редагування. +Відхилити зміни і все одно закрити? + + + Export database to CSV file + Експортувати сховище в файл CSV + + + CSV file + Файл CSV + + + Writing the CSV file failed. + Не вдалось записати CSV файл. + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + Це сховище заблоковано іншою запущеною копією KeePassX. +Ви впевнені, що хочете зберегти його? + + + + DatabaseWidget + + Change master key + Змінити майстер-пароль + + + Delete entry? + Видалити запис? + + + Do you really want to delete the entry "%1" for good? + Ви дійсно хочете видалити запис «%1»? + + + Delete entries? + Видалити записи? + + + Do you really want to delete %1 entries for good? + Ви дійсно хочете назавжди видалити записи - %1 ? + + + Move entries to recycle bin? + Перемістити записи до смітника? + + + Do you really want to move %n entry(s) to the recycle bin? + Ви дійсно хочете перемістити %n запис в смітник?Ви дійсно хочете перемістити %n записи в смітник?Ви дійсно хочете перемістити %n записів в смітник? + + + Delete group? + Видалити групу? + + + Do you really want to delete the group "%1" for good? + Ви дійсно хочете назавжди видалити групу «%1»? + + + Current group + Поточна група + + + Error + Помилка + + + Unable to calculate master key + Неможливо вирахувати майстер-пароль + + + + EditEntryWidget + + Entry + Запис + + + Advanced + Розширені + + + Icon + Значок + + + Auto-Type + Автозаповнення + + + Properties + Параметри + + + History + Історія + + + Entry history + Історія запису + + + Add entry + Додати запис + + + Edit entry + Змінити запис + + + Error + Помилка + + + Different passwords supplied. + Паролі не співпадають. + + + New attribute + Новий атрибут + + + Select file + Вибрати файл + + + Unable to open file + Неможливо відкрити файл + + + Save attachment + Зберегти вкладення + + + Unable to save the attachment: + + Неможливо зберегти вкладення: + + + + Tomorrow + Завтра + + + %n week(s) + %n тиждень%n тижні%n тижнів + + + %n month(s) + %n місяць%n місяці%n місяців + + + 1 year + 1 рік + + + + EditEntryWidgetAdvanced + + Additional attributes + Додаткові атрибути + + + Add + Додати + + + Edit + Змінити + + + Remove + Видалити + + + Attachments + Вкладення + + + Save + Зберегти + + + Open + Відкрити + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + Увімкнути автозаповнення для цього запису + + + Inherit default Auto-Type sequence from the group + Успадкувати типову послідовність автозаповнення від групи + + + Use custom Auto-Type sequence: + Використовувати свою послідовність автозаповнення: + + + + + + + + + - + - + + + Window title: + Заголовок вікна: + + + Use default sequence + Використовувати типову послідовність + + + Set custom sequence: + Встановити свою послідовність: + + + + EditEntryWidgetHistory + + Show + Показати + + + Restore + Відновити + + + Delete + Видалити + + + Delete all + Видалити все + + + + EditEntryWidgetMain + + Title: + Заголовок: + + + Username: + Ім’я користувача: + + + Password: + Пароль: + + + Repeat: + Пароль ще раз: + + + Gen. + Генер. + + + URL: + URL: + + + Expires + Закінчується + + + Presets + Заготовки + + + Notes: + Примітки: + + + + EditGroupWidget + + Group + Група + + + Icon + Значок + + + Properties + Властивості + + + Add group + Додати групу + + + Edit group + Редагувати групу + + + Enable + Увімкнено + + + Disable + Вимкнено + + + Inherit from parent group (%1) + Успадкувати від батьківської групи (%1) + + + + EditGroupWidgetMain + + Name + Ім’я + + + Notes + Примітки + + + Expires + Закінчується + + + Search + Пошук + + + Auto-type + Автозаповнення + + + Use default auto-type sequence of parent group + Використовувати типову послідовність автозаповнення батьківської групи + + + Set default auto-type sequence + Типова послідовність автозаповнення + + + + EditWidgetIcons + + Use default icon + Використовувати типовий значок + + + Use custom icon + Використовувати свій значок + + + Add custom icon + Додати свій значок + + + Delete custom icon + Видалити свій значок + + + Images + Зображення + + + All files + Всі файли + + + Select Image + Вибір зображення + + + Can't delete icon! + Неможливо видалити значок! + + + Can't delete icon. Still used by %n item(s). + Ви дійсно хочете перемістити %n запис в смітник?Ви дійсно хочете перемістити %n записи в смітник?Ви дійсно хочете перемістити %n записів в смітник? + + + + EditWidgetProperties + + Created: + Створено: + + + Modified: + Змінено: + + + Accessed: + Доступ: + + + Uuid: + Uuid: + + + + EntryAttributesModel + + Name + Ім’я + + + + EntryHistoryModel + + Last modified + Остання зміна + + + Title + Заголовок + + + Username + Ім’я користувача + + + URL + URL + + + + EntryModel + + Group + Група + + + Title + Заголовок + + + Username + Ім’я користувача + + + URL + URL + + + + Group + + Recycle Bin + Смітник + + + + KeePass1OpenWidget + + Import KeePass1 database + Імпортувати сховище KeePass 1 + + + Error + Помилка + + + Unable to open the database. + Неможливо відкрити сховище. + + + + KeePass1Reader + + Unable to read keyfile. + Неможливо прочитати файл-ключ. + + + Not a KeePass database. + Це не сховище KeePass. + + + Unsupported encryption algorithm. + Алгоритм шифрування не підтримується. + + + Unsupported KeePass database version. + Версія сховища KeePass не підтримується. + + + Root + Корінь + + + Unable to calculate master key + Неможливо вирахувати майстер-пароль + + + + KeePass2Reader + + Not a KeePass database. + Не сховище KeePass. + + + Unsupported KeePass database version. + Версія сховища KeePass не підтримується. + + + Wrong key or database file is corrupt. + Неправильний ключ або файл сховища пошкоджено. + + + Unable to calculate master key + Неможливо вирахувати майстер-пароль + + + The selected file is an old KeePass 1 database (.kdb). + +You can import it by clicking on Database > 'Import KeePass 1 database'. +This is a one-way migration. You won't be able to open the imported database with the old KeePassX 0.4 version. + Обрано файл сховища попередньої версії KeePass 1 (.kdb). + +Ви можете імпортувати його, натиснувши Сховище > 'Імпортувати сховище KeePass 1'. +Це односторонній спосіб міграції. Ви не зможете відкрити імпортоване сховище в попередній версії KeePassX 0.4. + + + + Main + + Fatal error while testing the cryptographic functions. + Невиправна помилка в процесі тестування криптографічних функцій. + + + KeePassX - Error + KeePassX — Помилка + + + + MainWindow + + Database + Сховище + + + Recent databases + Недавні сховища + + + Help + Довідка + + + Entries + Записи + + + Copy attribute to clipboard + Копіювати атрибут в буфер обміну + + + Groups + Групи + + + View + Вигляд + + + Quit + Вихід + + + About + Про програму + + + Open database + Відкрити сховище + + + Save database + Зберегти сховище + + + Close database + Закрити сховище + + + New database + Нове сховище + + + Add new entry + Додати новий запис + + + View/Edit entry + Проглянути/змінити запис + + + Delete entry + Видалити запис + + + Add new group + Додати нову групу + + + Edit group + Редагувати групу + + + Delete group + Видалити групу + + + Save database as + Зберегти сховище як + + + Change master key + Змінити майстер-пароль + + + Database settings + Параметри сховища + + + Import KeePass 1 database + Імпортувати сховище KeePass 1 + + + Clone entry + Клонувати запис + + + Find + Знайти + + + Copy username to clipboard + Копіювати ім’я користувача в буфер обміну + + + Copy password to clipboard + Копіювати пароль в буфер обміну + + + Settings + Налаштування + + + Perform Auto-Type + Здійснити автозаповнення + + + Open URL + Відкрити URL + + + Lock databases + Заблокувати сховище + + + Title + Заголовок + + + URL + URL + + + Notes + Примітки + + + Show toolbar + Показати панель инструментів + + + read-only + тільки для читання + + + Toggle window + Перемкнути вікно + + + Tools + Інструменти + + + Copy username + Копіювати ім’я користувача + + + Copy password + Копіювати пароль + + + Export to CSV file + Експортувати в файл CSV + + + + PasswordGeneratorWidget + + Password: + Пароль: + + + Length: + Довжина: + + + Character Types + Види символів + + + Upper Case Letters + Великі літери + + + Lower Case Letters + Малі літери + + + Numbers + Цифри + + + Special Characters + Спеціальні символи + + + Exclude look-alike characters + Виключити неоднозначні символи + + + Ensure that the password contains characters from every group + Переконатися, що пароль містить символи всіх видів + + + Accept + Прийняти + + + + QCommandLineParser + + Displays version information. + Показує інформацію про версію. + + + Displays this help. + Показує цю довідку. + + + Unknown option '%1'. + Невідома опція «%1». + + + Unknown options: %1. + Невідомі опції %1. + + + Missing value after '%1'. + Пропущено значення після «%1». + + + Unexpected value after '%1'. + Непередбачене значення після «%1». + + + [options] + [опції] + + + Usage: %1 + Використання: %1 + + + Options: + Опції: + + + Arguments: + Аргументи: + + + + QSaveFile + + Existing file %1 is not writable + Існуючий файл %1 непридатний для запису + + + Writing canceled by application + Запис відмінено застосунком + + + Partial write. Partition full? + Частковий запис. Разділ переповнений? + + + + QtIOCompressor + + Internal zlib error when compressing: + Внутрішня помилка zlib при стисненні: + + + Error writing to underlying device: + Помилка запису на основний пристрій: + + + Error opening underlying device: + Помилка відкриття основного пристрою: + + + Error reading data from underlying device: + Помилка читання з основного пристрою: + + + Internal zlib error when decompressing: + Внутрішня помилка zlib при розпакуванні: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + Формат gzip не підтримується в цій версії zlib. + + + Internal zlib error: + Внутрішня помилка zlib: + + + + SearchWidget + + Find: + Знайти: + + + Case sensitive + Враховується регістр + + + Current group + Поточна група + + + Root group + Коренева група + + + + SettingsWidget + + Application Settings + Параметри застосунку + + + General + Загальні + + + Security + Безпека + + + + SettingsWidgetGeneral + + Remember last databases + Пам’ятати останнє сховище + + + Open previous databases on startup + Відкривати останнє сховище під час запуску + + + Automatically save on exit + Автоматично зберігати при виході + + + Automatically save after every change + Автоматично зберігати після кожної зміни + + + Minimize when copying to clipboard + Згортати при копіюванні до буфера обміну + + + Use group icon on entry creation + Використовувати для нових записів значок групи + + + Global Auto-Type shortcut + Глобальні сполучення клавіш для автозаповнення + + + Use entry title to match windows for global auto-type + Використовувати заголовок запису для вибору вікон для глобального автозаповнення + + + Language + Мова + + + Show a system tray icon + Показувати значок в треї + + + Hide window to system tray when minimized + При згортанні ховати вікно в область системних повідомлень + + + Remember last key files + Пам’ятати останні файл-ключі + + + + SettingsWidgetSecurity + + Clear clipboard after + Очищати буфер обміну через + + + sec + сек + + + Lock databases after inactivity of + Заблокувати сховище, неактивне протягом + + + Show passwords in cleartext by default + Типово показувати пароль у відкритому вигляді + + + Always ask before performing auto-type + Завжди запитувати перед автозаповненням + + + + UnlockDatabaseWidget + + Unlock database + Розблокувати сховище + + + + WelcomeWidget + + Welcome! + Ласкаво просимо! + + + + main + + KeePassX - cross-platform password manager + KeePassX — кросплатформний менеджер паролів + + + filename of the password database to open (*.kdbx) + назва файла сховища паролів, що відкривається (*.kdbx) + + + path to a custom config file + шлях до власного файла налаштувань + + + key file of the database + файл-ключ сховища + + + \ No newline at end of file diff --git a/share/translations/keepassx_zh_CN.ts b/share/translations/keepassx_zh_CN.ts new file mode 100644 index 00000000..aae763da --- /dev/null +++ b/share/translations/keepassx_zh_CN.ts @@ -0,0 +1,1280 @@ + + + AboutDialog + + About KeePassX + 关于 KeePassX + + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. + KeePassX 使用的是第 2 版 GNU 通用公共授权协议(GPL)(你可以根据需要选用第 3 版). + + + + AutoType + + Auto-Type - KeePassX + KeePassX - 自动输入 + + + Couldn't find an entry that matches the window title: + 无法找到符合窗口标题的项目 + + + + AutoTypeAssociationsModel + + Window + 窗口 + + + Sequence + 顺序 + + + Default sequence + 默认顺序 + + + + AutoTypeSelectDialog + + Auto-Type - KeePassX + KeePassX - 自动输入 + + + Select entry to Auto-Type: + 选择自动输入的项目 + + + + ChangeMasterKeyWidget + + Password + 密码 + + + Enter password: + 输入密码: + + + Repeat password: + 重复密码: + + + Key file + 秘钥文件 + + + Browse + 浏览 + + + Create + 创建 + + + Key files + 秘钥文件 + + + All files + 所有文件 + + + Create Key File... + 创建秘钥文件... + + + Error + 错误 + + + Unable to create Key File : + 无法创建秘钥文件: + + + Select a key file + 选择一个秘钥文件 + + + Question + 问题 + + + Do you really want to use an empty string as password? + 你确定要使用空密码? + + + Different passwords supplied. + 你输入了不同的密码 + + + Failed to set key file + 设置秘钥文件失败 + + + Failed to set %1 as the Key file: +%2 + 无法设置 %1 为秘钥文件: +%2 + + + + DatabaseOpenWidget + + Enter master key + 输入主密码 + + + Key File: + 秘钥文件: + + + Password: + 密码: + + + Browse + 浏览 + + + Error + 错误 + + + Unable to open the database. + 无法打开数据库 + + + Can't open key file + 无法打开秘钥文件 + + + All files + 所有文件 + + + Key files + 秘钥文件 + + + Select key file + 选择秘钥文件 + + + + DatabaseSettingsWidget + + Database name: + 数据库名称: + + + Database description: + 数据库介绍: + + + Transform rounds: + 加密转换次数: + + + Default username: + 默认用户名: + + + Use recycle bin: + 使用垃圾桶: + + + MiB + MiB + + + Benchmark + 基准测试 + + + Max. history items: + 最大历史记录数: + + + Max. history size: + 最大历史记录大小: + + + + DatabaseTabWidget + + Root + + + + KeePass 2 Database + KeePass 2 数据库 + + + All files + 所有文件 + + + Open database + 打开数据库 + + + Warning + 警告 + + + File not found! + 找不到文件! + + + Open KeePass 1 database + 打开 KeePass 1 数据库 + + + KeePass 1 database + KeePass 1 数据库 + + + All files (*) + 所有文件 (*) + + + Close? + 关闭? + + + Save changes? + 保存修改? + + + "%1" was modified. +Save changes? + "%1" 已被修改。 +要保存吗? + + + Error + 错误 + + + Writing the database failed. + 数据库写入失败 + + + Save database as + 另存数据库为 + + + New database + 新建数据库 + + + locked + 已锁 + + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + 你要打开的数据库已被另一个KeePassX锁住。 +你确定要以只读方式的打开吗? + + + Lock database + 锁住数据库 + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + 不能锁住正在编辑的数据库。 +选择取消继续编辑, 确定忽略编辑。 + + + This database has never been saved. +You can save the database or stop locking it. + 数据库未保存。 +你可以保存数据库或者中止锁住它。 + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + 数据库已经更改。 +你想在锁住它以前保存修改吗? +否则修改将会丢失。 + + + "%1" is in edit mode. +Discard changes and close anyway? + + + + Export database to CSV file + + + + CSV file + + + + Writing the CSV file failed. + + + + + DatabaseWidget + + Change master key + 更改主密码 + + + Delete entry? + 删除项目? + + + Do you really want to delete the entry "%1" for good? + 你确定永远删除 "%1" 项目吗? + + + Delete entries? + 删除项目? + + + Do you really want to delete %1 entries for good? + 你确定永远删除 "%1" 项目吗? + + + Move entries to recycle bin? + 移动项目到垃圾桶? + + + Do you really want to move %n entry(s) to the recycle bin? + 你确定要将 %n 个项目移到垃圾桶? + + + Delete group? + 删除群组? + + + Do you really want to delete the group "%1" for good? + 你确定永远删除 "%1" 群组吗? + + + Current group + 当前群组 + + + Error + 错误 + + + Unable to calculate master key + 无法计算主密码 + + + + EditEntryWidget + + Entry + 项目 + + + Advanced + 高级 + + + Icon + 图标 + + + Auto-Type + 自动输入 + + + Properties + 属性 + + + History + 历史记录 + + + Entry history + 项目历史 + + + Add entry + 添加项目 + + + Edit entry + 编辑项目 + + + Error + 错误 + + + Different passwords supplied. + 你输入了不同的密码 + + + New attribute + 新建属性 + + + Select file + 选择文件 + + + Unable to open file + 无法打开文件 + + + Save attachment + 保存附件 + + + Unable to save the attachment: + + 无法保存附件: + + + + Tomorrow + 明天 + + + %n week(s) + %n 周 + + + %n month(s) + %n 个月 + + + 1 year + 1 年 + + + + EditEntryWidgetAdvanced + + Additional attributes + 附加属性 + + + Add + 添加 + + + Edit + 编辑 + + + Remove + 移除 + + + Attachments + 附件 + + + Save + 保存 + + + Open + 打开 + + + + EditEntryWidgetAutoType + + Enable Auto-Type for this entry + 打开此项目的自动输入 + + + Inherit default Auto-Type sequence from the group + 从父群组继承默认的自动输入顺序 + + + Use custom Auto-Type sequence: + 使用自定义自动输入顺序 + + + + + + + + + - + - + + + Window title: + 窗口标题: + + + Use default sequence + 使用默认顺序 + + + Set custom sequence: + 设置自定义顺序 + + + + EditEntryWidgetHistory + + Show + 显示 + + + Restore + 还原 + + + Delete + 删除 + + + Delete all + 全部删除 + + + + EditEntryWidgetMain + + Title: + 标题: + + + Username: + 用户名: + + + Password: + 密码: + + + Repeat: + 重复: + + + Gen. + 生成. + + + URL: + 网址: + + + Expires + 过期 + + + Presets + 预设 + + + Notes: + 备注: + + + + EditGroupWidget + + Group + 群组 + + + Icon + 图标 + + + Properties + 属性 + + + Add group + 添加群组 + + + Edit group + 编辑群组 + + + Enable + 启用 + + + Disable + 禁用 + + + Inherit from parent group (%1) + 继承自父群组(%1) + + + + EditGroupWidgetMain + + Name + 名称 + + + Notes + 备注 + + + Expires + 过期 + + + Search + 搜索 + + + Auto-type + 自动输入 + + + Use default auto-type sequence of parent group + 使用父群组默认顺序 + + + Set default auto-type sequence + 设置默认自动输入顺序 + + + + EditWidgetIcons + + Use default icon + 使用默认图标 + + + Use custom icon + 使用自定义图标 + + + Add custom icon + 添加自定义图标 + + + Delete custom icon + 删除自定义图标 + + + Images + 图片 + + + All files + 所有文件 + + + Select Image + 选择图片 + + + Can't delete icon! + 不能删除图标! + + + Can't delete icon. Still used by %n item(s). + 不能删除图标。仍在被 %n 个项目使用 + + + + EditWidgetProperties + + Created: + 已创建: + + + Modified: + 已修改: + + + Accessed: + 已存取: + + + Uuid: + Uuid(通用唯一识别码): + + + + EntryAttributesModel + + Name + 名称 + + + + EntryHistoryModel + + Last modified + 最后修改 + + + Title + 标题 + + + Username + 用户名 + + + URL + 网址 + + + + EntryModel + + Group + 群组 + + + Title + 标题 + + + Username + 用户名 + + + URL + 网址 + + + + Group + + Recycle Bin + 垃圾桶 + + + + KeePass1OpenWidget + + Import KeePass1 database + 导入KeePass 1 数据库 + + + Error + 错误 + + + Unable to open the database. + 无法打开数据库。 + + + + KeePass1Reader + + Unable to read keyfile. + 无法读取秘钥文件。 + + + Not a KeePass database. + 不是KeePass 数据库。 + + + Unsupported encryption algorithm. + 不支持的加密算法。 + + + Unsupported KeePass database version. + 不支持的KeePass 数据库版本。 + + + Root + + + + Unable to calculate master key + 无法计算主密码 + + + + KeePass2Reader + + Not a KeePass database. + 不是KeePass 的数据库。 + + + Unsupported KeePass database version. + 不支持的KeePass 数据库版本。 + + + Wrong key or database file is corrupt. + 秘钥错误或数据库损坏。 + + + Unable to calculate master key + 无法计算主密码 + + + + Main + + Fatal error while testing the cryptographic functions. + 在测试加密函数时发生重大错误。 + + + KeePassX - Error + KeePassX - 错误 + + + + MainWindow + + Database + 数据库 + + + Recent databases + 最近的数据库 + + + Help + 帮助 + + + Entries + 项目 + + + Copy attribute to clipboard + 将属性复制到剪贴板 + + + Groups + 群组 + + + View + 显示 + + + Quit + 退出 + + + About + 关于 + + + Open database + 打开数据库 + + + Save database + 保存数据库 + + + Close database + 关闭数据库 + + + New database + 新建数据库 + + + Add new entry + 新增项目 + + + View/Edit entry + 浏览/编辑项目 + + + Delete entry + 删除项目 + + + Add new group + 新增群组 + + + Edit group + 编辑群组 + + + Delete group + 删除群组 + + + Save database as + 另存数据库为 + + + Change master key + 更改主密码 + + + Database settings + 数据库设置 + + + Import KeePass 1 database + 导入KeePass 1 数据库 + + + Clone entry + 复制项目 + + + Find + 查找 + + + Copy username to clipboard + 将用户名复制到剪贴板 + + + Copy password to clipboard + 将密码复制到剪贴板 + + + Settings + 设置 + + + Perform Auto-Type + 执行自动输入 + + + Open URL + 打开网址 + + + Lock databases + 锁住数据库 + + + Title + 标题 + + + URL + 网址 + + + Notes + 备注 + + + Show toolbar + 显示工具栏 + + + read-only + 只读 + + + Toggle window + 切换窗口 + + + Tools + 工具 + + + Copy username + + + + Copy password + + + + Export to CSV file + + + + + PasswordGeneratorWidget + + Password: + 密码: + + + Length: + 长度: + + + Character Types + 字符类型 + + + Upper Case Letters + 大写英文字母 + + + Lower Case Letters + 小写英文字母 + + + Numbers + 数字 + + + Special Characters + 特殊字符 + + + Exclude look-alike characters + 去除相似的字符 + + + Ensure that the password contains characters from every group + 确保密码包含每种的字符 + + + Accept + 接受 + + + + QCommandLineParser + + Displays version information. + 显示版本信息 + + + Displays this help. + 显示帮助信息 + + + Unknown option '%1'. + 未知选项 '%1'。 + + + Unknown options: %1. + 未知选项: %1。 + + + Missing value after '%1'. + 在 '%1' 后缺少值。 + + + Unexpected value after '%1'. + '%1' 后有无法识别的值。 + + + [options] + [选项] + + + Usage: %1 + 已用:%1 + + + Options: + 选项: + + + Arguments: + 参数: + + + + QSaveFile + + Existing file %1 is not writable + 当前文件%1 不可写 + + + Writing canceled by application + 应用程序取消写入 + + + Partial write. Partition full? + 写入不完整。磁盘满了吗? + + + + QtIOCompressor + + Internal zlib error when compressing: + 压缩函数库 zlib 出错: + + + Error writing to underlying device: + 下层设备写入出错: + + + Error opening underlying device: + 打开下层设备出错: + + + Error reading data from underlying device: + 读取下层设备出错: + + + Internal zlib error when decompressing: + 内部函数库 zlib 解压错误: + + + + QtIOCompressor::open + + The gzip format not supported in this version of zlib. + 当前版本的压缩函数库 zlib 不支援gzip。 + + + Internal zlib error: + 内部函数库 zlib 发生错误: + + + + SearchWidget + + Find: + 查找: + + + Case sensitive + 区分大小写 + + + Current group + 当前群组 + + + Root group + 根群组 + + + + SettingsWidget + + Application Settings + 应用程序设置 + + + General + 常规 + + + Security + 安全 + + + + SettingsWidgetGeneral + + Remember last databases + 记住最近的数据库 + + + Open previous databases on startup + 在启动时打开最近的数据库 + + + Automatically save on exit + 离开后自动保存 + + + Automatically save after every change + 修改后自动保存 + + + Minimize when copying to clipboard + 复制到剪贴板后最小化 + + + Use group icon on entry creation + 新增项目时使用群组图标 + + + Global Auto-Type shortcut + 自动输入全局快捷键 + + + Use entry title to match windows for global auto-type + 使用项目标题来查找自动输入的目标窗口 + + + Language + 语言 + + + Show a system tray icon + 显示任务栏图标 + + + Hide window to system tray when minimized + 将窗口最小化至任务栏 + + + Remember last key files + 记住最近的秘钥文件 + + + + SettingsWidgetSecurity + + Clear clipboard after + 在多久后清除剪贴板 + + + sec + + + + Lock databases after inactivity of + 在多久没有动作之后锁住数据库 + + + Show passwords in cleartext by default + 默认以明码显示密码 + + + Always ask before performing auto-type + 在执行自动输入前询问 + + + + UnlockDatabaseWidget + + Unlock database + 解锁数据库 + + + + WelcomeWidget + + Welcome! + 欢迎! + + + + main + + KeePassX - cross-platform password manager + KeePassX - 跨平台密码管理软件 + + + filename of the password database to open (*.kdbx) + 打开密码数据库文件名(*.kdbx) + + + path to a custom config file + 自定义配置文件路径 + + + password of the database (DANGEROUS!) + 数据库密码(危险!) + + + key file of the database + 数据库秘钥文件 + + + \ No newline at end of file diff --git a/share/translations/keepassx_zh_TW.ts b/share/translations/keepassx_zh_TW.ts index 76307744..1d7c2f2d 100644 --- a/share/translations/keepassx_zh_TW.ts +++ b/share/translations/keepassx_zh_TW.ts @@ -9,6 +9,10 @@ KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. KeePassX 是使用第 2 版 GNU 通用公共授權條款所發佈的 (或者,可根據你的選擇選用第 3 版) + + Revision + 修改紀錄 + AutoType @@ -109,6 +113,16 @@ Different passwords supplied. 提供了不同的密碼 + + Failed to set key file + 無法設定金鑰檔案 + + + Failed to set %1 as the Key file: +%2 + 無法設定 %1 成為金鑰檔案: +%2 + DatabaseOpenWidget @@ -234,11 +248,6 @@ Close? 關閉? - - "%1" is in edit mode. -Close anyway? - "%1" 正在編輯中。仍然要關閉嗎? - Save changes? 儲存修改? @@ -268,6 +277,60 @@ Save changes? locked 已鎖住 + + The database you are trying to open is locked by another instance of KeePassX. +Do you want to open it anyway? Alternatively the database is opened read-only. + 你嘗試要打開的資料庫已經被另一個正在執行的 KeePassX 鎖定 +你要打開它嗎?或者,打開唯讀的資料庫 + + + Lock database + 鎖定資料庫 + + + Can't lock the database as you are currently editing it. +Please press cancel to finish your changes or discard them. + 無法鎖定資料庫,因為目前你正在編輯它 +請按下取消完成修改或放棄 + + + This database has never been saved. +You can save the database or stop locking it. + 這個資料庫尚未被儲存 +你能儲存資料庫或不再鎖定它 + + + This database has been modified. +Do you want to save the database before locking it? +Otherwise your changes are lost. + 這個資料庫已經被修改 +想要在鎖定之前,儲存資料庫嗎? +否則,這次修改將會遺失 + + + "%1" is in edit mode. +Discard changes and close anyway? + "%1" 正在編輯模式。 +是否要放棄編輯及關閉? + + + Export database to CSV file + 將資料庫輸出成 CSV 檔案 + + + CSV file + CSV 檔案 + + + Writing the CSV file failed. + 寫入 CSV 檔案失敗 + + + The database you are trying to save as is locked by another instance of KeePassX. +Do you want to save it anyway? + 你嘗試要打開的資料庫已經被另一個正在執行的 KeePassX 鎖定 +還要儲存嗎? + DatabaseWidget @@ -311,6 +374,14 @@ Save changes? Current group 目前的群組 + + Error + 錯誤 + + + Unable to calculate master key + 無法計算主金鑰 + EditEntryWidget @@ -423,6 +494,10 @@ Save changes? Save 儲存 + + Open + 打開 + EditEntryWidgetAutoType @@ -574,6 +649,14 @@ Save changes? Auto-type 自動輸入 + + Use default auto-type sequence of parent group + 使用預設的父群組自動輸入序列 + + + Set default auto-type sequence + 設定預設自動輸入序列 + EditWidgetIcons @@ -722,6 +805,10 @@ Save changes? Root + + Unable to calculate master key + 無法計算主金鑰 + KeePass2Reader @@ -737,6 +824,10 @@ Save changes? Wrong key or database file is corrupt. 無法的金鑰或資料庫損壞 + + Unable to calculate master key + 無法計算主金鑰 + Main @@ -775,10 +866,6 @@ Save changes? Groups 群組 - - Extras - 其它 - View 顯示 @@ -855,18 +942,10 @@ Save changes? Find 尋找 - - Username - 使用者名稱 - Copy username to clipboard 將使用者名稱複製到剪貼簿 - - Password - 密碼 - Copy password to clipboard 將密碼複製到剪貼簿 @@ -911,6 +990,22 @@ Save changes? Toggle window 切換視窗 + + Tools + 工具 + + + Copy username + 複製使用者名稱 + + + Copy password + 複製密碼 + + + Export to CSV file + 輸出成 CSV 檔案 + PasswordGeneratorWidget @@ -1091,10 +1186,6 @@ Save changes? Open previous databases on startup 在啟動時開啟最近的資料庫 - - Mark as modified on expanded state changes - 擴展狀態發生變化時,標記為已修改 - Automatically save on exit 離開時,自動儲存 @@ -1131,6 +1222,10 @@ Save changes? Hide window to system tray when minimized 將視窗最小化至工作列 + + Remember last key files + 記住最近的金鑰檔案 + SettingsWidgetSecurity @@ -1161,14 +1256,6 @@ Save changes? Unlock database 解鎖資料庫 - - Error - 錯誤 - - - Wrong key. - 錯誤的金鑰 - WelcomeWidget @@ -1191,10 +1278,6 @@ Save changes? path to a custom config file 自定設定檔的路徑 - - password of the database (DANGEROUS!) - 資料庫的密碼(危險!) - key file of the database 資料庫的金鑰 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 67eb44c6..9277f772 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,6 +17,17 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) configure_file(config-keepassx.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-keepassx.h) +include(GetGitRevisionDescription) +get_git_head_revision(GIT_REFSPEC GIT_HEAD) +git_describe(GIT_DESCRIBE --long) + +if (NOT GIT_HEAD OR NOT GIT_DESCRIBE) + set(GIT_HEAD "") + set(GIT_DESCRIBE "") +endif() + +configure_file(version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/version.h @ONLY) + set(keepassx_SOURCES autotype/AutoType.cpp autotype/AutoTypeAction.cpp @@ -43,9 +54,6 @@ set(keepassx_SOURCES core/ListDeleter.h core/Metadata.cpp core/PasswordGenerator.cpp - core/qlockfile.cpp - core/qsavefile.cpp - core/qsavefile_p.h core/SignalMultiplexer.cpp core/TimeDelta.cpp core/TimeInfo.cpp @@ -53,19 +61,19 @@ set(keepassx_SOURCES core/Tools.cpp core/Translator.cpp core/Uuid.cpp - core/qcommandlineoption.cpp - core/qcommandlineparser.cpp crypto/Crypto.cpp crypto/CryptoHash.cpp crypto/Random.cpp crypto/SymmetricCipher.cpp crypto/SymmetricCipherBackend.h crypto/SymmetricCipherGcrypt.cpp + format/CsvExporter.cpp format/KeePass1.h format/KeePass1Reader.cpp format/KeePass2.h format/KeePass2RandomStream.cpp format/KeePass2Reader.cpp + format/KeePass2Repair.cpp format/KeePass2Writer.cpp format/KeePass2XmlReader.cpp format/KeePass2XmlWriter.cpp @@ -74,6 +82,7 @@ set(keepassx_SOURCES gui/ChangeMasterKeyWidget.cpp gui/Clipboard.cpp gui/DatabaseOpenWidget.cpp + gui/DatabaseRepairWidget.cpp gui/DatabaseSettingsWidget.cpp gui/DatabaseTabWidget.cpp gui/DatabaseWidget.cpp @@ -127,85 +136,11 @@ set(keepassx_SOURCES streams/SymmetricCipherStream.cpp ) -if(NOT GCRYPT_HAS_SALSA20) - set(keepassx_SOURCES - ${keepassx_SOURCES} - crypto/salsa20/ecrypt-config.h - crypto/salsa20/ecrypt-machine.h - crypto/salsa20/ecrypt-portable.h - crypto/salsa20/ecrypt-sync.h - crypto/salsa20/salsa20.c - crypto/SymmetricCipherSalsa20.cpp - ) -endif() - -if(UNIX) - set(keepassx_SOURCES - ${keepassx_SOURCES} - core/qlockfile_unix.cpp - ) -elseif(MINGW) - set(keepassx_SOURCES - ${keepassx_SOURCES} - core/qlockfile_win.cpp - ) -endif() - set(keepassx_SOURCES_MAINEXE main.cpp ) set(keepassx_MOC - autotype/AutoType.h - autotype/AutoTypeSelectDialog.h - autotype/AutoTypeSelectView.h - autotype/ShortcutWidget.h - autotype/WindowSelectComboBox.h - core/AutoTypeAssociations.h - core/Config.h - core/Database.h - core/Entry.h - core/EntryAttachments.h - core/EntryAttributes.h - core/Group.h - core/InactivityTimer.h - core/Metadata.h - core/qsavefile.h - gui/AboutDialog.h - gui/Application.h - gui/ChangeMasterKeyWidget.h - gui/Clipboard.h - gui/DatabaseOpenWidget.h - gui/DatabaseSettingsWidget.h - gui/DatabaseTabWidget.h - gui/DatabaseWidget.h - gui/DatabaseWidgetStateSync.h - gui/DialogyWidget.h - gui/DragTabBar.h - gui/EditWidget.h - gui/EditWidgetIcons.h - gui/EditWidgetProperties.h - gui/IconModels.h - gui/KeePass1OpenWidget.h - gui/LineEdit.h - gui/MainWindow.h - gui/PasswordEdit.h - gui/PasswordGeneratorWidget.h - gui/PasswordComboBox.h - gui/SettingsWidget.h - gui/SortFilterHideProxyModel.h - gui/UnlockDatabaseWidget.h - gui/WelcomeWidget.h - gui/entry/AutoTypeAssociationsModel.h - gui/entry/EditEntryWidget.h - gui/entry/EntryAttachmentsModel.h - gui/entry/EntryAttributesModel.h - gui/entry/EntryHistoryModel.h - gui/entry/EntryModel.h - gui/entry/EntryView.h - gui/group/EditGroupWidget.h - gui/group/GroupModel.h - gui/group/GroupView.h http/AccessControlDialog.h http/EntryConfig.h http/HttpPasswordGeneratorWidget.h @@ -213,12 +148,6 @@ set(keepassx_MOC http/Protocol.h http/Server.h http/Service.h - keys/CompositeKey_p.h - streams/HashedBlockStream.h - streams/LayeredStream.h - streams/qtiocompressor.h - streams/StoreDataStream.h - streams/SymmetricCipherStream.h ) set(keepassx_FORMS @@ -251,27 +180,21 @@ if(MINGW) ${CMAKE_SOURCE_DIR}/share/windows/icon.rc) endif() -qt4_wrap_ui(keepassx_SOURCES ${keepassx_FORMS}) -qt4_wrap_cpp(keepassx_SOURCES ${keepassx_MOC}) +qt5_wrap_ui(keepassx_SOURCES ${keepassx_FORMS}) add_library(keepassx_core STATIC ${keepassx_SOURCES}) set_target_properties(keepassx_core PROPERTIES COMPILE_DEFINITIONS KEEPASSX_BUILDING_CORE) +target_link_libraries(keepassx_core Qt5::Core Qt5::Concurrent Qt5::Widgets) add_executable(${PROGNAME} WIN32 MACOSX_BUNDLE ${keepassx_SOURCES_MAINEXE}) target_link_libraries(${PROGNAME} keepassx_core - qjson - ${MHD_LIBRARIES} - ${QT_QTCORE_LIBRARY} - ${QT_QTGUI_LIBRARY} - ${QT_QTNETWORK_LIBRARY} + Qt5::Core + Qt5::Concurrent + Qt5::Widgets ${GCRYPT_LIBRARIES} ${ZLIB_LIBRARIES}) -if(UNIX AND NOT APPLE) - target_link_libraries(${PROGNAME} ${QT_QTDBUS_LIBRARY}) -endif() - set_target_properties(${PROGNAME} PROPERTIES ENABLE_EXPORTS ON) if(APPLE) @@ -286,7 +209,7 @@ install(TARGETS ${PROGNAME} add_subdirectory(autotype) -if(APPLE AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8)) +if(APPLE) if(QT_MAC_USE_COCOA AND EXISTS "${QT_LIBRARY_DIR}/Resources/qt_menu.nib") install(DIRECTORY "${QT_LIBRARY_DIR}/Resources/qt_menu.nib" DESTINATION "${DATA_INSTALL_DIR}") @@ -304,7 +227,7 @@ if(APPLE AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8)) install_qt4_executable(${PROGNAME}.app "qjpeg;qgif;qico;qtaccessiblewidgets") endif() -if(MINGW AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8)) +if(MINGW ) set(CPACK_GENERATOR "ZIP") set(CPACK_STRIP_FILES ON) set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSX_VERSION_NUM}") diff --git a/src/autotype/AutoType.cpp b/src/autotype/AutoType.cpp index ce68ae47..15185b29 100644 --- a/src/autotype/AutoType.cpp +++ b/src/autotype/AutoType.cpp @@ -32,7 +32,7 @@ #include "core/Tools.h" #include "gui/MessageBox.h" -AutoType* AutoType::m_instance = Q_NULLPTR; +AutoType* AutoType::m_instance = nullptr; AutoType::AutoType(QObject* parent, bool test) : QObject(parent) @@ -40,8 +40,8 @@ AutoType::AutoType(QObject* parent, bool test) , m_currentGlobalKey(static_cast(0)) , m_currentGlobalModifiers(0) , m_pluginLoader(new QPluginLoader(this)) - , m_plugin(Q_NULLPTR) - , m_executor(Q_NULLPTR) + , m_plugin(nullptr) + , m_executor(nullptr) , m_windowFromGlobal(0) { // prevent crash when the plugin has unresolved symbols @@ -49,7 +49,7 @@ AutoType::AutoType(QObject* parent, bool test) QString pluginName = "keepassx-autotype-"; if (!test) { - pluginName += Tools::platform(); + pluginName += QApplication::platformName(); } else { pluginName += "test"; @@ -68,7 +68,7 @@ AutoType::~AutoType() { if (m_executor) { delete m_executor; - m_executor = Q_NULLPTR; + m_executor = nullptr; } } @@ -79,9 +79,16 @@ void AutoType::loadPlugin(const QString& pluginPath) QObject* pluginInstance = m_pluginLoader->instance(); if (pluginInstance) { m_plugin = qobject_cast(pluginInstance); + m_executor = nullptr; + if (m_plugin) { - m_executor = m_plugin->createExecutor(); - connect(pluginInstance, SIGNAL(globalShortcutTriggered()), SIGNAL(globalShortcutTriggered())); + if (m_plugin->isAvailable()) { + m_executor = m_plugin->createExecutor(); + connect(pluginInstance, SIGNAL(globalShortcutTriggered()), SIGNAL(globalShortcutTriggered())); + } + else { + unloadPlugin(); + } } } @@ -195,11 +202,11 @@ void AutoType::performGlobalAutoType(const QList& dbList) QString message = tr("Couldn't find an entry that matches the window title:"); message.append("\n\n"); message.append(windowTitle); - MessageBox::information(Q_NULLPTR, tr("Auto-Type - KeePassX"), message); + MessageBox::information(nullptr, tr("Auto-Type - KeePassX"), message); } else if ((entryList.size() == 1) && !config()->get("security/autotypeask").toBool()) { m_inAutoType = false; - performAutoType(entryList.first(), Q_NULLPTR, sequenceHash[entryList.first()]); + performAutoType(entryList.first(), nullptr, sequenceHash[entryList.first()]); } else { m_windowFromGlobal = m_plugin->activeWindow(); @@ -218,8 +225,10 @@ void AutoType::performAutoTypeFromGlobal(Entry* entry, const QString& sequence) { Q_ASSERT(m_inAutoType); + m_plugin->raiseWindow(m_windowFromGlobal); + m_inAutoType = false; - performAutoType(entry, Q_NULLPTR, sequence, m_windowFromGlobal); + performAutoType(entry, nullptr, sequence, m_windowFromGlobal); } void AutoType::resetInAutoType() @@ -233,12 +242,12 @@ void AutoType::unloadPlugin() { if (m_executor) { delete m_executor; - m_executor = Q_NULLPTR; + m_executor = nullptr; } if (m_plugin) { m_plugin->unload(); - m_plugin = Q_NULLPTR; + m_plugin = nullptr; } } @@ -566,7 +575,7 @@ bool AutoType::windowMatches(const QString& windowTitle, const QString& windowPa { if (windowPattern.startsWith("//") && windowPattern.endsWith("//") && windowPattern.size() >= 4) { QRegExp regExp(windowPattern.mid(2, windowPattern.size() - 4), Qt::CaseInsensitive, QRegExp::RegExp2); - return regExp.exactMatch(windowTitle); + return (regExp.indexIn(windowTitle) != -1); } else { return WildcardMatcher(windowTitle).match(windowPattern); diff --git a/src/autotype/AutoType.h b/src/autotype/AutoType.h index f3d626c8..d1c88174 100644 --- a/src/autotype/AutoType.h +++ b/src/autotype/AutoType.h @@ -22,8 +22,6 @@ #include #include -#include "core/Global.h" - class AutoTypeAction; class AutoTypeExecutor; class AutoTypePlatformInterface; @@ -37,7 +35,7 @@ class AutoType : public QObject public: QStringList windowTitles(); - void performAutoType(const Entry* entry, QWidget* hideWindow = Q_NULLPTR, + void performAutoType(const Entry* entry, QWidget* hideWindow = nullptr, const QString& customSequence = QString(), WId window = 0); bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers); void unregisterGlobalShortcut(); @@ -62,7 +60,7 @@ private Q_SLOTS: void unloadPlugin(); private: - explicit AutoType(QObject* parent = Q_NULLPTR, bool test = false); + explicit AutoType(QObject* parent = nullptr, bool test = false); ~AutoType(); void loadPlugin(const QString& pluginPath); bool parseActions(const QString& sequence, const Entry* entry, QList& actions); diff --git a/src/autotype/AutoTypeAction.h b/src/autotype/AutoTypeAction.h index 07e050b1..490f0d89 100644 --- a/src/autotype/AutoTypeAction.h +++ b/src/autotype/AutoTypeAction.h @@ -66,7 +66,7 @@ public: class KEEPASSX_EXPORT AutoTypeClearField : public AutoTypeAction { public: - explicit AutoTypeClearField(); + AutoTypeClearField(); AutoTypeAction* clone(); void accept(AutoTypeExecutor* executor); }; diff --git a/src/autotype/AutoTypePlatformPlugin.h b/src/autotype/AutoTypePlatformPlugin.h index 1e78f0d2..dadc7a0d 100644 --- a/src/autotype/AutoTypePlatformPlugin.h +++ b/src/autotype/AutoTypePlatformPlugin.h @@ -26,6 +26,7 @@ class AutoTypePlatformInterface { public: virtual ~AutoTypePlatformInterface() {} + virtual bool isAvailable() = 0; virtual QStringList windowTitles() = 0; virtual WId activeWindow() = 0; virtual QString activeWindowTitle() = 0; @@ -33,6 +34,7 @@ public: virtual void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) = 0; virtual int platformEventFilter(void* event) = 0; virtual int initialTimeout() = 0; + virtual bool raiseWindow(WId window) = 0; virtual void unload() {} virtual AutoTypeExecutor* createExecutor() = 0; diff --git a/src/autotype/AutoTypeSelectDialog.cpp b/src/autotype/AutoTypeSelectDialog.cpp index 36125dec..3e7a2476 100644 --- a/src/autotype/AutoTypeSelectDialog.cpp +++ b/src/autotype/AutoTypeSelectDialog.cpp @@ -33,6 +33,8 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) , m_entryActivatedEmitted(false) { setAttribute(Qt::WA_DeleteOnClose); + // Places the window on the active (virtual) desktop instead of where the main window is. + setAttribute(Qt::WA_X11BypassTransientForHint); setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); setWindowTitle(tr("Auto-Type - KeePassX")); setWindowIcon(filePath()->applicationIcon()); @@ -41,7 +43,7 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent) resize(size); // move dialog to the center of the screen - QPoint screenCenter = QApplication::desktop()->screenGeometry(QCursor::pos()).center(); + QPoint screenCenter = QApplication::desktop()->availableGeometry(QCursor::pos()).center(); move(screenCenter.x() - (size.width() / 2), screenCenter.y() - (size.height() / 2)); QVBoxLayout* layout = new QVBoxLayout(this); diff --git a/src/autotype/AutoTypeSelectDialog.h b/src/autotype/AutoTypeSelectDialog.h index 4f455c75..c0dbfe47 100644 --- a/src/autotype/AutoTypeSelectDialog.h +++ b/src/autotype/AutoTypeSelectDialog.h @@ -22,8 +22,6 @@ #include #include -#include "core/Global.h" - class AutoTypeSelectView; class Entry; @@ -32,7 +30,7 @@ class AutoTypeSelectDialog : public QDialog Q_OBJECT public: - explicit AutoTypeSelectDialog(QWidget* parent = Q_NULLPTR); + explicit AutoTypeSelectDialog(QWidget* parent = nullptr); void setEntries(const QList& entries, const QHash& sequences); Q_SIGNALS: diff --git a/src/autotype/AutoTypeSelectView.h b/src/autotype/AutoTypeSelectView.h index bcbb2627..749f6a9f 100644 --- a/src/autotype/AutoTypeSelectView.h +++ b/src/autotype/AutoTypeSelectView.h @@ -18,7 +18,6 @@ #ifndef KEEPASSX_AUTOTYPESELECTVIEW_H #define KEEPASSX_AUTOTYPESELECTVIEW_H -#include "core/Global.h" #include "gui/entry/EntryView.h" class Entry; @@ -28,10 +27,10 @@ class AutoTypeSelectView : public EntryView Q_OBJECT public: - explicit AutoTypeSelectView(QWidget* parent = Q_NULLPTR); + explicit AutoTypeSelectView(QWidget* parent = nullptr); protected: - void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent* event) override; private Q_SLOTS: void selectFirstEntry(); diff --git a/src/autotype/CMakeLists.txt b/src/autotype/CMakeLists.txt index 0bf5fc25..707edf91 100644 --- a/src/autotype/CMakeLists.txt +++ b/src/autotype/CMakeLists.txt @@ -1,11 +1,12 @@ -if(Q_WS_X11) +if(UNIX AND NOT APPLE) find_package(X11) - if(PRINT_SUMMARY) - add_feature_info(libXtest X11_XTest_FOUND "The X11 XTEST Protocol library is required for auto-type") - endif() + find_package(Qt5X11Extras 5.2) + add_feature_info(libXi X11_Xi_FOUND "The X11 Xi Protocol library is required for auto-type") + add_feature_info(libXtest X11_XTest_FOUND "The X11 XTEST Protocol library is required for auto-type") + add_feature_info(Qt5X11Extras Qt5X11Extras_FOUND "The Qt5X11Extras library is required for auto-type") - if(X11_FOUND AND X11_XTest_FOUND) - add_subdirectory(x11) + if(X11_FOUND AND X11_Xi_FOUND AND X11_XTest_FOUND AND Qt5X11Extras_FOUND) + add_subdirectory(xcb) endif() endif() diff --git a/src/autotype/ShortcutWidget.h b/src/autotype/ShortcutWidget.h index 5ff306c0..60898ab7 100644 --- a/src/autotype/ShortcutWidget.h +++ b/src/autotype/ShortcutWidget.h @@ -20,21 +20,19 @@ #include -#include "core/Global.h" - class ShortcutWidget : public QLineEdit { Q_OBJECT public: - explicit ShortcutWidget(QWidget* parent = Q_NULLPTR); + explicit ShortcutWidget(QWidget* parent = nullptr); Qt::Key key() const; Qt::KeyboardModifiers modifiers() const; void setShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers); protected: - void keyPressEvent(QKeyEvent* event) Q_DECL_OVERRIDE; - void keyReleaseEvent(QKeyEvent* event) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent* event) override; + void keyReleaseEvent(QKeyEvent* event) override; private: void keyEvent(QKeyEvent* event); diff --git a/src/autotype/WindowSelectComboBox.h b/src/autotype/WindowSelectComboBox.h index 661bc84e..244119af 100644 --- a/src/autotype/WindowSelectComboBox.h +++ b/src/autotype/WindowSelectComboBox.h @@ -20,19 +20,17 @@ #include -#include "core/Global.h" - class WindowSelectComboBox : public QComboBox { Q_OBJECT public: - explicit WindowSelectComboBox(QWidget* parent = Q_NULLPTR); + explicit WindowSelectComboBox(QWidget* parent = nullptr); void refreshWindowList(); - void showPopup() Q_DECL_OVERRIDE; - QSize sizeHint() const Q_DECL_OVERRIDE; - QSize minimumSizeHint() const Q_DECL_OVERRIDE; + void showPopup() override; + QSize sizeHint() const override; + QSize minimumSizeHint() const override; }; #endif // KEEPASSX_WINDOWSELECTCOMBOBOX_H diff --git a/src/autotype/test/AutoTypeTest.cpp b/src/autotype/test/AutoTypeTest.cpp index d48d17fe..979af8bd 100644 --- a/src/autotype/test/AutoTypeTest.cpp +++ b/src/autotype/test/AutoTypeTest.cpp @@ -17,6 +17,11 @@ #include "AutoTypeTest.h" +bool AutoTypePlatformTest::isAvailable() +{ + return true; +} + QString AutoTypePlatformTest::keyToString(Qt::Key key) { return QString("[Key0x%1]").arg(key, 0, 16); @@ -103,6 +108,13 @@ int AutoTypePlatformTest::initialTimeout() return 0; } +bool AutoTypePlatformTest::raiseWindow(WId window) +{ + Q_UNUSED(window); + + return false; +} + AutoTypeExecturorTest::AutoTypeExecturorTest(AutoTypePlatformTest* platform) : m_platform(platform) { @@ -117,5 +129,3 @@ void AutoTypeExecturorTest::execKey(AutoTypeKey* action) { m_platform->addActionKey(action); } - -Q_EXPORT_PLUGIN2(keepassx-autotype-test, AutoTypePlatformTest) diff --git a/src/autotype/test/AutoTypeTest.h b/src/autotype/test/AutoTypeTest.h index a39269b0..8c6e5244 100644 --- a/src/autotype/test/AutoTypeTest.h +++ b/src/autotype/test/AutoTypeTest.h @@ -23,32 +23,34 @@ #include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypeAction.h" #include "autotype/test/AutoTypeTestInterface.h" -#include "core/Global.h" class AutoTypePlatformTest : public QObject, public AutoTypePlatformInterface, public AutoTypeTestInterface { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformInterface") Q_INTERFACES(AutoTypePlatformInterface AutoTypeTestInterface) public: - QString keyToString(Qt::Key key); + QString keyToString(Qt::Key key) override; - QStringList windowTitles(); - WId activeWindow(); - QString activeWindowTitle(); - bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers); - void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers); - int platformEventFilter(void* event); - int initialTimeout(); - AutoTypeExecutor* createExecutor(); + bool isAvailable() override; + QStringList windowTitles() override; + WId activeWindow() override; + QString activeWindowTitle() override; + bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override; + void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override; + int platformEventFilter(void* event) override; + int initialTimeout() override; + bool raiseWindow(WId window) override; + AutoTypeExecutor* createExecutor() override; - void setActiveWindowTitle(const QString& title); + void setActiveWindowTitle(const QString& title) override; - QString actionChars(); - int actionCount(); - void clearActions(); + QString actionChars() override; + int actionCount() override; + void clearActions() override; void addActionChar(AutoTypeChar* action); void addActionKey(AutoTypeKey* action); @@ -67,8 +69,8 @@ class AutoTypeExecturorTest : public AutoTypeExecutor public: explicit AutoTypeExecturorTest(AutoTypePlatformTest* platform); - void execChar(AutoTypeChar* action); - void execKey(AutoTypeKey* action); + void execChar(AutoTypeChar* action) override; + void execKey(AutoTypeKey* action) override; private: AutoTypePlatformTest* const m_platform; diff --git a/src/autotype/test/CMakeLists.txt b/src/autotype/test/CMakeLists.txt index 749f7d5f..9b3dbd49 100644 --- a/src/autotype/test/CMakeLists.txt +++ b/src/autotype/test/CMakeLists.txt @@ -2,11 +2,5 @@ set(autotype_test_SOURCES AutoTypeTest.cpp ) -set(autotype_test_MOC - AutoTypeTest.h -) - -qt4_wrap_cpp(autotype_test_SOURCES ${autotype_test_MOC}) - add_library(keepassx-autotype-test MODULE ${autotype_test_SOURCES}) -target_link_libraries(keepassx-autotype-test testautotype ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY}) +target_link_libraries(keepassx-autotype-test testautotype Qt5::Core Qt5::Widgets) diff --git a/src/autotype/x11/CMakeLists.txt b/src/autotype/x11/CMakeLists.txt deleted file mode 100644 index e9835577..00000000 --- a/src/autotype/x11/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -include_directories(SYSTEM ${X11_X11_INCLUDE_PATH}) - -set(autotype_X11_SOURCES - AutoTypeX11.cpp -) - -set(autotype_X11_MOC - AutoTypeX11.h -) - -qt4_wrap_cpp(autotype_X11_SOURCES ${autotype_X11_MOC}) - -add_library(keepassx-autotype-x11 MODULE ${autotype_X11_SOURCES}) -target_link_libraries(keepassx-autotype-x11 ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${X11_X11_LIB} ${X11_XTest_LIB}) -install(TARGETS keepassx-autotype-x11 - BUNDLE DESTINATION . COMPONENT Runtime - LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime) diff --git a/src/autotype/x11/AutoTypeX11.cpp b/src/autotype/xcb/AutoTypeXCB.cpp similarity index 80% rename from src/autotype/x11/AutoTypeX11.cpp rename to src/autotype/xcb/AutoTypeXCB.cpp index ddcf809e..40acaf66 100644 --- a/src/autotype/x11/AutoTypeX11.cpp +++ b/src/autotype/xcb/AutoTypeXCB.cpp @@ -16,25 +16,28 @@ * along with this program. If not, see . */ -#include "AutoTypeX11.h" +#include "AutoTypeXCB.h" #include "KeySymMap.h" +#include "core/Tools.h" #include +#include bool AutoTypePlatformX11::m_catchXErrors = false; bool AutoTypePlatformX11::m_xErrorOccured = false; -int (*AutoTypePlatformX11::m_oldXErrorHandler)(Display*, XErrorEvent*) = Q_NULLPTR; +int (*AutoTypePlatformX11::m_oldXErrorHandler)(Display*, XErrorEvent*) = nullptr; AutoTypePlatformX11::AutoTypePlatformX11() { m_dpy = QX11Info::display(); m_rootWindow = QX11Info::appRootWindow(); - m_atomWmState = XInternAtom(m_dpy, "WM_STATE", true); - m_atomWmName = XInternAtom(m_dpy, "WM_NAME", true); - m_atomNetWmName = XInternAtom(m_dpy, "_NET_WM_NAME", true); - m_atomString = XInternAtom(m_dpy, "STRING", true); - m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", true); + m_atomWmState = XInternAtom(m_dpy, "WM_STATE", True); + m_atomWmName = XInternAtom(m_dpy, "WM_NAME", True); + m_atomNetWmName = XInternAtom(m_dpy, "_NET_WM_NAME", True); + m_atomString = XInternAtom(m_dpy, "STRING", True); + m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True); + m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True); m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome m_classBlacklist << "kdesktop" << "kicker"; // KDE 3 @@ -45,8 +48,8 @@ AutoTypePlatformX11::AutoTypePlatformX11() m_currentGlobalKey = static_cast(0); m_currentGlobalModifiers = 0; - m_keysymTable = Q_NULLPTR; - m_xkb = Q_NULLPTR; + m_keysymTable = nullptr; + m_xkb = nullptr; m_remapKeycode = 0; m_currentRemapKeysym = NoSymbol; m_modifierMask = ControlMask | ShiftMask | Mod1Mask | Mod4Mask; @@ -56,6 +59,31 @@ AutoTypePlatformX11::AutoTypePlatformX11() updateKeymap(); } +bool AutoTypePlatformX11::isAvailable() +{ + int ignore; + + if (!XQueryExtension(m_dpy, "XInputExtension", &ignore, &ignore, &ignore)) { + return false; + } + + if (!XQueryExtension(m_dpy, "XTEST", &ignore, &ignore, &ignore)) { + return false; + } + + if (!m_xkb) { + XkbDescPtr kbd = getKeyboard(); + + if (!kbd) { + return false; + } + + XkbFreeKeyboard(kbd, XkbAllComponentsMask, True); + } + + return true; +} + void AutoTypePlatformX11::unload() { // Restore the KeyboardMapping to its original state. @@ -93,7 +121,7 @@ WId AutoTypePlatformX11::activeWindow() Window root; Window parent; - Window* children = Q_NULLPTR; + Window* children = nullptr; unsigned int numChildren; tree = XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren); window = parent; @@ -116,12 +144,12 @@ bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifi uint nativeModifiers = qtToNativeModifiers(modifiers); startCatchXErrors(); - XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, true, GrabModeAsync, GrabModeAsync); - XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, true, GrabModeAsync, + XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, True, GrabModeAsync, GrabModeAsync); + XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync, GrabModeAsync); - XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, true, GrabModeAsync, + XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync, GrabModeAsync); - XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, true, + XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True, GrabModeAsync, GrabModeAsync); stopCatchXErrors(); @@ -160,7 +188,7 @@ uint AutoTypePlatformX11::qtToNativeModifiers(Qt::KeyboardModifiers modifiers) void AutoTypePlatformX11::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) { - KeyCode keycode = XKeysymToKeycode(m_dpy, keyToKeySym(key)); + KeyCode keycode = XKeysymToKeycode(m_dpy, charToKeySym(key)); uint nativeModifiers = qtToNativeModifiers(modifiers); XUngrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow); @@ -176,22 +204,42 @@ void AutoTypePlatformX11::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModi int AutoTypePlatformX11::platformEventFilter(void* event) { - XEvent* xevent = static_cast(event); + xcb_generic_event_t* genericEvent = static_cast(event); + quint8 type = genericEvent->response_type & 0x7f; - if ((xevent->type == KeyPress || xevent->type == KeyRelease) - && m_currentGlobalKey - && xevent->xkey.keycode == m_currentGlobalKeycode - && (xevent->xkey.state & m_modifierMask) == m_currentGlobalNativeModifiers - && !QApplication::focusWidget() - && m_loaded) { - if (xevent->type == KeyPress) { - Q_EMIT globalShortcutTriggered(); + if (type == XCB_KEY_PRESS || type == XCB_KEY_RELEASE) { + xcb_key_press_event_t* keyPressEvent = static_cast(event); + if (keyPressEvent->detail == m_currentGlobalKeycode + && (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers + && (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized()) + && m_loaded) { + if (type == XCB_KEY_PRESS) { + Q_EMIT globalShortcutTriggered(); + } + + return 1; } - return 1; } - if (xevent->type == MappingNotify && m_loaded) { - XRefreshKeyboardMapping(reinterpret_cast(xevent)); - updateKeymap(); + else if (type == XCB_MAPPING_NOTIFY) { + xcb_mapping_notify_event_t* mappingNotifyEvent = static_cast(event); + if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD + || mappingNotifyEvent->request == XCB_MAPPING_MODIFIER) + { + XMappingEvent xMappingEvent; + memset(&xMappingEvent, 0, sizeof(xMappingEvent)); + xMappingEvent.type = MappingNotify; + xMappingEvent.display = m_dpy; + if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD) { + xMappingEvent.request = MappingKeyboard; + } + else { + xMappingEvent.request = MappingModifier; + } + xMappingEvent.first_keycode = mappingNotifyEvent->first_keycode; + xMappingEvent.count = mappingNotifyEvent->count; + XRefreshKeyboardMapping(&xMappingEvent); + updateKeymap(); + } } return -1; @@ -210,11 +258,11 @@ QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist) int format; unsigned long nitems; unsigned long after; - unsigned char* data = Q_NULLPTR; + unsigned char* data = nullptr; // the window manager spec says we should read _NET_WM_NAME first, then fall back to WM_NAME - int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, false, m_atomUtf8String, + int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String, &type, &format, &nitems, &after, &data); if ((retVal == 0) && data) { @@ -224,7 +272,7 @@ QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist) XTextProperty textProp; retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName); if ((retVal != 0) && textProp.value) { - char** textList = Q_NULLPTR; + char** textList = nullptr; int count; if (textProp.encoding == m_atomUtf8String) { @@ -276,8 +324,8 @@ QString AutoTypePlatformX11::windowClassName(Window window) QString className; XClassHint wmClass; - wmClass.res_name = Q_NULLPTR; - wmClass.res_class = Q_NULLPTR; + wmClass.res_name = nullptr; + wmClass.res_class = nullptr; if (XGetClassHint(m_dpy, window, &wmClass) && wmClass.res_name) { className = QString::fromLocal8Bit(wmClass.res_name); @@ -316,7 +364,7 @@ QStringList AutoTypePlatformX11::windowTitlesRecursive(Window window) Window root; Window parent; - Window* children = Q_NULLPTR; + Window* children = nullptr; unsigned int numChildren; if (XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren) && children) { for (uint i = 0; i < numChildren; i++) { @@ -336,8 +384,8 @@ bool AutoTypePlatformX11::isTopLevelWindow(Window window) int format; unsigned long nitems; unsigned long after; - unsigned char* data = Q_NULLPTR; - int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 0, false, AnyPropertyType, &type, &format, + unsigned char* data = nullptr; + int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 0, False, AnyPropertyType, &type, &format, &nitems, &after, &data); if (data) { XFree(data); @@ -357,9 +405,9 @@ KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch) } /* mapping table generated from keysymdef.h */ - const uint* match = qBinaryFind(m_unicodeToKeysymKeys, - m_unicodeToKeysymKeys + m_unicodeToKeysymLen, - unicode); + const uint* match = Tools::binaryFind(m_unicodeToKeysymKeys, + m_unicodeToKeysymKeys + m_unicodeToKeysymLen, + unicode); int index = match - m_unicodeToKeysymKeys; if (index != m_unicodeToKeysymLen) { return m_unicodeToKeysymValues[index]; @@ -436,21 +484,10 @@ void AutoTypePlatformX11::updateKeymap() int mod_index, mod_key; XModifierKeymap *modifiers; - if (m_xkb != NULL) XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True); - - XDeviceInfo* devices; - int num_devices; - XID keyboard_id = XkbUseCoreKbd; - devices = XListInputDevices(m_dpy, &num_devices); - - for (int i = 0; i < num_devices; i++) { - if (QString(devices[i].name) == "Virtual core XTEST keyboard") { - keyboard_id = devices[i].id; - break; - } + if (m_xkb) { + XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True); } - - m_xkb = XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id); + m_xkb = getKeyboard(); XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode); if (m_keysymTable != NULL) XFree(m_keysymTable); @@ -491,7 +528,7 @@ void AutoTypePlatformX11::updateKeymap() timespec ts; ts.tv_sec = 0; ts.tv_nsec = 30 * 1000 * 1000; - nanosleep(&ts, Q_NULLPTR); + nanosleep(&ts, nullptr); } bool AutoTypePlatformX11::isRemapKeycodeValid() @@ -519,7 +556,7 @@ void AutoTypePlatformX11::stopCatchXErrors() { Q_ASSERT(m_catchXErrors); - XSync(m_dpy, false); + XSync(m_dpy, False); XSetErrorHandler(m_oldXErrorHandler); m_catchXErrors = false; } @@ -536,6 +573,27 @@ int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error) return 1; } +XkbDescPtr AutoTypePlatformX11::getKeyboard() +{ + int num_devices; + XID keyboard_id = XkbUseCoreKbd; + XDeviceInfo* devices = XListInputDevices(m_dpy, &num_devices); + if (!devices) { + return nullptr; + } + + for (int i = 0; i < num_devices; i++) { + if (QString(devices[i].name) == "Virtual core XTEST keyboard") { + keyboard_id = devices[i].id; + break; + } + } + + XFreeDeviceList(devices); + + return XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id); +} + // -------------------------------------------------------------------------- // The following code is taken from xvkbd 3.0 and has been slightly modified. // -------------------------------------------------------------------------- @@ -568,11 +626,18 @@ int AutoTypePlatformX11::AddKeysym(KeySym keysym) */ void AutoTypePlatformX11::SendEvent(XKeyEvent* event, int event_type) { - XSync(event->display, FALSE); + XSync(event->display, False); int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler); event->type = event_type; - XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0); + Bool press; + if (event->type == KeyPress) { + press = True; + } + else { + press = False; + } + XTestFakeKeyEvent(event->display, event->keycode, press, 0); XFlush(event->display); XSetErrorHandler(oldHandler); @@ -670,7 +735,7 @@ void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym) event.y = 1; event.x_root = 1; event.y_root = 1; - event.same_screen = TRUE; + event.same_screen = True; Window root, child; int root_x, root_y, x, y; @@ -770,4 +835,36 @@ int AutoTypePlatformX11::initialTimeout() return 500; } -Q_EXPORT_PLUGIN2(keepassx-autotype-x11, AutoTypePlatformX11) +bool AutoTypePlatformX11::raiseWindow(WId window) +{ + if (m_atomNetActiveWindow == None) { + return false; + } + + XRaiseWindow(m_dpy, window); + + XEvent event; + event.xclient.type = ClientMessage; + event.xclient.serial = 0; + event.xclient.send_event = True; + event.xclient.window = window; + event.xclient.message_type = m_atomNetActiveWindow; + event.xclient.format = 32; + event.xclient.data.l[0] = 1; // FromApplication + event.xclient.data.l[1] = QX11Info::appUserTime(); + QWidget* activeWindow = QApplication::activeWindow(); + if (activeWindow) { + event.xclient.data.l[2] = activeWindow->internalWinId(); + } + else { + event.xclient.data.l[2] = 0; + } + event.xclient.data.l[3] = 0; + event.xclient.data.l[4] = 0; + XSendEvent(m_dpy, m_rootWindow, False, + SubstructureRedirectMask | SubstructureNotifyMask, + &event); + XFlush(m_dpy); + + return true; +} diff --git a/src/autotype/x11/AutoTypeX11.h b/src/autotype/xcb/AutoTypeXCB.h similarity index 83% rename from src/autotype/x11/AutoTypeX11.h rename to src/autotype/xcb/AutoTypeXCB.h index 1fa45503..8adee770 100644 --- a/src/autotype/x11/AutoTypeX11.h +++ b/src/autotype/xcb/AutoTypeXCB.h @@ -16,8 +16,8 @@ * along with this program. If not, see . */ -#ifndef KEEPASSX_AUTOTYPEX11_H -#define KEEPASSX_AUTOTYPEX11_H +#ifndef KEEPASSX_AUTOTYPEXCB_H +#define KEEPASSX_AUTOTYPEXCB_H #include #include @@ -31,26 +31,28 @@ #include "autotype/AutoTypePlatformPlugin.h" #include "autotype/AutoTypeAction.h" -#include "core/Global.h" #define N_MOD_INDICES (Mod5MapIndex + 1) class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformX11") Q_INTERFACES(AutoTypePlatformInterface) public: AutoTypePlatformX11(); - void unload() Q_DECL_OVERRIDE; - QStringList windowTitles(); - WId activeWindow(); - QString activeWindowTitle(); - bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers); - void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers); - int platformEventFilter(void* event); - int initialTimeout(); - AutoTypeExecutor* createExecutor(); + bool isAvailable() override; + void unload() override; + QStringList windowTitles() override; + WId activeWindow() override; + QString activeWindowTitle() override; + bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override; + void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override; + int platformEventFilter(void* event) override; + int initialTimeout() override; + bool raiseWindow(WId window) override; + AutoTypeExecutor* createExecutor() override; KeySym charToKeySym(const QChar& ch); KeySym keyToKeySym(Qt::Key key); @@ -71,6 +73,7 @@ private: void stopCatchXErrors(); static int x11ErrorHandler(Display* display, XErrorEvent* error); + XkbDescPtr getKeyboard(); void updateKeymap(); bool isRemapKeycodeValid(); int AddKeysym(KeySym keysym); @@ -89,6 +92,7 @@ private: Atom m_atomNetWmName; Atom m_atomString; Atom m_atomUtf8String; + Atom m_atomNetActiveWindow; QSet m_classBlacklist; Qt::Key m_currentGlobalKey; Qt::KeyboardModifiers m_currentGlobalModifiers; @@ -120,11 +124,11 @@ class AutoTypeExecturorX11 : public AutoTypeExecutor public: explicit AutoTypeExecturorX11(AutoTypePlatformX11* platform); - void execChar(AutoTypeChar* action); - void execKey(AutoTypeKey* action); + void execChar(AutoTypeChar* action) override; + void execKey(AutoTypeKey* action) override; private: AutoTypePlatformX11* const m_platform; }; -#endif // KEEPASSX_AUTOTYPEX11_H +#endif // KEEPASSX_AUTOTYPEXCB_H diff --git a/src/autotype/xcb/CMakeLists.txt b/src/autotype/xcb/CMakeLists.txt new file mode 100644 index 00000000..3b56b311 --- /dev/null +++ b/src/autotype/xcb/CMakeLists.txt @@ -0,0 +1,11 @@ +include_directories(SYSTEM ${X11_X11_INCLUDE_PATH}) + +set(autotype_XCB_SOURCES + AutoTypeXCB.cpp +) + +add_library(keepassx-autotype-xcb MODULE ${autotype_XCB_SOURCES}) +target_link_libraries(keepassx-autotype-xcb Qt5::Core Qt5::Widgets Qt5::X11Extras ${X11_X11_LIB} ${X11_Xi_LIB} ${X11_XTest_LIB}) +install(TARGETS keepassx-autotype-xcb + BUNDLE DESTINATION . COMPONENT Runtime + LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime) diff --git a/src/autotype/x11/KeySymMap.h b/src/autotype/xcb/KeySymMap.h similarity index 100% rename from src/autotype/x11/KeySymMap.h rename to src/autotype/xcb/KeySymMap.h diff --git a/src/autotype/x11/keysymmap.py b/src/autotype/xcb/keysymmap.py similarity index 100% rename from src/autotype/x11/keysymmap.py rename to src/autotype/xcb/keysymmap.py diff --git a/src/config-keepassx.h.cmake b/src/config-keepassx.h.cmake index 197c0d32..dc418b6e 100644 --- a/src/config-keepassx.h.cmake +++ b/src/config-keepassx.h.cmake @@ -16,6 +16,4 @@ #cmakedefine HAVE_RLIMIT_CORE 1 #cmakedefine HAVE_PT_DENY_ATTACH 1 -#cmakedefine GCRYPT_HAS_SALSA20 - #endif // KEEPASSX_CONFIG_KEEPASSX_H diff --git a/src/core/AutoTypeAssociations.h b/src/core/AutoTypeAssociations.h index 1b5871b3..491a5db1 100644 --- a/src/core/AutoTypeAssociations.h +++ b/src/core/AutoTypeAssociations.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class AutoTypeAssociations : public QObject { Q_OBJECT @@ -36,7 +34,7 @@ public: bool operator!=(const AutoTypeAssociations::Association& other) const; }; - explicit AutoTypeAssociations(QObject* parent = Q_NULLPTR); + explicit AutoTypeAssociations(QObject* parent = nullptr); void copyDataFrom(const AutoTypeAssociations* other); void add(const AutoTypeAssociations::Association& association); void remove(int index); diff --git a/src/core/Config.cpp b/src/core/Config.cpp index 0650b1c2..d9c737eb 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -18,12 +18,12 @@ #include "Config.h" #include -#include #include #include +#include #include -Config* Config::m_instance(Q_NULLPTR); +Config* Config::m_instance(nullptr); QVariant Config::get(const QString& key) { @@ -53,7 +53,7 @@ Config::Config(QObject* parent) QString homePath = QDir::homePath(); #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) - // we can't use QDesktopServices on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME + // we can't use QStandardPaths on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME QByteArray env = qgetenv("XDG_CONFIG_HOME"); if (env.isEmpty()) { userPath = homePath; @@ -70,7 +70,7 @@ Config::Config(QObject* parent) userPath += "/keepassx/"; #else - userPath = QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::DataLocation)); + userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); // storageLocation() appends the application name ("/keepassx") to the end userPath += "/"; #endif diff --git a/src/core/Config.h b/src/core/Config.h index ca0f74cb..09aa02fb 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -21,8 +21,6 @@ #include #include -#include "core/Global.h" - class QSettings; class Config : public QObject diff --git a/src/core/Database.cpp b/src/core/Database.cpp index 098cc06a..6f942357 100644 --- a/src/core/Database.cpp +++ b/src/core/Database.cpp @@ -23,7 +23,6 @@ #include "core/Group.h" #include "core/Metadata.h" -#include "core/Tools.h" #include "crypto/Random.h" #include "format/KeePass2.h" @@ -105,7 +104,7 @@ Entry* Database::recFindEntry(const Uuid& uuid, Group* group) } } - return Q_NULLPTR; + return nullptr; } Group* Database::resolveGroup(const Uuid& uuid) @@ -126,7 +125,7 @@ Group* Database::recFindGroup(const Uuid& uuid, Group* group) } } - return Q_NULLPTR; + return nullptr; } QList Database::deletedObjects() @@ -143,7 +142,7 @@ void Database::addDeletedObject(const DeletedObject& delObj) void Database::addDeletedObject(const Uuid& uuid) { DeletedObject delObj; - delObj.deletionTime = Tools::currentDateTimeUtc(); + delObj.deletionTime = QDateTime::currentDateTimeUtc(); delObj.uuid = uuid; addDeletedObject(delObj); @@ -223,7 +222,7 @@ bool Database::setKey(const CompositeKey& key, const QByteArray& transformSeed, m_data.transformedMasterKey = transformedMasterKey; m_data.hasKey = true; if (updateChangedTime) { - m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc()); + m_metadata->setMasterKeyChanged(QDateTime::currentDateTimeUtc()); } Q_EMIT modifiedImmediate(); diff --git a/src/core/Database.h b/src/core/Database.h index 97ccad23..6fde3c60 100644 --- a/src/core/Database.h +++ b/src/core/Database.h @@ -20,6 +20,7 @@ #include #include +#include #include "core/Uuid.h" #include "keys/CompositeKey.h" diff --git a/src/core/DatabaseIcons.cpp b/src/core/DatabaseIcons.cpp index d6e816fb..4e62f79e 100644 --- a/src/core/DatabaseIcons.cpp +++ b/src/core/DatabaseIcons.cpp @@ -19,7 +19,7 @@ #include "core/FilePath.h" -DatabaseIcons* DatabaseIcons::m_instance(Q_NULLPTR); +DatabaseIcons* DatabaseIcons::m_instance(nullptr); const int DatabaseIcons::IconCount(69); const int DatabaseIcons::ExpiredIconIndex(45); const char* const DatabaseIcons::m_indexToName[] = { diff --git a/src/core/DatabaseIcons.h b/src/core/DatabaseIcons.h index 68d1e0cb..a1d9480b 100644 --- a/src/core/DatabaseIcons.h +++ b/src/core/DatabaseIcons.h @@ -23,8 +23,6 @@ #include #include -#include "core/Global.h" - class DatabaseIcons { public: diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 4f977915..2fd52d0b 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -21,7 +21,6 @@ #include "core/DatabaseIcons.h" #include "core/Group.h" #include "core/Metadata.h" -#include "core/Tools.h" const int Entry::DefaultIconNumber = 0; @@ -29,7 +28,7 @@ Entry::Entry() : m_attributes(new EntryAttributes(this)) , m_attachments(new EntryAttachments(this)) , m_autoTypeAssociations(new AutoTypeAssociations(this)) - , m_tmpHistoryItem(Q_NULLPTR) + , m_tmpHistoryItem(nullptr) , m_modifiedSinceBegin(false) , m_updateTimeinfo(true) { @@ -74,8 +73,8 @@ template inline bool Entry::set(T& property, const T& value) void Entry::updateTimeinfo() { if (m_updateTimeinfo) { - m_data.timeInfo.setLastModificationTime(Tools::currentDateTimeUtc()); - m_data.timeInfo.setLastAccessTime(Tools::currentDateTimeUtc()); + m_data.timeInfo.setLastModificationTime(QDateTime::currentDateTimeUtc()); + m_data.timeInfo.setLastAccessTime(QDateTime::currentDateTimeUtc()); } } @@ -114,13 +113,25 @@ QPixmap Entry::iconPixmap() const else { Q_ASSERT(database()); - QPixmap pixmap; - if (database() && !QPixmapCache::find(m_pixmapCacheKey, &pixmap)) { - pixmap = QPixmap::fromImage(database()->metadata()->customIcon(m_data.customIcon)); - m_pixmapCacheKey = QPixmapCache::insert(pixmap); + if (database()) { + return database()->metadata()->customIconPixmap(m_data.customIcon); } + else { + return QPixmap(); + } + } +} - return pixmap; +QPixmap Entry::iconScaledPixmap() const +{ + if (m_data.customIcon.isNull()) { + // built-in icons are 16x16 so don't need to be scaled + return databaseIcons()->iconPixmap(m_data.iconNumber); + } + else { + Q_ASSERT(database()); + + return database()->metadata()->customIconScaledPixmap(m_data.customIcon); } } @@ -211,7 +222,7 @@ QString Entry::notes() const bool Entry::isExpired() const { - return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Tools::currentDateTimeUtc(); + return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc(); } EntryAttributes* Entry::attributes() @@ -248,8 +259,6 @@ void Entry::setIcon(int iconNumber) m_data.iconNumber = iconNumber; m_data.customIcon = Uuid(); - m_pixmapCacheKey = QPixmapCache::Key(); - Q_EMIT modified(); emitDataChanged(); } @@ -263,8 +272,6 @@ void Entry::setIcon(const Uuid& uuid) m_data.customIcon = uuid; m_data.iconNumber = 0; - m_pixmapCacheKey = QPixmapCache::Key(); - Q_EMIT modified(); emitDataChanged(); } @@ -466,7 +473,7 @@ Entry* Entry::clone(CloneFlags flags) const entry->setUpdateTimeinfo(true); if (flags & CloneResetTimeInfo) { - QDateTime now = Tools::currentDateTimeUtc(); + QDateTime now = QDateTime::currentDateTimeUtc(); entry->m_data.timeInfo.setCreationTime(now); entry->m_data.timeInfo.setLastModificationTime(now); entry->m_data.timeInfo.setLastAccessTime(now); @@ -514,7 +521,7 @@ void Entry::endUpdate() delete m_tmpHistoryItem; } - m_tmpHistoryItem = Q_NULLPTR; + m_tmpHistoryItem = nullptr; } void Entry::updateModifiedSinceBegin() @@ -560,7 +567,7 @@ void Entry::setGroup(Group* group) QObject::setParent(group); if (m_updateTimeinfo) { - m_data.timeInfo.setLocationChanged(Tools::currentDateTimeUtc()); + m_data.timeInfo.setLocationChanged(QDateTime::currentDateTimeUtc()); } } @@ -575,7 +582,7 @@ const Database* Entry::database() const return m_group->database(); } else { - return Q_NULLPTR; + return nullptr; } } diff --git a/src/core/Entry.h b/src/core/Entry.h index ae07ed45..cd7c7b77 100644 --- a/src/core/Entry.h +++ b/src/core/Entry.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -30,7 +29,6 @@ #include "core/AutoTypeAssociations.h" #include "core/EntryAttachments.h" #include "core/EntryAttributes.h" -#include "core/Global.h" #include "core/TimeInfo.h" #include "core/Uuid.h" @@ -61,6 +59,7 @@ public: Uuid uuid() const; QImage icon() const; QPixmap iconPixmap() const; + QPixmap iconScaledPixmap() const; int iconNumber() const; Uuid iconUuid() const; QColor foregroundColor() const; @@ -169,7 +168,6 @@ private: Entry* m_tmpHistoryItem; bool m_modifiedSinceBegin; QPointer m_group; - mutable QPixmapCache::Key m_pixmapCacheKey; bool m_updateTimeinfo; }; diff --git a/src/core/EntryAttachments.h b/src/core/EntryAttachments.h index 3446b315..903ca10b 100644 --- a/src/core/EntryAttachments.h +++ b/src/core/EntryAttachments.h @@ -21,14 +21,12 @@ #include #include -#include "core/Global.h" - class EntryAttachments : public QObject { Q_OBJECT public: - explicit EntryAttachments(QObject* parent = Q_NULLPTR); + explicit EntryAttachments(QObject* parent = nullptr); QList keys() const; bool hasKey(const QString& key) const; QList values() const; diff --git a/src/core/EntryAttributes.h b/src/core/EntryAttributes.h index 0c6591a2..1c0ddaae 100644 --- a/src/core/EntryAttributes.h +++ b/src/core/EntryAttributes.h @@ -23,14 +23,12 @@ #include #include -#include "core/Global.h" - class EntryAttributes : public QObject { Q_OBJECT public: - explicit EntryAttributes(QObject* parent = Q_NULLPTR); + explicit EntryAttributes(QObject* parent = nullptr); QList keys() const; bool hasKey(const QString& key) const; QList customKeys(); diff --git a/src/core/EntrySearcher.cpp b/src/core/EntrySearcher.cpp index 82a553e3..05c4c589 100644 --- a/src/core/EntrySearcher.cpp +++ b/src/core/EntrySearcher.cpp @@ -19,7 +19,8 @@ #include "core/Group.h" -QList EntrySearcher::search(const QString &searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity) +QList EntrySearcher::search(const QString& searchTerm, const Group* group, + Qt::CaseSensitivity caseSensitivity) { if (!group->resolveSearchingEnabled()) { return QList(); @@ -28,7 +29,8 @@ QList EntrySearcher::search(const QString &searchTerm, const Group* grou return searchEntries(searchTerm, group, caseSensitivity); } -QList EntrySearcher::searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity) +QList EntrySearcher::searchEntries(const QString& searchTerm, const Group* group, + Qt::CaseSensitivity caseSensitivity) { QList searchResult; @@ -44,7 +46,8 @@ QList EntrySearcher::searchEntries(const QString& searchTerm, const Grou return searchResult; } -QList EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity) +QList EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, + Qt::CaseSensitivity caseSensitivity) { QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts); Q_FOREACH (const QString& word, wordList) { diff --git a/src/core/EntrySearcher.h b/src/core/EntrySearcher.h index 246538cb..c7075dc9 100644 --- a/src/core/EntrySearcher.h +++ b/src/core/EntrySearcher.h @@ -28,10 +28,11 @@ class EntrySearcher { public: QList search(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity); + private: QList searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity); QList matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity); - bool wordMatch(const QString &word, Entry *entry, Qt::CaseSensitivity caseSensitivity); + bool wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity); }; #endif // KEEPASSX_ENTRYSEARCHER_H diff --git a/src/core/FilePath.cpp b/src/core/FilePath.cpp index 5366fe5c..497568ad 100644 --- a/src/core/FilePath.cpp +++ b/src/core/FilePath.cpp @@ -23,7 +23,7 @@ #include "config-keepassx.h" -FilePath* FilePath::m_instance(Q_NULLPTR); +FilePath* FilePath::m_instance(nullptr); QString FilePath::dataPath(const QString& name) { @@ -113,7 +113,7 @@ QIcon FilePath::icon(const QString& category, const QString& name, bool fromThem icon.addFile(filename, QSize(size, size)); } } - filename = QString("%1/icons/application/scalable/%3.svgz").arg(m_dataPath, combinedName); + filename = QString("%1/icons/application/scalable/%2.svgz").arg(m_dataPath, combinedName); if (QFile::exists(filename)) { icon.addFile(filename); } @@ -158,7 +158,7 @@ QIcon FilePath::onOffIcon(const QString& category, const QString& name) icon.addFile(filename, QSize(size, size), QIcon::Normal, state); } } - filename = QString("%1/icons/application/scalable/%3-%4.svgz").arg(m_dataPath, combinedName, stateName); + filename = QString("%1/icons/application/scalable/%2-%3.svgz").arg(m_dataPath, combinedName, stateName); if (QFile::exists(filename)) { icon.addFile(filename, QSize(), QIcon::Normal, state); } @@ -173,6 +173,7 @@ FilePath::FilePath() { const QString appDirPath = QCoreApplication::applicationDirPath(); bool isDataDirAbsolute = QDir::isAbsolutePath(KEEPASSX_DATA_DIR); + Q_UNUSED(isDataDirAbsolute); if (false) { } diff --git a/src/core/FilePath.h b/src/core/FilePath.h index 9e98d3e3..c37a9088 100644 --- a/src/core/FilePath.h +++ b/src/core/FilePath.h @@ -22,8 +22,6 @@ #include #include -#include "core/Global.h" - class FilePath { public: diff --git a/src/core/Global.h b/src/core/Global.h index 914c7b41..14281eee 100644 --- a/src/core/Global.h +++ b/src/core/Global.h @@ -20,104 +20,8 @@ #ifndef KEEPASSX_GLOBAL_H #define KEEPASSX_GLOBAL_H -// mostly copied from qcompilerdetection.h which is part of Qt 5 - #include -#ifdef Q_CC_CLANG -# if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) -# if __has_feature(cxx_strong_enums) -# define COMPILER_CLASS_ENUM -# endif -# if __has_feature(cxx_constexpr) -# define COMPILER_CONSTEXPR -# endif -# if __has_feature(cxx_decltype) /* && __has_feature(cxx_decltype_incomplete_return_types) */ -# define COMPILER_DECLTYPE -# endif -# if __has_feature(cxx_override_control) -# define COMPILER_EXPLICIT_OVERRIDES -# endif -# if __has_feature(cxx_nullptr) -# define COMPILER_NULLPTR -# endif -# if __has_feature(cxx_static_assert) -# define COMPILER_STATIC_ASSERT -# endif -# endif -#endif // Q_CC_CLANG - -#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG) -# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403 -# define COMPILER_DECLTYPE -# define COMPILER_STATIC_ASSERT -# endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404 -# define COMPILER_CLASS_ENUM -# endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 -# define COMPILER_CONSTEXPR -# define COMPILER_NULLPTR -# endif -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 -# define COMPILER_EXPLICIT_OVERRIDES -# endif -# endif -#endif - -/* - * C++11 keywords and expressions - */ -#if !defined(Q_NULLPTR) -# ifdef COMPILER_NULLPTR -# define Q_NULLPTR nullptr -# else -# define Q_NULLPTR 0 -# endif -#endif - -#if !defined(Q_DECL_CONSTEXPR) -# ifdef COMPILER_CONSTEXPR -# define Q_DECL_CONSTEXPR constexpr -# else -# define Q_DECL_CONSTEXPR -# endif -#endif - -#if !defined(Q_DECL_OVERRIDE) && !defined(Q_DECL_FINAL) && !defined(Q_DECL_FINAL_CLASS) -# ifdef COMPILER_EXPLICIT_OVERRIDES -# define Q_DECL_OVERRIDE override -# define Q_DECL_FINAL final -# ifdef COMPILER_DECLTYPE -# define Q_DECL_FINAL_CLASS final -# else -# define Q_DECL_FINAL_CLASS -# endif -# else -# define Q_DECL_OVERRIDE -# define Q_DECL_FINAL -# define Q_DECL_FINAL_CLASS -# endif -#endif - -#if !defined(Q_STATIC_ASSERT) && !defined(Q_STATIC_ASSERT_X) -#ifdef COMPILER_STATIC_ASSERT -#define Q_STATIC_ASSERT(Condition) static_assert(static_cast(Condition), #Condition) -#define Q_STATIC_ASSERT_X(Condition, Message) static_assert(static_cast(Condition), Message) -#else -// Intentionally undefined -template class QStaticAssertFailure; -template <> class QStaticAssertFailure {}; - -#define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) -#define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B -#define Q_STATIC_ASSERT(Condition) \ - enum {Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) = sizeof(QStaticAssertFailure)} -#define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition) -#endif // COMPILER_STATIC_ASSERT -#endif // !defined(Q_STATIC_ASSERT) && !defined(Q_STATIC_ASSERT_X) - #if defined(Q_OS_WIN) # if defined(KEEPASSX_BUILDING_CORE) # define KEEPASSX_EXPORT Q_DECL_EXPORT diff --git a/src/core/Group.cpp b/src/core/Group.cpp index 57e0bae9..2b9e9bcf 100644 --- a/src/core/Group.cpp +++ b/src/core/Group.cpp @@ -20,7 +20,6 @@ #include "core/Config.h" #include "core/DatabaseIcons.h" #include "core/Metadata.h" -#include "core/Tools.h" const int Group::DefaultIconNumber = 48; const int Group::RecycleBinIconNumber = 43; @@ -50,7 +49,7 @@ Group::~Group() if (m_db && m_parent) { DeletedObject delGroup; - delGroup.deletionTime = Tools::currentDateTimeUtc(); + delGroup.deletionTime = QDateTime::currentDateTimeUtc(); delGroup.uuid = m_uuid; m_db->addDeletedObject(delGroup); } @@ -84,8 +83,8 @@ template inline bool Group::set(P& property, const V& value) void Group::updateTimeinfo() { if (m_updateTimeinfo) { - m_data.timeInfo.setLastModificationTime(Tools::currentDateTimeUtc()); - m_data.timeInfo.setLastAccessTime(Tools::currentDateTimeUtc()); + m_data.timeInfo.setLastModificationTime(QDateTime::currentDateTimeUtc()); + m_data.timeInfo.setLastAccessTime(QDateTime::currentDateTimeUtc()); } } @@ -134,13 +133,30 @@ QPixmap Group::iconPixmap() const else { Q_ASSERT(m_db); - QPixmap pixmap; - if (m_db && !QPixmapCache::find(m_pixmapCacheKey, &pixmap)) { - pixmap = QPixmap::fromImage(m_db->metadata()->customIcon(m_data.customIcon)); - m_pixmapCacheKey = QPixmapCache::insert(pixmap); + if (m_db) { + return m_db->metadata()->customIconPixmap(m_data.customIcon); } + else { + return QPixmap(); + } + } +} - return pixmap; +QPixmap Group::iconScaledPixmap() const +{ + if (m_data.customIcon.isNull()) { + // built-in icons are 16x16 so don't need to be scaled + return databaseIcons()->iconPixmap(m_data.iconNumber); + } + else { + Q_ASSERT(m_db); + + if (m_db) { + return m_db->metadata()->customIconScaledPixmap(m_data.customIcon); + } + else { + return QPixmap(); + } } } @@ -186,7 +202,7 @@ Entry* Group::lastTopVisibleEntry() const bool Group::isExpired() const { - return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Tools::currentDateTimeUtc(); + return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc(); } void Group::setUuid(const Uuid& uuid) @@ -214,8 +230,6 @@ void Group::setIcon(int iconNumber) m_data.iconNumber = iconNumber; m_data.customIcon = Uuid(); - m_pixmapCacheKey = QPixmapCache::Key(); - updateTimeinfo(); Q_EMIT modified(); Q_EMIT dataChanged(this); @@ -230,8 +244,6 @@ void Group::setIcon(const Uuid& uuid) m_data.customIcon = uuid; m_data.iconNumber = 0; - m_pixmapCacheKey = QPixmapCache::Key(); - updateTimeinfo(); Q_EMIT modified(); Q_EMIT dataChanged(this); @@ -352,7 +364,7 @@ void Group::setParent(Group* parent, int index) } if (m_updateTimeinfo) { - m_data.timeInfo.setLocationChanged(Tools::currentDateTimeUtc()); + m_data.timeInfo.setLocationChanged(QDateTime::currentDateTimeUtc()); } Q_EMIT modified(); @@ -372,7 +384,7 @@ void Group::setParent(Database* db) cleanupParent(); - m_parent = Q_NULLPTR; + m_parent = nullptr; recSetDatabase(db); QObject::setParent(db); @@ -497,7 +509,7 @@ Group* Group::clone(Entry::CloneFlags entryFlags) const clonedGroup->setUpdateTimeinfo(true); - QDateTime now = Tools::currentDateTimeUtc(); + QDateTime now = QDateTime::currentDateTimeUtc(); clonedGroup->m_data.timeInfo.setCreationTime(now); clonedGroup->m_data.timeInfo.setLastModificationTime(now); clonedGroup->m_data.timeInfo.setLastAccessTime(now); diff --git a/src/core/Group.h b/src/core/Group.h index 3d361804..3881ed24 100644 --- a/src/core/Group.h +++ b/src/core/Group.h @@ -58,6 +58,7 @@ public: QString notes() const; QImage icon() const; QPixmap iconPixmap() const; + QPixmap iconScaledPixmap() const; int iconNumber() const; Uuid iconUuid() const; TimeInfo timeInfo() const; @@ -155,7 +156,6 @@ private: QList m_entries; QPointer m_parent; - mutable QPixmapCache::Key m_pixmapCacheKey; bool m_updateTimeinfo; diff --git a/src/core/InactivityTimer.cpp b/src/core/InactivityTimer.cpp index 762c8720..dd162e69 100644 --- a/src/core/InactivityTimer.cpp +++ b/src/core/InactivityTimer.cpp @@ -67,7 +67,14 @@ bool InactivityTimer::eventFilter(QObject* watched, QEvent* event) void InactivityTimer::timeout() { + // make sure we don't emit the signal a second time while it's still processed + if (!m_emitMutx.tryLock()) { + return; + } + if (m_active && !m_timer->isActive()) { Q_EMIT inactivityDetected(); } + + m_emitMutx.unlock(); } diff --git a/src/core/InactivityTimer.h b/src/core/InactivityTimer.h index 14e4852b..ba571a5e 100644 --- a/src/core/InactivityTimer.h +++ b/src/core/InactivityTimer.h @@ -18,10 +18,9 @@ #ifndef KEEPASSX_INACTIVITYTIMER_H #define KEEPASSX_INACTIVITYTIMER_H +#include #include -#include "core/Global.h" - class QTimer; class InactivityTimer : public QObject @@ -29,7 +28,7 @@ class InactivityTimer : public QObject Q_OBJECT public: - explicit InactivityTimer(QObject* parent = Q_NULLPTR); + explicit InactivityTimer(QObject* parent = nullptr); void setInactivityTimeout(int inactivityTimeout); void activate(); void deactivate(); @@ -46,6 +45,7 @@ private Q_SLOTS: private: QTimer* m_timer; bool m_active; + QMutex m_emitMutx; }; #endif // KEEPASSX_INACTIVITYTIMER_H diff --git a/src/core/Metadata.cpp b/src/core/Metadata.cpp index 3256ca05..a50c6ef4 100644 --- a/src/core/Metadata.cpp +++ b/src/core/Metadata.cpp @@ -42,7 +42,7 @@ Metadata::Metadata(QObject* parent) m_data.protectNotes = false; // m_data.autoEnableVisualHiding = false; - QDateTime now = Tools::currentDateTimeUtc(); + QDateTime now = QDateTime::currentDateTimeUtc(); m_data.nameChanged = now; m_data.descriptionChanged = now; m_data.defaultUserNameChanged = now; @@ -67,7 +67,7 @@ template bool Metadata::set(P& property, const V& value, QDat if (property != value) { property = value; if (m_updateDatetime) { - dateTime = Tools::currentDateTimeUtc(); + dateTime = QDateTime::currentDateTimeUtc(); } Q_EMIT modified(); return true; @@ -167,6 +167,43 @@ QImage Metadata::customIcon(const Uuid& uuid) const return m_customIcons.value(uuid); } +QPixmap Metadata::customIconPixmap(const Uuid& uuid) const +{ + QPixmap pixmap; + + if (!m_customIcons.contains(uuid)) { + return pixmap; + } + + QPixmapCache::Key& cacheKey = m_customIconCacheKeys[uuid]; + + if (!QPixmapCache::find(cacheKey, &pixmap)) { + pixmap = QPixmap::fromImage(m_customIcons.value(uuid)); + cacheKey = QPixmapCache::insert(pixmap); + } + + return pixmap; +} + +QPixmap Metadata::customIconScaledPixmap(const Uuid& uuid) const +{ + QPixmap pixmap; + + if (!m_customIcons.contains(uuid)) { + return pixmap; + } + + QPixmapCache::Key& cacheKey = m_customIconScaledCacheKeys[uuid]; + + if (!QPixmapCache::find(cacheKey, &pixmap)) { + QImage image = m_customIcons.value(uuid).scaled(16, 16, Qt::KeepAspectRatio, Qt::SmoothTransformation); + pixmap = QPixmap::fromImage(image); + cacheKey = QPixmapCache::insert(pixmap); + } + + return pixmap; +} + bool Metadata::containsCustomIcon(const Uuid& uuid) const { return m_customIcons.contains(uuid); @@ -177,6 +214,17 @@ QHash Metadata::customIcons() const return m_customIcons; } +QHash Metadata::customIconsScaledPixmaps() const +{ + QHash result; + + Q_FOREACH (const Uuid& uuid, m_customIconsOrder) { + result.insert(uuid, customIconScaledPixmap(uuid)); + } + + return result; +} + QList Metadata::customIconsOrder() const { return m_customIconsOrder; @@ -338,6 +386,9 @@ void Metadata::addCustomIcon(const Uuid& uuid, const QImage& icon) Q_ASSERT(!m_customIcons.contains(uuid)); m_customIcons.insert(uuid, icon); + // reset cache in case there is also an icon with that uuid + m_customIconCacheKeys[uuid] = QPixmapCache::Key(); + m_customIconScaledCacheKeys[uuid] = QPixmapCache::Key(); m_customIconsOrder.append(uuid); Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count()); Q_EMIT modified(); @@ -365,6 +416,10 @@ void Metadata::removeCustomIcon(const Uuid& uuid) Q_ASSERT(m_customIcons.contains(uuid)); m_customIcons.remove(uuid); + QPixmapCache::remove(m_customIconCacheKeys.value(uuid)); + m_customIconCacheKeys.remove(uuid); + QPixmapCache::remove(m_customIconScaledCacheKeys.value(uuid)); + m_customIconScaledCacheKeys.remove(uuid); m_customIconsOrder.removeAll(uuid); Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count()); Q_EMIT modified(); diff --git a/src/core/Metadata.h b/src/core/Metadata.h index 4164fb63..c35aed39 100644 --- a/src/core/Metadata.h +++ b/src/core/Metadata.h @@ -22,9 +22,10 @@ #include #include #include +#include +#include #include -#include "core/Global.h" #include "core/Uuid.h" class Database; @@ -35,7 +36,7 @@ class Metadata : public QObject Q_OBJECT public: - explicit Metadata(QObject* parent = Q_NULLPTR); + explicit Metadata(QObject* parent = nullptr); struct MetadataData { @@ -78,10 +79,13 @@ public: bool protectNotes() const; // bool autoEnableVisualHiding() const; QImage customIcon(const Uuid& uuid) const; + QPixmap customIconPixmap(const Uuid& uuid) const; + QPixmap customIconScaledPixmap(const Uuid& uuid) const; bool containsCustomIcon(const Uuid& uuid) const; QHash customIcons() const; QList customIconsOrder() const; bool recycleBinEnabled() const; + QHash customIconsScaledPixmaps() const; Group* recycleBin(); const Group* recycleBin() const; QDateTime recycleBinChanged() const; @@ -153,6 +157,8 @@ private: MetadataData m_data; QHash m_customIcons; + mutable QHash m_customIconCacheKeys; + mutable QHash m_customIconScaledCacheKeys; QList m_customIconsOrder; QPointer m_recycleBin; diff --git a/src/core/PasswordGenerator.h b/src/core/PasswordGenerator.h index 54982ac9..4edeb005 100644 --- a/src/core/PasswordGenerator.h +++ b/src/core/PasswordGenerator.h @@ -22,8 +22,6 @@ #include #include -#include "core/Global.h" - typedef QVector PasswordGroup; class PasswordGenerator diff --git a/src/core/SignalMultiplexer.cpp b/src/core/SignalMultiplexer.cpp index a70e9efc..ebf38bf6 100644 --- a/src/core/SignalMultiplexer.cpp +++ b/src/core/SignalMultiplexer.cpp @@ -24,7 +24,7 @@ SignalMultiplexer::SignalMultiplexer() SignalMultiplexer::~SignalMultiplexer() { // disconnect all connections - setCurrentObject(Q_NULLPTR); + setCurrentObject(nullptr); } QObject* SignalMultiplexer::currentObject() const diff --git a/src/core/SignalMultiplexer.h b/src/core/SignalMultiplexer.h index 6d39cd5b..b27e1f3a 100644 --- a/src/core/SignalMultiplexer.h +++ b/src/core/SignalMultiplexer.h @@ -21,8 +21,6 @@ #include #include -#include "core/Global.h" - class SignalMultiplexer { public: diff --git a/src/core/TimeInfo.cpp b/src/core/TimeInfo.cpp index 26133259..ec6ebdee 100644 --- a/src/core/TimeInfo.cpp +++ b/src/core/TimeInfo.cpp @@ -23,7 +23,7 @@ TimeInfo::TimeInfo() : m_expires(false) , m_usageCount(0) { - QDateTime now = Tools::currentDateTimeUtc(); + QDateTime now = QDateTime::currentDateTimeUtc(); m_lastModificationTime = now; m_creationTime = now; m_lastAccessTime = now; diff --git a/src/core/Tools.cpp b/src/core/Tools.cpp index 8034417f..06eb73d1 100644 --- a/src/core/Tools.cpp +++ b/src/core/Tools.cpp @@ -23,14 +23,10 @@ #include #include -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) #include -#else -#include -#endif #ifdef Q_OS_WIN -#include // for Sleep() +#include // for Sleep(), SetDllDirectoryA() and SetSearchPathMode() #endif #ifdef Q_OS_UNIX @@ -122,15 +118,6 @@ bool readAllFromDevice(QIODevice* device, QByteArray& data) } } -QDateTime currentDateTimeUtc() -{ -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - return QDateTime::currentDateTimeUtc(); -#else - return QDateTime::currentDateTime().toUTC(); -#endif -} - QString imageReaderFilter() { QList formats = QImageReader::supportedImageFormats(); @@ -160,6 +147,16 @@ bool isHex(const QByteArray& ba) return true; } +bool isBase64(const QByteArray& ba) +{ + QRegExp regexp("^(?:[a-z0-9+/]{4})*(?:[a-z0-9+/]{3}=|[a-z0-9+/]{2}==)?$", + Qt::CaseInsensitive, QRegExp::RegExp2); + + QString base64 = QString::fromLatin1(ba.constData(), ba.size()); + + return regexp.exactMatch(base64); +} + void sleep(int ms) { Q_ASSERT(ms >= 0); @@ -174,7 +171,7 @@ void sleep(int ms) timespec ts; ts.tv_sec = ms / 1000; ts.tv_nsec = (ms % 1000) * 1000 * 1000; - nanosleep(&ts, Q_NULLPTR); + nanosleep(&ts, nullptr); #endif } @@ -186,11 +183,7 @@ void wait(int ms) return; } -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) QElapsedTimer timer; -#else - QTime timer; -#endif timer.start(); if (ms <= 50) { @@ -205,23 +198,10 @@ void wait(int ms) QCoreApplication::processEvents(QEventLoop::AllEvents, timeLeft); sleep(10); } - } while (timer.elapsed() < ms); + } while (!timer.hasExpired(ms)); } } -QString platform() -{ -#if defined(Q_WS_X11) - return "x11"; -#elif defined(Q_WS_MAC) - return "mac"; -#elif defined(Q_WS_WIN) - return "win"; -#else - return QString(); -#endif -} - void disableCoreDumps() { // default to true @@ -249,4 +229,13 @@ void disableCoreDumps() } } +void setupSearchPaths() +{ +#ifdef Q_OS_WIN + // Make sure Windows doesn't load DLLs from the current working directory + SetDllDirectoryA(""); + SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE); +#endif +} + } // namespace Tools diff --git a/src/core/Tools.h b/src/core/Tools.h index 8058f251..65df1ea4 100644 --- a/src/core/Tools.h +++ b/src/core/Tools.h @@ -18,11 +18,13 @@ #ifndef KEEPASSX_TOOLS_H #define KEEPASSX_TOOLS_H +#include "core/Global.h" + #include #include #include -#include "core/Global.h" +#include class QIODevice; @@ -32,13 +34,26 @@ QString humanReadableFileSize(qint64 bytes); bool hasChild(const QObject* parent, const QObject* child); bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384); bool readAllFromDevice(QIODevice* device, QByteArray& data); -QDateTime currentDateTimeUtc(); QString imageReaderFilter(); bool isHex(const QByteArray& ba); +bool isBase64(const QByteArray& ba); void sleep(int ms); void wait(int ms); -QString platform(); void disableCoreDumps(); +void setupSearchPaths(); + +template +RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value) +{ + RandomAccessIterator it = std::lower_bound(begin, end, value); + + if ((it == end) || (value < *it)) { + return end; + } + else { + return it; + } +} } // namespace Tools diff --git a/src/core/Translator.cpp b/src/core/Translator.cpp index bc4d2b62..ed63693c 100644 --- a/src/core/Translator.cpp +++ b/src/core/Translator.cpp @@ -67,8 +67,15 @@ QList > Translator::availableLanguages() langcode = "en"; } - languages.append(QPair(langcode, - QLocale::languageToString(QLocale(langcode).language()))); + QLocale locale(langcode); + QString languageStr = QLocale::languageToString(locale.language()); + QString countryStr; + if (langcode.contains("_")) { + countryStr = QString(" (%1)").arg(QLocale::countryToString(locale.country())); + } + + QPair language(langcode, languageStr + countryStr); + languages.append(language); } } } diff --git a/src/core/qcommandlineoption.cpp b/src/core/qcommandlineoption.cpp deleted file mode 100644 index c908807b..00000000 --- a/src/core/qcommandlineoption.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Laszlo Papp -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qcommandlineoption.h" - -#include - -class QCommandLineOptionPrivate : public QSharedData -{ -public: - inline QCommandLineOptionPrivate() - { } - - void setNames(const QStringList &nameList); - - //! The list of names used for this option. - QStringList names; - - //! The documentation name for the value, if one is expected - //! Example: "-o " means valueName == "file" - QString valueName; - - //! The description used for this option. - QString description; - - //! The list of default values used for this option. - QStringList defaultValues; -}; - -/*! - \since 5.2 - \class QCommandLineOption - \brief The QCommandLineOption class defines a possible command-line option. - \inmodule QtCore - \ingroup shared - \ingroup tools - - This class is used to describe an option on the command line. It allows - different ways of defining the same option with multiple aliases possible. - It is also used to describe how the option is used - it may be a flag (e.g. \c{-v}) - or take an argument (e.g. \c{-o file}). - - Examples: - \snippet code/src_corelib_tools_qcommandlineoption.cpp 0 - - \sa QCommandLineParser -*/ - -/*! - Constructs a command line option object with the given arguments. - - The name of the option is set to \a name. - The name can be either short or long. If the name is one character in - length, it is considered a short name. Option names must not be empty, - must not start with a dash or a slash character, must not contain a \c{=} - and cannot be repeated. - - The description is set to \a description. It is customary to add a "." - at the end of the description. - - In addition, the \a valueName can be set if the option expects a value. - The default value for the option is set to \a defaultValue. - - \sa setDescription(), setValueName(), setDefaultValues() -*/ -QCommandLineOption::QCommandLineOption(const QString &name, const QString &description, - const QString &valueName, - const QString &defaultValue) - : d(new QCommandLineOptionPrivate) -{ - d->setNames(QStringList(name)); - setValueName(valueName); - setDescription(description); - setDefaultValue(defaultValue); -} - -/*! - Constructs a command line option object with the given arguments. - - This overload allows to set multiple names for the option, for instance - \c{o} and \c{output}. - - The names of the option are set to \a names. - The names can be either short or long. Any name in the list that is one - character in length is a short name. Option names must not be empty, - must not start with a dash or a slash character, must not contain a \c{=} - and cannot be repeated. - - The description is set to \a description. It is customary to add a "." - at the end of the description. - - In addition, the \a valueName can be set if the option expects a value. - The default value for the option is set to \a defaultValue. - - \sa setDescription(), setValueName(), setDefaultValues() -*/ -QCommandLineOption::QCommandLineOption(const QStringList &names, const QString &description, - const QString &valueName, - const QString &defaultValue) - : d(new QCommandLineOptionPrivate) -{ - d->setNames(names); - setValueName(valueName); - setDescription(description); - setDefaultValue(defaultValue); -} - -/*! - Constructs a QCommandLineOption object that is a copy of the QCommandLineOption - object \a other. - - \sa operator=() -*/ -QCommandLineOption::QCommandLineOption(const QCommandLineOption &other) - : d(other.d) -{ -} - -/*! - Destroys the command line option object. -*/ -QCommandLineOption::~QCommandLineOption() -{ -} - -/*! - Makes a copy of the \a other object and assigns it to this QCommandLineOption - object. -*/ -QCommandLineOption &QCommandLineOption::operator=(const QCommandLineOption &other) -{ - d = other.d; - return *this; -} - -/*! - Returns the names set for this option. - */ -QStringList QCommandLineOption::names() const -{ - return d->names; -} - -void QCommandLineOptionPrivate::setNames(const QStringList &nameList) -{ - QStringList newNames; - if (nameList.isEmpty()) - qWarning("QCommandLineOption: Options must have at least one name"); - Q_FOREACH (const QString &name, nameList) { - if (name.isEmpty()) { - qWarning("QCommandLineOption: Option names cannot be empty"); - } else { - const QChar c = name.at(0); - if (c == QLatin1Char('-')) - qWarning("QCommandLineOption: Option names cannot start with a '-'"); - else if (c == QLatin1Char('/')) - qWarning("QCommandLineOption: Option names cannot start with a '/'"); - else if (name.contains(QLatin1Char('='))) - qWarning("QCommandLineOption: Option names cannot contain a '='"); - else - newNames.append(name); - } - } - // commit - names = newNames; -} - -/*! - Sets the name of the expected value, for the documentation, to \a valueName. - - Options without a value assigned have a boolean-like behavior: - either the user specifies --option or they don't. - - Options with a value assigned need to set a name for the expected value, - for the documentation of the option in the help output. An option with names \c{o} and \c{output}, - and a value name of \c{file} will appear as \c{-o, --output }. - - Call QCommandLineParser::argument() if you expect the option to be present - only once, and QCommandLineParser::arguments() if you expect that option - to be present multiple times. - - \sa valueName() - */ -void QCommandLineOption::setValueName(const QString &valueName) -{ - d->valueName = valueName; -} - -/*! - Returns the name of the expected value. - - If empty, the option doesn't take a value. - - \sa setValueName() - */ -QString QCommandLineOption::valueName() const -{ - return d->valueName; -} - -/*! - Sets the description used for this option to \a description. - - It is customary to add a "." at the end of the description. - - The description is used by QCommandLineParser::showHelp(). - - \sa description() - */ -void QCommandLineOption::setDescription(const QString &description) -{ - d->description = description; -} - -/*! - Returns the description set for this option. - - \sa setDescription() - */ -QString QCommandLineOption::description() const -{ - return d->description; -} - -/*! - Sets the default value used for this option to \a defaultValue. - - The default value is used if the user of the application does not specify - the option on the command line. - - If \a defaultValue is empty, the option has no default values. - - \sa defaultValues() setDefaultValues() - */ -void QCommandLineOption::setDefaultValue(const QString &defaultValue) -{ - QStringList newDefaultValues; - if (!defaultValue.isEmpty()) { - newDefaultValues << defaultValue; - } - // commit: - d->defaultValues = newDefaultValues; -} - -/*! - Sets the list of default values used for this option to \a defaultValues. - - The default values are used if the user of the application does not specify - the option on the command line. - - \sa defaultValues() setDefaultValue() - */ -void QCommandLineOption::setDefaultValues(const QStringList &defaultValues) -{ - d->defaultValues = defaultValues; -} - -/*! - Returns the default values set for this option. - - \sa setDefaultValues() - */ -QStringList QCommandLineOption::defaultValues() const -{ - return d->defaultValues; -} diff --git a/src/core/qcommandlineoption.h b/src/core/qcommandlineoption.h deleted file mode 100644 index b97d44c3..00000000 --- a/src/core/qcommandlineoption.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Laszlo Papp -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QCOMMANDLINEOPTION_H -#define QCOMMANDLINEOPTION_H - -#include -#include - -class QCommandLineOptionPrivate; - -class QCommandLineOption -{ -public: - explicit QCommandLineOption(const QString &name, const QString &description = QString(), - const QString &valueName = QString(), - const QString &defaultValue = QString()); - explicit QCommandLineOption(const QStringList &names, const QString &description = QString(), - const QString &valueName = QString(), - const QString &defaultValue = QString()); - QCommandLineOption(const QCommandLineOption &other); - - ~QCommandLineOption(); - - QCommandLineOption &operator=(const QCommandLineOption &other); - - QStringList names() const; - - void setValueName(const QString &name); - QString valueName() const; - - void setDescription(const QString &description); - QString description() const; - - void setDefaultValue(const QString &defaultValue); - void setDefaultValues(const QStringList &defaultValues); - QStringList defaultValues() const; - -private: - QSharedDataPointer d; -}; - -#endif // QCOMMANDLINEOPTION_H diff --git a/src/core/qcommandlineparser.cpp b/src/core/qcommandlineparser.cpp deleted file mode 100644 index f97d78a3..00000000 --- a/src/core/qcommandlineparser.cpp +++ /dev/null @@ -1,944 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Laszlo Papp -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qcommandlineparser.h" - -#include -#include -#include -#include -#include - -typedef QHash NameHash_t; - -class QCommandLineParserPrivate -{ -public: - inline QCommandLineParserPrivate() - : singleDashWordOptionMode(QCommandLineParser::ParseAsCompactedShortOptions), - builtinVersionOption(false), - builtinHelpOption(false), - needsParsing(true) - { } - - bool parse(const QStringList &args); - void checkParsed(const char *method); - QStringList aliases(const QString &name) const; - QString helpText() const; - bool registerFoundOption(const QString &optionName); - bool parseOptionValue(const QString &optionName, const QString &argument, - QStringList::const_iterator *argumentIterator, - QStringList::const_iterator argsEnd); - - //! Error text set when parse() returns false - QString errorText; - - //! The command line options used for parsing - QList commandLineOptionList; - - //! Hash mapping option names to their offsets in commandLineOptionList and optionArgumentList. - NameHash_t nameHash; - - //! Option values found (only for options with a value) - QHash optionValuesHash; - - //! Names of options found on the command line. - QStringList optionNames; - - //! Arguments which did not belong to any option. - QStringList positionalArgumentList; - - //! Names of options which were unknown. - QStringList unknownOptionNames; - - //! Application description - QString description; - - //! Documentation for positional arguments - struct PositionalArgumentDefinition - { - QString name; - QString description; - QString syntax; - }; - QVector positionalArgumentDefinitions; - - //! The parsing mode for "-abc" - QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode; - - //! Whether addVersionOption was called - bool builtinVersionOption; - - //! Whether addHelpOption was called - bool builtinHelpOption; - - //! True if parse() needs to be called - bool needsParsing; -}; - -QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const -{ - const NameHash_t::const_iterator it = nameHash.find(optionName); - if (it == nameHash.end()) { - qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName)); - return QStringList(); - } - return commandLineOptionList.at(*it).names(); -} - -/*! - \since 5.2 - \class QCommandLineParser - \inmodule QtCore - \ingroup tools - - \brief The QCommandLineParser class provides a means for handling the - command line options. - - QCoreApplication provides the command-line arguments as a simple list of strings. - QCommandLineParser provides the ability to define a set of options, parse the - command-line arguments, and store which options have actually been used, as - well as option values. - - Any argument that isn't an option (i.e. doesn't start with a \c{-}) is stored - as a "positional argument". - - The parser handles short names, long names, more than one name for the same - option, and option values. - - Options on the command line are recognized as starting with a single or - double \c{-} character(s). - The option \c{-} (single dash alone) is a special case, often meaning standard - input, and not treated as an option. The parser will treat everything after the - option \c{--} (double dash) as positional arguments. - - Short options are single letters. The option \c{v} would be specified by - passing \c{-v} on the command line. In the default parsing mode, short options - can be written in a compact form, for instance \c{-abc} is equivalent to \c{-a -b -c}. - The parsing mode for can be set to ParseAsLongOptions, in which case \c{-abc} - will be parsed as the long option \c{abc}. - - Long options are more than one letter long and cannot be compacted together. - The long option \c{verbose} would be passed as \c{--verbose} or \c{-verbose}. - - Passing values to options can be done using the assignment operator: \c{-v=value} - \c{--verbose=value}, or a space: \c{-v value} \c{--verbose value}, i.e. the next - argument is used as value (even if it starts with a \c{-}). - - The parser does not support optional values - if an option is set to - require a value, one must be present. If such an option is placed last - and has no value, the option will be treated as if it had not been - specified. - - The parser does not automatically support negating or disabling long options - by using the format \c{--disable-option} or \c{--no-option}. However, it is - possible to handle this case explicitly by making an option with \c{no-option} - as one of its names, and handling the option explicitly. - - Example: - \snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0 - - Known limitation: the parsing of Qt options inside QCoreApplication and subclasses - happens before QCommandLineParser exists, so it can't take it into account. This - means any option value that looks like a builtin Qt option, will be treated by - QCoreApplication as a builtin Qt option. Example: \c{--profile -reverse} will - lead to QGuiApplication seeing the -reverse option set, and removing it from - QCoreApplication::arguments() before QCommandLineParser defines the \c{profile} - option and parses the command line. - - \sa QCommandLineOption, QCoreApplication -*/ - -/*! - Constructs a command line parser object. -*/ -QCommandLineParser::QCommandLineParser() - : d(new QCommandLineParserPrivate) -{ -} - -/*! - Destroys the command line parser object. -*/ -QCommandLineParser::~QCommandLineParser() -{ - delete d; -} - -/*! - \enum QCommandLineParser::SingleDashWordOptionMode - - This enum describes the way the parser interprets command-line - options that use a single dash followed by multiple letters, as as \c{-abc}. - - \value ParseAsCompactedShortOptions \c{-abc} is interpreted as \c{-a -b -c}, - i.e. as three short options that have been compacted on the command-line, - if none of the options take a value. If \c{a} takes a value, then it - is interpreted as \c{-a bc}, i.e. the short option \c{a} followed by the value \c{bc}. - This is typically used in tools that behave like compilers, in order - to handle options such as \c{-DDEFINE=VALUE} or \c{-I/include/path}. - This is the default parsing mode. New applications are recommended to - use this mode. - - \value ParseAsLongOptions \c{-abc} is interpreted as \c{--abc}, - i.e. as the long option named \c{abc}. This is how Qt's own tools - (uic, rcc...) have always been parsing arguments. This mode should be - used for preserving compatibility in applications that were parsing - arguments in such a way. - - \sa setSingleDashWordOptionMode() -*/ - -/*! - Sets the parsing mode to \a singleDashWordOptionMode. - This must be called before process() or parse(). -*/ -void QCommandLineParser::setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode) -{ - d->singleDashWordOptionMode = singleDashWordOptionMode; -} - -/*! - Adds the option \a option to look for while parsing. - - Returns \c true if adding the option was successful; otherwise returns \c false. - - Adding the option fails if there is no name attached to the option, or - the option has a name that clashes with an option name added before. - */ -bool QCommandLineParser::addOption(const QCommandLineOption &option) -{ - QStringList optionNames = option.names(); - - if (!optionNames.isEmpty()) { - Q_FOREACH (const QString &name, optionNames) { - if (d->nameHash.contains(name)) - return false; - } - - d->commandLineOptionList.append(option); - - const int offset = d->commandLineOptionList.size() - 1; - Q_FOREACH (const QString &name, optionNames) - d->nameHash.insert(name, offset); - - return true; - } - - return false; -} - -/*! - Adds the \c{-v} / \c{--version} option, which displays the version string of the application. - - This option is handled automatically by QCommandLineParser. - - You can set the actual version string by using QCoreApplication::setApplicationVersion(). - - Returns the option instance, which can be used to call isSet(). -*/ -QCommandLineOption QCommandLineParser::addVersionOption() -{ - QCommandLineOption opt(QStringList() << "v" << "version", tr("Displays version information.")); - addOption(opt); - d->builtinVersionOption = true; - return opt; -} - -/*! - Adds the help option (\c{-h}, \c{--help} and \c{-?} on Windows) - This option is handled automatically by QCommandLineParser. - - Remember to use setApplicationDescription to set the application description, - which will be displayed when this option is used. - - Example: - \snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0 - - Returns the option instance, which can be used to call isSet(). -*/ -QCommandLineOption QCommandLineParser::addHelpOption() -{ - QCommandLineOption opt(QStringList() -#ifdef Q_OS_WIN - << "?" -#endif - << "h" - << "help", tr("Displays this help.")); - addOption(opt); - d->builtinHelpOption = true; - return opt; -} - -/*! - Sets the application \a description shown by helpText(). -*/ -void QCommandLineParser::setApplicationDescription(const QString &description) -{ - d->description = description; -} - -/*! - Returns the application description set in setApplicationDescription(). -*/ -QString QCommandLineParser::applicationDescription() const -{ - return d->description; -} - -/*! - Defines an additional argument to the application, for the benefit of the help text. - - The argument \a name and \a description will appear under the \c{Arguments:} section - of the help. If \a syntax is specified, it will be appended to the Usage line, otherwise - the \a name will be appended. - - Example: - \snippet code/src_corelib_tools_qcommandlineparser.cpp 2 - - \sa addHelpOption(), helpText() -*/ -void QCommandLineParser::addPositionalArgument(const QString &name, const QString &description, const QString &syntax) -{ - QCommandLineParserPrivate::PositionalArgumentDefinition arg; - arg.name = name; - arg.description = description; - arg.syntax = syntax.isEmpty() ? name : syntax; - d->positionalArgumentDefinitions.append(arg); -} - -/*! - Clears the definitions of additional arguments from the help text. - - This is only needed for the special case of tools which support multiple commands - with different options. Once the actual command has been identified, the options - for this command can be defined, and the help text for the command can be adjusted - accordingly. - - Example: - \snippet code/src_corelib_tools_qcommandlineparser.cpp 3 -*/ -void QCommandLineParser::clearPositionalArguments() -{ - d->positionalArgumentDefinitions.clear(); -} - -/*! - Parses the command line \a arguments. - - Most programs don't need to call this, a simple call to process() is enough. - - parse() is more low-level, and only does the parsing. The application will have to - take care of the error handling, using errorText() if parse() returns \c false. - This can be useful for instance to show a graphical error message in graphical programs. - - Calling parse() instead of process() can also be useful in order to ignore unknown - options temporarily, because more option definitions will be provided later on - (depending on one of the arguments), before calling process(). - - Don't forget that \a arguments must start with the name of the executable (ignored, though). - - Returns \c false in case of a parse error (unknown option or missing value); returns \c true otherwise. - - \sa process() -*/ -bool QCommandLineParser::parse(const QStringList &arguments) -{ - return d->parse(arguments); -} - -/*! - Returns a translated error text for the user. - This should only be called when parse() returns \c false. -*/ -QString QCommandLineParser::errorText() const -{ - if (!d->errorText.isEmpty()) - return d->errorText; - if (d->unknownOptionNames.count() == 1) - return tr("Unknown option '%1'.").arg(d->unknownOptionNames.first()); - if (d->unknownOptionNames.count() > 1) - return tr("Unknown options: %1.").arg(d->unknownOptionNames.join(", ")); - return QString(); -} - -/*! - Processes the command line \a arguments. - - In addition to parsing the options (like parse()), this function also handles the builtin - options and handles errors. - - The builtin options are \c{--version} if addVersionOption was called and \c{--help} if addHelpOption was called. - - When invoking one of these options, or when an error happens (for instance an unknown option was - passed), the current process will then stop, using the exit() function. - - \sa QCoreApplication::arguments(), parse() - */ -void QCommandLineParser::process(const QStringList &arguments) -{ - if (!d->parse(arguments)) { - fprintf(stderr, "%s\n", qPrintable(errorText())); - ::exit(EXIT_FAILURE); - } - - if (d->builtinVersionOption && isSet("version")) { - printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion())); - ::exit(EXIT_SUCCESS); - } - - if (d->builtinHelpOption && isSet("help")) - showHelp(EXIT_SUCCESS); -} - -/*! - \overload - - The command line is obtained from the QCoreApplication instance \a app. - */ -void QCommandLineParser::process(const QCoreApplication &app) -{ - // QCoreApplication::arguments() is static, but the app instance must exist so we require it as parameter - Q_UNUSED(app); - process(QCoreApplication::arguments()); -} - -void QCommandLineParserPrivate::checkParsed(const char *method) -{ - if (needsParsing) - qWarning("QCommandLineParser: call process() or parse() before %s", method); -} - -/*! - \internal - Looks up the option \a optionName (found on the command line) and register it as found. - Returns \c true on success. - */ -bool QCommandLineParserPrivate::registerFoundOption(const QString &optionName) -{ - if (nameHash.contains(optionName)) { - optionNames.append(optionName); - return true; - } else { - unknownOptionNames.append(optionName); - return false; - } -} - -/*! - \internal - \brief Parse the value for a given option, if it was defined to expect one. - - The value is taken from the next argument, or after the equal sign in \a argument. - - \param optionName the short option name - \param argument the argument from the command line currently parsed. Only used for -k=value parsing. - \param argumentIterator iterator to the currently parsed argument. Incremented if the next argument contains the value. - \param argsEnd args.end(), to check if ++argumentIterator goes out of bounds - Returns \c true on success. - */ -bool QCommandLineParserPrivate::parseOptionValue(const QString &optionName, const QString &argument, - QStringList::const_iterator *argumentIterator, QStringList::const_iterator argsEnd) -{ - const QLatin1Char assignChar('='); - const NameHash_t::const_iterator nameHashIt = nameHash.constFind(optionName); - if (nameHashIt != nameHash.constEnd()) { - const int assignPos = argument.indexOf(assignChar); - const NameHash_t::mapped_type optionOffset = *nameHashIt; - const bool withValue = !commandLineOptionList.at(optionOffset).valueName().isEmpty(); - if (withValue) { - if (assignPos == -1) { - ++(*argumentIterator); - if (*argumentIterator == argsEnd) { - errorText = QCommandLineParser::tr("Missing value after '%1'.").arg(argument); - return false; - } - optionValuesHash[optionOffset].append(*(*argumentIterator)); - } else { - optionValuesHash[optionOffset].append(argument.mid(assignPos + 1)); - } - } else { - if (assignPos != -1) { - errorText = QCommandLineParser::tr("Unexpected value after '%1'.").arg(argument.left(assignPos)); - return false; - } - } - } - return true; -} - -/*! - \internal - - Parse the list of arguments \a args, and fills in - optionNames, optionValuesHash, unknownOptionNames, positionalArguments, and errorText. - - Any results from a previous parse operation are removed. - - The parser will not look for further options once it encounters the option - \c{--}; this does not include when \c{--} follows an option that requires a value. - */ -bool QCommandLineParserPrivate::parse(const QStringList &args) -{ - needsParsing = false; - bool error = false; - - const QString doubleDashString("--"); - const QLatin1Char dashChar('-'); - const QLatin1Char assignChar('='); - - bool doubleDashFound = false; - errorText.clear(); - positionalArgumentList.clear(); - optionNames.clear(); - unknownOptionNames.clear(); - optionValuesHash.clear(); - - if (args.isEmpty()) { - qWarning("QCommandLineParser: argument list cannot be empty, it should contain at least the executable name"); - return false; - } - - QStringList::const_iterator argumentIterator = args.begin(); - ++argumentIterator; // skip executable name - - for (; argumentIterator != args.end() ; ++argumentIterator) { - QString argument = *argumentIterator; - - if (doubleDashFound) { - positionalArgumentList.append(argument); - } else if (argument.startsWith(doubleDashString)) { - if (argument.length() > 2) { - QString optionName = argument.mid(2).section(assignChar, 0, 0); - if (registerFoundOption(optionName)) { - if (!parseOptionValue(optionName, argument, &argumentIterator, args.end())) - error = true; - } else { - error = true; - } - } else { - doubleDashFound = true; - } - } else if (argument.startsWith(dashChar)) { - if (argument.size() == 1) { // single dash ("stdin") - positionalArgumentList.append(argument); - continue; - } - switch (singleDashWordOptionMode) { - case QCommandLineParser::ParseAsCompactedShortOptions: - { - QString optionName; - bool valueFound = false; - for (int pos = 1 ; pos < argument.size(); ++pos) { - optionName = argument.mid(pos, 1); - if (!registerFoundOption(optionName)) { - error = true; - } else { - const NameHash_t::const_iterator nameHashIt = nameHash.constFind(optionName); - Q_ASSERT(nameHashIt != nameHash.constEnd()); // checked by registerFoundOption - const NameHash_t::mapped_type optionOffset = *nameHashIt; - const bool withValue = !commandLineOptionList.at(optionOffset).valueName().isEmpty(); - if (withValue) { - if (pos + 1 < argument.size()) { - if (argument.at(pos + 1) == assignChar) - ++pos; - optionValuesHash[optionOffset].append(argument.mid(pos + 1)); - valueFound = true; - } - break; - } - if (pos + 1 < argument.size() && argument.at(pos + 1) == assignChar) - break; - } - } - if (!valueFound && !parseOptionValue(optionName, argument, &argumentIterator, args.end())) - error = true; - break; - } - case QCommandLineParser::ParseAsLongOptions: - { - const QString optionName = argument.mid(1).section(assignChar, 0, 0); - if (registerFoundOption(optionName)) { - if (!parseOptionValue(optionName, argument, &argumentIterator, args.end())) - error = true; - } else { - error = true; - } - break; - } - } - } else { - positionalArgumentList.append(argument); - } - if (argumentIterator == args.end()) - break; - } - return !error; -} - -/*! - Checks whether the option \a name was passed to the application. - - Returns \c true if the option \a name was set, false otherwise. - - The name provided can be any long or short name of any option that was - added with \c addOption(). All the options names are treated as being - equivalent. If the name is not recognized or that option was not present, - false is returned. - - Example: - \snippet code/src_corelib_tools_qcommandlineparser.cpp 0 - */ - -bool QCommandLineParser::isSet(const QString &name) const -{ - d->checkParsed("isSet"); - if (d->optionNames.contains(name)) - return true; - const QStringList aliases = d->aliases(name); - Q_FOREACH (const QString &optionName, d->optionNames) { - if (aliases.contains(optionName)) - return true; - } - return false; -} - -/*! - Returns the option value found for the given option name \a optionName, or - an empty string if not found. - - The name provided can be any long or short name of any option that was - added with \c addOption(). All the option names are treated as being - equivalent. If the name is not recognized or that option was not present, an - empty string is returned. - - For options found by the parser, the last value found for - that option is returned. If the option wasn't specified on the command line, - the default value is returned. - - An empty string is returned if the option does not take a value. - - \sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues() - */ - -QString QCommandLineParser::value(const QString &optionName) const -{ - d->checkParsed("value"); - const QStringList valueList = values(optionName); - - if (!valueList.isEmpty()) - return valueList.last(); - - return QString(); -} - -/*! - Returns a list of option values found for the given option name \a - optionName, or an empty list if not found. - - The name provided can be any long or short name of any option that was - added with \c addOption(). All the options names are treated as being - equivalent. If the name is not recognized or that option was not present, an - empty list is returned. - - For options found by the parser, the list will contain an entry for - each time the option was encountered by the parser. If the option wasn't - specified on the command line, the default values are returned. - - An empty list is returned if the option does not take a value. - - \sa value(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues() - */ - -QStringList QCommandLineParser::values(const QString &optionName) const -{ - d->checkParsed("values"); - const NameHash_t::const_iterator it = d->nameHash.constFind(optionName); - if (it != d->nameHash.constEnd()) { - const int optionOffset = *it; - QStringList values = d->optionValuesHash.value(optionOffset); - if (values.isEmpty()) - values = d->commandLineOptionList.at(optionOffset).defaultValues(); - return values; - } - - qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName)); - return QStringList(); -} - -/*! - \overload - Checks whether the \a option was passed to the application. - - Returns \c true if the \a option was set, false otherwise. - - This is the recommended way to check for options with no values. - - Example: - \snippet code/src_corelib_tools_qcommandlineparser.cpp 1 -*/ -bool QCommandLineParser::isSet(const QCommandLineOption &option) const -{ - // option.names() might be empty if the constructor failed - return !option.names().isEmpty() && isSet(option.names().first()); -} - -/*! - \overload - Returns the option value found for the given \a option, or - an empty string if not found. - - For options found by the parser, the last value found for - that option is returned. If the option wasn't specified on the command line, - the default value is returned. - - An empty string is returned if the option does not take a value. - - \sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues() -*/ -QString QCommandLineParser::value(const QCommandLineOption &option) const -{ - return value(option.names().first()); -} - -/*! - \overload - Returns a list of option values found for the given \a option, - or an empty list if not found. - - For options found by the parser, the list will contain an entry for - each time the option was encountered by the parser. If the option wasn't - specified on the command line, the default values are returned. - - An empty list is returned if the option does not take a value. - - \sa value(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues() -*/ -QStringList QCommandLineParser::values(const QCommandLineOption &option) const -{ - return values(option.names().first()); -} - -/*! - Returns a list of positional arguments. - - These are all of the arguments that were not recognized as part of an - option. - */ - -QStringList QCommandLineParser::positionalArguments() const -{ - d->checkParsed("positionalArguments"); - return d->positionalArgumentList; -} - -/*! - Returns a list of option names that were found. - - This returns a list of all the recognized option names found by the - parser, in the order in which they were found. For any long options - that were in the form {--option=value}, the value part will have been - dropped. - - The names in this list do not include the preceding dash characters. - Names may appear more than once in this list if they were encountered - more than once by the parser. - - Any entry in the list can be used with \c value() or with - \c values() to get any relevant option values. - */ - -QStringList QCommandLineParser::optionNames() const -{ - d->checkParsed("optionNames"); - return d->optionNames; -} - -/*! - Returns a list of unknown option names. - - This list will include both long an short name options that were not - recognized. For any long options that were in the form {--option=value}, - the value part will have been dropped and only the long name is added. - - The names in this list do not include the preceding dash characters. - Names may appear more than once in this list if they were encountered - more than once by the parser. - - \sa optionNames() - */ - -QStringList QCommandLineParser::unknownOptionNames() const -{ - d->checkParsed("unknownOptionNames"); - return d->unknownOptionNames; -} - -/*! - Displays the help information, and exits the application. - This is automatically triggered by the --help option, but can also - be used to display the help when the user is not invoking the - application correctly. - The exit code is set to \a exitCode. It should be set to 0 if the - user requested to see the help, and to any other value in case of - an error. - - \sa helpText() -*/ -void QCommandLineParser::showHelp(int exitCode) -{ - fprintf(stdout, "%s", qPrintable(d->helpText())); - ::exit(exitCode); -} - -/*! - Returns a string containing the complete help information. - - \sa showHelp() -*/ -QString QCommandLineParser::helpText() const -{ - return d->helpText(); -} - -static QString wrapText(const QString &names, int longestOptionNameString, const QString &description) -{ - const QLatin1Char nl('\n'); - QString text = QString(" ") + names.leftJustified(longestOptionNameString) + QLatin1Char(' '); - const int indent = text.length(); - int lineStart = 0; - int lastBreakable = -1; - const int max = 79 - indent; - int x = 0; - const int len = description.length(); - - for (int i = 0; i < len; ++i) { - ++x; - const QChar c = description.at(i); - if (c.isSpace()) - lastBreakable = i; - - int breakAt = -1; - int nextLineStart = -1; - if (x > max && lastBreakable != -1) { - // time to break and we know where - breakAt = lastBreakable; - nextLineStart = lastBreakable + 1; - } else if ((x > max - 1 && lastBreakable == -1) || i == len - 1) { - // time to break but found nowhere [-> break here], or end of last line - breakAt = i + 1; - nextLineStart = breakAt; - } else if (c == nl) { - // forced break - breakAt = i; - nextLineStart = i + 1; - } - - if (breakAt != -1) { - const int numChars = breakAt - lineStart; - //qDebug() << "breakAt=" << description.at(breakAt) << "breakAtSpace=" << breakAtSpace << lineStart << "to" << breakAt << description.mid(lineStart, numChars); - if (lineStart > 0) - text += QString(indent, QLatin1Char(' ')); - text += description.mid(lineStart, numChars) + nl; - x = 0; - lastBreakable = -1; - lineStart = nextLineStart; - if (lineStart < len && description.at(lineStart).isSpace()) - ++lineStart; // don't start a line with a space - i = lineStart; - } - } - - return text; -} - -QString QCommandLineParserPrivate::helpText() const -{ - const QLatin1Char nl('\n'); - QString text; - const QString exeName = QCoreApplication::instance()->arguments().first(); - QString usage = exeName; - if (!commandLineOptionList.isEmpty()) { - usage += QLatin1Char(' '); - usage += QCommandLineParser::tr("[options]"); - } - Q_FOREACH (const PositionalArgumentDefinition &arg, positionalArgumentDefinitions) { - usage += QLatin1Char(' '); - usage += arg.syntax; - } - text += QCommandLineParser::tr("Usage: %1").arg(usage) + nl; - if (!description.isEmpty()) - text += description + nl; - text += nl; - if (!commandLineOptionList.isEmpty()) - text += QCommandLineParser::tr("Options:") + nl; - QStringList optionNameList; - int longestOptionNameString = 0; - Q_FOREACH (const QCommandLineOption &option, commandLineOptionList) { - QStringList optionNames; - Q_FOREACH (const QString &optionName, option.names()) { - if (optionName.length() == 1) - optionNames.append(QLatin1Char('-') + optionName); - else - optionNames.append(QString("--") + optionName); - } - QString optionNamesString = optionNames.join(", "); - if (!option.valueName().isEmpty()) - optionNamesString += QString(" <") + option.valueName() + QLatin1Char('>'); - optionNameList.append(optionNamesString); - longestOptionNameString = qMax(longestOptionNameString, optionNamesString.length()); - } - ++longestOptionNameString; - for (int i = 0; i < commandLineOptionList.count(); ++i) { - const QCommandLineOption &option = commandLineOptionList.at(i); - text += wrapText(optionNameList.at(i), longestOptionNameString, option.description()); - } - if (!positionalArgumentDefinitions.isEmpty()) { - if (!commandLineOptionList.isEmpty()) - text += nl; - text += QCommandLineParser::tr("Arguments:") + nl; - Q_FOREACH (const PositionalArgumentDefinition &arg, positionalArgumentDefinitions) { - text += wrapText(arg.name, longestOptionNameString, arg.description); - } - } - return text; -} diff --git a/src/core/qcommandlineparser.h b/src/core/qcommandlineparser.h deleted file mode 100644 index eeecf2da..00000000 --- a/src/core/qcommandlineparser.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Laszlo Papp -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QCOMMANDLINEPARSER_H -#define QCOMMANDLINEPARSER_H - -#include -#include - -#include "qcommandlineoption.h" - -class QCommandLineParserPrivate; -class QCoreApplication; - -class QCommandLineParser -{ - Q_DECLARE_TR_FUNCTIONS(QCommandLineParser) -public: - QCommandLineParser(); - ~QCommandLineParser(); - - enum SingleDashWordOptionMode { - ParseAsCompactedShortOptions, - ParseAsLongOptions - }; - void setSingleDashWordOptionMode(SingleDashWordOptionMode parsingMode); - - bool addOption(const QCommandLineOption &commandLineOption); - - QCommandLineOption addVersionOption(); - QCommandLineOption addHelpOption(); - void setApplicationDescription(const QString &description); - QString applicationDescription() const; - void addPositionalArgument(const QString &name, const QString &description, const QString &syntax = QString()); - void clearPositionalArguments(); - - void process(const QStringList &arguments); - void process(const QCoreApplication &app); - - bool parse(const QStringList &arguments); - QString errorText() const; - - bool isSet(const QString &name) const; - QString value(const QString &name) const; - QStringList values(const QString &name) const; - - bool isSet(const QCommandLineOption &option) const; - QString value(const QCommandLineOption &option) const; - QStringList values(const QCommandLineOption &option) const; - - QStringList positionalArguments() const; - QStringList optionNames() const; - QStringList unknownOptionNames() const; - - void showHelp(int exitCode = 0); - QString helpText() const; - -private: - Q_DISABLE_COPY(QCommandLineParser) - - QCommandLineParserPrivate * const d; -}; - -#endif // QCOMMANDLINEPARSER_H diff --git a/src/core/qlockfile.cpp b/src/core/qlockfile.cpp deleted file mode 100644 index 980f8ed8..00000000 --- a/src/core/qlockfile.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qlockfile.h" -#include "qlockfile_p.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -/*! - \class QLockFile - \inmodule QtCore - \brief The QLockFile class provides locking between processes using a file. - \since 5.1 - - A lock file can be used to prevent multiple processes from accessing concurrently - the same resource. For instance, a configuration file on disk, or a socket, a port, - a region of shared memory... - - Serialization is only guaranteed if all processes that access the shared resource - use QLockFile, with the same file path. - - QLockFile supports two use cases: - to protect a resource for a short-term operation (e.g. verifying if a configuration - file has changed before saving new settings), and for long-lived protection of a - resource (e.g. a document opened by a user in an editor) for an indefinite amount of time. - - When protecting for a short-term operation, it is acceptable to call lock() and wait - until any running operation finishes. - When protecting a resource over a long time, however, the application should always - call setStaleLockTime(0) and then tryLock() with a short timeout, in order to - warn the user that the resource is locked. - - If the process holding the lock crashes, the lock file stays on disk and can prevent - any other process from accessing the shared resource, ever. For this reason, QLockFile - tries to detect such a "stale" lock file, based on the process ID written into the file, - and (in case that process ID got reused meanwhile), on the last modification time of - the lock file (30s by default, for the use case of a short-lived operation). - If the lock file is found to be stale, it will be deleted. - - For the use case of protecting a resource over a long time, you should therefore call - setStaleLockTime(0), and when tryLock() returns LockFailedError, inform the user - that the document is locked, possibly using getLockInfo() for more details. -*/ - -/*! - \enum QLockFile::LockError - - This enum describes the result of the last call to lock() or tryLock(). - - \value NoError The lock was acquired successfully. - \value LockFailedError The lock could not be acquired because another process holds it. - \value PermissionError The lock file could not be created, for lack of permissions - in the parent directory. - \value UnknownError Another error happened, for instance a full partition - prevented writing out the lock file. -*/ - -/*! - Constructs a new lock file object. - The object is created in an unlocked state. - When calling lock() or tryLock(), a lock file named \a fileName will be created, - if it doesn't already exist. - - \sa lock(), unlock() -*/ -QLockFile::QLockFile(const QString &fileName) - : d_ptr(new QLockFilePrivate(fileName)) -{ -} - -/*! - Destroys the lock file object. - If the lock was acquired, this will release the lock, by deleting the lock file. -*/ -QLockFile::~QLockFile() -{ - unlock(); -} - -/*! - Sets \a staleLockTime to be the time in milliseconds after which - a lock file is considered stale. - The default value is 30000, i.e. 30 seconds. - If your application typically keeps the file locked for more than 30 seconds - (for instance while saving megabytes of data for 2 minutes), you should set - a bigger value using setStaleLockTime(). - - The value of \a staleLockTime is used by lock() and tryLock() in order - to determine when an existing lock file is considered stale, i.e. left over - by a crashed process. This is useful for the case where the PID got reused - meanwhile, so the only way to detect a stale lock file is by the fact that - it has been around for a long time. - - \sa staleLockTime() -*/ -void QLockFile::setStaleLockTime(int staleLockTime) -{ - Q_D(QLockFile); - d->staleLockTime = staleLockTime; -} - -/*! - Returns the time in milliseconds after which - a lock file is considered stale. - - \sa setStaleLockTime() -*/ -int QLockFile::staleLockTime() const -{ - Q_D(const QLockFile); - return d->staleLockTime; -} - -/*! - Returns \c true if the lock was acquired by this QLockFile instance, - otherwise returns \c false. - - \sa lock(), unlock(), tryLock() -*/ -bool QLockFile::isLocked() const -{ - Q_D(const QLockFile); - return d->isLocked; -} - -/*! - Creates the lock file. - - If another process (or another thread) has created the lock file already, - this function will block until that process (or thread) releases it. - - Calling this function multiple times on the same lock from the same - thread without unlocking first is not allowed. This function will - \e dead-lock when the file is locked recursively. - - Returns \c true if the lock was acquired, false if it could not be acquired - due to an unrecoverable error, such as no permissions in the parent directory. - - \sa unlock(), tryLock() -*/ -bool QLockFile::lock() -{ - return tryLock(-1); -} - -/*! - Attempts to create the lock file. This function returns \c true if the - lock was obtained; otherwise it returns \c false. If another process (or - another thread) has created the lock file already, this function will - wait for at most \a timeout milliseconds for the lock file to become - available. - - Note: Passing a negative number as the \a timeout is equivalent to - calling lock(), i.e. this function will wait forever until the lock - file can be locked if \a timeout is negative. - - If the lock was obtained, it must be released with unlock() - before another process (or thread) can successfully lock it. - - Calling this function multiple times on the same lock from the same - thread without unlocking first is not allowed, this function will - \e always return false when attempting to lock the file recursively. - - \sa lock(), unlock() -*/ -bool QLockFile::tryLock(int timeout) -{ - Q_D(QLockFile); - QElapsedTimer timer; - if (timeout > 0) - timer.start(); - int sleepTime = 100; - Q_FOREVER { - d->lockError = d->tryLock_sys(); - switch (d->lockError) { - case NoError: - d->isLocked = true; - return true; - case PermissionError: - case UnknownError: - return false; - case LockFailedError: - if (!d->isLocked && d->isApparentlyStale()) { - // Stale lock from another thread/process - // Ensure two processes don't remove it at the same time - QLockFile rmlock(d->fileName + QLatin1String(".rmlock")); - if (rmlock.tryLock()) { - if (d->isApparentlyStale() && d->removeStaleLock()) - continue; - } - } - break; - } - if (timeout == 0 || (timeout > 0 && timer.hasExpired(timeout))) - return false; - QLockFileThread::msleep(sleepTime); - if (sleepTime < 5 * 1000) - sleepTime *= 2; - } - // not reached - return false; -} - -/*! - \fn void QLockFile::unlock() - Releases the lock, by deleting the lock file. - - Calling unlock() without locking the file first, does nothing. - - \sa lock(), tryLock() -*/ - -/*! - Retrieves information about the current owner of the lock file. - - If tryLock() returns \c false, and error() returns LockFailedError, - this function can be called to find out more information about the existing - lock file: - \list - \li the PID of the application (returned in \a pid) - \li the \a hostname it's running on (useful in case of networked filesystems), - \li the name of the application which created it (returned in \a appname), - \endlist - - Note that tryLock() automatically deleted the file if there is no - running application with this PID, so LockFailedError can only happen if there is - an application with this PID (it could be unrelated though). - - This can be used to inform users about the existing lock file and give them - the choice to delete it. After removing the file using removeStaleLockFile(), - the application can call tryLock() again. - - This function returns \c true if the information could be successfully retrieved, false - if the lock file doesn't exist or doesn't contain the expected data. - This can happen if the lock file was deleted between the time where tryLock() failed - and the call to this function. Simply call tryLock() again if this happens. -*/ -bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const -{ - Q_D(const QLockFile); - return d->getLockInfo(pid, hostname, appname); -} - -bool QLockFilePrivate::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const -{ - QFile reader(fileName); - if (!reader.open(QIODevice::ReadOnly)) - return false; - - QByteArray pidLine = reader.readLine(); - pidLine.chop(1); - QByteArray appNameLine = reader.readLine(); - appNameLine.chop(1); - QByteArray hostNameLine = reader.readLine(); - hostNameLine.chop(1); - if (pidLine.isEmpty()) - return false; - - qint64 thePid = pidLine.toLongLong(); - if (pid) - *pid = thePid; - if (appname) - *appname = QString::fromUtf8(appNameLine); - if (hostname) - *hostname = QString::fromUtf8(hostNameLine); - return thePid > 0; -} - -/*! - Attempts to forcefully remove an existing lock file. - - Calling this is not recommended when protecting a short-lived operation: QLockFile - already takes care of removing lock files after they are older than staleLockTime(). - - This method should only be called when protecting a resource for a long time, i.e. - with staleLockTime(0), and after tryLock() returned LockFailedError, and the user - agreed on removing the lock file. - - Returns \c true on success, false if the lock file couldn't be removed. This happens - on Windows, when the application owning the lock is still running. -*/ -bool QLockFile::removeStaleLockFile() -{ - Q_D(QLockFile); - if (d->isLocked) { - qWarning("removeStaleLockFile can only be called when not holding the lock"); - return false; - } - return d->removeStaleLock(); -} - -/*! - Returns the lock file error status. - - If tryLock() returns \c false, this function can be called to find out - the reason why the locking failed. -*/ -QLockFile::LockError QLockFile::error() const -{ - Q_D(const QLockFile); - return d->lockError; -} - -QT_END_NAMESPACE diff --git a/src/core/qlockfile.h b/src/core/qlockfile.h deleted file mode 100644 index 673026f2..00000000 --- a/src/core/qlockfile.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QLOCKFILE_H -#define QLOCKFILE_H - -#include -#include - -QT_BEGIN_NAMESPACE - -class QLockFilePrivate; - -class QLockFile -{ -public: - QLockFile(const QString &fileName); - ~QLockFile(); - - bool lock(); - bool tryLock(int timeout = 0); - void unlock(); - - void setStaleLockTime(int); - int staleLockTime() const; - - bool isLocked() const; - bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const; - bool removeStaleLockFile(); - - enum LockError { - NoError = 0, - LockFailedError = 1, - PermissionError = 2, - UnknownError = 3 - }; - LockError error() const; - -protected: - QScopedPointer d_ptr; - -private: - Q_DECLARE_PRIVATE(QLockFile) - Q_DISABLE_COPY(QLockFile) -}; - -QT_END_NAMESPACE - -#endif // QLOCKFILE_H diff --git a/src/core/qlockfile_p.h b/src/core/qlockfile_p.h deleted file mode 100644 index 93092683..00000000 --- a/src/core/qlockfile_p.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QLOCKFILE_P_H -#define QLOCKFILE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qlockfile.h" - -#include -#include - -#ifdef Q_OS_WIN -#include -#endif - -QT_BEGIN_NAMESPACE - -class QLockFileThread : public QThread -{ -public: - static void msleep(unsigned long msecs) { QThread::msleep(msecs); } -}; - -class QLockFilePrivate -{ -public: - QLockFilePrivate(const QString &fn) - : fileName(fn), -#ifdef Q_OS_WIN - fileHandle(INVALID_HANDLE_VALUE), -#else - fileHandle(-1), -#endif - staleLockTime(30 * 1000), // 30 seconds - lockError(QLockFile::NoError), - isLocked(false) - { - } - QLockFile::LockError tryLock_sys(); - bool removeStaleLock(); - bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const; - // Returns \c true if the lock belongs to dead PID, or is old. - // The attempt to delete it will tell us if it was really stale or not, though. - bool isApparentlyStale() const; - -#ifdef Q_OS_UNIX - static int checkFcntlWorksAfterFlock(); -#endif - - QString fileName; -#ifdef Q_OS_WIN - Qt::HANDLE fileHandle; -#else - int fileHandle; -#endif - int staleLockTime; // "int milliseconds" is big enough for 24 days - QLockFile::LockError lockError; - bool isLocked; -}; - -QT_END_NAMESPACE - -#endif /* QLOCKFILE_P_H */ diff --git a/src/core/qlockfile_unix.cpp b/src/core/qlockfile_unix.cpp deleted file mode 100644 index 99678c0b..00000000 --- a/src/core/qlockfile_unix.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qlockfile_p.h" - -#include -#include -#include -#include -#include - -#include // flock -#include // kill -#include // kill -#include - -#include - -QT_BEGIN_NAMESPACE - -#define EINTR_LOOP(var, cmd) \ - do { \ - var = cmd; \ - } while (var == -1 && errno == EINTR) - -// don't call QT_OPEN or ::open -// call qt_safe_open -static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777) -{ -#ifdef O_CLOEXEC - flags |= O_CLOEXEC; -#endif - int fd; - EINTR_LOOP(fd, ::open(pathname, flags, mode)); - - // unknown flags are ignored, so we have no way of verifying if - // O_CLOEXEC was accepted - if (fd != -1) - ::fcntl(fd, F_SETFD, FD_CLOEXEC); - return fd; -} - -static inline qint64 qt_safe_write(int fd, const void *data, qint64 len) -{ - qint64 ret = 0; - EINTR_LOOP(ret, ::write(fd, data, len)); - return ret; -} - -static QString localHostName() // from QHostInfo::localHostName() -{ - char hostName[512]; - if (gethostname(hostName, sizeof(hostName)) == -1) - return QString(); - hostName[sizeof(hostName) - 1] = '\0'; - return QString::fromLocal8Bit(hostName); -} - -// ### merge into qt_safe_write? -static qint64 qt_write_loop(int fd, const char *data, qint64 len) -{ - qint64 pos = 0; - while (pos < len) { - const qint64 ret = qt_safe_write(fd, data + pos, len - pos); - if (ret == -1) // e.g. partition full - return pos; - pos += ret; - } - return pos; -} - -static bool setNativeLocks(int fd) -{ -#if defined(LOCK_EX) && defined(LOCK_NB) - if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs - return false; -#endif - struct flock flockData; - flockData.l_type = F_WRLCK; - flockData.l_whence = SEEK_SET; - flockData.l_start = 0; - flockData.l_len = 0; // 0 = entire file - flockData.l_pid = getpid(); - if (fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems - return false; - return true; -} - -QLockFile::LockError QLockFilePrivate::tryLock_sys() -{ - // Assemble data, to write in a single call to write - // (otherwise we'd have to check every write call) - // Use operator% from the fast builder to avoid multiple memory allocations. - QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) + '\n' - + qAppName().toUtf8() + '\n' - + localHostName().toUtf8() + '\n'; - - const QByteArray lockFileName = QFile::encodeName(fileName); - const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0644); - if (fd < 0) { - switch (errno) { - case EEXIST: - return QLockFile::LockFailedError; - case EACCES: - case EROFS: - return QLockFile::PermissionError; - default: - return QLockFile::UnknownError; - } - } - // Ensure nobody else can delete the file while we have it - if (!setNativeLocks(fd)) - qWarning() << "setNativeLocks failed:" << strerror(errno); - - if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) { - close(fd); - if (!QFile::remove(fileName)) - qWarning("QLockFile: Could not remove our own lock file %s.", qPrintable(fileName)); - return QLockFile::UnknownError; // partition full - } - - // We hold the lock, continue. - fileHandle = fd; - - return QLockFile::NoError; -} - -bool QLockFilePrivate::removeStaleLock() -{ - const QByteArray lockFileName = QFile::encodeName(fileName); - const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644); - if (fd < 0) // gone already? - return false; - bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0); - close(fd); - return success; -} - -bool QLockFilePrivate::isApparentlyStale() const -{ - qint64 pid; - QString hostname, appname; - if (!getLockInfo(&pid, &hostname, &appname)) - return false; - if (hostname.isEmpty() || hostname == localHostName()) { - if (::kill(pid, 0) == -1 && errno == ESRCH) - return true; // PID doesn't exist anymore - } - const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); - return staleLockTime > 0 && age > staleLockTime; -} - -void QLockFile::unlock() -{ - Q_D(QLockFile); - if (!d->isLocked) - return; - close(d->fileHandle); - d->fileHandle = -1; - if (!QFile::remove(d->fileName)) { - qWarning() << "Could not remove our own lock file" << d->fileName << "maybe permissions changed meanwhile?"; - // This is bad because other users of this lock file will now have to wait for the stale-lock-timeout... - } - QFile::remove(d->fileName); - d->lockError = QLockFile::NoError; - d->isLocked = false; -} - -QT_END_NAMESPACE diff --git a/src/core/qlockfile_win.cpp b/src/core/qlockfile_win.cpp deleted file mode 100644 index 4ca07eb7..00000000 --- a/src/core/qlockfile_win.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef _UNICODE -#define _UNICODE -#endif - -#ifndef UNICODE -#define UNICODE -#endif - -#include "qlockfile_p.h" - -#include - -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -static inline QByteArray localHostName() -{ - return qgetenv("COMPUTERNAME"); -} - -static inline bool fileExists(const wchar_t *fileName) -{ - WIN32_FILE_ATTRIBUTE_DATA data; - return GetFileAttributesEx(fileName, GetFileExInfoStandard, &data); -} - -QLockFile::LockError QLockFilePrivate::tryLock_sys() -{ - const ushort* nativePath = QDir::toNativeSeparators(fileName).utf16(); - // When writing, allow others to read. - // When reading, QFile will allow others to read and write, all good. - // Adding FILE_SHARE_DELETE would allow forceful deletion of stale files, - // but Windows doesn't allow recreating it while this handle is open anyway, - // so this would only create confusion (can't lock, but no lock file to read from). - const DWORD dwShareMode = FILE_SHARE_READ; -#ifndef Q_OS_WINRT - SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; - HANDLE fh = CreateFile((const wchar_t*)nativePath, - GENERIC_WRITE, - dwShareMode, - &securityAtts, - CREATE_NEW, // error if already exists - FILE_ATTRIBUTE_NORMAL, - NULL); -#else // !Q_OS_WINRT - HANDLE fh = CreateFile2((const wchar_t*)nativePath, - GENERIC_WRITE, - dwShareMode, - CREATE_NEW, // error if already exists - NULL); -#endif // Q_OS_WINRT - if (fh == INVALID_HANDLE_VALUE) { - const DWORD lastError = GetLastError(); - switch (lastError) { - case ERROR_SHARING_VIOLATION: - case ERROR_ALREADY_EXISTS: - case ERROR_FILE_EXISTS: - return QLockFile::LockFailedError; - case ERROR_ACCESS_DENIED: - // readonly file, or file still in use by another process. - // Assume the latter if the file exists, since we don't create it readonly. - return fileExists((const wchar_t*)nativePath) - ? QLockFile::LockFailedError - : QLockFile::PermissionError; - default: - qWarning() << "Got unexpected locking error" << lastError; - return QLockFile::UnknownError; - } - } - - // We hold the lock, continue. - fileHandle = fh; - // Assemble data, to write in a single call to write - // (otherwise we'd have to check every write call) - QByteArray fileData; - fileData += QByteArray::number(QCoreApplication::applicationPid()); - fileData += '\n'; - fileData += QCoreApplication::applicationName().toUtf8(); - fileData += '\n'; - fileData += localHostName(); - fileData += '\n'; - DWORD bytesWritten = 0; - QLockFile::LockError error = QLockFile::NoError; - if (!WriteFile(fh, fileData.constData(), fileData.size(), &bytesWritten, NULL) || !FlushFileBuffers(fh)) - error = QLockFile::UnknownError; // partition full - return error; -} - -bool QLockFilePrivate::removeStaleLock() -{ - // QFile::remove fails on Windows if the other process is still using the file, so it's not stale. - return QFile::remove(fileName); -} - -bool QLockFilePrivate::isApparentlyStale() const -{ - qint64 pid; - QString hostname, appname; - if (!getLockInfo(&pid, &hostname, &appname)) - return false; - - // On WinRT there seems to be no way of obtaining information about other - // processes due to sandboxing -#ifndef Q_OS_WINRT - if (hostname == QString::fromLocal8Bit(localHostName())) { - HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); - if (!procHandle) - return true; - // We got a handle but check if process is still alive - DWORD dwR = ::WaitForSingleObject(procHandle, 0); - ::CloseHandle(procHandle); - if (dwR == WAIT_TIMEOUT) - return true; - } -#endif // !Q_OS_WINRT - const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); - return staleLockTime > 0 && age > staleLockTime; -} - -void QLockFile::unlock() -{ - Q_D(QLockFile); - if (!d->isLocked) - return; - CloseHandle(d->fileHandle); - int attempts = 0; - static const int maxAttempts = 500; // 500ms - while (!QFile::remove(d->fileName) && ++attempts < maxAttempts) { - // Someone is reading the lock file right now (on Windows this prevents deleting it). - QLockFileThread::msleep(1); - } - if (attempts == maxAttempts) { - qWarning() << "Could not remove our own lock file" << d->fileName << ". Either other users of the lock file are reading it constantly for 500 ms, or we (no longer) have permissions to delete the file"; - // This is bad because other users of this lock file will now have to wait for the stale-lock-timeout... - } - d->lockError = QLockFile::NoError; - d->isLocked = false; -} - -QT_END_NAMESPACE diff --git a/src/core/qsavefile.cpp b/src/core/qsavefile.cpp deleted file mode 100644 index 24753500..00000000 --- a/src/core/qsavefile.cpp +++ /dev/null @@ -1,435 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsavefile.h" -#include "qsavefile_p.h" - -#include -#include -#include - -QSaveFilePrivate::QSaveFilePrivate() - : tempFile(0), error(QFile::NoError) -{ -} - -QSaveFilePrivate::~QSaveFilePrivate() -{ -} - -/*! - \class QSaveFile - \brief The QSaveFile class provides an interface for safely writing to files. - - \ingroup io - - \reentrant - - QSaveFile is an I/O device for writing text and binary files, without losing - existing data if the writing operation fails. - - While writing, the contents will be written to a temporary file, and if - no error happened, commit() will move it to the final file. This ensures that - no data at the final file is lost in case an error happens while writing, - and no partially-written file is ever present at the final location. Always - use QSaveFile when saving entire documents to disk. - - QSaveFile automatically detects errors while writing, such as the full partition - situation, where write() cannot write all the bytes. It will remember that - an error happened, and will discard the temporary file in commit(). - - Much like with QFile, the file is opened with open(). Data is usually read - and written using QDataStream or QTextStream, but you can also call the - QIODevice-inherited functions read(), readLine(), readAll(), write(). - - Unlike QFile, calling close() is not allowed. commit() replaces it. If commit() - was not called and the QSaveFile instance is destroyed, the temporary file is - discarded. - - \sa QTextStream, QDataStream, QFileInfo, QDir, QFile, QTemporaryFile -*/ - -/*! - \internal -*/ -QSaveFile::QSaveFile() - : QIODevice(), d_ptr(new QSaveFilePrivate) -{ -} -/*! - Constructs a new file object with the given \a parent. -*/ -QSaveFile::QSaveFile(QObject *parent) - : QIODevice(parent), d_ptr(new QSaveFilePrivate) -{ -} -/*! - Constructs a new file object to represent the file with the given \a name. -*/ -QSaveFile::QSaveFile(const QString &name) - : QIODevice(0), d_ptr(new QSaveFilePrivate) -{ - Q_D(QSaveFile); - d->fileName = name; -} -/*! - Constructs a new file object with the given \a parent to represent the - file with the specified \a name. -*/ -QSaveFile::QSaveFile(const QString &name, QObject *parent) - : QIODevice(parent), d_ptr(new QSaveFilePrivate) -{ - Q_D(QSaveFile); - d->fileName = name; -} - -/*! - Destroys the file object, discarding the saved contents unless commit() was called. -*/ -QSaveFile::~QSaveFile() -{ - Q_D(QSaveFile); - if (d->tempFile) { - d->tempFile->setAutoRemove(true); - delete d->tempFile; - } - QIODevice::close(); - delete d; -} - -/*! - Returns false since temporary files support random access. - - \sa QIODevice::isSequential() -*/ -bool QSaveFile::isSequential() const -{ - return false; -} - -/*! - Returns the file error status. - - The I/O device status returns an error code. For example, if open() - returns false, or a read/write operation returns -1, this function can - be called to find out the reason why the operation failed. - - Unlike QFile which clears the error on the next operation, QSaveFile remembers - the error until the file is closed, in order to discard the file contents in close(). - - \sa unsetError() -*/ - -QFile::FileError QSaveFile::error() const -{ - return d_func()->error; -} - -/*! - Sets the file's error to QFile::NoError. - - This will make QSaveFile forget that an error happened during saving, so you - probably don't want to call this, unless you're really sure that you want to - save the file anyway. - - \sa error() -*/ -void QSaveFile::unsetError() -{ - d_func()->error = QFile::NoError; - setErrorString(QString()); -} - -/*! - Returns the name set by setFileName() or to the QSaveFile - constructor. - - \sa setFileName() -*/ -QString QSaveFile::fileName() const -{ - return d_func()->fileName; -} - -/*! - Sets the \a name of the file. The name can have no path, a - relative path, or an absolute path. - - \sa QFile::setFileName(), fileName() -*/ -void QSaveFile::setFileName(const QString &name) -{ - d_func()->fileName = name; -} - -/*! - Opens the file using OpenMode \a mode, returning true if successful; - otherwise false. - - Important: the \a mode must be QIODevice::WriteOnly. - It may also have additional flags, such as QIODevice::Text and QIODevice::Unbuffered. - - QIODevice::ReadWrite and QIODevice::Append are not supported at the moment. - - \sa QIODevice::OpenMode, setFileName() -*/ -bool QSaveFile::open(OpenMode mode) -{ - Q_D(QSaveFile); - if (isOpen()) { - qWarning("QSaveFile::open: File (%s) already open", qPrintable(fileName())); - return false; - } - unsetError(); - if ((mode & (ReadOnly | WriteOnly)) == 0) { - qWarning("QSaveFile::open: Open mode not specified"); - return false; - } - // In the future we could implement Append and ReadWrite by copying from the existing file to the temp file... - if ((mode & ReadOnly) || (mode & Append)) { - qWarning("QSaveFile::open: Unsupported open mode %d", int(mode)); - return false; - } - - // check if existing file is writable - QFileInfo existingFile(d->fileName); - if (existingFile.exists() && !existingFile.isWritable()) { - d->error = QFile::WriteError; - setErrorString(QSaveFile::tr("Existing file %1 is not writable").arg(d->fileName)); - return false; - } - d->tempFile = new QTemporaryFile; - d->tempFile->setAutoRemove(false); - d->tempFile->setFileTemplate(d->fileName); - if (!d->tempFile->open()) { - d->error = d->tempFile->error(); - setErrorString(d->tempFile->errorString()); - delete d->tempFile; - d->tempFile = 0; - return false; - } - QIODevice::open(mode); - if (existingFile.exists()) - d->tempFile->setPermissions(existingFile.permissions()); - return true; -} - -/*! - \reimp - Cannot be called. - Call commit() instead. -*/ -void QSaveFile::close() -{ - qFatal("QSaveFile::close called"); -} - -/* - Commits the changes to disk, if all previous writes were successful. - - It is mandatory to call this at the end of the saving operation, otherwise the file will be - discarded. - - If an error happened during writing, deletes the temporary file and returns false. - Otherwise, renames it to the final fileName and returns true on success. - Finally, closes the device. - - \sa cancelWriting() -*/ -bool QSaveFile::commit() -{ - Q_D(QSaveFile); - if (!d->tempFile) - return false; - Q_ASSERT(isOpen()); - QIODevice::close(); // flush and close - if (d->error != QFile::NoError) { - d->tempFile->remove(); - unsetError(); - delete d->tempFile; - d->tempFile = 0; - return false; - } - d->tempFile->close(); -#ifdef Q_OS_WIN - // On Windows QAbstractFileEngine::rename() fails if the the target exists, - // so we have to rename the target. - // Ideally the winapi ReplaceFile() method should be used. - QString bakname = d->fileName + "~"; - QFile::remove(bakname); - QFile::rename(d->fileName, bakname); -#endif - QAbstractFileEngine* fileEngine = d->tempFile->fileEngine(); - Q_ASSERT(fileEngine); - if (!fileEngine->rename(d->fileName)) { - d->error = fileEngine->error(); - setErrorString(fileEngine->errorString()); - d->tempFile->remove(); - delete d->tempFile; - d->tempFile = 0; -#ifdef Q_OS_WIN - QFile::rename(bakname, d->fileName); -#endif - return false; - } - delete d->tempFile; - d->tempFile = 0; -#ifdef Q_OS_WIN - QFile::remove(bakname); -#endif - return true; -} - -/*! - Sets an error code so that commit() discards the temporary file. - - Further write operations are possible after calling this method, but none - of it will have any effect, the written file will be discarded. - - \sa commit() -*/ -void QSaveFile::cancelWriting() -{ - if (!isOpen()) - return; - d_func()->error = QFile::WriteError; - setErrorString(QSaveFile::tr("Writing canceled by application")); -} - -/*! - Returns the size of the file. - \sa QFile::size() -*/ -qint64 QSaveFile::size() const -{ - Q_D(const QSaveFile); - return d->tempFile ? d->tempFile->size() : qint64(-1); -} - -/*! - \reimp -*/ -qint64 QSaveFile::pos() const -{ - Q_D(const QSaveFile); - return d->tempFile ? d->tempFile->pos() : qint64(-1); -} - -/*! - \reimp -*/ -bool QSaveFile::seek(qint64 offset) -{ - Q_D(QSaveFile); - return d->tempFile ? d->tempFile->seek(offset) : false; -} - -/*! - \reimp -*/ -bool QSaveFile::atEnd() const -{ - Q_D(const QSaveFile); - return d->tempFile ? d->tempFile->atEnd() : true; -} - -/*! - Flushes any buffered data to the file. Returns true if successful; - otherwise returns false. -*/ -bool QSaveFile::flush() -{ - Q_D(QSaveFile); - if (d->tempFile) { - if (!d->tempFile->flush()) { - d->error = d->tempFile->error(); - setErrorString(d->tempFile->errorString()); - return false; - } - return true; - } - return false; -} - -/*! - Returns the file handle of the temporary file. - - \sa QFile::handle() -*/ -int QSaveFile::handle() const -{ - Q_D(const QSaveFile); - return d->tempFile ? d->tempFile->handle() : -1; -} - -/*! - \reimp -*/ -qint64 QSaveFile::readData(char *data, qint64 maxlen) -{ - Q_D(QSaveFile); - return d->tempFile ? d->tempFile->read(data, maxlen) : -1; -} - -/*! - \reimp -*/ -qint64 QSaveFile::writeData(const char *data, qint64 len) -{ - Q_D(QSaveFile); - if (!d->tempFile) - return -1; - const qint64 written = d->tempFile->write(data, len); - if (written != len) { - d->error = QFile::WriteError; - setErrorString(QSaveFile::tr("Partial write. Partition full?")); - } - return written; -} - -/*! - \reimp -*/ -qint64 QSaveFile::readLineData(char *data, qint64 maxlen) -{ - Q_D(QSaveFile); - return d->tempFile ? d->tempFile->readLine(data, maxlen) : -1; -} diff --git a/src/core/qsavefile.h b/src/core/qsavefile.h deleted file mode 100644 index 84d5a245..00000000 --- a/src/core/qsavefile.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSAVEFILE_H -#define QSAVEFILE_H - -#include -#include - -#ifdef open -#error qsavefile.h must be included before any header file that defines open -#endif - -class QAbstractFileEngine; -class QSaveFilePrivate; - -class QSaveFile : public QIODevice -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QSaveFile) - -public: - - QSaveFile(); - explicit QSaveFile(const QString &name); - explicit QSaveFile(QObject *parent); - QSaveFile(const QString &name, QObject *parent); - ~QSaveFile(); - - QFile::FileError error() const; - void unsetError(); - - QString fileName() const; - void setFileName(const QString &name); - - bool isSequential() const; - - virtual bool open(OpenMode flags); - bool commit(); - - void cancelWriting(); - - qint64 size() const; - qint64 pos() const; - bool seek(qint64 offset); - bool atEnd() const; - bool flush(); - - bool resize(qint64 sz); - - int handle() const; - -protected: - qint64 readData(char *data, qint64 maxlen); - qint64 writeData(const char *data, qint64 len); - qint64 readLineData(char *data, qint64 maxlen); - -private: - virtual void close(); - -private: - Q_DISABLE_COPY(QSaveFile) - - QSaveFilePrivate* const d_ptr; -}; - -#endif // QSAVEFILE_H diff --git a/src/core/qsavefile_p.h b/src/core/qsavefile_p.h deleted file mode 100644 index 549ecc1b..00000000 --- a/src/core/qsavefile_p.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSAVEFILE_P_H -#define QSAVEFILE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -class QSaveFilePrivate -{ -public: - QSaveFilePrivate(); - ~QSaveFilePrivate(); - - QString fileName; - QTemporaryFile *tempFile; - - QFile::FileError error; -}; - -#endif // QSAVEFILE_P_H - diff --git a/src/crypto/Crypto.cpp b/src/crypto/Crypto.cpp index e32e2d2d..1ff6fded 100644 --- a/src/crypto/Crypto.cpp +++ b/src/crypto/Crypto.cpp @@ -27,43 +27,7 @@ bool Crypto::m_initalized(false); QString Crypto::m_errorStr; - -#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600) -static int gcry_qt_mutex_init(void** p_sys) -{ - *p_sys = new QMutex(); - return 0; -} - -static int gcry_qt_mutex_destroy(void** p_sys) -{ - delete reinterpret_cast(*p_sys); - return 0; -} - -static int gcry_qt_mutex_lock(void** p_sys) -{ - reinterpret_cast(*p_sys)->lock(); - return 0; -} - -static int gcry_qt_mutex_unlock(void** p_sys) -{ - reinterpret_cast(*p_sys)->unlock(); - return 0; -} - -static const struct gcry_thread_cbs gcry_threads_qt = -{ - GCRY_THREAD_OPTION_USER, - 0, - gcry_qt_mutex_init, - gcry_qt_mutex_destroy, - gcry_qt_mutex_lock, - gcry_qt_mutex_unlock, - 0, 0, 0, 0, 0, 0, 0, 0 -}; -#endif +QString Crypto::m_backendVersion; Crypto::Crypto() { @@ -76,11 +40,7 @@ bool Crypto::init() return true; } - // libgcrypt >= 1.6 doesn't allow custom thread callbacks anymore. -#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600) - gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_qt); -#endif - gcry_check_version(0); + m_backendVersion = QString::fromLocal8Bit(gcry_check_version(0)); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); if (!checkAlgorithms()) { @@ -108,6 +68,11 @@ QString Crypto::errorString() return m_errorStr; } +QString Crypto::backendVersion() +{ + return QString("libgcrypt ").append(m_backendVersion); +} + bool Crypto::backendSelfTest() { return (gcry_control(GCRYCTL_SELFTEST) == 0); @@ -115,18 +80,18 @@ bool Crypto::backendSelfTest() bool Crypto::checkAlgorithms() { - if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) { + if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) { m_errorStr = "GCRY_CIPHER_AES256 not found."; qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr)); return false; } - if (gcry_cipher_algo_info(GCRY_CIPHER_TWOFISH, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) { + if (gcry_cipher_algo_info(GCRY_CIPHER_TWOFISH, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) { m_errorStr = "GCRY_CIPHER_TWOFISH not found."; qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr)); return false; } #ifdef GCRYPT_HAS_SALSA20 - if (gcry_cipher_algo_info(GCRY_CIPHER_SALSA20, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) { + if (gcry_cipher_algo_info(GCRY_CIPHER_SALSA20, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) { m_errorStr = "GCRY_CIPHER_SALSA20 not found."; qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr)); return false; diff --git a/src/crypto/Crypto.h b/src/crypto/Crypto.h index b801cbb5..0ce2903c 100644 --- a/src/crypto/Crypto.h +++ b/src/crypto/Crypto.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class Crypto { public: @@ -29,6 +27,7 @@ public: static bool initalized(); static bool backendSelfTest(); static QString errorString(); + static QString backendVersion(); private: Crypto(); @@ -43,6 +42,7 @@ private: static bool m_initalized; static QString m_errorStr; + static QString m_backendVersion; }; #endif // KEEPASSX_CRYPTO_H diff --git a/src/crypto/Random.cpp b/src/crypto/Random.cpp index 2a375f3b..dc0667fa 100644 --- a/src/crypto/Random.cpp +++ b/src/crypto/Random.cpp @@ -19,15 +19,16 @@ #include +#include "core/Global.h" #include "crypto/Crypto.h" class RandomBackendGcrypt : public RandomBackend { public: - void randomize(void* data, int len) Q_DECL_OVERRIDE; + void randomize(void* data, int len) override; }; -Random* Random::m_instance(Q_NULLPTR); +Random* Random::m_instance(nullptr); void Random::randomize(QByteArray& ba) { diff --git a/src/crypto/SymmetricCipher.cpp b/src/crypto/SymmetricCipher.cpp index 454548ca..12ec264f 100644 --- a/src/crypto/SymmetricCipher.cpp +++ b/src/crypto/SymmetricCipher.cpp @@ -19,7 +19,6 @@ #include "config-keepassx.h" #include "crypto/SymmetricCipherGcrypt.h" -#include "crypto/SymmetricCipherSalsa20.h" SymmetricCipher::SymmetricCipher(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, SymmetricCipher::Direction direction) @@ -61,19 +60,12 @@ SymmetricCipherBackend* SymmetricCipher::createBackend(SymmetricCipher::Algorith switch (algo) { case SymmetricCipher::Aes256: case SymmetricCipher::Twofish: -#if defined(GCRYPT_HAS_SALSA20) case SymmetricCipher::Salsa20: -#endif return new SymmetricCipherGcrypt(algo, mode, direction); -#if !defined(GCRYPT_HAS_SALSA20) - case SymmetricCipher::Salsa20: - return new SymmetricCipherSalsa20(algo, mode, direction); -#endif - default: Q_ASSERT(false); - return Q_NULLPTR; + return nullptr; } } diff --git a/src/crypto/SymmetricCipher.h b/src/crypto/SymmetricCipher.h index b8b3eb13..4fc06b7d 100644 --- a/src/crypto/SymmetricCipher.h +++ b/src/crypto/SymmetricCipher.h @@ -22,7 +22,6 @@ #include #include -#include "core/Global.h" #include "crypto/SymmetricCipherBackend.h" class SymmetricCipher diff --git a/src/crypto/SymmetricCipherGcrypt.cpp b/src/crypto/SymmetricCipherGcrypt.cpp index 5c4fe6ab..cd432406 100644 --- a/src/crypto/SymmetricCipherGcrypt.cpp +++ b/src/crypto/SymmetricCipherGcrypt.cpp @@ -22,7 +22,7 @@ SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode, SymmetricCipher::Direction direction) - : m_ctx(Q_NULLPTR) + : m_ctx(nullptr) , m_algo(gcryptAlgo(algo)) , m_mode(gcryptMode(mode)) , m_direction(direction) @@ -44,10 +44,8 @@ int SymmetricCipherGcrypt::gcryptAlgo(SymmetricCipher::Algorithm algo) case SymmetricCipher::Twofish: return GCRY_CIPHER_TWOFISH; -#ifdef GCRYPT_HAS_SALSA20 case SymmetricCipher::Salsa20: return GCRY_CIPHER_SALSA20; -#endif default: Q_ASSERT(false); @@ -95,7 +93,7 @@ bool SymmetricCipherGcrypt::init() } size_t blockSizeT; - error = gcry_cipher_algo_info(m_algo, GCRYCTL_GET_BLKLEN, Q_NULLPTR, &blockSizeT); + error = gcry_cipher_algo_info(m_algo, GCRYCTL_GET_BLKLEN, nullptr, &blockSizeT); if (error != 0) { setErrorString(error); return false; @@ -163,10 +161,10 @@ bool SymmetricCipherGcrypt::processInPlace(QByteArray& data) gcry_error_t error; if (m_direction == SymmetricCipher::Decrypt) { - error = gcry_cipher_decrypt(m_ctx, data.data(), data.size(), Q_NULLPTR, 0); + error = gcry_cipher_decrypt(m_ctx, data.data(), data.size(), nullptr, 0); } else { - error = gcry_cipher_encrypt(m_ctx, data.data(), data.size(), Q_NULLPTR, 0); + error = gcry_cipher_encrypt(m_ctx, data.data(), data.size(), nullptr, 0); } if (error != 0) { @@ -188,7 +186,7 @@ bool SymmetricCipherGcrypt::processInPlace(QByteArray& data, quint64 rounds) if (m_direction == SymmetricCipher::Decrypt) { for (quint64 i = 0; i != rounds; ++i) { - error = gcry_cipher_decrypt(m_ctx, rawData, size, Q_NULLPTR, 0); + error = gcry_cipher_decrypt(m_ctx, rawData, size, nullptr, 0); if (error != 0) { setErrorString(error); @@ -198,7 +196,7 @@ bool SymmetricCipherGcrypt::processInPlace(QByteArray& data, quint64 rounds) } else { for (quint64 i = 0; i != rounds; ++i) { - error = gcry_cipher_encrypt(m_ctx, rawData, size, Q_NULLPTR, 0); + error = gcry_cipher_encrypt(m_ctx, rawData, size, nullptr, 0); if (error != 0) { setErrorString(error); diff --git a/src/crypto/salsa20/ecrypt-config.h b/src/crypto/salsa20/ecrypt-config.h deleted file mode 100644 index 0914fbc7..00000000 --- a/src/crypto/salsa20/ecrypt-config.h +++ /dev/null @@ -1,260 +0,0 @@ -/* ecrypt-config.h */ - -/* *** Normally, it should not be necessary to edit this file. *** */ - -#ifndef ECRYPT_CONFIG -#define ECRYPT_CONFIG - -/* ------------------------------------------------------------------------- */ - -/* Guess the endianness of the target architecture. */ - -#include - -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN -#define ECRYPT_LITTLE_ENDIAN -#elif Q_BYTE_ORDER == Q_BIG_ENDIAN -#define ECRYPT_BIG_ENDIAN -#else -#define ECRYPT_UNKNOWN -#endif - -/* ------------------------------------------------------------------------- */ - -/* - * Find minimal-width types to store 8-bit, 16-bit, 32-bit, and 64-bit - * integers. - * - * Note: to enable 64-bit types on 32-bit compilers, it might be - * necessary to switch from ISO C90 mode to ISO C99 mode (e.g., gcc - * -std=c99), or to allow compiler-specific extensions. - */ - -#include - -/* --- check char --- */ - -#if (UCHAR_MAX / 0xFU > 0xFU) -#ifndef I8T -#define I8T char -#define U8C(v) (v##U) - -#if (UCHAR_MAX == 0xFFU) -#define ECRYPT_I8T_IS_BYTE -#endif - -#endif - -#if (UCHAR_MAX / 0xFFU > 0xFFU) -#ifndef I16T -#define I16T char -#define U16C(v) (v##U) -#endif - -#if (UCHAR_MAX / 0xFFFFU > 0xFFFFU) -#ifndef I32T -#define I32T char -#define U32C(v) (v##U) -#endif - -#if (UCHAR_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU) -#ifndef I64T -#define I64T char -#define U64C(v) (v##U) -#define ECRYPT_NATIVE64 -#endif - -#endif -#endif -#endif -#endif - -/* --- check short --- */ - -#if (USHRT_MAX / 0xFU > 0xFU) -#ifndef I8T -#define I8T short -#define U8C(v) (v##U) - -#if (USHRT_MAX == 0xFFU) -#define ECRYPT_I8T_IS_BYTE -#endif - -#endif - -#if (USHRT_MAX / 0xFFU > 0xFFU) -#ifndef I16T -#define I16T short -#define U16C(v) (v##U) -#endif - -#if (USHRT_MAX / 0xFFFFU > 0xFFFFU) -#ifndef I32T -#define I32T short -#define U32C(v) (v##U) -#endif - -#if (USHRT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU) -#ifndef I64T -#define I64T short -#define U64C(v) (v##U) -#define ECRYPT_NATIVE64 -#endif - -#endif -#endif -#endif -#endif - -/* --- check int --- */ - -#if (UINT_MAX / 0xFU > 0xFU) -#ifndef I8T -#define I8T int -#define U8C(v) (v##U) - -#if (ULONG_MAX == 0xFFU) -#define ECRYPT_I8T_IS_BYTE -#endif - -#endif - -#if (UINT_MAX / 0xFFU > 0xFFU) -#ifndef I16T -#define I16T int -#define U16C(v) (v##U) -#endif - -#if (UINT_MAX / 0xFFFFU > 0xFFFFU) -#ifndef I32T -#define I32T int -#define U32C(v) (v##U) -#endif - -#if (UINT_MAX / 0xFFFFFFFFU > 0xFFFFFFFFU) -#ifndef I64T -#define I64T int -#define U64C(v) (v##U) -#define ECRYPT_NATIVE64 -#endif - -#endif -#endif -#endif -#endif - -/* --- check long --- */ - -#if (ULONG_MAX / 0xFUL > 0xFUL) -#ifndef I8T -#define I8T long -#define U8C(v) (v##UL) - -#if (ULONG_MAX == 0xFFUL) -#define ECRYPT_I8T_IS_BYTE -#endif - -#endif - -#if (ULONG_MAX / 0xFFUL > 0xFFUL) -#ifndef I16T -#define I16T long -#define U16C(v) (v##UL) -#endif - -#if (ULONG_MAX / 0xFFFFUL > 0xFFFFUL) -#ifndef I32T -#define I32T long -#define U32C(v) (v##UL) -#endif - -#if (ULONG_MAX / 0xFFFFFFFFUL > 0xFFFFFFFFUL) -#ifndef I64T -#define I64T long -#define U64C(v) (v##UL) -#define ECRYPT_NATIVE64 -#endif - -#endif -#endif -#endif -#endif - -/* --- check long long --- */ - -#ifdef ULLONG_MAX - -#if (ULLONG_MAX / 0xFULL > 0xFULL) -#ifndef I8T -#define I8T long long -#define U8C(v) (v##ULL) - -#if (ULLONG_MAX == 0xFFULL) -#define ECRYPT_I8T_IS_BYTE -#endif - -#endif - -#if (ULLONG_MAX / 0xFFULL > 0xFFULL) -#ifndef I16T -#define I16T long long -#define U16C(v) (v##ULL) -#endif - -#if (ULLONG_MAX / 0xFFFFULL > 0xFFFFULL) -#ifndef I32T -#define I32T long long -#define U32C(v) (v##ULL) -#endif - -#if (ULLONG_MAX / 0xFFFFFFFFULL > 0xFFFFFFFFULL) -#ifndef I64T -#define I64T long long -#define U64C(v) (v##ULL) -#endif - -#endif -#endif -#endif -#endif - -#endif - -/* --- check __int64 --- */ - -#if !defined(__STDC__) && defined(_UI64_MAX) - -#ifndef I64T -#define I64T __int64 -#define U64C(v) (v##ui64) -#endif - -#endif - -/* ------------------------------------------------------------------------- */ - -/* find the largest type on this platform (used for alignment) */ - -#if defined(__SSE__) || (defined(_MSC_VER) && (_MSC_VER >= 1300)) - -#include -#define MAXT __m128 - -#elif defined(__MMX__) - -#include -#define MAXT __m64 - -#elif defined(__ALTIVEC__) - -#define MAXT __vector int - -#else - -#define MAXT long - -#endif - -/* ------------------------------------------------------------------------- */ - -#endif diff --git a/src/crypto/salsa20/ecrypt-machine.h b/src/crypto/salsa20/ecrypt-machine.h deleted file mode 100644 index d006bede..00000000 --- a/src/crypto/salsa20/ecrypt-machine.h +++ /dev/null @@ -1,49 +0,0 @@ -/* ecrypt-machine.h */ - -/* - * This file is included by 'ecrypt-portable.h'. It allows to override - * the default macros for specific platforms. Please carefully check - * the machine code generated by your compiler (with optimisations - * turned on) before deciding to edit this file. - */ - -/* ------------------------------------------------------------------------- */ - -#if (defined(ECRYPT_DEFAULT_ROT) && !defined(ECRYPT_MACHINE_ROT)) - -#define ECRYPT_MACHINE_ROT - -#if (defined(WIN32) && defined(_MSC_VER)) - -#undef ROTL32 -#undef ROTR32 -#undef ROTL64 -#undef ROTR64 - -#include - -#pragma intrinsic(_lrotl) /* compile rotations "inline" */ -#pragma intrinsic(_lrotr) - -#define ROTL32(v, n) _lrotl(v, n) -#define ROTR32(v, n) _lrotr(v, n) -#define ROTL64(v, n) _rotl64(v, n) -#define ROTR64(v, n) _rotr64(v, n) - -#endif - -#endif - -/* ------------------------------------------------------------------------- */ - -#if (defined(ECRYPT_DEFAULT_SWAP) && !defined(ECRYPT_MACHINE_SWAP)) - -#define ECRYPT_MACHINE_SWAP - -/* - * If you want to overwrite the default swap macros, put it here. And so on. - */ - -#endif - -/* ------------------------------------------------------------------------- */ diff --git a/src/crypto/salsa20/ecrypt-portable.h b/src/crypto/salsa20/ecrypt-portable.h deleted file mode 100644 index 438a464a..00000000 --- a/src/crypto/salsa20/ecrypt-portable.h +++ /dev/null @@ -1,310 +0,0 @@ -/* ecrypt-portable.h */ - -/* - * WARNING: the conversions defined below are implemented as macros, - * and should be used carefully. They should NOT be used with - * parameters which perform some action. E.g., the following two lines - * are not equivalent: - * - * 1) ++x; y = ROTL32(x, n); - * 2) y = ROTL32(++x, n); - */ - -/* - * *** Please do not edit this file. *** - * - * The default macros can be overridden for specific architectures by - * editing 'ecrypt-machine.h'. - */ - -#ifndef ECRYPT_PORTABLE -#define ECRYPT_PORTABLE - -#include "ecrypt-config.h" - -/* ------------------------------------------------------------------------- */ - -/* - * The following types are defined (if available): - * - * u8: unsigned integer type, at least 8 bits - * u16: unsigned integer type, at least 16 bits - * u32: unsigned integer type, at least 32 bits - * u64: unsigned integer type, at least 64 bits - * - * s8, s16, s32, s64 -> signed counterparts of u8, u16, u32, u64 - * - * The selection of minimum-width integer types is taken care of by - * 'ecrypt-config.h'. Note: to enable 64-bit types on 32-bit - * compilers, it might be necessary to switch from ISO C90 mode to ISO - * C99 mode (e.g., gcc -std=c99). - */ - -#ifdef I8T -typedef signed I8T s8; -typedef unsigned I8T u8; -#endif - -#ifdef I16T -typedef signed I16T s16; -typedef unsigned I16T u16; -#endif - -#ifdef I32T -typedef signed I32T s32; -typedef unsigned I32T u32; -#endif - -#ifdef I64T -typedef signed I64T s64; -typedef unsigned I64T u64; -#endif - -/* - * The following macros are used to obtain exact-width results. - */ - -#define U8V(v) ((u8)(v) & U8C(0xFF)) -#define U16V(v) ((u16)(v) & U16C(0xFFFF)) -#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) -#define U64V(v) ((u64)(v) & U64C(0xFFFFFFFFFFFFFFFF)) - -/* ------------------------------------------------------------------------- */ - -/* - * The following macros return words with their bits rotated over n - * positions to the left/right. - */ - -#define ECRYPT_DEFAULT_ROT - -#define ROTL8(v, n) \ - (U8V((v) << (n)) | ((v) >> (8 - (n)))) - -#define ROTL16(v, n) \ - (U16V((v) << (n)) | ((v) >> (16 - (n)))) - -#define ROTL32(v, n) \ - (U32V((v) << (n)) | ((v) >> (32 - (n)))) - -#define ROTL64(v, n) \ - (U64V((v) << (n)) | ((v) >> (64 - (n)))) - -#define ROTR8(v, n) ROTL8(v, 8 - (n)) -#define ROTR16(v, n) ROTL16(v, 16 - (n)) -#define ROTR32(v, n) ROTL32(v, 32 - (n)) -#define ROTR64(v, n) ROTL64(v, 64 - (n)) - -#include "ecrypt-machine.h" - -/* ------------------------------------------------------------------------- */ - -/* - * The following macros return a word with bytes in reverse order. - */ - -#define ECRYPT_DEFAULT_SWAP - -#define SWAP16(v) \ - ROTL16(v, 8) - -#define SWAP32(v) \ - ((ROTL32(v, 8) & U32C(0x00FF00FF)) | \ - (ROTL32(v, 24) & U32C(0xFF00FF00))) - -#ifdef ECRYPT_NATIVE64 -#define SWAP64(v) \ - ((ROTL64(v, 8) & U64C(0x000000FF000000FF)) | \ - (ROTL64(v, 24) & U64C(0x0000FF000000FF00)) | \ - (ROTL64(v, 40) & U64C(0x00FF000000FF0000)) | \ - (ROTL64(v, 56) & U64C(0xFF000000FF000000))) -#else -#define SWAP64(v) \ - (((u64)SWAP32(U32V(v)) << 32) | (u64)SWAP32(U32V(v >> 32))) -#endif - -#include "ecrypt-machine.h" - -#define ECRYPT_DEFAULT_WTOW - -#ifdef ECRYPT_LITTLE_ENDIAN -#define U16TO16_LITTLE(v) (v) -#define U32TO32_LITTLE(v) (v) -#define U64TO64_LITTLE(v) (v) - -#define U16TO16_BIG(v) SWAP16(v) -#define U32TO32_BIG(v) SWAP32(v) -#define U64TO64_BIG(v) SWAP64(v) -#endif - -#ifdef ECRYPT_BIG_ENDIAN -#define U16TO16_LITTLE(v) SWAP16(v) -#define U32TO32_LITTLE(v) SWAP32(v) -#define U64TO64_LITTLE(v) SWAP64(v) - -#define U16TO16_BIG(v) (v) -#define U32TO32_BIG(v) (v) -#define U64TO64_BIG(v) (v) -#endif - -#include "ecrypt-machine.h" - -/* - * The following macros load words from an array of bytes with - * different types of endianness, and vice versa. - */ - -#define ECRYPT_DEFAULT_BTOW - -#if (!defined(ECRYPT_UNKNOWN) && defined(ECRYPT_I8T_IS_BYTE)) - -#define U8TO16_LITTLE(p) U16TO16_LITTLE(((u16*)(p))[0]) -#define U8TO32_LITTLE(p) U32TO32_LITTLE(((u32*)(p))[0]) -#define U8TO64_LITTLE(p) U64TO64_LITTLE(((u64*)(p))[0]) - -#define U8TO16_BIG(p) U16TO16_BIG(((u16*)(p))[0]) -#define U8TO32_BIG(p) U32TO32_BIG(((u32*)(p))[0]) -#define U8TO64_BIG(p) U64TO64_BIG(((u64*)(p))[0]) - -#define U16TO8_LITTLE(p, v) (((u16*)(p))[0] = U16TO16_LITTLE(v)) -#define U32TO8_LITTLE(p, v) (((u32*)(p))[0] = U32TO32_LITTLE(v)) -#define U64TO8_LITTLE(p, v) (((u64*)(p))[0] = U64TO64_LITTLE(v)) - -#define U16TO8_BIG(p, v) (((u16*)(p))[0] = U16TO16_BIG(v)) -#define U32TO8_BIG(p, v) (((u32*)(p))[0] = U32TO32_BIG(v)) -#define U64TO8_BIG(p, v) (((u64*)(p))[0] = U64TO64_BIG(v)) - -#else - -#define U8TO16_LITTLE(p) \ - (((u16)((p)[0]) ) | \ - ((u16)((p)[1]) << 8)) - -#define U8TO32_LITTLE(p) \ - (((u32)((p)[0]) ) | \ - ((u32)((p)[1]) << 8) | \ - ((u32)((p)[2]) << 16) | \ - ((u32)((p)[3]) << 24)) - -#ifdef ECRYPT_NATIVE64 -#define U8TO64_LITTLE(p) \ - (((u64)((p)[0]) ) | \ - ((u64)((p)[1]) << 8) | \ - ((u64)((p)[2]) << 16) | \ - ((u64)((p)[3]) << 24) | \ - ((u64)((p)[4]) << 32) | \ - ((u64)((p)[5]) << 40) | \ - ((u64)((p)[6]) << 48) | \ - ((u64)((p)[7]) << 56)) -#else -#define U8TO64_LITTLE(p) \ - ((u64)U8TO32_LITTLE(p) | ((u64)U8TO32_LITTLE((p) + 4) << 32)) -#endif - -#define U8TO16_BIG(p) \ - (((u16)((p)[0]) << 8) | \ - ((u16)((p)[1]) )) - -#define U8TO32_BIG(p) \ - (((u32)((p)[0]) << 24) | \ - ((u32)((p)[1]) << 16) | \ - ((u32)((p)[2]) << 8) | \ - ((u32)((p)[3]) )) - -#ifdef ECRYPT_NATIVE64 -#define U8TO64_BIG(p) \ - (((u64)((p)[0]) << 56) | \ - ((u64)((p)[1]) << 48) | \ - ((u64)((p)[2]) << 40) | \ - ((u64)((p)[3]) << 32) | \ - ((u64)((p)[4]) << 24) | \ - ((u64)((p)[5]) << 16) | \ - ((u64)((p)[6]) << 8) | \ - ((u64)((p)[7]) )) -#else -#define U8TO64_BIG(p) \ - (((u64)U8TO32_BIG(p) << 32) | (u64)U8TO32_BIG((p) + 4)) -#endif - -#define U16TO8_LITTLE(p, v) \ - do { \ - (p)[0] = U8V((v) ); \ - (p)[1] = U8V((v) >> 8); \ - } while (0) - -#define U32TO8_LITTLE(p, v) \ - do { \ - (p)[0] = U8V((v) ); \ - (p)[1] = U8V((v) >> 8); \ - (p)[2] = U8V((v) >> 16); \ - (p)[3] = U8V((v) >> 24); \ - } while (0) - -#ifdef ECRYPT_NATIVE64 -#define U64TO8_LITTLE(p, v) \ - do { \ - (p)[0] = U8V((v) ); \ - (p)[1] = U8V((v) >> 8); \ - (p)[2] = U8V((v) >> 16); \ - (p)[3] = U8V((v) >> 24); \ - (p)[4] = U8V((v) >> 32); \ - (p)[5] = U8V((v) >> 40); \ - (p)[6] = U8V((v) >> 48); \ - (p)[7] = U8V((v) >> 56); \ - } while (0) -#else -#define U64TO8_LITTLE(p, v) \ - do { \ - U32TO8_LITTLE((p), U32V((v) )); \ - U32TO8_LITTLE((p) + 4, U32V((v) >> 32)); \ - } while (0) -#endif - -#define U16TO8_BIG(p, v) \ - do { \ - (p)[0] = U8V((v) ); \ - (p)[1] = U8V((v) >> 8); \ - } while (0) - -#define U32TO8_BIG(p, v) \ - do { \ - (p)[0] = U8V((v) >> 24); \ - (p)[1] = U8V((v) >> 16); \ - (p)[2] = U8V((v) >> 8); \ - (p)[3] = U8V((v) ); \ - } while (0) - -#ifdef ECRYPT_NATIVE64 -#define U64TO8_BIG(p, v) \ - do { \ - (p)[0] = U8V((v) >> 56); \ - (p)[1] = U8V((v) >> 48); \ - (p)[2] = U8V((v) >> 40); \ - (p)[3] = U8V((v) >> 32); \ - (p)[4] = U8V((v) >> 24); \ - (p)[5] = U8V((v) >> 16); \ - (p)[6] = U8V((v) >> 8); \ - (p)[7] = U8V((v) ); \ - } while (0) -#else -#define U64TO8_BIG(p, v) \ - do { \ - U32TO8_BIG((p), U32V((v) >> 32)); \ - U32TO8_BIG((p) + 4, U32V((v) )); \ - } while (0) -#endif - -#endif - -#include "ecrypt-machine.h" - -/* ------------------------------------------------------------------------- */ - -#define AT_LEAST_ONE(n) (((n) < 1) ? 1 : (n)) - -#define ALIGN(t, v, n) \ - union { t b[n]; MAXT l[AT_LEAST_ONE(n * sizeof(t) / sizeof(MAXT))]; } v - -/* ------------------------------------------------------------------------- */ - -#endif diff --git a/src/crypto/salsa20/ecrypt-sync.h b/src/crypto/salsa20/ecrypt-sync.h deleted file mode 100644 index 245793e1..00000000 --- a/src/crypto/salsa20/ecrypt-sync.h +++ /dev/null @@ -1,287 +0,0 @@ -/* ecrypt-sync.h */ - -/* - * Header file for synchronous stream ciphers without authentication - * mechanism. - * - * *** Please only edit parts marked with "[edit]". *** - */ - -#ifndef ECRYPT_SYNC -#define ECRYPT_SYNC - -#ifdef __cplusplus -extern "C" { -#endif - -#include "ecrypt-portable.h" - -/* ------------------------------------------------------------------------- */ - -/* Cipher parameters */ - -/* - * The name of your cipher. - */ -#define ECRYPT_NAME "Salsa20" /* [edit] */ -#define ECRYPT_PROFILE "S!_H." - -/* - * Specify which key and IV sizes are supported by your cipher. A user - * should be able to enumerate the supported sizes by running the - * following code: - * - * for (i = 0; ECRYPT_KEYSIZE(i) <= ECRYPT_MAXKEYSIZE; ++i) - * { - * keysize = ECRYPT_KEYSIZE(i); - * - * ... - * } - * - * All sizes are in bits. - */ - -#define ECRYPT_MAXKEYSIZE 256 /* [edit] */ -#define ECRYPT_KEYSIZE(i) (128 + (i)*128) /* [edit] */ - -#define ECRYPT_MAXIVSIZE 64 /* [edit] */ -#define ECRYPT_IVSIZE(i) (64 + (i)*64) /* [edit] */ - -/* ------------------------------------------------------------------------- */ - -/* Data structures */ - -/* - * ECRYPT_ctx is the structure containing the representation of the - * internal state of your cipher. - */ - -typedef struct -{ - u32 input[16]; /* could be compressed */ - /* - * [edit] - * - * Put here all state variable needed during the encryption process. - */ -} ECRYPT_ctx; - -/* ------------------------------------------------------------------------- */ - -/* Mandatory functions */ - -/* - * Key and message independent initialization. This function will be - * called once when the program starts (e.g., to build expanded S-box - * tables). - */ -void ECRYPT_init(); - -/* - * Key setup. It is the user's responsibility to select the values of - * keysize and ivsize from the set of supported values specified - * above. - */ -void ECRYPT_keysetup( - ECRYPT_ctx* ctx, - const u8* key, - u32 keysize, /* Key size in bits. */ - u32 ivsize); /* IV size in bits. */ - -/* - * IV setup. After having called ECRYPT_keysetup(), the user is - * allowed to call ECRYPT_ivsetup() different times in order to - * encrypt/decrypt different messages with the same key but different - * IV's. - */ -void ECRYPT_ivsetup( - ECRYPT_ctx* ctx, - const u8* iv); - -/* - * Encryption/decryption of arbitrary length messages. - * - * For efficiency reasons, the API provides two types of - * encrypt/decrypt functions. The ECRYPT_encrypt_bytes() function - * (declared here) encrypts byte strings of arbitrary length, while - * the ECRYPT_encrypt_blocks() function (defined later) only accepts - * lengths which are multiples of ECRYPT_BLOCKLENGTH. - * - * The user is allowed to make multiple calls to - * ECRYPT_encrypt_blocks() to incrementally encrypt a long message, - * but he is NOT allowed to make additional encryption calls once he - * has called ECRYPT_encrypt_bytes() (unless he starts a new message - * of course). For example, this sequence of calls is acceptable: - * - * ECRYPT_keysetup(); - * - * ECRYPT_ivsetup(); - * ECRYPT_encrypt_blocks(); - * ECRYPT_encrypt_blocks(); - * ECRYPT_encrypt_bytes(); - * - * ECRYPT_ivsetup(); - * ECRYPT_encrypt_blocks(); - * ECRYPT_encrypt_blocks(); - * - * ECRYPT_ivsetup(); - * ECRYPT_encrypt_bytes(); - * - * The following sequence is not: - * - * ECRYPT_keysetup(); - * ECRYPT_ivsetup(); - * ECRYPT_encrypt_blocks(); - * ECRYPT_encrypt_bytes(); - * ECRYPT_encrypt_blocks(); - */ - -void ECRYPT_encrypt_bytes( - ECRYPT_ctx* ctx, - const u8* plaintext, - u8* ciphertext, - u32 msglen); /* Message length in bytes. */ - -void ECRYPT_decrypt_bytes( - ECRYPT_ctx* ctx, - const u8* ciphertext, - u8* plaintext, - u32 msglen); /* Message length in bytes. */ - -/* ------------------------------------------------------------------------- */ - -/* Optional features */ - -/* - * For testing purposes it can sometimes be useful to have a function - * which immediately generates keystream without having to provide it - * with a zero plaintext. If your cipher cannot provide this function - * (e.g., because it is not strictly a synchronous cipher), please - * reset the ECRYPT_GENERATES_KEYSTREAM flag. - */ - -#define ECRYPT_GENERATES_KEYSTREAM -#ifdef ECRYPT_GENERATES_KEYSTREAM - -void ECRYPT_keystream_bytes( - ECRYPT_ctx* ctx, - u8* keystream, - u32 length); /* Length of keystream in bytes. */ - -#endif - -/* ------------------------------------------------------------------------- */ - -/* Optional optimizations */ - -/* - * By default, the functions in this section are implemented using - * calls to functions declared above. However, you might want to - * implement them differently for performance reasons. - */ - -/* - * All-in-one encryption/decryption of (short) packets. - * - * The default definitions of these functions can be found in - * "ecrypt-sync.c". If you want to implement them differently, please - * undef the ECRYPT_USES_DEFAULT_ALL_IN_ONE flag. - */ -#define ECRYPT_USES_DEFAULT_ALL_IN_ONE /* [edit] */ - -void ECRYPT_encrypt_packet( - ECRYPT_ctx* ctx, - const u8* iv, - const u8* plaintext, - u8* ciphertext, - u32 msglen); - -void ECRYPT_decrypt_packet( - ECRYPT_ctx* ctx, - const u8* iv, - const u8* ciphertext, - u8* plaintext, - u32 msglen); - -/* - * Encryption/decryption of blocks. - * - * By default, these functions are defined as macros. If you want to - * provide a different implementation, please undef the - * ECRYPT_USES_DEFAULT_BLOCK_MACROS flag and implement the functions - * declared below. - */ - -#define ECRYPT_BLOCKLENGTH 64 /* [edit] */ - -#define ECRYPT_USES_DEFAULT_BLOCK_MACROS /* [edit] */ -#ifdef ECRYPT_USES_DEFAULT_BLOCK_MACROS - -#define ECRYPT_encrypt_blocks(ctx, plaintext, ciphertext, blocks) \ - ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext, \ - (blocks) * ECRYPT_BLOCKLENGTH) - -#define ECRYPT_decrypt_blocks(ctx, ciphertext, plaintext, blocks) \ - ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext, \ - (blocks) * ECRYPT_BLOCKLENGTH) - -#ifdef ECRYPT_GENERATES_KEYSTREAM - -#define ECRYPT_keystream_blocks(ctx, keystream, blocks) \ - ECRYPT_keystream_bytes(ctx, keystream, \ - (blocks) * ECRYPT_BLOCKLENGTH) - -#endif - -#else - -void ECRYPT_encrypt_blocks( - ECRYPT_ctx* ctx, - const u8* plaintext, - u8* ciphertext, - u32 blocks); /* Message length in blocks. */ - -void ECRYPT_decrypt_blocks( - ECRYPT_ctx* ctx, - const u8* ciphertext, - u8* plaintext, - u32 blocks); /* Message length in blocks. */ - -#ifdef ECRYPT_GENERATES_KEYSTREAM - -void ECRYPT_keystream_blocks( - ECRYPT_ctx* ctx, - const u8* keystream, - u32 blocks); /* Keystream length in blocks. */ - -#endif - -#endif - -/* - * If your cipher can be implemented in different ways, you can use - * the ECRYPT_VARIANT parameter to allow the user to choose between - * them at compile time (e.g., gcc -DECRYPT_VARIANT=3 ...). Please - * only use this possibility if you really think it could make a - * significant difference and keep the number of variants - * (ECRYPT_MAXVARIANT) as small as possible (definitely not more than - * 10). Note also that all variants should have exactly the same - * external interface (i.e., the same ECRYPT_BLOCKLENGTH, etc.). - */ -#define ECRYPT_MAXVARIANT 1 /* [edit] */ - -#ifndef ECRYPT_VARIANT -#define ECRYPT_VARIANT 1 -#endif - -#if (ECRYPT_VARIANT > ECRYPT_MAXVARIANT) -#error this variant does not exist -#endif - -/* ------------------------------------------------------------------------- */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/crypto/salsa20/salsa20.c b/src/crypto/salsa20/salsa20.c deleted file mode 100644 index 74f806ca..00000000 --- a/src/crypto/salsa20/salsa20.c +++ /dev/null @@ -1,133 +0,0 @@ -/* -salsa20-ref.c version 20051118 -D. J. Bernstein -Public domain. -*/ - -#include "ecrypt-sync.h" - -#define ROTATE(v,c) (ROTL32(v,c)) -#define XOR(v,w) ((v) ^ (w)) -#define PLUS(v,w) (U32V((v) + (w))) -#define PLUSONE(v) (PLUS((v),1)) - -static void salsa20_wordtobyte(u8 output[64],const u32 input[16]) -{ - u32 x[16]; - int i; - - for (i = 0;i < 16;++i) x[i] = input[i]; - for (i = 20;i > 0;i -= 2) { - x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 0],x[12]), 7)); - x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[ 4],x[ 0]), 9)); - x[12] = XOR(x[12],ROTATE(PLUS(x[ 8],x[ 4]),13)); - x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[12],x[ 8]),18)); - x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 5],x[ 1]), 7)); - x[13] = XOR(x[13],ROTATE(PLUS(x[ 9],x[ 5]), 9)); - x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[13],x[ 9]),13)); - x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 1],x[13]),18)); - x[14] = XOR(x[14],ROTATE(PLUS(x[10],x[ 6]), 7)); - x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[14],x[10]), 9)); - x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 2],x[14]),13)); - x[10] = XOR(x[10],ROTATE(PLUS(x[ 6],x[ 2]),18)); - x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[15],x[11]), 7)); - x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 3],x[15]), 9)); - x[11] = XOR(x[11],ROTATE(PLUS(x[ 7],x[ 3]),13)); - x[15] = XOR(x[15],ROTATE(PLUS(x[11],x[ 7]),18)); - x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[ 0],x[ 3]), 7)); - x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[ 1],x[ 0]), 9)); - x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[ 2],x[ 1]),13)); - x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[ 3],x[ 2]),18)); - x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 5],x[ 4]), 7)); - x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 6],x[ 5]), 9)); - x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 7],x[ 6]),13)); - x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 4],x[ 7]),18)); - x[11] = XOR(x[11],ROTATE(PLUS(x[10],x[ 9]), 7)); - x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[11],x[10]), 9)); - x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 8],x[11]),13)); - x[10] = XOR(x[10],ROTATE(PLUS(x[ 9],x[ 8]),18)); - x[12] = XOR(x[12],ROTATE(PLUS(x[15],x[14]), 7)); - x[13] = XOR(x[13],ROTATE(PLUS(x[12],x[15]), 9)); - x[14] = XOR(x[14],ROTATE(PLUS(x[13],x[12]),13)); - x[15] = XOR(x[15],ROTATE(PLUS(x[14],x[13]),18)); - } - for (i = 0;i < 16;++i) x[i] = PLUS(x[i],input[i]); - for (i = 0;i < 16;++i) U32TO8_LITTLE(output + 4 * i,x[i]); -} - -void ECRYPT_init(void) -{ - return; -} - -static const char sigma[16] = "expand 32-byte k"; -static const char tau[16] = "expand 16-byte k"; - -void ECRYPT_keysetup(ECRYPT_ctx *x,const u8 *k,u32 kbits,u32 ivbits) -{ - (void)ivbits; - const char *constants; - - x->input[1] = U8TO32_LITTLE(k + 0); - x->input[2] = U8TO32_LITTLE(k + 4); - x->input[3] = U8TO32_LITTLE(k + 8); - x->input[4] = U8TO32_LITTLE(k + 12); - if (kbits == 256) { /* recommended */ - k += 16; - constants = sigma; - } else { /* kbits == 128 */ - constants = tau; - } - x->input[11] = U8TO32_LITTLE(k + 0); - x->input[12] = U8TO32_LITTLE(k + 4); - x->input[13] = U8TO32_LITTLE(k + 8); - x->input[14] = U8TO32_LITTLE(k + 12); - x->input[0] = U8TO32_LITTLE(constants + 0); - x->input[5] = U8TO32_LITTLE(constants + 4); - x->input[10] = U8TO32_LITTLE(constants + 8); - x->input[15] = U8TO32_LITTLE(constants + 12); -} - -void ECRYPT_ivsetup(ECRYPT_ctx *x,const u8 *iv) -{ - x->input[6] = U8TO32_LITTLE(iv + 0); - x->input[7] = U8TO32_LITTLE(iv + 4); - x->input[8] = 0; - x->input[9] = 0; -} - -void ECRYPT_encrypt_bytes(ECRYPT_ctx *x,const u8 *m,u8 *c,u32 bytes) -{ - u8 output[64]; - u32 i; - - if (!bytes) return; - for (;;) { - salsa20_wordtobyte(output,x->input); - x->input[8] = PLUSONE(x->input[8]); - if (!x->input[8]) { - x->input[9] = PLUSONE(x->input[9]); - /* stopping at 2^70 bytes per nonce is user's responsibility */ - } - if (bytes <= 64) { - for (i = 0;i < bytes;++i) c[i] = m[i] ^ output[i]; - return; - } - for (i = 0;i < 64;++i) c[i] = m[i] ^ output[i]; - bytes -= 64; - c += 64; - m += 64; - } -} - -void ECRYPT_decrypt_bytes(ECRYPT_ctx *x,const u8 *c,u8 *m,u32 bytes) -{ - ECRYPT_encrypt_bytes(x,c,m,bytes); -} - -void ECRYPT_keystream_bytes(ECRYPT_ctx *x,u8 *stream,u32 bytes) -{ - u32 i; - for (i = 0;i < bytes;++i) stream[i] = 0; - ECRYPT_encrypt_bytes(x,stream,stream,bytes); -} diff --git a/src/format/CsvExporter.cpp b/src/format/CsvExporter.cpp new file mode 100644 index 00000000..11378642 --- /dev/null +++ b/src/format/CsvExporter.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2015 Florian Geyer + * Copyright (C) 2015 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CsvExporter.h" + +#include + +#include "core/Database.h" +#include "core/Group.h" + +bool CsvExporter::exportDatabase(const QString& filename, const Database* db) +{ + QFile file(filename); + if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + m_error = file.errorString(); + return false; + } + return exportDatabase(&file, db); +} + +bool CsvExporter::exportDatabase(QIODevice* device, const Database* db) +{ + QString header; + addColumn(header, "Group"); + addColumn(header, "Title"); + addColumn(header, "Username"); + addColumn(header, "Password"); + addColumn(header, "URL"); + addColumn(header, "Notes"); + header.append("\n"); + + if (device->write(header.toUtf8()) == -1) { + m_error = device->errorString(); + return false; + } + + return writeGroup(device, db->rootGroup()); +} + +QString CsvExporter::errorString() const +{ + return m_error; +} + +bool CsvExporter::writeGroup(QIODevice* device, const Group* group, QString groupPath) +{ + if (!groupPath.isEmpty()) { + groupPath.append("/"); + } + groupPath.append(group->name()); + + Q_FOREACH (const Entry* entry, group->entries()) { + QString line; + + addColumn(line, groupPath); + addColumn(line, entry->title()); + addColumn(line, entry->username()); + addColumn(line, entry->password()); + addColumn(line, entry->url()); + addColumn(line, entry->notes()); + + line.append("\n"); + + if (device->write(line.toUtf8()) == -1) { + m_error = device->errorString(); + return false; + } + } + + Q_FOREACH (const Group* child, group->children()) { + if (!writeGroup(device, child, groupPath)) { + return false; + } + } + + return true; +} + +void CsvExporter::addColumn(QString& str, const QString& column) +{ + if (!str.isEmpty()) { + str.append(","); + } + + str.append("\""); + str.append(QString(column).replace("\"", "\"\"")); + str.append("\""); +} diff --git a/src/format/CsvExporter.h b/src/format/CsvExporter.h new file mode 100644 index 00000000..4040a350 --- /dev/null +++ b/src/format/CsvExporter.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 Florian Geyer + * Copyright (C) 2015 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_CSVEXPORTER_H +#define KEEPASSX_CSVEXPORTER_H + +#include + +class Database; +class Group; +class QIODevice; + +class CsvExporter +{ +public: + bool exportDatabase(const QString& filename, const Database* db); + bool exportDatabase(QIODevice* device, const Database* db); + QString errorString() const; + +private: + bool writeGroup(QIODevice* device, const Group* group, QString groupPath = QString()); + void addColumn(QString& str, const QString& column); + + QString m_error; +}; + +#endif // KEEPASSX_CSVEXPORTER_H diff --git a/src/format/KeePass1Reader.cpp b/src/format/KeePass1Reader.cpp index 929632bf..89775b50 100644 --- a/src/format/KeePass1Reader.cpp +++ b/src/format/KeePass1Reader.cpp @@ -49,9 +49,9 @@ private: KeePass1Reader::KeePass1Reader() - : m_db(Q_NULLPTR) - , m_tmpParent(Q_NULLPTR) - , m_device(Q_NULLPTR) + : m_db(nullptr) + , m_tmpParent(nullptr) + , m_device(nullptr) , m_encryptionFlags(0) , m_transformRounds(0) , m_error(false) @@ -72,16 +72,16 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor if (keyfileData.isEmpty()) { raiseError(tr("Unable to read keyfile.").append("\n").append(keyfileDevice->errorString())); - return Q_NULLPTR; + return nullptr; } if (!keyfileDevice->seek(0)) { raiseError(tr("Unable to read keyfile.").append("\n").append(keyfileDevice->errorString())); - return Q_NULLPTR; + return nullptr; } if (!newFileKey.load(keyfileDevice)) { raiseError(tr("Unable to read keyfile.").append("\n").append(keyfileDevice->errorString())); - return Q_NULLPTR; + return nullptr; } } @@ -96,72 +96,72 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor quint32 signature1 = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok); if (!ok || signature1 != KeePass1::SIGNATURE_1) { raiseError(tr("Not a KeePass database.")); - return Q_NULLPTR; + return nullptr; } quint32 signature2 = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok); if (!ok || signature2 != KeePass1::SIGNATURE_2) { raiseError(tr("Not a KeePass database.")); - return Q_NULLPTR; + return nullptr; } m_encryptionFlags = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok); if (!ok || !(m_encryptionFlags & KeePass1::Rijndael || m_encryptionFlags & KeePass1::Twofish)) { raiseError(tr("Unsupported encryption algorithm.")); - return Q_NULLPTR; + return nullptr; } quint32 version = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok); if (!ok || (version & KeePass1::FILE_VERSION_CRITICAL_MASK) != (KeePass1::FILE_VERSION & KeePass1::FILE_VERSION_CRITICAL_MASK)) { raiseError(tr("Unsupported KeePass database version.")); - return Q_NULLPTR; + return nullptr; } m_masterSeed = m_device->read(16); if (m_masterSeed.size() != 16) { raiseError("Unable to read master seed"); - return Q_NULLPTR; + return nullptr; } m_encryptionIV = m_device->read(16); if (m_encryptionIV.size() != 16) { raiseError("Unable to read encryption IV"); - return Q_NULLPTR; + return nullptr; } quint32 numGroups = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok); if (!ok) { raiseError("Invalid number of groups"); - return Q_NULLPTR; + return nullptr; } quint32 numEntries = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok); if (!ok) { raiseError("Invalid number of entries"); - return Q_NULLPTR; + return nullptr; } m_contentHashHeader = m_device->read(32); if (m_contentHashHeader.size() != 32) { raiseError("Invalid content hash size"); - return Q_NULLPTR; + return nullptr; } m_transformSeed = m_device->read(32); if (m_transformSeed.size() != 32) { raiseError("Invalid transform seed size"); - return Q_NULLPTR; + return nullptr; } m_transformRounds = Endian::readUInt32(m_device, KeePass1::BYTEORDER, &ok); if (!ok) { raiseError("Invalid number of transform rounds"); - return Q_NULLPTR; + return nullptr; } if (!m_db->setTransformRounds(m_transformRounds)) { raiseError(tr("Unable to calculate master key")); - return Q_NULLPTR; + return nullptr; } qint64 contentPos = m_device->pos(); @@ -169,14 +169,14 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor QScopedPointer cipherStream(testKeys(password, keyfileData, contentPos)); if (!cipherStream) { - return Q_NULLPTR; + return nullptr; } QList groups; for (quint32 i = 0; i < numGroups; i++) { Group* group = readGroup(cipherStream.data()); if (!group) { - return Q_NULLPTR; + return nullptr; } groups.append(group); } @@ -185,14 +185,14 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor for (quint32 i = 0; i < numEntries; i++) { Entry* entry = readEntry(cipherStream.data()); if (!entry) { - return Q_NULLPTR; + return nullptr; } entries.append(entry); } if (!constructGroupTree(groups)) { raiseError("Unable to construct group tree"); - return Q_NULLPTR; + return nullptr; } Q_FOREACH (Entry* entry, entries) { @@ -243,7 +243,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor if (!db->setKey(key)) { raiseError(tr("Unable to calculate master key")); - return Q_NULLPTR; + return nullptr; } return db.take(); @@ -257,7 +257,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor keyFile.reset(new QFile(keyfileName)); if (!keyFile->open(QFile::ReadOnly)) { raiseError(keyFile->errorString()); - return Q_NULLPTR; + return nullptr; } } @@ -272,14 +272,14 @@ Database* KeePass1Reader::readDatabase(const QString& filename, const QString& p QFile dbFile(filename); if (!dbFile.open(QFile::ReadOnly)) { raiseError(dbFile.errorString()); - return Q_NULLPTR; + return nullptr; } Database* db = readDatabase(&dbFile, password, keyfileName); if (dbFile.error() != QFile::NoError) { raiseError(dbFile.errorString()); - return Q_NULLPTR; + return nullptr; } return db; @@ -337,7 +337,7 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q QByteArray finalKey = key(passwordData, keyfileData); if (finalKey.isEmpty()) { - return Q_NULLPTR; + return nullptr; } if (m_encryptionFlags & KeePass1::Rijndael) { cipherStream.reset(new SymmetricCipherStream(m_device, SymmetricCipher::Aes256, @@ -350,11 +350,11 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q if (!cipherStream->init(finalKey, m_encryptionIV)) { raiseError(cipherStream->errorString()); - return Q_NULLPTR; + return nullptr; } if (!cipherStream->open(QIODevice::ReadOnly)) { raiseError(cipherStream->errorString()); - return Q_NULLPTR; + return nullptr; } bool success = verifyKey(cipherStream.data()); @@ -368,7 +368,7 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q } raiseError(msg); - return Q_NULLPTR; + return nullptr; } cipherStream->open(QIODevice::ReadOnly); @@ -442,19 +442,19 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) quint16 fieldType = Endian::readUInt16(cipherStream, KeePass1::BYTEORDER, &ok); if (!ok) { raiseError("Invalid group field type number"); - return Q_NULLPTR; + return nullptr; } int fieldSize = static_cast(Endian::readUInt32(cipherStream, KeePass1::BYTEORDER, &ok)); if (!ok) { raiseError("Invalid group field size"); - return Q_NULLPTR; + return nullptr; } QByteArray fieldData = cipherStream->read(fieldSize); if (fieldData.size() != fieldSize) { raiseError("Read group field data doesn't match size"); - return Q_NULLPTR; + return nullptr; } switch (fieldType) { @@ -464,7 +464,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) case 0x0001: if (fieldSize != 4) { raiseError("Incorrect group id field size"); - return Q_NULLPTR; + return nullptr; } groupId = Endian::bytesToUInt32(fieldData, KeePass1::BYTEORDER); groupIdSet = true; @@ -476,7 +476,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) { if (fieldSize != 5) { raiseError("Incorrect group creation time field size"); - return Q_NULLPTR; + return nullptr; } QDateTime dateTime = dateFromPackedStruct(fieldData); if (dateTime.isValid()) { @@ -488,7 +488,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) { if (fieldSize != 5) { raiseError("Incorrect group modification time field size"); - return Q_NULLPTR; + return nullptr; } QDateTime dateTime = dateFromPackedStruct(fieldData); if (dateTime.isValid()) { @@ -523,7 +523,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) { if (fieldSize != 4) { raiseError("Incorrect group icon field size"); - return Q_NULLPTR; + return nullptr; } quint32 iconNumber = Endian::bytesToUInt32(fieldData, KeePass1::BYTEORDER); group->setIcon(iconNumber); @@ -533,7 +533,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) { if (fieldSize != 2) { raiseError("Incorrect group level field size"); - return Q_NULLPTR; + return nullptr; } groupLevel = Endian::bytesToUInt16(fieldData, KeePass1::BYTEORDER); groupLevelSet = true; @@ -548,13 +548,13 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream) default: // invalid field raiseError("Invalid group field type"); - return Q_NULLPTR; + return nullptr; } } while (!reachedEnd); if (!groupIdSet || !groupLevelSet) { raiseError("Missing group id or level"); - return Q_NULLPTR; + return nullptr; } group->setUuid(Uuid::random()); @@ -580,19 +580,19 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) quint16 fieldType = Endian::readUInt16(cipherStream, KeePass1::BYTEORDER, &ok); if (!ok) { raiseError("Missing entry field type number"); - return Q_NULLPTR; + return nullptr; } int fieldSize = static_cast(Endian::readUInt32(cipherStream, KeePass1::BYTEORDER, &ok)); if (!ok) { raiseError("Invalid entry field size"); - return Q_NULLPTR; + return nullptr; } QByteArray fieldData = cipherStream->read(fieldSize); if (fieldData.size() != fieldSize) { raiseError("Read entry field data doesn't match size"); - return Q_NULLPTR; + return nullptr; } switch (fieldType) { @@ -602,7 +602,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) case 0x0001: if (fieldSize != 16) { raiseError("Invalid entry uuid field size"); - return Q_NULLPTR; + return nullptr; } m_entryUuids.insert(fieldData, entry.data()); break; @@ -610,7 +610,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) { if (fieldSize != 4) { raiseError("Invalid entry group id field size"); - return Q_NULLPTR; + return nullptr; } quint32 groupId = Endian::bytesToUInt32(fieldData, KeePass1::BYTEORDER); m_entryGroupIds.insert(entry.data(), groupId); @@ -620,7 +620,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) { if (fieldSize != 4) { raiseError("Invalid entry icon field size"); - return Q_NULLPTR; + return nullptr; } quint32 iconNumber = Endian::bytesToUInt32(fieldData, KeePass1::BYTEORDER); entry->setIcon(iconNumber); @@ -645,7 +645,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) { if (fieldSize != 5) { raiseError("Invalid entry creation time field size"); - return Q_NULLPTR; + return nullptr; } QDateTime dateTime = dateFromPackedStruct(fieldData); if (dateTime.isValid()) { @@ -657,7 +657,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) { if (fieldSize != 5) { raiseError("Invalid entry modification time field size"); - return Q_NULLPTR; + return nullptr; } QDateTime dateTime = dateFromPackedStruct(fieldData); if (dateTime.isValid()) { @@ -669,7 +669,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) { if (fieldSize != 5) { raiseError("Invalid entry creation time field size"); - return Q_NULLPTR; + return nullptr; } QDateTime dateTime = dateFromPackedStruct(fieldData); if (dateTime.isValid()) { @@ -681,7 +681,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) { if (fieldSize != 5) { raiseError("Invalid entry expiry time field size"); - return Q_NULLPTR; + return nullptr; } QDateTime dateTime = dateFromPackedStruct(fieldData); if (dateTime.isValid()) { @@ -704,7 +704,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream) default: // invalid field raiseError("Invalid entry field type"); - return Q_NULLPTR; + return nullptr; } } while (!reachedEnd); @@ -901,10 +901,10 @@ bool KeePass1Reader::parseCustomIcons4(const QByteArray& data) QByteArray entryUuid = data.mid(pos, 16); pos += 16; - int iconId = Endian::bytesToUInt32(data.mid(pos, 4), KeePass1::BYTEORDER); + quint32 iconId = Endian::bytesToUInt32(data.mid(pos, 4), KeePass1::BYTEORDER); pos += 4; - if (m_entryUuids.contains(entryUuid) && (iconId < iconUuids.size())) { + if (m_entryUuids.contains(entryUuid) && (iconId < static_cast(iconUuids.size()))) { m_entryUuids[entryUuid]->setIcon(iconUuids[iconId]); } } @@ -917,10 +917,10 @@ bool KeePass1Reader::parseCustomIcons4(const QByteArray& data) quint32 groupId = Endian::bytesToUInt32(data.mid(pos, 4), KeePass1::BYTEORDER); pos += 4; - int iconId = Endian::bytesToUInt32(data.mid(pos, 4), KeePass1::BYTEORDER); + quint32 iconId = Endian::bytesToUInt32(data.mid(pos, 4), KeePass1::BYTEORDER); pos += 4; - if (m_groupIds.contains(groupId) && (iconId < iconUuids.size())) { + if (m_groupIds.contains(groupId) && (iconId < static_cast(iconUuids.size()))) { m_groupIds[groupId]->setIcon(iconUuids[iconId]); } } diff --git a/src/format/KeePass2Reader.cpp b/src/format/KeePass2Reader.cpp index 2a25001c..00ebc070 100644 --- a/src/format/KeePass2Reader.cpp +++ b/src/format/KeePass2Reader.cpp @@ -24,6 +24,7 @@ #include "core/Database.h" #include "core/Endian.h" #include "crypto/CryptoHash.h" +#include "format/KeePass1.h" #include "format/KeePass2.h" #include "format/KeePass2RandomStream.h" #include "format/KeePass2XmlReader.h" @@ -33,16 +34,16 @@ #include "streams/SymmetricCipherStream.h" KeePass2Reader::KeePass2Reader() - : m_device(Q_NULLPTR) - , m_headerStream(Q_NULLPTR) + : m_device(nullptr) + , m_headerStream(nullptr) , m_error(false) , m_headerEnd(false) , m_saveXml(false) - , m_db(Q_NULLPTR) + , m_db(nullptr) { } -Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& key) +Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& key, bool keepDatabase) { QScopedPointer db(new Database()); m_db = db.data(); @@ -66,13 +67,20 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke quint32 signature1 = Endian::readUInt32(m_headerStream, KeePass2::BYTEORDER, &ok); if (!ok || signature1 != KeePass2::SIGNATURE_1) { raiseError(tr("Not a KeePass database.")); - return Q_NULLPTR; + return nullptr; } quint32 signature2 = Endian::readUInt32(m_headerStream, KeePass2::BYTEORDER, &ok); - if (!ok || signature2 != KeePass2::SIGNATURE_2) { + if (ok && signature2 == KeePass1::SIGNATURE_2) { + raiseError(tr("The selected file is an old KeePass 1 database (.kdb).\n\n" + "You can import it by clicking on Database > 'Import KeePass 1 database'.\n" + "This is a one-way migration. You won't be able to open the imported " + "database with the old KeePassX 0.4 version.")); + return nullptr; + } + else if (!ok || signature2 != KeePass2::SIGNATURE_2) { raiseError(tr("Not a KeePass database.")); - return Q_NULLPTR; + return nullptr; } quint32 version = Endian::readUInt32(m_headerStream, KeePass2::BYTEORDER, &ok) @@ -80,7 +88,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke quint32 maxVersion = KeePass2::FILE_VERSION & KeePass2::FILE_VERSION_CRITICAL_MASK; if (!ok || (version < KeePass2::FILE_VERSION_MIN) || (version > maxVersion)) { raiseError(tr("Unsupported KeePass database version.")); - return Q_NULLPTR; + return nullptr; } while (readHeaderField() && !hasError()) { @@ -89,7 +97,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke headerStream.close(); if (hasError()) { - return Q_NULLPTR; + return nullptr; } // check if all required headers were present @@ -97,12 +105,12 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke || m_streamStartBytes.isEmpty() || m_protectedStreamKey.isEmpty() || m_db->cipher().isNull()) { raiseError("missing database headers"); - return Q_NULLPTR; + return nullptr; } if (!m_db->setKey(key, m_transformSeed, false)) { raiseError(tr("Unable to calculate master key")); - return Q_NULLPTR; + return nullptr; } CryptoHash hash(CryptoHash::Sha256); @@ -114,24 +122,24 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke SymmetricCipher::Cbc, SymmetricCipher::Decrypt); if (!cipherStream.init(finalKey, m_encryptionIV)) { raiseError(cipherStream.errorString()); - return Q_NULLPTR; + return nullptr; } if (!cipherStream.open(QIODevice::ReadOnly)) { raiseError(cipherStream.errorString()); - return Q_NULLPTR; + return nullptr; } QByteArray realStart = cipherStream.read(32); if (realStart != m_streamStartBytes) { raiseError(tr("Wrong key or database file is corrupt.")); - return Q_NULLPTR; + return nullptr; } HashedBlockStream hashedStream(&cipherStream); if (!hashedStream.open(QIODevice::ReadOnly)) { raiseError(hashedStream.errorString()); - return Q_NULLPTR; + return nullptr; } QIODevice* xmlDevice; @@ -145,7 +153,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke ioCompressor->setStreamFormat(QtIOCompressor::GzipFormat); if (!ioCompressor->open(QIODevice::ReadOnly)) { raiseError(ioCompressor->errorString()); - return Q_NULLPTR; + return nullptr; } xmlDevice = ioCompressor.data(); } @@ -153,7 +161,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke KeePass2RandomStream randomStream; if (!randomStream.init(m_protectedStreamKey)) { raiseError(randomStream.errorString()); - return Q_NULLPTR; + return nullptr; } QScopedPointer buffer; @@ -170,7 +178,12 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke if (xmlReader.hasError()) { raiseError(xmlReader.errorString()); - return Q_NULLPTR; + if (keepDatabase) { + return db.take(); + } + else { + return nullptr; + } } Q_ASSERT(version < 0x00030001 || !xmlReader.headerHash().isEmpty()); @@ -179,7 +192,7 @@ Database* KeePass2Reader::readDatabase(QIODevice* device, const CompositeKey& ke QByteArray headerHash = CryptoHash::hash(headerStream.storedData(), CryptoHash::Sha256); if (headerHash != xmlReader.headerHash()) { raiseError("Head doesn't match hash"); - return Q_NULLPTR; + return nullptr; } } @@ -191,14 +204,14 @@ Database* KeePass2Reader::readDatabase(const QString& filename, const CompositeK QFile file(filename); if (!file.open(QFile::ReadOnly)) { raiseError(file.errorString()); - return Q_NULLPTR; + return nullptr; } QScopedPointer db(readDatabase(&file, key)); if (file.error() != QFile::NoError) { raiseError(file.errorString()); - return Q_NULLPTR; + return nullptr; } return db.take(); @@ -224,6 +237,11 @@ QByteArray KeePass2Reader::xmlData() return m_xmlData; } +QByteArray KeePass2Reader::streamKey() +{ + return m_protectedStreamKey; +} + void KeePass2Reader::raiseError(const QString& errorMessage) { m_error = true; diff --git a/src/format/KeePass2Reader.h b/src/format/KeePass2Reader.h index 2c9daab2..827e671c 100644 --- a/src/format/KeePass2Reader.h +++ b/src/format/KeePass2Reader.h @@ -31,12 +31,13 @@ class KeePass2Reader public: KeePass2Reader(); - Database* readDatabase(QIODevice* device, const CompositeKey& key); + Database* readDatabase(QIODevice* device, const CompositeKey& key, bool keepDatabase = false); Database* readDatabase(const QString& filename, const CompositeKey& key); bool hasError(); QString errorString(); void setSaveXml(bool save); QByteArray xmlData(); + QByteArray streamKey(); private: void raiseError(const QString& errorMessage); diff --git a/src/format/KeePass2Repair.cpp b/src/format/KeePass2Repair.cpp new file mode 100644 index 00000000..81ada2fd --- /dev/null +++ b/src/format/KeePass2Repair.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2016 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "KeePass2Repair.h" + +#include +#include + +#include "format/KeePass2RandomStream.h" +#include "format/KeePass2Reader.h" +#include "format/KeePass2XmlReader.h" + +KeePass2Repair::KeePass2Repair() + : m_db(nullptr) +{ +} + +KeePass2Repair::RepairResult KeePass2Repair::repairDatabase(QIODevice* device, const CompositeKey& key) +{ + m_db = nullptr; + m_errorStr.clear(); + + KeePass2Reader reader; + reader.setSaveXml(true); + + Database* db = reader.readDatabase(device, key, true); + if (!reader.hasError()) { + delete db; + return NothingTodo; + } + + QByteArray xmlData = reader.xmlData(); + if (!db || xmlData.isEmpty()) { + delete db; + m_errorStr = reader.errorString(); + return UnableToOpen; + } + + bool repairAction = false; + + QString xmlStart = QString::fromLatin1(xmlData.constData(), qMin(100, xmlData.size())); + QRegExp encodingRegExp("encoding=\"([^\"]+)\"", Qt::CaseInsensitive, QRegExp::RegExp2); + if (encodingRegExp.indexIn(xmlStart) != -1) { + if (encodingRegExp.cap(1).compare("utf-8", Qt::CaseInsensitive) != 0 + && encodingRegExp.cap(1).compare("utf8", Qt::CaseInsensitive) != 0) + { + // database is not utf-8 encoded, we don't support repairing that + delete db; + return RepairFailed; + } + } + + // try to fix broken databases because of bug #392 + for (int i = (xmlData.size() - 1); i >= 0; i--) { + quint8 ch = static_cast(xmlData.at(i)); + if (ch < 0x20 && ch != 0x09 && ch != 0x0A && ch != 0x0D) { + xmlData.remove(i, 1); + repairAction = true; + } + } + + if (!repairAction) { + // we were unable to find the problem + delete db; + return RepairFailed; + } + + KeePass2RandomStream randomStream; + randomStream.init(reader.streamKey()); + KeePass2XmlReader xmlReader; + QBuffer buffer(&xmlData); + buffer.open(QIODevice::ReadOnly); + xmlReader.readDatabase(&buffer, db, &randomStream); + + if (xmlReader.hasError()) { + delete db; + return RepairFailed; + } + else { + m_db = db; + return RepairSuccess; + } +} + +Database* KeePass2Repair::database() const +{ + return m_db; +} + +QString KeePass2Repair::errorString() const +{ + return m_errorStr; +} diff --git a/src/format/KeePass2Repair.h b/src/format/KeePass2Repair.h new file mode 100644 index 00000000..fe2f9dbf --- /dev/null +++ b/src/format/KeePass2Repair.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2016 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_KEEPASS2REPAIR_H +#define KEEPASSX_KEEPASS2REPAIR_H + +#include +#include + +#include "core/Database.h" +#include "keys/CompositeKey.h" + +class KeePass2Repair +{ + Q_DECLARE_TR_FUNCTIONS(KeePass2Repair) + +public: + enum RepairResult + { + NothingTodo, + UnableToOpen, + RepairSuccess, + RepairFailed + }; + + KeePass2Repair(); + RepairResult repairDatabase(QIODevice* device, const CompositeKey& key); + Database* database() const; + QString errorString() const; + +private: + Database* m_db; + QString m_errorStr; +}; + +#endif // KEEPASSX_KEEPASS2REPAIR_H diff --git a/src/format/KeePass2Writer.cpp b/src/format/KeePass2Writer.cpp index f233ac73..dfbbf353 100644 --- a/src/format/KeePass2Writer.cpp +++ b/src/format/KeePass2Writer.cpp @@ -127,6 +127,20 @@ void KeePass2Writer::writeDatabase(QIODevice* device, Database* db) KeePass2XmlWriter xmlWriter; xmlWriter.writeDatabase(m_device, db, &randomStream, headerHash); + // Explicitly close/reset streams so they are flushed and we can detect + // errors. QIODevice::close() resets errorString() etc. + if (ioCompressor) { + ioCompressor->close(); + } + if (!hashedStream.reset()) { + raiseError(hashedStream.errorString()); + return; + } + if (!cipherStream.reset()) { + raiseError(cipherStream.errorString()); + return; + } + if (xmlWriter.hasError()) { raiseError(xmlWriter.errorString()); } diff --git a/src/format/KeePass2XmlReader.cpp b/src/format/KeePass2XmlReader.cpp index 9af89db7..40087a63 100644 --- a/src/format/KeePass2XmlReader.cpp +++ b/src/format/KeePass2XmlReader.cpp @@ -31,10 +31,10 @@ typedef QPair StringPair; KeePass2XmlReader::KeePass2XmlReader() - : m_randomStream(Q_NULLPTR) - , m_db(Q_NULLPTR) - , m_meta(Q_NULLPTR) - , m_tmpParent(Q_NULLPTR) + : m_randomStream(nullptr) + , m_db(nullptr) + , m_meta(nullptr) + , m_tmpParent(nullptr) , m_error(false) , m_strictMode(false) { @@ -357,7 +357,7 @@ void KeePass2XmlReader::parseIcon() while (!m_xml.error() && m_xml.readNextStartElement()) { if (m_xml.name() == "UUID") { uuid = readUuid(); - uuidSet = true; + uuidSet = !uuid.isNull(); } else if (m_xml.name() == "Data") { icon.loadFromData(readBinary()); @@ -523,6 +523,7 @@ Group* KeePass2XmlReader::parseGroup() if (m_strictMode) { raiseError("Invalid group icon number"); } + iconId = 0; } else { if (iconId >= DatabaseIcons::IconCount) { @@ -702,6 +703,7 @@ Entry* KeePass2XmlReader::parseEntry(bool history) if (m_strictMode) { raiseError("Invalid entry icon number"); } + iconId = 0; } else { entry->setIcon(iconId); @@ -1043,7 +1045,7 @@ QDateTime KeePass2XmlReader::readDateTime() raiseError("Invalid date time value"); } else { - dt = Tools::currentDateTimeUtc(); + dt = QDateTime::currentDateTimeUtc(); } } @@ -1104,7 +1106,10 @@ int KeePass2XmlReader::readNumber() Uuid KeePass2XmlReader::readUuid() { QByteArray uuidBin = readBinary(); - if (uuidBin.length() != Uuid::Length) { + if (uuidBin.isEmpty()) { + return Uuid(); + } + else if (uuidBin.length() != Uuid::Length) { if (m_strictMode) { raiseError("Invalid uuid value"); } @@ -1141,7 +1146,7 @@ QByteArray KeePass2XmlReader::readCompressedBinary() Group* KeePass2XmlReader::getGroup(const Uuid& uuid) { if (uuid.isNull()) { - return Q_NULLPTR; + return nullptr; } if (m_groups.contains(uuid)) { @@ -1160,7 +1165,7 @@ Group* KeePass2XmlReader::getGroup(const Uuid& uuid) Entry* KeePass2XmlReader::getEntry(const Uuid& uuid) { if (uuid.isNull()) { - return Q_NULLPTR; + return nullptr; } if (m_entries.contains(uuid)) { diff --git a/src/format/KeePass2XmlReader.h b/src/format/KeePass2XmlReader.h index ca311b0e..d2e0e002 100644 --- a/src/format/KeePass2XmlReader.h +++ b/src/format/KeePass2XmlReader.h @@ -25,7 +25,6 @@ #include #include -#include "core/Global.h" #include "core/TimeInfo.h" #include "core/Uuid.h" @@ -42,7 +41,7 @@ class KeePass2XmlReader public: KeePass2XmlReader(); Database* readDatabase(QIODevice* device); - void readDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = Q_NULLPTR); + void readDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = nullptr); Database* readDatabase(const QString& filename); bool hasError(); QString errorString(); diff --git a/src/format/KeePass2XmlWriter.cpp b/src/format/KeePass2XmlWriter.cpp index dda98011..7fd03cc0 100644 --- a/src/format/KeePass2XmlWriter.cpp +++ b/src/format/KeePass2XmlWriter.cpp @@ -25,9 +25,9 @@ #include "streams/QtIOCompressor" KeePass2XmlWriter::KeePass2XmlWriter() - : m_db(Q_NULLPTR) - , m_meta(Q_NULLPTR) - , m_randomStream(Q_NULLPTR) + : m_db(nullptr) + , m_meta(nullptr) + , m_randomStream(nullptr) , m_error(false) { m_xml.setAutoFormatting(true); @@ -57,6 +57,10 @@ void KeePass2XmlWriter::writeDatabase(QIODevice* device, Database* db, KeePass2R m_xml.writeEndElement(); m_xml.writeEndDocument(); + + if (m_xml.hasError()) { + raiseError(device->errorString()); + } } void KeePass2XmlWriter::writeDatabase(const QString& filename, Database* db) @@ -368,7 +372,7 @@ void KeePass2XmlWriter::writeEntry(const Entry* entry) } if (!value.isEmpty()) { - m_xml.writeCharacters(value); + m_xml.writeCharacters(stripInvalidXml10Chars(value)); } m_xml.writeEndElement(); @@ -439,7 +443,7 @@ void KeePass2XmlWriter::writeString(const QString& qualifiedName, const QString& m_xml.writeEmptyElement(qualifiedName); } else { - m_xml.writeTextElement(qualifiedName, string); + m_xml.writeTextElement(qualifiedName, stripInvalidXml10Chars(string)); } } @@ -543,6 +547,31 @@ QString KeePass2XmlWriter::colorPartToString(int value) return str; } +QString KeePass2XmlWriter::stripInvalidXml10Chars(QString str) +{ + for (int i = str.size() - 1; i >= 0; i--) { + const QChar ch = str.at(i); + const ushort uc = ch.unicode(); + + if (ch.isLowSurrogate() && i != 0 && str.at(i - 1).isHighSurrogate()) { + // keep valid surrogate pair + i--; + } + else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control chracters + || (uc >= 0x7F && uc <= 0x84) // control chracters, valid but discouraged by XML + || (uc >= 0x86 && uc <= 0x9F) // control chracters, valid but discouraged by XML + || (uc > 0xFFFD) // noncharacter + || ch.isLowSurrogate() // single low surrogate + || ch.isHighSurrogate()) // single high surrogate + { + qWarning("Stripping invalid XML 1.0 codepoint %x", uc); + str.remove(i, 1); + } + } + + return str; +} + void KeePass2XmlWriter::raiseError(const QString& errorMessage) { m_error = true; diff --git a/src/format/KeePass2XmlWriter.h b/src/format/KeePass2XmlWriter.h index ea621244..23e148db 100644 --- a/src/format/KeePass2XmlWriter.h +++ b/src/format/KeePass2XmlWriter.h @@ -36,7 +36,7 @@ class KeePass2XmlWriter { public: KeePass2XmlWriter(); - void writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = Q_NULLPTR, + void writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = nullptr, const QByteArray& headerHash = QByteArray()); void writeDatabase(const QString& filename, Database* db); bool hasError(); @@ -73,6 +73,7 @@ private: void writeColor(const QString& qualifiedName, const QColor& color); void writeTriState(const QString& qualifiedName, Group::TriState triState); QString colorPartToString(int value); + QString stripInvalidXml10Chars(QString str); void raiseError(const QString& errorMessage); diff --git a/src/gui/AboutDialog.cpp b/src/gui/AboutDialog.cpp index b1fdeda2..6ca02d1a 100644 --- a/src/gui/AboutDialog.cpp +++ b/src/gui/AboutDialog.cpp @@ -19,7 +19,9 @@ #include "ui_AboutDialog.h" #include "config-keepassx.h" +#include "version.h" #include "core/FilePath.h" +#include "crypto/Crypto.h" AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent) @@ -35,6 +37,25 @@ AboutDialog::AboutDialog(QWidget* parent) m_ui->iconLabel->setPixmap(filePath()->applicationIcon().pixmap(48)); + QString commitHash; + if (!QString(GIT_HEAD).isEmpty()) { + commitHash = GIT_HEAD; + } + else if (!QString(DIST_HASH).contains("Format")) { + commitHash = DIST_HASH; + } + + if (!commitHash.isEmpty()) { + QString labelText = tr("Revision").append(": ").append(commitHash); + m_ui->label_git->setText(labelText); + } + + QString libs = QString("%1\n- Qt %2\n- %3") + .arg(m_ui->label_libs->text()) + .arg(QString::fromLocal8Bit(qVersion())) + .arg(Crypto::backendVersion()); + m_ui->label_libs->setText(libs); + setAttribute(Qt::WA_DeleteOnClose); connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(close())); } diff --git a/src/gui/AboutDialog.h b/src/gui/AboutDialog.h index 1436aee4..08db6c88 100644 --- a/src/gui/AboutDialog.h +++ b/src/gui/AboutDialog.h @@ -21,8 +21,6 @@ #include #include -#include "core/Global.h" - namespace Ui { class AboutDialog; } @@ -32,7 +30,7 @@ class AboutDialog : public QDialog Q_OBJECT public: - explicit AboutDialog(QWidget* parent = Q_NULLPTR); + explicit AboutDialog(QWidget* parent = nullptr); ~AboutDialog(); private: diff --git a/src/gui/AboutDialog.ui b/src/gui/AboutDialog.ui index 0a610ec0..0a66b602 100644 --- a/src/gui/AboutDialog.ui +++ b/src/gui/AboutDialog.ui @@ -14,10 +14,20 @@ About KeePassX + + QLayout::SetFixedSize + - + + + + 0 + 0 + + + @@ -36,6 +46,12 @@ + + + 0 + 0 + + <a href="http://www.keepassx.org/">http://www.keepassx.org/</a> @@ -46,6 +62,12 @@ + + + 0 + 0 + + KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3. @@ -54,6 +76,23 @@ + + + + + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + Using: + + + diff --git a/src/gui/Application.cpp b/src/gui/Application.cpp index 2dede3f8..70550c55 100644 --- a/src/gui/Application.cpp +++ b/src/gui/Application.cpp @@ -18,13 +18,43 @@ #include "Application.h" +#include #include #include "autotype/AutoType.h" +#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX) +class XcbEventFilter : public QAbstractNativeEventFilter +{ +public: + bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override + { + Q_UNUSED(result) + + if (eventType == QByteArrayLiteral("xcb_generic_event_t")) { + int retCode = autoType()->callEventFilter(message); + if (retCode == 1) { + return true; + } + } + + return false; + } +}; +#endif + Application::Application(int& argc, char** argv) : QApplication(argc, argv) + , m_mainWindow(nullptr) { +#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX) + installNativeEventFilter(new XcbEventFilter()); +#endif +} + +void Application::setMainWindow(QWidget* mainWindow) +{ + m_mainWindow = mainWindow; } bool Application::event(QEvent* event) @@ -34,22 +64,16 @@ bool Application::event(QEvent* event) Q_EMIT openFile(static_cast(event)->file()); return true; } +#ifdef Q_OS_MAC + // restore main window when clicking on the docker icon + else if ((event->type() == QEvent::ApplicationActivate) && m_mainWindow) { + m_mainWindow->ensurePolished(); + m_mainWindow->setWindowState(m_mainWindow->windowState() & ~Qt::WindowMinimized); + m_mainWindow->show(); + m_mainWindow->raise(); + m_mainWindow->activateWindow(); + } +#endif return QApplication::event(event); } - -#ifdef Q_WS_X11 -bool Application::x11EventFilter(XEvent* event) -{ - int retCode = autoType()->callEventFilter(event); - - if (retCode == 0) { - return false; - } - else if (retCode == 1) { - return true; - } - - return QApplication::x11EventFilter(event); -} -#endif diff --git a/src/gui/Application.h b/src/gui/Application.h index a5f55d4d..149b61dd 100644 --- a/src/gui/Application.h +++ b/src/gui/Application.h @@ -21,22 +21,21 @@ #include -#include "core/Global.h" - class Application : public QApplication { Q_OBJECT public: Application(int& argc, char** argv); + void setMainWindow(QWidget* mainWindow); - bool event(QEvent* event) Q_DECL_OVERRIDE; -#ifdef Q_WS_X11 - bool x11EventFilter(XEvent* event) Q_DECL_OVERRIDE; -#endif + bool event(QEvent* event) override; Q_SIGNALS: void openFile(const QString& filename); + +private: + QWidget* m_mainWindow; }; #endif // KEEPASSX_APPLICATION_H diff --git a/src/gui/ChangeMasterKeyWidget.h b/src/gui/ChangeMasterKeyWidget.h index 46fc3efc..8985ff7a 100644 --- a/src/gui/ChangeMasterKeyWidget.h +++ b/src/gui/ChangeMasterKeyWidget.h @@ -33,7 +33,7 @@ class ChangeMasterKeyWidget : public DialogyWidget Q_OBJECT public: - explicit ChangeMasterKeyWidget(QWidget* parent = Q_NULLPTR); + explicit ChangeMasterKeyWidget(QWidget* parent = nullptr); ~ChangeMasterKeyWidget(); void clearForms(); CompositeKey newMasterKey(); diff --git a/src/gui/ChangeMasterKeyWidget.ui b/src/gui/ChangeMasterKeyWidget.ui index 862a7a92..d14941cc 100644 --- a/src/gui/ChangeMasterKeyWidget.ui +++ b/src/gui/ChangeMasterKeyWidget.ui @@ -7,7 +7,7 @@ 0 0 438 - 249 + 256 @@ -155,8 +155,8 @@ passwordGroup enterPasswordEdit - togglePasswordButton repeatPasswordEdit + togglePasswordButton keyFileGroup keyFileCombo browseKeyFileButton diff --git a/src/gui/Clipboard.cpp b/src/gui/Clipboard.cpp index 7d8f71fa..bf4db8ff 100644 --- a/src/gui/Clipboard.cpp +++ b/src/gui/Clipboard.cpp @@ -21,14 +21,9 @@ #include #include -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) -#include -#include -#endif - #include "core/Config.h" -Clipboard* Clipboard::m_instance(Q_NULLPTR); +Clipboard* Clipboard::m_instance(nullptr); Clipboard::Clipboard(QObject* parent) : QObject(parent) @@ -36,7 +31,7 @@ Clipboard::Clipboard(QObject* parent) { m_timer->setSingleShot(true); connect(m_timer, SIGNAL(timeout()), SLOT(clearClipboard())); - connect(qApp, SIGNAL(aboutToQuit()), SLOT(cleanup())); + connect(qApp, SIGNAL(aboutToQuit()), SLOT(clearCopiedText())); } void Clipboard::setText(const QString& text) @@ -57,6 +52,14 @@ void Clipboard::setText(const QString& text) } } +void Clipboard::clearCopiedText() +{ + if (m_timer->isActive()) { + m_timer->stop(); + clearClipboard(); + } +} + void Clipboard::clearClipboard() { QClipboard* clipboard = QApplication::clipboard(); @@ -75,22 +78,9 @@ void Clipboard::clearClipboard() clipboard->clear(QClipboard::Selection); } -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) - QDBusMessage message = QDBusMessage::createMethodCall("org.kde.klipper", "/klipper", "", "clearClipboardHistory"); - QDBusConnection::sessionBus().send(message); -#endif - m_lastCopied.clear(); } -void Clipboard::cleanup() -{ - if (m_timer->isActive()) { - m_timer->stop(); - clearClipboard(); - } -} - Clipboard* Clipboard::instance() { if (!m_instance) { diff --git a/src/gui/Clipboard.h b/src/gui/Clipboard.h index 8b6ea69f..dafce70a 100644 --- a/src/gui/Clipboard.h +++ b/src/gui/Clipboard.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class QTimer; class Clipboard : public QObject @@ -33,12 +31,14 @@ public: static Clipboard* instance(); +public Q_SLOTS: + void clearCopiedText(); + private Q_SLOTS: void clearClipboard(); - void cleanup(); private: - explicit Clipboard(QObject* parent = Q_NULLPTR); + explicit Clipboard(QObject* parent = nullptr); static Clipboard* m_instance; diff --git a/src/gui/DatabaseOpenWidget.cpp b/src/gui/DatabaseOpenWidget.cpp index e15c3c97..beb8d54c 100644 --- a/src/gui/DatabaseOpenWidget.cpp +++ b/src/gui/DatabaseOpenWidget.cpp @@ -31,7 +31,7 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) : DialogyWidget(parent) , m_ui(new Ui::DatabaseOpenWidget()) - , m_db(Q_NULLPTR) + , m_db(nullptr) { m_ui->setupUi(this); @@ -50,10 +50,6 @@ DatabaseOpenWidget::DatabaseOpenWidget(QWidget* parent) connect(m_ui->editPassword, SIGNAL(textChanged(QString)), SLOT(activatePassword())); connect(m_ui->comboKeyFile, SIGNAL(editTextChanged(QString)), SLOT(activateKeyFile())); - connect(m_ui->checkPassword, SIGNAL(toggled(bool)), SLOT(setOkButtonEnabled())); - connect(m_ui->checkKeyFile, SIGNAL(toggled(bool)), SLOT(setOkButtonEnabled())); - connect(m_ui->comboKeyFile, SIGNAL(editTextChanged(QString)), SLOT(setOkButtonEnabled())); - connect(m_ui->buttonBox, SIGNAL(accepted()), SLOT(openDatabase())); connect(m_ui->buttonBox, SIGNAL(rejected()), SLOT(reject())); } @@ -76,6 +72,7 @@ void DatabaseOpenWidget::load(const QString& filename) } } + m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); m_ui->editPassword->setFocus(); } @@ -100,9 +97,6 @@ void DatabaseOpenWidget::openDatabase() { KeePass2Reader reader; CompositeKey masterKey = databaseKey(); - if (masterKey.isEmpty()) { - return; - } QFile file(m_filename); if (!file.open(QIODevice::ReadOnly)) { @@ -179,14 +173,6 @@ void DatabaseOpenWidget::activateKeyFile() m_ui->checkKeyFile->setChecked(true); } -void DatabaseOpenWidget::setOkButtonEnabled() -{ - bool enable = m_ui->checkPassword->isChecked() - || (m_ui->checkKeyFile->isChecked() && !m_ui->comboKeyFile->currentText().isEmpty()); - - m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(enable); -} - void DatabaseOpenWidget::browseKeyFile() { QString filters = QString("%1 (*);;%2 (*.key)").arg(tr("All files"), tr("Key files")); diff --git a/src/gui/DatabaseOpenWidget.h b/src/gui/DatabaseOpenWidget.h index ad40c571..ba55e4c4 100644 --- a/src/gui/DatabaseOpenWidget.h +++ b/src/gui/DatabaseOpenWidget.h @@ -35,7 +35,7 @@ class DatabaseOpenWidget : public DialogyWidget Q_OBJECT public: - explicit DatabaseOpenWidget(QWidget* parent = Q_NULLPTR); + explicit DatabaseOpenWidget(QWidget* parent = nullptr); ~DatabaseOpenWidget(); void load(const QString& filename); void enterKey(const QString& pw, const QString& keyFile); @@ -54,7 +54,6 @@ protected Q_SLOTS: private Q_SLOTS: void activatePassword(); void activateKeyFile(); - void setOkButtonEnabled(); void browseKeyFile(); protected: diff --git a/src/gui/DatabaseRepairWidget.cpp b/src/gui/DatabaseRepairWidget.cpp new file mode 100644 index 00000000..f1b760f9 --- /dev/null +++ b/src/gui/DatabaseRepairWidget.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2016 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "DatabaseRepairWidget.h" + +#include +#include + +#include "ui_DatabaseOpenWidget.h" +#include "core/Database.h" +#include "core/Metadata.h" +#include "format/KeePass2Repair.h" +#include "gui/MessageBox.h" +#include "keys/FileKey.h" +#include "keys/PasswordKey.h" + +DatabaseRepairWidget::DatabaseRepairWidget(QWidget* parent) + : DatabaseOpenWidget(parent) +{ + m_ui->labelHeadline->setText(tr("Repair database")); + + connect(this, SIGNAL(editFinished(bool)), this, SLOT(processEditFinished(bool))); +} + +void DatabaseRepairWidget::openDatabase() +{ + CompositeKey masterKey; + + if (m_ui->checkPassword->isChecked()) { + masterKey.addKey(PasswordKey(m_ui->editPassword->text())); + } + + if (m_ui->checkKeyFile->isChecked()) { + FileKey key; + QString keyFilename = m_ui->comboKeyFile->currentText(); + QString errorMsg; + if (!key.load(keyFilename, &errorMsg)) { + MessageBox::warning(this, tr("Error"), tr("Can't open key file").append(":\n").append(errorMsg)); + Q_EMIT editFinished(false); + return; + } + masterKey.addKey(key); + } + + KeePass2Repair repair; + + QFile file(m_filename); + if (!file.open(QIODevice::ReadOnly)) { + // TODO: error message + Q_EMIT editFinished(false); + return; + } + if (m_db) { + delete m_db; + } + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + KeePass2Repair::RepairResult repairResult = repair.repairDatabase(&file, masterKey); + QApplication::restoreOverrideCursor(); + + switch (repairResult) { + case KeePass2Repair::NothingTodo: + MessageBox::information(this, tr("Error"), tr("Database opened fine. Nothing to do.")); + Q_EMIT editFinished(false); + return; + case KeePass2Repair::UnableToOpen: + MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") + .append(repair.errorString())); + Q_EMIT editFinished(false); + return; + case KeePass2Repair::RepairSuccess: + m_db = repair.database(); + MessageBox::warning(this, tr("Success"), tr("The database has been successfully repaired\nYou can now save it.")); + Q_EMIT editFinished(true); + return; + case KeePass2Repair::RepairFailed: + MessageBox::warning(this, tr("Error"), tr("Unable to repair the database.")); + Q_EMIT editFinished(false); + return; + } +} + +void DatabaseRepairWidget::processEditFinished(bool result) +{ + if (result) { + Q_EMIT success(); + } + else { + Q_EMIT error(); + } +} diff --git a/tests/TestQSaveFile.h b/src/gui/DatabaseRepairWidget.h similarity index 58% rename from tests/TestQSaveFile.h rename to src/gui/DatabaseRepairWidget.h index 8e1caf0e..6775d2dc 100644 --- a/tests/TestQSaveFile.h +++ b/src/gui/DatabaseRepairWidget.h @@ -1,6 +1,5 @@ /* - * Copyright (C) 2012 Felix Geyer - * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2016 Felix Geyer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,24 +15,27 @@ * along with this program. If not, see . */ -#ifndef KEEPASSX_TESTQSAVEFILE_H -#define KEEPASSX_TESTQSAVEFILE_H +#ifndef KEEPASSX_DATABASEREPAIRWIDGET_H +#define KEEPASSX_DATABASEREPAIRWIDGET_H -#include +#include "gui/DatabaseOpenWidget.h" -class TestQSaveFile : public QObject +class DatabaseRepairWidget : public DatabaseOpenWidget { Q_OBJECT -private Q_SLOTS: - void transactionalWrite(); - void autoFlush(); - void transactionalWriteNoPermissions(); - void transactionalWriteCanceled(); - void transactionalWriteErrorRenaming(); +public: + explicit DatabaseRepairWidget(QWidget* parent = nullptr); -private: - QString tmpDir(); +Q_SIGNALS: + void success(); + void error(); + +protected: + void openDatabase() override; + +private Q_SLOTS: + void processEditFinished(bool result); }; -#endif // KEEPASSX_TESTQSAVEFILE_H +#endif // KEEPASSX_DATABASEREPAIRWIDGET_H diff --git a/src/gui/DatabaseSettingsWidget.cpp b/src/gui/DatabaseSettingsWidget.cpp index 007c44a0..d4ca8ddb 100644 --- a/src/gui/DatabaseSettingsWidget.cpp +++ b/src/gui/DatabaseSettingsWidget.cpp @@ -26,7 +26,7 @@ DatabaseSettingsWidget::DatabaseSettingsWidget(QWidget* parent) : DialogyWidget(parent) , m_ui(new Ui::DatabaseSettingsWidget()) - , m_db(Q_NULLPTR) + , m_db(nullptr) { m_ui->setupUi(this); diff --git a/src/gui/DatabaseSettingsWidget.h b/src/gui/DatabaseSettingsWidget.h index a7d28326..040e0dbe 100644 --- a/src/gui/DatabaseSettingsWidget.h +++ b/src/gui/DatabaseSettingsWidget.h @@ -33,7 +33,7 @@ class DatabaseSettingsWidget : public DialogyWidget Q_OBJECT public: - explicit DatabaseSettingsWidget(QWidget* parent = Q_NULLPTR); + explicit DatabaseSettingsWidget(QWidget* parent = nullptr); ~DatabaseSettingsWidget(); void load(Database* db); diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index dbf458e0..69b4f7e7 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -18,6 +18,8 @@ #include "DatabaseTabWidget.h" #include +#include +#include #include #include "autotype/AutoType.h" @@ -25,7 +27,8 @@ #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" -#include "core/qsavefile.h" +#include "format/CsvExporter.h" +#include "gui/Clipboard.h" #include "gui/DatabaseWidget.h" #include "gui/DatabaseWidgetStateSync.h" #include "gui/DragTabBar.h" @@ -35,8 +38,8 @@ #include "gui/group/GroupView.h" DatabaseManagerStruct::DatabaseManagerStruct() - : dbWidget(Q_NULLPTR) - , lockFile(Q_NULLPTR) + : dbWidget(nullptr) + , lockFile(nullptr) , saveToFilename(false) , modified(false) , readOnly(false) @@ -51,8 +54,8 @@ DatabaseTabWidget::DatabaseTabWidget(QWidget* parent) , m_dbWidgetSateSync(new DatabaseWidgetStateSync(this)) { DragTabBar* tabBar = new DragTabBar(this); - tabBar->setDrawBase(false); setTabBar(tabBar); + setDocumentMode(true); connect(this, SIGNAL(tabCloseRequested(int)), SLOT(closeDatabase(int))); connect(this, SIGNAL(currentChanged(int)), SLOT(emitActivateDatabaseChanged())); @@ -158,7 +161,7 @@ void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, if (result == QMessageBox::No) { dbStruct.readOnly = true; delete lockFile; - lockFile = Q_NULLPTR; + lockFile = nullptr; } else { // take over the lock file if possible @@ -225,24 +228,28 @@ bool DatabaseTabWidget::closeDatabase(Database* db) QMessageBox::StandardButton result = MessageBox::question( this, tr("Close?"), - tr("\"%1\" is in edit mode.\nClose anyway?").arg(dbName), - QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); - if (result == QMessageBox::No) { + tr("\"%1\" is in edit mode.\nDiscard changes and close anyway?").arg(dbName), + QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Cancel); + if (result == QMessageBox::Cancel) { return false; } } if (dbStruct.modified) { if (config()->get("AutoSaveOnExit").toBool()) { - saveDatabase(db); + if (!saveDatabase(db)) { + return false; + } } else { QMessageBox::StandardButton result = MessageBox::question( this, tr("Save changes?"), tr("\"%1\" was modified.\nSave changes?").arg(dbName), - QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes); + QMessageBox::Yes | QMessageBox::Discard | QMessageBox::Cancel, QMessageBox::Yes); if (result == QMessageBox::Yes) { - saveDatabase(db); + if (!saveDatabase(db)) { + return false; + } } else if (result == QMessageBox::Cancel) { return false; @@ -290,24 +297,24 @@ bool DatabaseTabWidget::saveDatabase(Database* db) DatabaseManagerStruct& dbStruct = m_dbList[db]; if (dbStruct.saveToFilename) { - bool result = false; - QSaveFile saveFile(dbStruct.filePath); if (saveFile.open(QIODevice::WriteOnly)) { m_writer.writeDatabase(&saveFile, db); - result = saveFile.commit(); + if (m_writer.hasError()) { + MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n" + + m_writer.errorString()); + return false; + } + if (!saveFile.commit()) { + MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n" + + saveFile.errorString()); + return false; + } } - if (result) { - dbStruct.modified = false; - updateTabName(db); - return true; - } - else { - MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n" - + saveFile.errorString()); - return false; - } + dbStruct.modified = false; + updateTabName(db); + return true; } else { return saveDatabaseAs(db); @@ -321,39 +328,77 @@ bool DatabaseTabWidget::saveDatabaseAs(Database* db) if (dbStruct.saveToFilename) { oldFileName = dbStruct.filePath; } + else { + oldFileName = tr("New database").append(".kdbx"); + } QString fileName = fileDialog()->getSaveFileName(this, tr("Save database as"), - oldFileName, tr("KeePass 2 Database").append(" (*.kdbx)")); + oldFileName, tr("KeePass 2 Database").append(" (*.kdbx)"), + nullptr, 0, "kdbx"); if (!fileName.isEmpty()) { - bool result = false; - - QSaveFile saveFile(fileName); - if (saveFile.open(QIODevice::WriteOnly)) { - m_writer.writeDatabase(&saveFile, db); - result = saveFile.commit(); - } - - if (result) { - dbStruct.modified = false; - dbStruct.saveToFilename = true; - QFileInfo fileInfo(fileName); - dbStruct.filePath = fileInfo.absoluteFilePath(); - dbStruct.canonicalFilePath = fileInfo.canonicalFilePath(); - dbStruct.fileName = fileInfo.fileName(); - dbStruct.dbWidget->updateFilename(dbStruct.filePath); - QString lockFileName = QString("%1/.%2.lock") - .arg(fileInfo.canonicalPath(), fileInfo.fileName()); - dbStruct.lockFile = new QLockFile(lockFileName); - dbStruct.lockFile->setStaleLockTime(0); - dbStruct.lockFile->tryLock(); - updateTabName(db); - updateLastDatabases(dbStruct.filePath); - return true; + QFileInfo fileInfo(fileName); + QString lockFilePath; + if (fileInfo.exists()) { + // returns empty string when file doesn't exist + lockFilePath = fileInfo.canonicalPath(); } else { + lockFilePath = fileInfo.absolutePath(); + } + QString lockFileName = QString("%1/.%2.lock").arg(lockFilePath, fileInfo.fileName()); + QScopedPointer lockFile(new QLockFile(lockFileName)); + lockFile->setStaleLockTime(0); + if (!lockFile->tryLock()) { + // for now silently ignore if we can't create a lock file + // due to lack of permissions + if (lockFile->error() != QLockFile::PermissionError) { + QMessageBox::StandardButton result = MessageBox::question(this, tr("Save database as"), + tr("The database you are trying to save as is locked by another instance of KeePassX.\n" + "Do you want to save it anyway?"), + QMessageBox::Yes | QMessageBox::No); + + if (result == QMessageBox::No) { + return false; + } + else { + // take over the lock file if possible + if (lockFile->removeStaleLockFile()) { + lockFile->tryLock(); + } + } + } + } + + QSaveFile saveFile(fileName); + if (!saveFile.open(QIODevice::WriteOnly)) { MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n" + saveFile.errorString()); return false; } + + m_writer.writeDatabase(&saveFile, db); + if (m_writer.hasError()) { + MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n" + + m_writer.errorString()); + return false; + } + if (!saveFile.commit()) { + MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n" + + saveFile.errorString()); + return false; + } + + dbStruct.modified = false; + dbStruct.saveToFilename = true; + dbStruct.readOnly = false; + dbStruct.filePath = fileInfo.absoluteFilePath(); + dbStruct.canonicalFilePath = fileInfo.canonicalFilePath(); + dbStruct.fileName = fileInfo.fileName(); + dbStruct.dbWidget->updateFilename(dbStruct.filePath); + delete dbStruct.lockFile; + dbStruct.lockFile = lockFile.take(); + updateTabName(db); + updateLastDatabases(dbStruct.filePath); + return true; } else { return false; @@ -399,6 +444,28 @@ bool DatabaseTabWidget::saveDatabaseAs(int index) return saveDatabaseAs(indexDatabase(index)); } +void DatabaseTabWidget::exportToCsv() +{ + Database* db = indexDatabase(currentIndex()); + if (!db) { + Q_ASSERT(false); + return; + } + + QString fileName = fileDialog()->getSaveFileName(this, tr("Export database to CSV file"), + QString(), tr("CSV file").append(" (*.csv)"), + nullptr, 0, "csv"); + if (fileName.isEmpty()) { + return; + } + + CsvExporter csvExporter; + if (!csvExporter.exportDatabase(fileName, db)) { + MessageBox::critical(this, tr("Error"), tr("Writing the CSV file failed.") + "\n\n" + + csvExporter.errorString()); + } +} + void DatabaseTabWidget::changeMasterKey() { currentDatabaseWidget()->switchToMasterKeyChange(); @@ -427,7 +494,7 @@ void DatabaseTabWidget::updateTabName(Database* db) QString tabName; - if (dbStruct.saveToFilename) { + if (dbStruct.saveToFilename || dbStruct.readOnly) { if (db->metadata()->name().isEmpty()) { tabName = dbStruct.fileName; } @@ -492,7 +559,7 @@ Database* DatabaseTabWidget::indexDatabase(int index) } } - return Q_NULLPTR; + return nullptr; } DatabaseManagerStruct DatabaseTabWidget::indexDatabaseManagerStruct(int index) @@ -520,7 +587,7 @@ Database* DatabaseTabWidget::databaseFromDatabaseWidget(DatabaseWidget* dbWidget } } - return Q_NULLPTR; + return nullptr; } void DatabaseTabWidget::insertDatabase(Database* db, const DatabaseManagerStruct& dbStruct) @@ -545,7 +612,7 @@ DatabaseWidget* DatabaseTabWidget::currentDatabaseWidget() return m_dbList[db].dbWidget; } else { - return Q_NULLPTR; + return nullptr; } } @@ -567,6 +634,8 @@ bool DatabaseTabWidget::hasLockableDatabases() const void DatabaseTabWidget::lockDatabases() { + clipboard()->clearCopiedText(); + for (int i = 0; i < count(); i++) { DatabaseWidget* dbWidget = static_cast(widget(i)); Database* db = databaseFromDatabaseWidget(dbWidget); diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index 2ad3010d..de4a9ca1 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -21,7 +21,6 @@ #include #include -#include "core/qlockfile.h" #include "format/KeePass2Writer.h" #include "gui/DatabaseWidget.h" @@ -29,6 +28,7 @@ class DatabaseWidget; class DatabaseWidgetStateSync; class DatabaseOpenWidget; class QFile; +class QLockFile; struct DatabaseManagerStruct { @@ -51,7 +51,7 @@ class DatabaseTabWidget : public QTabWidget Q_OBJECT public: - explicit DatabaseTabWidget(QWidget* parent = Q_NULLPTR); + explicit DatabaseTabWidget(QWidget* parent = nullptr); ~DatabaseTabWidget(); void openDatabase(const QString& fileName, const QString& pw = QString(), const QString& keyFile = QString()); @@ -66,6 +66,7 @@ public Q_SLOTS: void importKeePass1Database(); bool saveDatabase(int index = -1); bool saveDatabaseAs(int index = -1); + void exportToCsv(); bool closeDatabase(int index = -1); void closeDatabaseFromSender(); bool closeAllDatabases(); @@ -100,7 +101,7 @@ private: Database* databaseFromDatabaseWidget(DatabaseWidget* dbWidget); void insertDatabase(Database* db, const DatabaseManagerStruct& dbStruct); void updateLastDatabases(const QString& filename); - void connectDatabase(Database* newDb, Database* oldDb = Q_NULLPTR); + void connectDatabase(Database* newDb, Database* oldDb = nullptr); KeePass2Writer m_writer; QHash m_dbList; diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp index c5b7b514..3bca6fa3 100644 --- a/src/gui/DatabaseWidget.cpp +++ b/src/gui/DatabaseWidget.cpp @@ -23,8 +23,10 @@ #include #include #include +#include #include #include +#include #include "autotype/AutoType.h" #include "core/Config.h" @@ -50,9 +52,9 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) , m_db(db) , m_searchUi(new Ui::SearchWidget()) , m_searchWidget(new QWidget()) - , m_newGroup(Q_NULLPTR) - , m_newEntry(Q_NULLPTR) - , m_newParent(Q_NULLPTR) + , m_newGroup(nullptr) + , m_newEntry(nullptr) + , m_newParent(nullptr) { m_searchUi->setupUi(m_searchWidget); @@ -87,6 +89,7 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent) m_searchUi->closeSearchButton->setShortcut(Qt::Key_Escape); m_searchWidget->hide(); m_searchUi->caseSensitiveCheckBox->setVisible(false); + m_searchUi->searchEdit->installEventFilter(this); QVBoxLayout* vLayout = new QVBoxLayout(rightHandSideWidget); vLayout->setMargin(0); @@ -172,7 +175,7 @@ DatabaseWidget::~DatabaseWidget() DatabaseWidget::Mode DatabaseWidget::currentMode() const { - if (currentWidget() == Q_NULLPTR) { + if (currentWidget() == nullptr) { return DatabaseWidget::None; } else if (currentWidget() == m_mainWidget) { @@ -452,8 +455,19 @@ void DatabaseWidget::openUrl() void DatabaseWidget::openUrlForEntry(Entry* entry) { - if (!entry->url().isEmpty()) { - QDesktopServices::openUrl(entry->url()); + QString urlString = entry->resolvePlaceholders(entry->url()); + if (urlString.isEmpty()) { + return; + } + + if (urlString.startsWith("cmd://")) { + if (urlString.length() > 6) { + QProcess::startDetached(urlString.mid(6)); + } + } + else { + QUrl url = QUrl::fromUserInput(urlString); + QDesktopServices::openUrl(url); } } @@ -540,8 +554,8 @@ void DatabaseWidget::switchToView(bool accepted) delete m_newGroup; } - m_newGroup = Q_NULLPTR; - m_newParent = Q_NULLPTR; + m_newGroup = nullptr; + m_newParent = nullptr; } else if (m_newEntry) { if (accepted) { @@ -553,8 +567,8 @@ void DatabaseWidget::switchToView(bool accepted) delete m_newEntry; } - m_newEntry = Q_NULLPTR; - m_newParent = Q_NULLPTR; + m_newEntry = nullptr; + m_newParent = nullptr; } setCurrentWidget(m_mainWidget); @@ -624,9 +638,9 @@ void DatabaseWidget::openDatabase(bool accepted) // We won't need those anymore and KeePass1OpenWidget closes // the file in its dtor. delete m_databaseOpenWidget; - m_databaseOpenWidget = Q_NULLPTR; + m_databaseOpenWidget = nullptr; delete m_keepass1OpenWidget; - m_keepass1OpenWidget = Q_NULLPTR; + m_keepass1OpenWidget = nullptr; } else { if (m_databaseOpenWidget->database()) { @@ -869,7 +883,7 @@ bool DatabaseWidget::isInSearchMode() const void DatabaseWidget::clearLastGroup(Group* group) { if (group) { - m_lastGroup = Q_NULLPTR; + m_lastGroup = nullptr; m_searchWidget->hide(); } } @@ -877,8 +891,17 @@ void DatabaseWidget::clearLastGroup(Group* group) void DatabaseWidget::lock() { Q_ASSERT(currentMode() != DatabaseWidget::LockedMode); + if (isInSearchMode()) { + closeSearch(); + } + + if (m_groupView->currentGroup()) { + m_groupBeforeLock = m_groupView->currentGroup()->uuid(); + } + else { + m_groupBeforeLock = m_db->rootGroup()->uuid(); + } - m_groupBeforeLock = m_groupView->currentGroup()->uuid(); clearAllWidgets(); m_unlockDatabaseWidget->load(m_filename); setCurrentWidget(m_unlockDatabaseWidget); @@ -909,7 +932,7 @@ QStringList DatabaseWidget::customEntryAttributes() const bool DatabaseWidget::isGroupSelected() const { - return m_groupView->currentGroup() != Q_NULLPTR; + return m_groupView->currentGroup() != nullptr; } bool DatabaseWidget::currentEntryHasTitle() @@ -961,3 +984,34 @@ bool DatabaseWidget::currentEntryHasNotes() } return !currentEntry->notes().isEmpty(); } + +bool DatabaseWidget::eventFilter(QObject* object, QEvent* event) +{ + if (object == m_searchUi->searchEdit) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent* keyEvent = static_cast(event); + + if (keyEvent->matches(QKeySequence::Copy)) { + // If Control+C is pressed in the search edit when no + // text is selected, copy the password of the current + // entry. + Entry* currentEntry = m_entryView->currentEntry(); + if (currentEntry && !m_searchUi->searchEdit->hasSelectedText()) { + setClipboardTextAndMinimize(currentEntry->password()); + return true; + } + } + else if (keyEvent->matches(QKeySequence::MoveToNextLine)) { + // If Down is pressed at EOL in the search edit, move + // the focus to the entry view. + if (!m_searchUi->searchEdit->hasSelectedText() + && m_searchUi->searchEdit->cursorPosition() == m_searchUi->searchEdit->text().size()) { + m_entryView->setFocus(); + return true; + } + } + } + } + + return false; +} diff --git a/src/gui/DatabaseWidget.h b/src/gui/DatabaseWidget.h index 1ba3dd1f..38a685cc 100644 --- a/src/gui/DatabaseWidget.h +++ b/src/gui/DatabaseWidget.h @@ -21,7 +21,6 @@ #include #include -#include "core/Global.h" #include "core/Uuid.h" #include "gui/entry/EntryModel.h" @@ -59,7 +58,7 @@ public: LockedMode }; - explicit DatabaseWidget(Database* db, QWidget* parent = Q_NULLPTR); + explicit DatabaseWidget(Database* db, QWidget* parent = nullptr); ~DatabaseWidget(); Database* database(); bool dbHasKey() const; @@ -102,6 +101,9 @@ Q_SIGNALS: void splitterSizesChanged(); void entryColumnSizesChanged(); +protected: + bool eventFilter(QObject* object, QEvent* event) override; + public Q_SLOTS: void createEntry(); void cloneEntry(); diff --git a/src/gui/DatabaseWidgetStateSync.cpp b/src/gui/DatabaseWidgetStateSync.cpp index 66b8492e..430380c5 100644 --- a/src/gui/DatabaseWidgetStateSync.cpp +++ b/src/gui/DatabaseWidgetStateSync.cpp @@ -22,7 +22,7 @@ DatabaseWidgetStateSync::DatabaseWidgetStateSync(QObject* parent) : QObject(parent) - , m_activeDbWidget(Q_NULLPTR) + , m_activeDbWidget(nullptr) , m_blockUpdates(false) { m_splitterSizes = variantToIntList(config()->get("GUI/SplitterState")); diff --git a/src/gui/DatabaseWidgetStateSync.h b/src/gui/DatabaseWidgetStateSync.h index f6a87cd9..a4861179 100644 --- a/src/gui/DatabaseWidgetStateSync.h +++ b/src/gui/DatabaseWidgetStateSync.h @@ -16,8 +16,8 @@ * along with this program. If not, see . */ -#ifndef KEEPASSX_HEADERVIEWSYNC_H -#define KEEPASSX_HEADERVIEWSYNC_H +#ifndef KEEPASSX_DATABASEWIDGETSTATESYNC_H +#define KEEPASSX_DATABASEWIDGETSTATESYNC_H #include "gui/DatabaseWidget.h" @@ -26,7 +26,7 @@ class DatabaseWidgetStateSync : public QObject Q_OBJECT public: - explicit DatabaseWidgetStateSync(QObject* parent = Q_NULLPTR); + explicit DatabaseWidgetStateSync(QObject* parent = nullptr); ~DatabaseWidgetStateSync(); public Q_SLOTS: @@ -51,4 +51,4 @@ private: QList m_columnSizesSearch; }; -#endif // KEEPASSX_HEADERVIEWSYNC_H +#endif // KEEPASSX_DATABASEWIDGETSTATESYNC_H diff --git a/src/gui/DialogyWidget.h b/src/gui/DialogyWidget.h index 9dd05283..b0915a27 100644 --- a/src/gui/DialogyWidget.h +++ b/src/gui/DialogyWidget.h @@ -21,17 +21,15 @@ #include #include -#include "core/Global.h" - class DialogyWidget : public QWidget { Q_OBJECT public: - explicit DialogyWidget(QWidget* parent = Q_NULLPTR); + explicit DialogyWidget(QWidget* parent = nullptr); protected: - virtual void keyPressEvent(QKeyEvent* e) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent* e) override; private: bool clickButton(QDialogButtonBox::StandardButton standardButton); diff --git a/src/gui/DragTabBar.h b/src/gui/DragTabBar.h index 1b6005df..a6117a04 100644 --- a/src/gui/DragTabBar.h +++ b/src/gui/DragTabBar.h @@ -20,21 +20,19 @@ #include -#include "core/Global.h" - class DragTabBar : public QTabBar { Q_OBJECT public: - explicit DragTabBar(QWidget* parent = Q_NULLPTR); + explicit DragTabBar(QWidget* parent = nullptr); protected: - void dragEnterEvent(QDragEnterEvent* event) Q_DECL_OVERRIDE; - void dragMoveEvent(QDragMoveEvent* event) Q_DECL_OVERRIDE; - void dragLeaveEvent(QDragLeaveEvent* event) Q_DECL_OVERRIDE; - void dropEvent(QDropEvent* event) Q_DECL_OVERRIDE; - void tabLayoutChange() Q_DECL_OVERRIDE; + void dragEnterEvent(QDragEnterEvent* event) override; + void dragMoveEvent(QDragMoveEvent* event) override; + void dragLeaveEvent(QDragLeaveEvent* event) override; + void dropEvent(QDropEvent* event) override; + void tabLayoutChange() override; private Q_SLOTS: void dragSwitchTab(); diff --git a/src/gui/EditWidget.h b/src/gui/EditWidget.h index d27abe9b..c5f507ac 100644 --- a/src/gui/EditWidget.h +++ b/src/gui/EditWidget.h @@ -33,7 +33,7 @@ class EditWidget : public DialogyWidget Q_OBJECT public: - explicit EditWidget(QWidget* parent = Q_NULLPTR); + explicit EditWidget(QWidget* parent = nullptr); ~EditWidget(); void add(const QString& labelText, QWidget* widget); diff --git a/src/gui/EditWidgetIcons.cpp b/src/gui/EditWidgetIcons.cpp index 5ea4db73..3d3565c5 100644 --- a/src/gui/EditWidgetIcons.cpp +++ b/src/gui/EditWidgetIcons.cpp @@ -35,7 +35,7 @@ IconStruct::IconStruct() EditWidgetIcons::EditWidgetIcons(QWidget* parent) : QWidget(parent) , m_ui(new Ui::EditWidgetIcons()) - , m_database(Q_NULLPTR) + , m_database(nullptr) , m_defaultIconModel(new DefaultIconModel(this)) , m_customIconModel(new CustomIconModel(this)) { @@ -85,7 +85,7 @@ IconStruct EditWidgetIcons::save() } } - m_database = Q_NULLPTR; + m_database = nullptr; m_currentUuid = Uuid(); return iconStruct; } @@ -98,7 +98,7 @@ void EditWidgetIcons::load(Uuid currentUuid, Database* database, IconStruct icon m_database = database; m_currentUuid = currentUuid; - m_customIconModel->setIcons(database->metadata()->customIcons(), + m_customIconModel->setIcons(database->metadata()->customIconsScaledPixmaps(), database->metadata()->customIconsOrder()); Uuid iconUuid = iconStruct.uuid; @@ -133,7 +133,7 @@ void EditWidgetIcons::addCustomIcon() if (!image.isNull()) { Uuid uuid = Uuid::random(); m_database->metadata()->addCustomIconScaled(uuid, image); - m_customIconModel->setIcons(m_database->metadata()->customIcons(), + m_customIconModel->setIcons(m_database->metadata()->customIconsScaledPixmaps(), m_database->metadata()->customIconsOrder()); QModelIndex index = m_customIconModel->indexFromUuid(uuid); m_ui->customIconsView->setCurrentIndex(index); @@ -183,7 +183,7 @@ void EditWidgetIcons::removeCustomIcon() } m_database->metadata()->removeCustomIcon(iconUuid); - m_customIconModel->setIcons(m_database->metadata()->customIcons(), + m_customIconModel->setIcons(m_database->metadata()->customIconsScaledPixmaps(), m_database->metadata()->customIconsOrder()); if (m_customIconModel->rowCount() > 0) { m_ui->customIconsView->setCurrentIndex(m_customIconModel->index(0, 0)); diff --git a/src/gui/EditWidgetIcons.h b/src/gui/EditWidgetIcons.h index e18f4440..f3f3f11c 100644 --- a/src/gui/EditWidgetIcons.h +++ b/src/gui/EditWidgetIcons.h @@ -20,7 +20,6 @@ #include -#include "core/Global.h" #include "core/Uuid.h" class Database; @@ -44,7 +43,7 @@ class EditWidgetIcons : public QWidget Q_OBJECT public: - explicit EditWidgetIcons(QWidget* parent = Q_NULLPTR); + explicit EditWidgetIcons(QWidget* parent = nullptr); ~EditWidgetIcons(); IconStruct save(); diff --git a/src/gui/EditWidgetProperties.h b/src/gui/EditWidgetProperties.h index c5d0eb03..4a2c0591 100644 --- a/src/gui/EditWidgetProperties.h +++ b/src/gui/EditWidgetProperties.h @@ -20,7 +20,6 @@ #include -#include "core/Global.h" #include "core/TimeInfo.h" #include "core/Uuid.h" @@ -33,7 +32,7 @@ class EditWidgetProperties : public QWidget Q_OBJECT public: - explicit EditWidgetProperties(QWidget* parent = Q_NULLPTR); + explicit EditWidgetProperties(QWidget* parent = nullptr); ~EditWidgetProperties(); void setFields(TimeInfo timeInfo, Uuid uuid); diff --git a/src/gui/FileDialog.cpp b/src/gui/FileDialog.cpp index 25b508e5..e293db2b 100644 --- a/src/gui/FileDialog.cpp +++ b/src/gui/FileDialog.cpp @@ -19,7 +19,7 @@ #include "core/Config.h" -FileDialog* FileDialog::m_instance(Q_NULLPTR); +FileDialog* FileDialog::m_instance(nullptr); QString FileDialog::getOpenFileName(QWidget* parent, const QString& caption, QString dir, const QString& filter, QString* selectedFilter, @@ -53,7 +53,7 @@ QString FileDialog::getOpenFileName(QWidget* parent, const QString& caption, QSt QString FileDialog::getSaveFileName(QWidget* parent, const QString& caption, QString dir, const QString& filter, QString* selectedFilter, - QFileDialog::Options options) + QFileDialog::Options options, const QString& defaultExtension) { if (!m_nextFileName.isEmpty()) { QString result = m_nextFileName; @@ -65,8 +65,30 @@ QString FileDialog::getSaveFileName(QWidget* parent, const QString& caption, QSt dir = config()->get("LastDir").toString(); } - QString result = QFileDialog::getSaveFileName(parent, caption, dir, filter, - selectedFilter, options); + QString result; +#if defined(Q_OS_MAC) || defined(Q_OS_WIN) + Q_UNUSED(defaultExtension); + // the native dialogs on these platforms already append the file extension + result = QFileDialog::getSaveFileName(parent, caption, dir, filter, + selectedFilter, options); +#else + QFileDialog dialog(parent, caption, dir, filter); + dialog.setAcceptMode(QFileDialog::AcceptSave); + dialog.setFileMode(QFileDialog::AnyFile); + if (selectedFilter) { + dialog.selectNameFilter(*selectedFilter); + } + dialog.setOptions(options); + dialog.setDefaultSuffix(defaultExtension); + + QStringList results; + if (dialog.exec()) { + results = dialog.selectedFiles(); + if (!results.isEmpty()) { + result = results[0]; + } + } +#endif // on Mac OS X the focus is lost after closing the native dialog if (parent) { diff --git a/src/gui/FileDialog.h b/src/gui/FileDialog.h index e2e848aa..9f8fbb54 100644 --- a/src/gui/FileDialog.h +++ b/src/gui/FileDialog.h @@ -20,17 +20,16 @@ #include -#include "core/Global.h" - class FileDialog { public: - QString getOpenFileName(QWidget* parent = Q_NULLPTR, const QString& caption = QString(), + QString getOpenFileName(QWidget* parent = nullptr, const QString& caption = QString(), QString dir = QString(), const QString& filter = QString(), - QString* selectedFilter = Q_NULLPTR, QFileDialog::Options options = Q_NULLPTR); - QString getSaveFileName(QWidget* parent = Q_NULLPTR, const QString& caption = QString(), + QString* selectedFilter = nullptr, QFileDialog::Options options = 0); + QString getSaveFileName(QWidget* parent = nullptr, const QString& caption = QString(), QString dir = QString(), const QString& filter = QString(), - QString* selectedFilter = Q_NULLPTR, QFileDialog::Options options = Q_NULLPTR); + QString* selectedFilter = nullptr, QFileDialog::Options options = 0, + const QString& defaultExtension = QString()); /** * Sets the result of the next get* method call. diff --git a/src/gui/IconModels.cpp b/src/gui/IconModels.cpp index c169e875..1c181eae 100644 --- a/src/gui/IconModels.cpp +++ b/src/gui/IconModels.cpp @@ -54,7 +54,7 @@ CustomIconModel::CustomIconModel(QObject* parent) { } -void CustomIconModel::setIcons(const QHash& icons, const QList& iconsOrder) +void CustomIconModel::setIcons(const QHash& icons, const QList& iconsOrder) { beginResetModel(); diff --git a/src/gui/IconModels.h b/src/gui/IconModels.h index a04efa20..868ce442 100644 --- a/src/gui/IconModels.h +++ b/src/gui/IconModels.h @@ -19,9 +19,8 @@ #define KEEPASSX_ICONMODELS_H #include -#include +#include -#include "core/Global.h" #include "core/Uuid.h" class DefaultIconModel : public QAbstractListModel @@ -29,10 +28,10 @@ class DefaultIconModel : public QAbstractListModel Q_OBJECT public: - explicit DefaultIconModel(QObject* parent = Q_NULLPTR); + explicit DefaultIconModel(QObject* parent = nullptr); - int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; }; class CustomIconModel : public QAbstractListModel @@ -40,16 +39,16 @@ class CustomIconModel : public QAbstractListModel Q_OBJECT public: - explicit CustomIconModel(QObject* parent = Q_NULLPTR); + explicit CustomIconModel(QObject* parent = nullptr); - virtual int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - void setIcons(const QHash& icons, const QList& iconsOrder); + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + void setIcons(const QHash& icons, const QList& iconsOrder); Uuid uuidFromIndex(const QModelIndex& index) const; QModelIndex indexFromUuid(const Uuid& uuid) const; private: - QHash m_icons; + QHash m_icons; QList m_iconsOrder; }; diff --git a/src/gui/KeePass1OpenWidget.h b/src/gui/KeePass1OpenWidget.h index a398f9a1..203b7863 100644 --- a/src/gui/KeePass1OpenWidget.h +++ b/src/gui/KeePass1OpenWidget.h @@ -25,10 +25,10 @@ class KeePass1OpenWidget : public DatabaseOpenWidget Q_OBJECT public: - explicit KeePass1OpenWidget(QWidget* parent = Q_NULLPTR); + explicit KeePass1OpenWidget(QWidget* parent = nullptr); protected: - void openDatabase() Q_DECL_OVERRIDE; + void openDatabase() override; }; #endif // KEEPASSX_KEEPASS1OPENWIDGET_H diff --git a/src/gui/LineEdit.h b/src/gui/LineEdit.h index 2672aae7..f5f05840 100644 --- a/src/gui/LineEdit.h +++ b/src/gui/LineEdit.h @@ -22,8 +22,6 @@ #include -#include "core/Global.h" - class QToolButton; class LineEdit : public QLineEdit @@ -31,10 +29,10 @@ class LineEdit : public QLineEdit Q_OBJECT public: - explicit LineEdit(QWidget* parent = Q_NULLPTR); + explicit LineEdit(QWidget* parent = nullptr); protected: - void resizeEvent(QResizeEvent* event) Q_DECL_OVERRIDE; + void resizeEvent(QResizeEvent* event) override; private Q_SLOTS: void updateCloseButton(const QString& text); diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 01d4c08b..24e52661 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -20,14 +20,19 @@ #include #include +#include #include "autotype/AutoType.h" #include "core/Config.h" #include "core/FilePath.h" #include "core/InactivityTimer.h" #include "core/Metadata.h" +#include "format/KeePass2Writer.h" #include "gui/AboutDialog.h" #include "gui/DatabaseWidget.h" +#include "gui/DatabaseRepairWidget.h" +#include "gui/FileDialog.h" +#include "gui/MessageBox.h" #include "http/Service.h" #include "http/HttpSettings.h" @@ -69,7 +74,7 @@ const QString MainWindow::BaseWindowTitle = "KeePassX"; MainWindow::MainWindow() : m_ui(new Ui::MainWindow()) - , m_trayIcon(Q_NULLPTR) + , m_trayIcon(nullptr) { appExitCalled = false; @@ -111,7 +116,7 @@ MainWindow::MainWindow() m_inactivityTimer = new InactivityTimer(this); connect(m_inactivityTimer, SIGNAL(inactivityDetected()), - m_ui->tabWidget, SLOT(lockDatabases())); + this, SLOT(lockDatabasesAfterInactivity())); applySettingsChanges(); setShortcut(m_ui->actionDatabaseOpen, QKeySequence::Open, Qt::CTRL + Qt::Key_O); @@ -129,10 +134,9 @@ MainWindow::MainWindow() m_ui->actionEntryCopyPassword->setShortcut(Qt::CTRL + Qt::Key_C); setShortcut(m_ui->actionEntryAutoType, QKeySequence::Paste, Qt::CTRL + Qt::Key_V); m_ui->actionEntryOpenUrl->setShortcut(Qt::CTRL + Qt::Key_U); + m_ui->actionEntryCopyURL->setShortcut(Qt::CTRL + Qt::ALT + Qt::Key_U); -#ifdef Q_OS_MAC new QShortcut(Qt::CTRL + Qt::Key_M, this, SLOT(showMinimized())); -#endif m_ui->actionDatabaseNew->setIcon(filePath()->icon("actions", "document-new")); m_ui->actionDatabaseOpen->setIcon(filePath()->icon("actions", "document-open")); @@ -202,6 +206,10 @@ MainWindow::MainWindow() SLOT(changeDatabaseSettings())); connect(m_ui->actionImportKeePass1, SIGNAL(triggered()), m_ui->tabWidget, SLOT(importKeePass1Database())); + connect(m_ui->actionRepairDatabase, SIGNAL(triggered()), this, + SLOT(repairDatabase())); + connect(m_ui->actionExportCsv, SIGNAL(triggered()), m_ui->tabWidget, + SLOT(exportToCsv())); connect(m_ui->actionLockDatabases, SIGNAL(triggered()), m_ui->tabWidget, SLOT(lockDatabases())); connect(m_ui->actionQuit, SIGNAL(triggered()), SLOT(appExit())); @@ -264,6 +272,7 @@ void MainWindow::updateLastDatabasesMenu() QStringList lastDatabases = config()->get("LastDatabases", QVariant()).toStringList(); Q_FOREACH (const QString& database, lastDatabases) { QAction* action = m_ui->menuRecentDatabases->addAction(database); + action->setData(database); m_lastDatabasesActions->addAction(action); } m_ui->menuRecentDatabases->addSeparator(); @@ -294,7 +303,7 @@ void MainWindow::updateCopyAttributesMenu() void MainWindow::openRecentDatabase(QAction* action) { - openDatabase(action->text()); + openDatabase(action->data().toString()); } void MainWindow::clearLastDatabases() @@ -346,7 +355,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionEntryCopyUsername->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUsername()); m_ui->actionEntryCopyPassword->setEnabled(singleEntrySelected && dbWidget->currentEntryHasPassword()); m_ui->actionEntryCopyURL->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUrl()); - m_ui->actionEntryCopyNotes->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUrl()); + m_ui->actionEntryCopyNotes->setEnabled(singleEntrySelected && dbWidget->currentEntryHasNotes()); m_ui->menuEntryCopyAttribute->setEnabled(singleEntrySelected); m_ui->actionEntryAutoType->setEnabled(singleEntrySelected); m_ui->actionEntryOpenUrl->setEnabled(singleEntrySelected && dbWidget->currentEntryHasUrl()); @@ -359,6 +368,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionChangeDatabaseSettings->setEnabled(true); m_ui->actionDatabaseSave->setEnabled(true); m_ui->actionDatabaseSaveAs->setEnabled(true); + m_ui->actionExportCsv->setEnabled(true); break; } case DatabaseWidget::EditMode: @@ -382,6 +392,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionChangeDatabaseSettings->setEnabled(false); m_ui->actionDatabaseSave->setEnabled(false); m_ui->actionDatabaseSaveAs->setEnabled(false); + m_ui->actionExportCsv->setEnabled(false); break; default: Q_ASSERT(false); @@ -410,6 +421,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionDatabaseSaveAs->setEnabled(false); m_ui->actionDatabaseClose->setEnabled(false); + m_ui->actionExportCsv->setEnabled(false); } bool inDatabaseTabWidgetOrWelcomeWidget = inDatabaseTabWidget || inWelcomeWidget; @@ -417,6 +429,7 @@ void MainWindow::setMenuActionState(DatabaseWidget::Mode mode) m_ui->actionDatabaseOpen->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->menuRecentDatabases->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->actionImportKeePass1->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); + m_ui->actionRepairDatabase->setEnabled(inDatabaseTabWidgetOrWelcomeWidget); m_ui->actionLockDatabases->setEnabled(m_ui->tabWidget->hasLockableDatabases()); } @@ -504,13 +517,14 @@ void MainWindow::closeEvent(QCloseEvent* event) } } -void MainWindow::changeEvent(QEvent *event) +void MainWindow::changeEvent(QEvent* event) { if ((event->type() == QEvent::WindowStateChange) && isMinimized() - && isTrayIconEnabled() && config()->get("GUI/MinimizeToTray").toBool()) + && isTrayIconEnabled() && m_trayIcon && m_trayIcon->isVisible() + && config()->get("GUI/MinimizeToTray").toBool()) { event->ignore(); - hide(); + QTimer::singleShot(0, this, SLOT(hide())); } else { QMainWindow::changeEvent(event); @@ -572,8 +586,9 @@ void MainWindow::updateTrayIcon() } else { if (m_trayIcon) { + m_trayIcon->hide(); delete m_trayIcon; - m_trayIcon = Q_NULLPTR; + m_trayIcon = nullptr; } } } @@ -635,18 +650,65 @@ void MainWindow::trayIconTriggered(QSystemTrayIcon::ActivationReason reason) void MainWindow::toggleWindow() { - if (QApplication::activeWindow() == this) { + if ((QApplication::activeWindow() == this) && isVisible() && !isMinimized()) { hide(); } else { + ensurePolished(); + setWindowState(windowState() & ~Qt::WindowMinimized); show(); raise(); activateWindow(); } } +void MainWindow::lockDatabasesAfterInactivity() +{ + // ignore event if a modal dialog is open (such as a message box or file dialog) + if (QApplication::activeModalWidget()) { + return; + } + + m_ui->tabWidget->lockDatabases(); +} + +void MainWindow::repairDatabase() +{ + QString filter = QString("%1 (*.kdbx);;%2 (*)").arg(tr("KeePass 2 Database"), tr("All files")); + QString fileName = fileDialog()->getOpenFileName(this, tr("Open database"), QString(), + filter); + if (fileName.isEmpty()) { + return; + } + + QScopedPointer dialog(new QDialog(this)); + DatabaseRepairWidget* dbRepairWidget = new DatabaseRepairWidget(dialog.data()); + connect(dbRepairWidget, SIGNAL(success()), dialog.data(), SLOT(accept())); + connect(dbRepairWidget, SIGNAL(error()), dialog.data(), SLOT(reject())); + dbRepairWidget->load(fileName); + if (dialog->exec() == QDialog::Accepted && dbRepairWidget->database()) { + QString saveFileName = fileDialog()->getSaveFileName(this, tr("Save repaired database"), QString(), + tr("KeePass 2 Database").append(" (*.kdbx)"), + nullptr, 0, "kdbx"); + + if (!saveFileName.isEmpty()) { + KeePass2Writer writer; + writer.writeDatabase(saveFileName, dbRepairWidget->database()); + if (writer.hasError()) { + MessageBox::critical(this, tr("Error"), tr("Writing the database failed.") + "\n\n" + + writer.errorString()); + } + } + } +} + bool MainWindow::isTrayIconEnabled() const { +#ifdef Q_OS_MAC + // systray not useful on OS X + return false; +#else return config()->get("GUI/ShowTrayIcon").toBool() && QSystemTrayIcon::isSystemTrayAvailable(); +#endif } diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 4d2ebb8c..02019312 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -45,8 +45,8 @@ public Q_SLOTS: const QString& keyFile = QString()); protected: - void closeEvent(QCloseEvent* event) Q_DECL_OVERRIDE; - void changeEvent(QEvent* event) Q_DECL_OVERRIDE; + void closeEvent(QCloseEvent* event) override; + void changeEvent(QEvent* event) override; private Q_SLOTS: void setMenuActionState(DatabaseWidget::Mode mode = DatabaseWidget::None); @@ -67,6 +67,8 @@ private Q_SLOTS: void trayIconTriggered(QSystemTrayIcon::ActivationReason reason); void toggleWindow(); void appExit(); + void lockDatabasesAfterInactivity(); + void repairDatabase(); private: static void setShortcut(QAction* action, QKeySequence::StandardKey standard, int fallback = 0); diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui index eb7001cd..66c040e9 100644 --- a/src/gui/MainWindow.ui +++ b/src/gui/MainWindow.ui @@ -120,6 +120,8 @@ + + @@ -141,8 +143,6 @@ Copy attribute to clipboard - - @@ -151,6 +151,8 @@ + + @@ -343,7 +345,7 @@ false - Username + Copy username Copy username to clipboard @@ -354,7 +356,7 @@ false - Password + Copy password Copy password to clipboard @@ -413,6 +415,19 @@ Notes + + + false + + + Export to CSV file + + + + + Repair database + + diff --git a/src/gui/MessageBox.h b/src/gui/MessageBox.h index abb12c07..1ea4022c 100644 --- a/src/gui/MessageBox.h +++ b/src/gui/MessageBox.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class MessageBox { public: diff --git a/src/gui/PasswordComboBox.cpp b/src/gui/PasswordComboBox.cpp index f11311a9..e1218505 100644 --- a/src/gui/PasswordComboBox.cpp +++ b/src/gui/PasswordComboBox.cpp @@ -24,7 +24,7 @@ PasswordComboBox::PasswordComboBox(QWidget* parent) : QComboBox(parent) - , m_generator(Q_NULLPTR) + , m_generator(nullptr) , m_alternatives(10) { setEditable(true); @@ -51,7 +51,6 @@ void PasswordComboBox::setEcho(bool echo) #else setStyleSheet("QComboBox { font-family: monospace,Courier; }"); #endif - } else { // clear items so the combobox indicates that no popup menu is available diff --git a/src/gui/PasswordComboBox.h b/src/gui/PasswordComboBox.h index 69ce1523..7c54e278 100644 --- a/src/gui/PasswordComboBox.h +++ b/src/gui/PasswordComboBox.h @@ -21,8 +21,6 @@ #include -#include "core/Global.h" - class PasswordGenerator; class PasswordComboBox : public QComboBox @@ -30,7 +28,7 @@ class PasswordComboBox : public QComboBox Q_OBJECT public: - explicit PasswordComboBox(QWidget* parent = Q_NULLPTR); + explicit PasswordComboBox(QWidget* parent = nullptr); ~PasswordComboBox(); void setGenerator(PasswordGenerator* generator); diff --git a/src/gui/PasswordEdit.cpp b/src/gui/PasswordEdit.cpp index b68eef68..e5bbf6b3 100644 --- a/src/gui/PasswordEdit.cpp +++ b/src/gui/PasswordEdit.cpp @@ -17,14 +17,12 @@ #include "PasswordEdit.h" -#include "core/Global.h" - const QColor PasswordEdit::CorrectSoFarColor = QColor(255, 205, 15); const QColor PasswordEdit::ErrorColor = QColor(255, 125, 125); PasswordEdit::PasswordEdit(QWidget* parent) : QLineEdit(parent) - , m_basePasswordEdit(Q_NULLPTR) + , m_basePasswordEdit(nullptr) { } diff --git a/src/gui/PasswordEdit.h b/src/gui/PasswordEdit.h index cfb4a764..7ce49087 100644 --- a/src/gui/PasswordEdit.h +++ b/src/gui/PasswordEdit.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class PasswordEdit : public QLineEdit { Q_OBJECT @@ -30,7 +28,7 @@ public: static const QColor CorrectSoFarColor; static const QColor ErrorColor; - explicit PasswordEdit(QWidget* parent = Q_NULLPTR); + explicit PasswordEdit(QWidget* parent = nullptr); void enableVerifyMode(PasswordEdit* baseEdit); public Q_SLOTS: diff --git a/src/gui/PasswordGeneratorWidget.h b/src/gui/PasswordGeneratorWidget.h index 96f3f602..cfb21bbe 100644 --- a/src/gui/PasswordGeneratorWidget.h +++ b/src/gui/PasswordGeneratorWidget.h @@ -21,7 +21,6 @@ #include #include -#include "core/Global.h" #include "core/PasswordGenerator.h" namespace Ui { @@ -35,7 +34,7 @@ class PasswordGeneratorWidget : public QWidget Q_OBJECT public: - explicit PasswordGeneratorWidget(QWidget* parent = Q_NULLPTR); + explicit PasswordGeneratorWidget(QWidget* parent = nullptr); ~PasswordGeneratorWidget(); void loadSettings(); void reset(); diff --git a/src/gui/SettingsWidget.cpp b/src/gui/SettingsWidget.cpp index d605b031..e0db8134 100644 --- a/src/gui/SettingsWidget.cpp +++ b/src/gui/SettingsWidget.cpp @@ -66,6 +66,11 @@ SettingsWidget::SettingsWidget(QWidget* parent) m_generalUi->autoTypeShortcutWidget->setVisible(autoType()->isAvailable()); m_generalUi->autoTypeShortcutLabel->setVisible(autoType()->isAvailable()); +#ifdef Q_OS_MAC + // systray not useful on OS X + m_generalUi->systrayShowCheckBox->setVisible(false); + m_generalUi->systrayMinimizeToTrayCheckBox->setVisible(false); +#endif connect(this, SIGNAL(accepted()), SLOT(saveSettings())); connect(this, SIGNAL(rejected()), SLOT(reject())); diff --git a/src/gui/SettingsWidget.h b/src/gui/SettingsWidget.h index 286c2800..23b444d0 100644 --- a/src/gui/SettingsWidget.h +++ b/src/gui/SettingsWidget.h @@ -39,7 +39,7 @@ class SettingsWidget : public EditWidget Q_OBJECT public: - explicit SettingsWidget(QWidget* parent = Q_NULLPTR); + explicit SettingsWidget(QWidget* parent = nullptr); ~SettingsWidget(); void addSettingsPage(ISettingsPage * page); void loadSettings(); diff --git a/src/gui/SortFilterHideProxyModel.cpp b/src/gui/SortFilterHideProxyModel.cpp index 09023610..0193d959 100644 --- a/src/gui/SortFilterHideProxyModel.cpp +++ b/src/gui/SortFilterHideProxyModel.cpp @@ -22,6 +22,11 @@ SortFilterHideProxyModel::SortFilterHideProxyModel(QObject* parent) { } +Qt::DropActions SortFilterHideProxyModel::supportedDragActions() const +{ + return sourceModel()->supportedDragActions(); +} + void SortFilterHideProxyModel::hideColumn(int column, bool hide) { m_hiddenColumns.resize(column + 1); diff --git a/src/gui/SortFilterHideProxyModel.h b/src/gui/SortFilterHideProxyModel.h index a6f1e712..58d9ff70 100644 --- a/src/gui/SortFilterHideProxyModel.h +++ b/src/gui/SortFilterHideProxyModel.h @@ -21,18 +21,17 @@ #include #include -#include "core/Global.h" - class SortFilterHideProxyModel : public QSortFilterProxyModel { Q_OBJECT public: - explicit SortFilterHideProxyModel(QObject* parent = Q_NULLPTR); + explicit SortFilterHideProxyModel(QObject* parent = nullptr); + Qt::DropActions supportedDragActions() const override; void hideColumn(int column, bool hide); protected: - bool filterAcceptsColumn(int sourceColumn, const QModelIndex& sourceParent) const Q_DECL_OVERRIDE; + bool filterAcceptsColumn(int sourceColumn, const QModelIndex& sourceParent) const override; private: QBitArray m_hiddenColumns; diff --git a/src/gui/UnlockDatabaseWidget.cpp b/src/gui/UnlockDatabaseWidget.cpp index 944198be..a005d0e6 100644 --- a/src/gui/UnlockDatabaseWidget.cpp +++ b/src/gui/UnlockDatabaseWidget.cpp @@ -33,5 +33,6 @@ void UnlockDatabaseWidget::clearForms() m_ui->comboKeyFile->clear(); m_ui->checkPassword->setChecked(false); m_ui->checkKeyFile->setChecked(false); - m_db = Q_NULLPTR; + m_ui->buttonTogglePassword->setChecked(false); + m_db = nullptr; } diff --git a/src/gui/UnlockDatabaseWidget.h b/src/gui/UnlockDatabaseWidget.h index 052578b7..adb5efbb 100644 --- a/src/gui/UnlockDatabaseWidget.h +++ b/src/gui/UnlockDatabaseWidget.h @@ -25,7 +25,7 @@ class UnlockDatabaseWidget : public DatabaseOpenWidget Q_OBJECT public: - explicit UnlockDatabaseWidget(QWidget* parent = Q_NULLPTR); + explicit UnlockDatabaseWidget(QWidget* parent = nullptr); void clearForms(); }; diff --git a/src/gui/WelcomeWidget.h b/src/gui/WelcomeWidget.h index 983aaa04..80a0dde1 100644 --- a/src/gui/WelcomeWidget.h +++ b/src/gui/WelcomeWidget.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - namespace Ui { class WelcomeWidget; } @@ -31,7 +29,7 @@ class WelcomeWidget : public QWidget Q_OBJECT public: - explicit WelcomeWidget(QWidget* parent = Q_NULLPTR); + explicit WelcomeWidget(QWidget* parent = nullptr); ~WelcomeWidget(); private: diff --git a/src/gui/entry/AutoTypeAssociationsModel.cpp b/src/gui/entry/AutoTypeAssociationsModel.cpp index 6d6dc975..49f6786b 100644 --- a/src/gui/entry/AutoTypeAssociationsModel.cpp +++ b/src/gui/entry/AutoTypeAssociationsModel.cpp @@ -19,7 +19,7 @@ AutoTypeAssociationsModel::AutoTypeAssociationsModel(QObject* parent) : QAbstractListModel(parent) - , m_autoTypeAssociations(Q_NULLPTR) + , m_autoTypeAssociations(nullptr) { } diff --git a/src/gui/entry/AutoTypeAssociationsModel.h b/src/gui/entry/AutoTypeAssociationsModel.h index ecb4247b..c75168c3 100644 --- a/src/gui/entry/AutoTypeAssociationsModel.h +++ b/src/gui/entry/AutoTypeAssociationsModel.h @@ -29,12 +29,12 @@ class AutoTypeAssociationsModel : public QAbstractListModel Q_OBJECT public: - explicit AutoTypeAssociationsModel(QObject* parent = Q_NULLPTR); + explicit AutoTypeAssociationsModel(QObject* parent = nullptr); void setAutoTypeAssociations(AutoTypeAssociations* autoTypeAssociations); - int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; public Q_SLOTS: void associationChange(int i); diff --git a/src/gui/entry/EditEntryWidget.cpp b/src/gui/entry/EditEntryWidget.cpp index beeda2ab..00d510cf 100644 --- a/src/gui/entry/EditEntryWidget.cpp +++ b/src/gui/entry/EditEntryWidget.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -45,7 +46,7 @@ EditEntryWidget::EditEntryWidget(QWidget* parent) : EditWidget(parent) - , m_entry(Q_NULLPTR) + , m_entry(nullptr) , m_mainUi(new Ui::EditEntryWidgetMain()) , m_advancedUi(new Ui::EditEntryWidgetAdvanced()) , m_autoTypeUi(new Ui::EditEntryWidgetAutoType()) @@ -232,7 +233,7 @@ void EditEntryWidget::useExpiryPreset(QAction* action) { m_mainUi->expireCheck->setChecked(true); TimeDelta delta = action->data().value(); - QDateTime now = Tools::currentDateTimeUtc().toLocalTime(); + QDateTime now = QDateTime::currentDateTime(); QDateTime expiryDateTime = now + delta; m_mainUi->expireDatePicker->setDateTime(expiryDateTime); } @@ -294,6 +295,7 @@ void EditEntryWidget::setForms(const Entry* entry, bool restore) m_mainUi->expireDatePicker->setReadOnly(m_history); m_mainUi->notesEdit->setReadOnly(m_history); m_mainUi->tooglePasswordGeneratorButton->setChecked(false); + m_mainUi->tooglePasswordGeneratorButton->setDisabled(m_history); m_mainUi->passwordGenerator->reset(); m_advancedUi->addAttachmentButton->setEnabled(!m_history); updateAttachmentButtonsEnabled(m_advancedUi->attachmentsView->currentIndex()); @@ -476,8 +478,8 @@ void EditEntryWidget::cancel() void EditEntryWidget::clear() { - m_entry = Q_NULLPTR; - m_database = Q_NULLPTR; + m_entry = nullptr; + m_database = nullptr; m_entryAttributes->clear(); m_entryAttachments->clear(); m_autoTypeAssoc->clear(); @@ -589,7 +591,7 @@ void EditEntryWidget::insertAttachment() QString defaultDir = config()->get("LastAttachmentDir").toString(); if (defaultDir.isEmpty() || !QDir(defaultDir).exists()) { - defaultDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); + defaultDir = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).value(0); } QString filename = fileDialog()->getOpenFileName(this, tr("Select file"), defaultDir); if (filename.isEmpty() || !QFile::exists(filename)) { @@ -623,7 +625,7 @@ void EditEntryWidget::saveCurrentAttachment() QString filename = m_attachmentsModel->keyByIndex(index); QString defaultDirName = config()->get("LastAttachmentDir").toString(); if (defaultDirName.isEmpty() || !QDir(defaultDirName).exists()) { - defaultDirName = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); + defaultDirName = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); } QDir dir(defaultDirName); QString savePath = fileDialog()->getSaveFileName(this, tr("Save attachment"), @@ -671,6 +673,14 @@ void EditEntryWidget::openAttachment(const QModelIndex& index) return; } + if (!file->flush()) { + MessageBox::warning(this, tr("Error"), + tr("Unable to save the attachment:\n").append(file->errorString())); + return; + } + + file->close(); + QDesktopServices::openUrl(QUrl::fromLocalFile(file->fileName())); } diff --git a/src/gui/entry/EditEntryWidget.h b/src/gui/entry/EditEntryWidget.h index 03811bf8..3c66b2a5 100644 --- a/src/gui/entry/EditEntryWidget.h +++ b/src/gui/entry/EditEntryWidget.h @@ -52,7 +52,7 @@ class EditEntryWidget : public EditWidget Q_OBJECT public: - explicit EditEntryWidget(QWidget* parent = Q_NULLPTR); + explicit EditEntryWidget(QWidget* parent = nullptr); ~EditEntryWidget(); void loadEntry(Entry* entry, bool create, bool history, const QString& parentName, diff --git a/src/gui/entry/EditEntryWidgetMain.ui b/src/gui/entry/EditEntryWidgetMain.ui index 82c9a3c3..b902bc72 100644 --- a/src/gui/entry/EditEntryWidgetMain.ui +++ b/src/gui/entry/EditEntryWidgetMain.ui @@ -164,8 +164,8 @@ titleEdit usernameEdit passwordEdit - togglePasswordButton passwordRepeatEdit + togglePasswordButton tooglePasswordGeneratorButton urlEdit expireCheck diff --git a/src/gui/entry/EntryAttachmentsModel.cpp b/src/gui/entry/EntryAttachmentsModel.cpp index e072d177..39ed69f1 100644 --- a/src/gui/entry/EntryAttachmentsModel.cpp +++ b/src/gui/entry/EntryAttachmentsModel.cpp @@ -20,9 +20,11 @@ #include "core/Entry.h" #include "core/Tools.h" +#include + EntryAttachmentsModel::EntryAttachmentsModel(QObject* parent) : QAbstractListModel(parent) - , m_entryAttachments(Q_NULLPTR) + , m_entryAttachments(nullptr) { } @@ -102,7 +104,7 @@ void EntryAttachmentsModel::attachmentAboutToAdd(const QString& key) { QList rows = m_entryAttachments->keys(); rows.append(key); - qSort(rows); + std::sort(rows.begin(), rows.end()); int row = rows.indexOf(key); beginInsertRows(QModelIndex(), row, row); } diff --git a/src/gui/entry/EntryAttachmentsModel.h b/src/gui/entry/EntryAttachmentsModel.h index 177cde06..c2e238ae 100644 --- a/src/gui/entry/EntryAttachmentsModel.h +++ b/src/gui/entry/EntryAttachmentsModel.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class EntryAttachments; class EntryAttachmentsModel : public QAbstractListModel @@ -29,11 +27,11 @@ class EntryAttachmentsModel : public QAbstractListModel Q_OBJECT public: - explicit EntryAttachmentsModel(QObject* parent = Q_NULLPTR); + explicit EntryAttachmentsModel(QObject* parent = nullptr); void setEntryAttachments(EntryAttachments* entry); - int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; QString keyByIndex(const QModelIndex& index) const; private Q_SLOTS: diff --git a/src/gui/entry/EntryAttributesModel.cpp b/src/gui/entry/EntryAttributesModel.cpp index f73a2d2e..297740c3 100644 --- a/src/gui/entry/EntryAttributesModel.cpp +++ b/src/gui/entry/EntryAttributesModel.cpp @@ -20,9 +20,11 @@ #include "core/Entry.h" #include "core/Tools.h" +#include + EntryAttributesModel::EntryAttributesModel(QObject* parent) : QAbstractListModel(parent) - , m_entryAttributes(Q_NULLPTR) + , m_entryAttributes(nullptr) , m_nextRenameDataChange(false) { } @@ -152,7 +154,7 @@ void EntryAttributesModel::attributeAboutToAdd(const QString& key) { QList rows = m_attributes; rows.append(key); - qSort(rows); + std::sort(rows.begin(), rows.end()); int row = rows.indexOf(key); beginInsertRows(QModelIndex(), row, row); } @@ -182,7 +184,7 @@ void EntryAttributesModel::attributeAboutToRename(const QString& oldKey, const Q QList rows = m_attributes; rows.removeOne(oldKey); rows.append(newKey); - qSort(rows); + std::sort(rows.begin(), rows.end()); int newRow = rows.indexOf(newKey); if (newRow > oldRow) { newRow++; diff --git a/src/gui/entry/EntryAttributesModel.h b/src/gui/entry/EntryAttributesModel.h index f6ac6514..1eec8bff 100644 --- a/src/gui/entry/EntryAttributesModel.h +++ b/src/gui/entry/EntryAttributesModel.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class EntryAttributes; class EntryAttributesModel : public QAbstractListModel @@ -29,14 +27,14 @@ class EntryAttributesModel : public QAbstractListModel Q_OBJECT public: - explicit EntryAttributesModel(QObject* parent = Q_NULLPTR); + explicit EntryAttributesModel(QObject* parent = nullptr); void setEntryAttributes(EntryAttributes* entryAttributes); - int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) Q_DECL_OVERRIDE; - Qt::ItemFlags flags(const QModelIndex& index) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override; + Qt::ItemFlags flags(const QModelIndex& index) const override; QModelIndex indexByKey(const QString& key) const; QString keyByIndex(const QModelIndex& index) const; diff --git a/src/gui/entry/EntryHistoryModel.h b/src/gui/entry/EntryHistoryModel.h index 6c8073ac..a7434e01 100644 --- a/src/gui/entry/EntryHistoryModel.h +++ b/src/gui/entry/EntryHistoryModel.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class Entry; class EntryHistoryModel : public QAbstractTableModel @@ -29,13 +27,13 @@ class EntryHistoryModel : public QAbstractTableModel Q_OBJECT public: - explicit EntryHistoryModel(QObject* parent = Q_NULLPTR); + explicit EntryHistoryModel(QObject* parent = nullptr); Entry* entryFromIndex(const QModelIndex& index) const; - int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role) const override; void setEntries(const QList& entries); void clear(); diff --git a/src/gui/entry/EntryModel.cpp b/src/gui/entry/EntryModel.cpp index 7ee1df8f..efb64dea 100644 --- a/src/gui/entry/EntryModel.cpp +++ b/src/gui/entry/EntryModel.cpp @@ -27,9 +27,8 @@ EntryModel::EntryModel(QObject* parent) : QAbstractTableModel(parent) - , m_group(Q_NULLPTR) + , m_group(nullptr) { - setSupportedDragActions(Qt::MoveAction | Qt::CopyAction); } Entry* EntryModel::entryFromIndex(const QModelIndex& index) const @@ -72,7 +71,7 @@ void EntryModel::setEntryList(const QList& entries) severConnections(); - m_group = Q_NULLPTR; + m_group = nullptr; m_allGroups.clear(); m_entries = entries; m_orgEntries = entries; @@ -146,7 +145,7 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const switch (index.column()) { case ParentGroup: if (entry->group()) { - return entry->group()->iconPixmap(); + return entry->group()->iconScaledPixmap(); } break; case Title: @@ -154,7 +153,7 @@ QVariant EntryModel::data(const QModelIndex& index, int role) const return databaseIcons()->iconPixmap(DatabaseIcons::ExpiredIconIndex); } else { - return entry->iconPixmap(); + return entry->iconScaledPixmap(); } } } @@ -191,6 +190,11 @@ Qt::DropActions EntryModel::supportedDropActions() const return 0; } +Qt::DropActions EntryModel::supportedDragActions() const +{ + return (Qt::MoveAction | Qt::CopyAction); +} + Qt::ItemFlags EntryModel::flags(const QModelIndex& modelIndex) const { if (!modelIndex.isValid()) { @@ -211,7 +215,7 @@ QStringList EntryModel::mimeTypes() const QMimeData* EntryModel::mimeData(const QModelIndexList& indexes) const { if (indexes.isEmpty()) { - return Q_NULLPTR; + return nullptr; } QMimeData* data = new QMimeData(); @@ -236,10 +240,10 @@ QMimeData* EntryModel::mimeData(const QModelIndexList& indexes) const if (seenEntries.isEmpty()) { delete data; - return Q_NULLPTR; + return nullptr; } else { - data->setData(mimeTypes().first(), encoded); + data->setData(mimeTypes().at(0), encoded); return data; } } @@ -294,11 +298,11 @@ void EntryModel::entryDataChanged(Entry* entry) void EntryModel::severConnections() { if (m_group) { - disconnect(m_group, Q_NULLPTR, this, Q_NULLPTR); + disconnect(m_group, nullptr, this, nullptr); } Q_FOREACH (const Group* group, m_allGroups) { - disconnect(group, Q_NULLPTR, this, Q_NULLPTR); + disconnect(group, nullptr, this, nullptr); } } diff --git a/src/gui/entry/EntryModel.h b/src/gui/entry/EntryModel.h index 20bcad99..0183c47b 100644 --- a/src/gui/entry/EntryModel.h +++ b/src/gui/entry/EntryModel.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class Entry; class Group; @@ -38,18 +36,19 @@ public: Url = 3 }; - explicit EntryModel(QObject* parent = Q_NULLPTR); + explicit EntryModel(QObject* parent = nullptr); Entry* entryFromIndex(const QModelIndex& index) const; QModelIndex indexFromEntry(Entry* entry) const; - int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - int columnCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE; - Qt::ItemFlags flags(const QModelIndex& modelIndex) const Q_DECL_OVERRIDE; - QStringList mimeTypes() const Q_DECL_OVERRIDE; - QMimeData* mimeData(const QModelIndexList& indexes) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + Qt::DropActions supportedDropActions() const override; + Qt::DropActions supportedDragActions() const override; + Qt::ItemFlags flags(const QModelIndex& modelIndex) const override; + QStringList mimeTypes() const override; + QMimeData* mimeData(const QModelIndexList& indexes) const override; void setEntryList(const QList& entries); diff --git a/src/gui/entry/EntryView.cpp b/src/gui/entry/EntryView.cpp index cd2c6fba..1c900a57 100644 --- a/src/gui/entry/EntryView.cpp +++ b/src/gui/entry/EntryView.cpp @@ -32,7 +32,6 @@ EntryView::EntryView(QWidget* parent) m_sortModel->setDynamicSortFilter(true); m_sortModel->setSortLocaleAware(true); m_sortModel->setSortCaseSensitivity(Qt::CaseInsensitive); - m_sortModel->setSupportedDragActions(m_model->supportedDragActions()); QTreeView::setModel(m_sortModel); setUniformRowHeights(true); @@ -75,7 +74,7 @@ void EntryView::setEntryList(const QList& entries) void EntryView::setFirstEntryActive() { - if(m_model->rowCount() > 0) { + if (m_model->rowCount() > 0) { QModelIndex index = m_sortModel->mapToSource(m_sortModel->index(0, 0)); setCurrentEntry(m_model->entryFromIndex(index)); } @@ -109,7 +108,7 @@ Entry* EntryView::currentEntry() return m_model->entryFromIndex(m_sortModel->mapToSource(list.first())); } else { - return Q_NULLPTR; + return nullptr; } } @@ -130,7 +129,7 @@ Entry* EntryView::entryFromIndex(const QModelIndex& index) return m_model->entryFromIndex(m_sortModel->mapToSource(index)); } else { - return Q_NULLPTR; + return nullptr; } } diff --git a/src/gui/entry/EntryView.h b/src/gui/entry/EntryView.h index c11d0417..fb9e3566 100644 --- a/src/gui/entry/EntryView.h +++ b/src/gui/entry/EntryView.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - #include "gui/entry/EntryModel.h" class Entry; @@ -34,8 +32,8 @@ class EntryView : public QTreeView Q_OBJECT public: - explicit EntryView(QWidget* parent = Q_NULLPTR); - void setModel(QAbstractItemModel* model) Q_DECL_OVERRIDE; + explicit EntryView(QWidget* parent = nullptr); + void setModel(QAbstractItemModel* model) override; Entry* currentEntry(); void setCurrentEntry(Entry* entry); Entry* entryFromIndex(const QModelIndex& index); @@ -52,7 +50,7 @@ Q_SIGNALS: void entrySelectionChanged(); protected: - void keyPressEvent(QKeyEvent* event) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent* event) override; private Q_SLOTS: void emitEntryActivated(const QModelIndex& index); diff --git a/src/gui/group/EditGroupWidget.cpp b/src/gui/group/EditGroupWidget.cpp index ebe5cb97..7fdec89a 100644 --- a/src/gui/group/EditGroupWidget.cpp +++ b/src/gui/group/EditGroupWidget.cpp @@ -28,8 +28,8 @@ EditGroupWidget::EditGroupWidget(QWidget* parent) , m_editGroupWidgetMain(new QWidget()) , m_editGroupWidgetIcons(new EditWidgetIcons()) , m_editWidgetProperties(new EditWidgetProperties()) - , m_group(Q_NULLPTR) - , m_database(Q_NULLPTR) + , m_group(nullptr) + , m_database(nullptr) { m_mainUi->setupUi(m_editGroupWidgetMain); @@ -142,8 +142,8 @@ void EditGroupWidget::cancel() void EditGroupWidget::clear() { - m_group = Q_NULLPTR; - m_database = Q_NULLPTR; + m_group = nullptr; + m_database = nullptr; } void EditGroupWidget::addTriStateItems(QComboBox* comboBox, bool inheritDefault) diff --git a/src/gui/group/EditGroupWidget.h b/src/gui/group/EditGroupWidget.h index c6d91a56..94ad891d 100644 --- a/src/gui/group/EditGroupWidget.h +++ b/src/gui/group/EditGroupWidget.h @@ -37,7 +37,7 @@ class EditGroupWidget : public EditWidget Q_OBJECT public: - explicit EditGroupWidget(QWidget* parent = Q_NULLPTR); + explicit EditGroupWidget(QWidget* parent = nullptr); ~EditGroupWidget(); void loadGroup(Group* group, bool create, Database* database); diff --git a/src/gui/group/GroupModel.cpp b/src/gui/group/GroupModel.cpp index b33a5ff5..fc6d83ea 100644 --- a/src/gui/group/GroupModel.cpp +++ b/src/gui/group/GroupModel.cpp @@ -28,7 +28,7 @@ GroupModel::GroupModel(Database* db, QObject* parent) : QAbstractItemModel(parent) - , m_db(Q_NULLPTR) + , m_db(nullptr) { changeDatabase(db); } @@ -136,7 +136,7 @@ QVariant GroupModel::data(const QModelIndex& index, int role) const return databaseIcons()->iconPixmap(DatabaseIcons::ExpiredIconIndex); } else { - return group->iconPixmap(); + return group->iconScaledPixmap(); } } else if (role == Qt::FontRole) { @@ -329,7 +329,7 @@ QStringList GroupModel::mimeTypes() const QMimeData* GroupModel::mimeData(const QModelIndexList& indexes) const { if (indexes.isEmpty()) { - return Q_NULLPTR; + return nullptr; } QMimeData* data = new QMimeData(); @@ -354,10 +354,10 @@ QMimeData* GroupModel::mimeData(const QModelIndexList& indexes) const if (seenGroups.isEmpty()) { delete data; - return Q_NULLPTR; + return nullptr; } else { - data->setData(mimeTypes().first(), encoded); + data->setData(mimeTypes().at(0), encoded); return data; } } diff --git a/src/gui/group/GroupModel.h b/src/gui/group/GroupModel.h index 173ea3a2..0ef0ba99 100644 --- a/src/gui/group/GroupModel.h +++ b/src/gui/group/GroupModel.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class Database; class Group; @@ -30,23 +28,23 @@ class GroupModel : public QAbstractItemModel Q_OBJECT public: - explicit GroupModel(Database* db, QObject* parent = Q_NULLPTR); + explicit GroupModel(Database* db, QObject* parent = nullptr); void changeDatabase(Database* newDb); QModelIndex index(Group* group) const; Group* groupFromIndex(const QModelIndex& index) const; - int rowCount(const QModelIndex& parent = QModelIndex()) const; - int columnCount(const QModelIndex& parent = QModelIndex()) const; - QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; - QModelIndex parent(const QModelIndex& index) const Q_DECL_OVERRIDE; - QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; - Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE; - Qt::ItemFlags flags(const QModelIndex& modelIndex) const Q_DECL_OVERRIDE; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex& index) const override; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + Qt::DropActions supportedDropActions() const override; + Qt::ItemFlags flags(const QModelIndex& modelIndex) const override; bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, - const QModelIndex& parent) Q_DECL_OVERRIDE; - QStringList mimeTypes() const Q_DECL_OVERRIDE; - QMimeData* mimeData(const QModelIndexList& indexes) const Q_DECL_OVERRIDE; + const QModelIndex& parent) override; + QStringList mimeTypes() const override; + QMimeData* mimeData(const QModelIndexList& indexes) const override; private: QModelIndex parent(Group* group) const; diff --git a/src/gui/group/GroupView.cpp b/src/gui/group/GroupView.cpp index 3c936622..1f94dc0f 100644 --- a/src/gui/group/GroupView.cpp +++ b/src/gui/group/GroupView.cpp @@ -19,6 +19,7 @@ #include #include +#include #include "core/Database.h" #include "core/Group.h" @@ -74,7 +75,7 @@ void GroupView::dragMoveEvent(QDragMoveEvent* event) Group* GroupView::currentGroup() { if (currentIndex() == QModelIndex()) { - return Q_NULLPTR; + return nullptr; } else { return m_model->groupFromIndex(currentIndex()); diff --git a/src/gui/group/GroupView.h b/src/gui/group/GroupView.h index 98073f63..69ca8281 100644 --- a/src/gui/group/GroupView.h +++ b/src/gui/group/GroupView.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class Database; class Group; class GroupModel; @@ -31,9 +29,9 @@ class GroupView : public QTreeView Q_OBJECT public: - explicit GroupView(Database* db, QWidget* parent = Q_NULLPTR); + explicit GroupView(Database* db, QWidget* parent = nullptr); void changeDatabase(Database* newDb); - void setModel(QAbstractItemModel* model) Q_DECL_OVERRIDE; + void setModel(QAbstractItemModel* model) override; Group* currentGroup(); void setCurrentGroup(Group* group); void expandGroup(Group* group, bool expand = true); @@ -49,7 +47,7 @@ private Q_SLOTS: void modelReset(); protected: - void dragMoveEvent(QDragMoveEvent* event); + void dragMoveEvent(QDragMoveEvent* event) override; private: void recInitExpanded(Group* group); diff --git a/src/keys/CompositeKey.cpp b/src/keys/CompositeKey.cpp index a0f2373c..d38f466f 100644 --- a/src/keys/CompositeKey.cpp +++ b/src/keys/CompositeKey.cpp @@ -18,8 +18,8 @@ #include "CompositeKey.h" #include "CompositeKey_p.h" -#include -#include +#include +#include #include "crypto/CryptoHash.h" #include "crypto/SymmetricCipher.h" @@ -94,7 +94,8 @@ QByteArray CompositeKey::transform(const QByteArray& seed, quint64 rounds, QByteArray key = rawKey(); - QFuture future = QtConcurrent::run(transformKeyRaw, key.left(16), seed, rounds, &okLeft, &errorStringLeft); + QFuture future = QtConcurrent::run(transformKeyRaw, key.left(16), seed, rounds, + &okLeft, &errorStringLeft); QByteArray result2 = transformKeyRaw(key.right(16), seed, rounds, &okRight, &errorStringRight); QByteArray transformed; @@ -182,14 +183,14 @@ void TransformKeyBenchmarkThread::run() SymmetricCipher::Encrypt); cipher.init(seed, iv); - QTime t; + QElapsedTimer t; t.start(); do { - if (!cipher.processInPlace(key, 100)) { + if (!cipher.processInPlace(key, 10000)) { m_rounds = -1; return; } - m_rounds += 100; - } while (t.elapsed() < m_msec); + m_rounds += 10000; + } while (!t.hasExpired(m_msec)); } diff --git a/src/keys/FileKey.cpp b/src/keys/FileKey.cpp index f03a6953..d399f545 100644 --- a/src/keys/FileKey.cpp +++ b/src/keys/FileKey.cpp @@ -211,7 +211,10 @@ QByteArray FileKey::loadXmlKey(QXmlStreamReader& xmlReader) while (!xmlReader.error() && xmlReader.readNextStartElement()) { if (xmlReader.name() == "Data") { // TODO: do we need to enforce a specific data.size()? - data = QByteArray::fromBase64(xmlReader.readElementText().toLatin1()); + QByteArray rawData = xmlReader.readElementText().toLatin1(); + if (Tools::isBase64(rawData)) { + data = QByteArray::fromBase64(rawData); + } } } diff --git a/src/keys/FileKey.h b/src/keys/FileKey.h index f9854336..7a9b1caf 100644 --- a/src/keys/FileKey.h +++ b/src/keys/FileKey.h @@ -20,7 +20,6 @@ #include -#include "core/Global.h" #include "keys/Key.h" class QIODevice; @@ -30,11 +29,11 @@ class FileKey : public Key public: FileKey(); bool load(QIODevice* device); - bool load(const QString& fileName, QString* errorMsg = Q_NULLPTR); + bool load(const QString& fileName, QString* errorMsg = nullptr); QByteArray rawKey() const; FileKey* clone() const; static void create(QIODevice* device); - static bool create(const QString& fileName, QString* errorMsg = Q_NULLPTR); + static bool create(const QString& fileName, QString* errorMsg = nullptr); private: bool loadXml(QIODevice* device); diff --git a/src/main.cpp b/src/main.cpp index 41df31c9..b185f78b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,11 +15,11 @@ * along with this program. If not, see . */ +#include #include #include "config-keepassx.h" #include "core/Config.h" -#include "core/qcommandlineparser.h" #include "core/Tools.h" #include "core/Translator.h" #include "crypto/Crypto.h" @@ -32,12 +32,13 @@ int main(int argc, char** argv) #ifdef QT_NO_DEBUG Tools::disableCoreDumps(); #endif + Tools::setupSearchPaths(); Application app(argc, argv); Application::setApplicationName("keepassx"); Application::setApplicationVersion(KEEPASSX_VERSION); // don't set organizationName as that changes the return value of - // QDesktopServices::storageLocation(QDesktopServices::DataLocation) + // QStandardPaths::writableLocation(QDesktopServices::DataLocation) QApplication::setQuitOnLastWindowClosed(false); @@ -46,7 +47,7 @@ int main(int argc, char** argv) "Fatal error while testing the cryptographic functions."); error.append("\n"); error.append(Crypto::errorString()); - MessageBox::critical(Q_NULLPTR, QCoreApplication::translate("Main", "KeePassX - Error"), error); + MessageBox::critical(nullptr, QCoreApplication::translate("Main", "KeePassX - Error"), error); return 1; } @@ -57,9 +58,6 @@ int main(int argc, char** argv) QCommandLineOption configOption("config", QCoreApplication::translate("main", "path to a custom config file"), "config"); - QCommandLineOption passwordOption("password", - QCoreApplication::translate("main", "password of the database (DANGEROUS!)"), - "password"); QCommandLineOption keyfileOption("keyfile", QCoreApplication::translate("main", "key file of the database"), "keyfile"); @@ -67,7 +65,6 @@ int main(int argc, char** argv) parser.addHelpOption(); parser.addVersionOption(); parser.addOption(configOption); - parser.addOption(passwordOption); parser.addOption(keyfileOption); parser.process(app); @@ -86,13 +83,14 @@ int main(int argc, char** argv) MainWindow mainWindow; mainWindow.show(); + app.setMainWindow(&mainWindow); QObject::connect(&app, SIGNAL(openFile(QString)), &mainWindow, SLOT(openDatabase(QString))); for (int ii=0; ii < args.length(); ii++) { QString filename = args[ii]; if (!filename.isEmpty() && QFile::exists(filename)) { - mainWindow.openDatabase(filename, parser.value(passwordOption), parser.value(keyfileOption)); + mainWindow.openDatabase(filename, QString(), parser.value(keyfileOption)); } } diff --git a/src/streams/HashedBlockStream.cpp b/src/streams/HashedBlockStream.cpp index cd43dc0b..ec59769a 100644 --- a/src/streams/HashedBlockStream.cpp +++ b/src/streams/HashedBlockStream.cpp @@ -54,7 +54,9 @@ void HashedBlockStream::init() bool HashedBlockStream::reset() { - if (isWritable()) { + // Write final block(s) only if device is writable and we haven't + // already written a final block. + if (isWritable() && (!m_buffer.isEmpty() || m_blockIndex != 0)) { if (!m_buffer.isEmpty()) { if (!writeHashedBlock()) { return false; @@ -74,7 +76,9 @@ bool HashedBlockStream::reset() void HashedBlockStream::close() { - if (isWritable()) { + // Write final block(s) only if device is writable and we haven't + // already written a final block. + if (isWritable() && (!m_buffer.isEmpty() || m_blockIndex != 0)) { if (!m_buffer.isEmpty()) { writeHashedBlock(); } diff --git a/src/streams/HashedBlockStream.h b/src/streams/HashedBlockStream.h index f38d5716..93e4af59 100644 --- a/src/streams/HashedBlockStream.h +++ b/src/streams/HashedBlockStream.h @@ -31,12 +31,12 @@ public: HashedBlockStream(QIODevice* baseDevice, qint32 blockSize); ~HashedBlockStream(); - bool reset(); - void close(); + bool reset() override; + void close() override; protected: - qint64 readData(char* data, qint64 maxSize) Q_DECL_OVERRIDE; - qint64 writeData(const char* data, qint64 maxSize) Q_DECL_OVERRIDE; + qint64 readData(char* data, qint64 maxSize) override; + qint64 writeData(const char* data, qint64 maxSize) override; private: void init(); diff --git a/src/streams/LayeredStream.h b/src/streams/LayeredStream.h index b243e55b..8586b413 100644 --- a/src/streams/LayeredStream.h +++ b/src/streams/LayeredStream.h @@ -20,8 +20,6 @@ #include -#include "core/Global.h" - class LayeredStream : public QIODevice { Q_OBJECT @@ -30,12 +28,12 @@ public: explicit LayeredStream(QIODevice* baseDevice); virtual ~LayeredStream(); - bool isSequential() const Q_DECL_OVERRIDE; - bool open(QIODevice::OpenMode mode) Q_DECL_OVERRIDE; + bool isSequential() const override; + bool open(QIODevice::OpenMode mode) override; protected: - qint64 readData(char* data, qint64 maxSize) Q_DECL_OVERRIDE; - qint64 writeData(const char* data, qint64 maxSize) Q_DECL_OVERRIDE; + qint64 readData(char* data, qint64 maxSize) override; + qint64 writeData(const char* data, qint64 maxSize) override; QIODevice* const m_baseDevice; diff --git a/src/streams/StoreDataStream.h b/src/streams/StoreDataStream.h index 41434385..9f39d6a7 100644 --- a/src/streams/StoreDataStream.h +++ b/src/streams/StoreDataStream.h @@ -26,11 +26,11 @@ class StoreDataStream : public LayeredStream public: explicit StoreDataStream(QIODevice* baseDevice); - bool open(QIODevice::OpenMode mode) Q_DECL_OVERRIDE; + bool open(QIODevice::OpenMode mode) override; QByteArray storedData() const; protected: - qint64 readData(char* data, qint64 maxSize) Q_DECL_OVERRIDE; + qint64 readData(char* data, qint64 maxSize) override; private: QByteArray m_storedData; diff --git a/src/streams/SymmetricCipherStream.cpp b/src/streams/SymmetricCipherStream.cpp index c713e522..643aa033 100644 --- a/src/streams/SymmetricCipherStream.cpp +++ b/src/streams/SymmetricCipherStream.cpp @@ -25,6 +25,7 @@ SymmetricCipherStream::SymmetricCipherStream(QIODevice* baseDevice, SymmetricCip , m_bufferFilling(false) , m_error(false) , m_isInitalized(false) + , m_dataWritten(false) { } @@ -43,6 +44,16 @@ bool SymmetricCipherStream::init(const QByteArray& key, const QByteArray& iv) return m_isInitalized; } +void SymmetricCipherStream::resetInternalState() +{ + m_buffer.clear(); + m_bufferPos = 0; + m_bufferFilling = false; + m_error = false; + m_dataWritten = false; + m_cipher->reset(); +} + bool SymmetricCipherStream::open(QIODevice::OpenMode mode) { if (!m_isInitalized) { @@ -54,27 +65,25 @@ bool SymmetricCipherStream::open(QIODevice::OpenMode mode) bool SymmetricCipherStream::reset() { - if (isWritable()) { + if (isWritable() && m_dataWritten) { if (!writeBlock(true)) { return false; } } - m_buffer.clear(); - m_bufferPos = 0; - m_bufferFilling = false; - m_error = false; - m_cipher->reset(); + resetInternalState(); return true; } void SymmetricCipherStream::close() { - if (isWritable()) { + if (isWritable() && m_dataWritten) { writeBlock(true); } + resetInternalState(); + LayeredStream::close(); } @@ -115,11 +124,25 @@ qint64 SymmetricCipherStream::readData(char* data, qint64 maxSize) bool SymmetricCipherStream::readBlock() { + QByteArray newData; + if (m_bufferFilling) { - m_buffer.append(m_baseDevice->read(m_cipher->blockSize() - m_buffer.size())); + newData.resize(m_cipher->blockSize() - m_buffer.size()); } else { - m_buffer = m_baseDevice->read(m_cipher->blockSize()); + m_buffer.clear(); + newData.resize(m_cipher->blockSize()); + } + + int readResult = m_baseDevice->read(newData.data(), newData.size()); + + if (readResult == -1) { + m_error = true; + setErrorString(m_baseDevice->errorString()); + return false; + } + else { + m_buffer.append(newData.left(readResult)); } if (m_buffer.size() != m_cipher->blockSize()) { @@ -172,6 +195,7 @@ qint64 SymmetricCipherStream::writeData(const char* data, qint64 maxSize) return -1; } + m_dataWritten = true; qint64 bytesRemaining = maxSize; qint64 offset = 0; @@ -200,6 +224,8 @@ qint64 SymmetricCipherStream::writeData(const char* data, qint64 maxSize) bool SymmetricCipherStream::writeBlock(bool lastBlock) { + Q_ASSERT(lastBlock || (m_buffer.size() == m_cipher->blockSize())); + if (lastBlock) { // PKCS7 padding int padLen = m_cipher->blockSize() - m_buffer.size(); @@ -207,9 +233,6 @@ bool SymmetricCipherStream::writeBlock(bool lastBlock) m_buffer.append(static_cast(padLen)); } } - else if (m_buffer.isEmpty()) { - return true; - } if (!m_cipher->processInPlace(m_buffer)) { m_error = true; @@ -219,7 +242,7 @@ bool SymmetricCipherStream::writeBlock(bool lastBlock) if (m_baseDevice->write(m_buffer) != m_buffer.size()) { m_error = true; - setErrorString(m_cipher->errorString()); + setErrorString(m_baseDevice->errorString()); return false; } else { diff --git a/src/streams/SymmetricCipherStream.h b/src/streams/SymmetricCipherStream.h index c1865bab..b6228e1b 100644 --- a/src/streams/SymmetricCipherStream.h +++ b/src/streams/SymmetricCipherStream.h @@ -33,15 +33,16 @@ public: SymmetricCipher::Mode mode, SymmetricCipher::Direction direction); ~SymmetricCipherStream(); bool init(const QByteArray& key, const QByteArray& iv); - bool open(QIODevice::OpenMode mode) Q_DECL_OVERRIDE; - bool reset() Q_DECL_OVERRIDE; - void close() Q_DECL_OVERRIDE; + bool open(QIODevice::OpenMode mode) override; + bool reset() override; + void close() override; protected: - qint64 readData(char* data, qint64 maxSize) Q_DECL_OVERRIDE; - qint64 writeData(const char* data, qint64 maxSize) Q_DECL_OVERRIDE; + qint64 readData(char* data, qint64 maxSize) override; + qint64 writeData(const char* data, qint64 maxSize) override; private: + void resetInternalState(); bool readBlock(); bool writeBlock(bool lastBlock); @@ -51,6 +52,7 @@ private: bool m_bufferFilling; bool m_error; bool m_isInitalized; + bool m_dataWritten; }; #endif // KEEPASSX_SYMMETRICCIPHERSTREAM_H diff --git a/src/version.h.cmake b/src/version.h.cmake new file mode 100644 index 00000000..7e67ecd6 --- /dev/null +++ b/src/version.h.cmake @@ -0,0 +1,5 @@ +#define GIT_HEAD "@GIT_HEAD@" +#define GIT_DESCRIBE "@GIT_DESCRIBE@" + +#define DIST_HASH "$Format:%H$" +#define DIST_DATE "$Format:%at$" diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9b4b7b3c..7ea399fe 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -52,10 +52,9 @@ macro(parse_arguments prefix arg_names option_names) endmacro(parse_arguments) macro(add_unit_test) - parse_arguments(TEST "NAME;SOURCES;MOCS;LIBS" "" ${ARGN}) + parse_arguments(TEST "NAME;SOURCES;LIBS" "" ${ARGN}) set(_test_NAME ${TEST_NAME}) set(_srcList ${TEST_SOURCES}) - qt4_wrap_cpp(_srcList ${TEST_MOCS}) add_executable(${_test_NAME} ${_srcList}) target_link_libraries(${_test_NAME} ${TEST_LIBS}) @@ -86,86 +85,80 @@ endmacro(add_unit_test) set(TEST_LIBRARIES keepassx_core - ${QT_QTCORE_LIBRARY} - ${QT_QTGUI_LIBRARY} - ${QT_QTTEST_LIBRARY} + Qt5::Core + Qt5::Concurrent + Qt5::Widgets + Qt5::Test ${GCRYPT_LIBRARIES} ${ZLIB_LIBRARIES} ) -if(UNIX AND NOT APPLE) - set(TEST_LIBRARIES ${TEST_LIBRARIES} ${QT_QTDBUS_LIBRARY}) -endif() +set(testsupport_SOURCES modeltest.cpp FailDevice.cpp) +add_library(testsupport STATIC ${testsupport_SOURCES}) +target_link_libraries(testsupport Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Test) -set(modeltest_SOURCRS modeltest.cpp) -qt4_wrap_cpp(modeltest_SOURCRS modeltest.h) -add_library(modeltest STATIC ${modeltest_SOURCRS}) - -add_unit_test(NAME testgroup SOURCES TestGroup.cpp MOCS TestGroup.h +add_unit_test(NAME testgroup SOURCES TestGroup.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testkeepass2xmlreader SOURCES TestKeePass2XmlReader.cpp MOCS TestKeePass2XmlReader.h +add_unit_test(NAME testkeepass2xmlreader SOURCES TestKeePass2XmlReader.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testkeys SOURCES TestKeys.cpp MOCS TestKeys.h +add_unit_test(NAME testkeys SOURCES TestKeys.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testkeepass2reader SOURCES TestKeePass2Reader.cpp MOCS TestKeePass2Reader.h +add_unit_test(NAME testkeepass2reader SOURCES TestKeePass2Reader.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testkeepass2writer SOURCES TestKeePass2Writer.cpp MOCS TestKeePass2Writer.h +add_unit_test(NAME testkeepass2writer SOURCES TestKeePass2Writer.cpp + LIBS testsupport ${TEST_LIBRARIES}) + +add_unit_test(NAME testgroupmodel SOURCES TestGroupModel.cpp + LIBS testsupport ${TEST_LIBRARIES}) + +add_unit_test(NAME testentrymodel SOURCES TestEntryModel.cpp + LIBS testsupport ${TEST_LIBRARIES}) + +add_unit_test(NAME testcryptohash SOURCES TestCryptoHash.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testgroupmodel SOURCES TestGroupModel.cpp MOCS TestGroupModel.h - LIBS modeltest ${TEST_LIBRARIES}) - -add_unit_test(NAME testentrymodel SOURCES TestEntryModel.cpp MOCS TestEntryModel.h - LIBS modeltest ${TEST_LIBRARIES}) - -add_unit_test(NAME testcryptohash SOURCES TestCryptoHash.cpp MOCS TestCryptoHash.h +add_unit_test(NAME testsymmetriccipher SOURCES TestSymmetricCipher.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testsymmetriccipher SOURCES TestSymmetricCipher.cpp MOCS TestSymmetricCipher.h +add_unit_test(NAME testhashedblockstream SOURCES TestHashedBlockStream.cpp + LIBS testsupport ${TEST_LIBRARIES}) + +add_unit_test(NAME testkeepass2randomstream SOURCES TestKeePass2RandomStream.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testhashedblockstream SOURCES TestHashedBlockStream.cpp MOCS TestHashedBlockStream.h +add_unit_test(NAME testmodified SOURCES TestModified.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testkeepass2randomstream SOURCES TestKeePass2RandomStream.cpp MOCS TestKeePass2RandomStream.h +add_unit_test(NAME testdeletedobjects SOURCES TestDeletedObjects.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testmodified SOURCES TestModified.cpp MOCS TestModified.h +add_unit_test(NAME testkeepass1reader SOURCES TestKeePass1Reader.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testdeletedobjects SOURCES TestDeletedObjects.cpp MOCS TestDeletedObjects.h +add_unit_test(NAME testwildcardmatcher SOURCES TestWildcardMatcher.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testkeepass1reader SOURCES TestKeePass1Reader.cpp MOCS TestKeePass1Reader.h - LIBS ${TEST_LIBRARIES}) - -add_unit_test(NAME testqsavefile SOURCES TestQSaveFile.cpp MOCS TestQSaveFile.h - LIBS ${TEST_LIBRARIES}) - -add_unit_test(NAME testwildcardmatcher SOURCES TestWildcardMatcher.cpp MOCS TestWildcardMatcher.h - LIBS ${TEST_LIBRARIES}) - -add_unit_test(NAME testautotype SOURCES TestAutoType.cpp MOCS TestAutoType.h +add_unit_test(NAME testautotype SOURCES TestAutoType.cpp LIBS ${TEST_LIBRARIES}) set_target_properties(testautotype PROPERTIES ENABLE_EXPORTS ON) -add_unit_test(NAME testentry SOURCES TestEntry.cpp MOCS TestEntry.h +add_unit_test(NAME testentry SOURCES TestEntry.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testqcommandlineparser SOURCES TestQCommandLineParser.cpp MOCS TestQCommandLineParser.h +add_unit_test(NAME testrandom SOURCES TestRandom.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testrandom SOURCES TestRandom.cpp MOCS TestRandom.h +add_unit_test(NAME testentrysearcher SOURCES TestEntrySearcher.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testentrysearcher SOURCES TestEntrySearcher.cpp MOCS TestEntrySearcher.h +add_unit_test(NAME testexporter SOURCES TestExporter.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testexporter SOURCES TestExporter.cpp MOCS TestExporter.h +add_unit_test(NAME testcsvexporter SOURCES TestCsvExporter.cpp LIBS ${TEST_LIBRARIES}) if(WITH_GUI_TESTS) diff --git a/tests/FailDevice.cpp b/tests/FailDevice.cpp new file mode 100644 index 00000000..5a25db28 --- /dev/null +++ b/tests/FailDevice.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "FailDevice.h" + +FailDevice::FailDevice(int failAfter, QObject* parent) + : QBuffer(parent) + , m_failAfter(failAfter) + , m_readCount(0) + , m_writeCount(0) +{ +} + +bool FailDevice::open(QIODevice::OpenMode openMode) +{ + return QBuffer::open(openMode | QIODevice::Unbuffered); +} + +qint64 FailDevice::readData(char* data, qint64 len) +{ + if (m_readCount >= m_failAfter) { + setErrorString("FAILDEVICE"); + return -1; + } + else { + qint64 result = QBuffer::readData(data, len); + if (result != -1) { + m_readCount += result; + } + + return result; + } +} + +qint64 FailDevice::writeData(const char* data, qint64 len) +{ + if (m_writeCount >= m_failAfter) { + setErrorString("FAILDEVICE"); + return -1; + } + else { + qint64 result = QBuffer::writeData(data, len); + if (result != -1) { + m_writeCount += result; + } + + return result; + } +} diff --git a/tests/FailDevice.h b/tests/FailDevice.h new file mode 100644 index 00000000..194d6174 --- /dev/null +++ b/tests/FailDevice.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2015 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_FAILDEVICE_H +#define KEEPASSX_FAILDEVICE_H + +#include + +class FailDevice : public QBuffer +{ + Q_OBJECT + +public: + explicit FailDevice(int failAfter, QObject* parent = nullptr); + bool open(QIODevice::OpenMode openMode) override; + +protected: + qint64 readData(char* data, qint64 len) override; + qint64 writeData(const char* data, qint64 len) override; + +private: + int m_failAfter; + int m_readCount; + int m_writeCount; +}; + +#endif // KEEPASSX_FAILDEVICE_H diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp index 818f57c9..cbd927fe 100644 --- a/tests/TestAutoType.cpp +++ b/tests/TestAutoType.cpp @@ -20,7 +20,6 @@ #include #include -#include "tests.h" #include "core/Config.h" #include "core/FilePath.h" #include "core/Entry.h" @@ -38,7 +37,6 @@ void TestAutoType::initTestCase() QVERIFY(Crypto::init()); Config::createTempFileInstance(); AutoType::createTestInstance(); - config()->set("AutoTypeEntryTitleMatch", false); config()->set("security/autotypeask", false); QPluginLoader loader(filePath()->pluginPath("keepassx-autotype-test")); @@ -56,6 +54,7 @@ void TestAutoType::initTestCase() void TestAutoType::init() { + config()->set("AutoTypeEntryTitleMatch", false); m_test->clearActions(); m_db = new Database(); @@ -64,11 +63,12 @@ void TestAutoType::init() m_group = new Group(); m_db->setRootGroup(m_group); + AutoTypeAssociations::Association association; + m_entry1 = new Entry(); m_entry1->setGroup(m_group); m_entry1->setUsername("myuser"); m_entry1->setPassword("mypass"); - AutoTypeAssociations::Association association; association.window = "custom window"; association.sequence = "{username}association{password}"; m_entry1->autoTypeAssociations()->add(association); @@ -77,6 +77,19 @@ void TestAutoType::init() m_entry2->setGroup(m_group); m_entry2->setPassword("myuser"); m_entry2->setTitle("entry title"); + + m_entry3 = new Entry(); + m_entry3->setGroup(m_group); + m_entry3->setPassword("regex"); + association.window = "//REGEX1//"; + association.sequence = "regex1"; + m_entry3->autoTypeAssociations()->add(association); + association.window = "//^REGEX2$//"; + association.sequence = "regex2"; + m_entry3->autoTypeAssociations()->add(association); + association.window = "//^REGEX3-([rd]\\d){2}$//"; + association.sequence = "regex3"; + m_entry3->autoTypeAssociations()->add(association); } void TestAutoType::cleanup() @@ -94,7 +107,7 @@ void TestAutoType::testInternal() void TestAutoType::testAutoTypeWithoutSequence() { - m_autoType->performAutoType(m_entry1, Q_NULLPTR); + m_autoType->performAutoType(m_entry1, nullptr); QCOMPARE(m_test->actionCount(), 14); QCOMPARE(m_test->actionChars(), @@ -105,7 +118,7 @@ void TestAutoType::testAutoTypeWithoutSequence() void TestAutoType::testAutoTypeWithSequence() { - m_autoType->performAutoType(m_entry1, Q_NULLPTR, "{Username}abc{PaSsWoRd}"); + m_autoType->performAutoType(m_entry1, nullptr, "{Username}abc{PaSsWoRd}"); QCOMPARE(m_test->actionCount(), 15); QCOMPARE(m_test->actionChars(), @@ -147,12 +160,36 @@ void TestAutoType::testGlobalAutoTypeTitleMatch() void TestAutoType::testGlobalAutoTypeTitleMatchDisabled() { - config()->set("AutoTypeEntryTitleMatch", false); - m_test->setActiveWindowTitle("An Entry Title!"); MessageBox::setNextAnswer(QMessageBox::Ok); m_autoType->performGlobalAutoType(m_dbList); QCOMPARE(m_test->actionChars(), QString()); - +} + +void TestAutoType::testGlobalAutoTypeRegExp() +{ + // substring matches are ok + m_test->setActiveWindowTitle("lorem REGEX1 ipsum"); + m_autoType->performGlobalAutoType(m_dbList); + QCOMPARE(m_test->actionChars(), QString("regex1")); + m_test->clearActions(); + + // should be case-insensitive + m_test->setActiveWindowTitle("lorem regex1 ipsum"); + m_autoType->performGlobalAutoType(m_dbList); + QCOMPARE(m_test->actionChars(), QString("regex1")); + m_test->clearActions(); + + // exact match + m_test->setActiveWindowTitle("REGEX2"); + m_autoType->performGlobalAutoType(m_dbList); + QCOMPARE(m_test->actionChars(), QString("regex2")); + m_test->clearActions(); + + // a bit more complicated regex + m_test->setActiveWindowTitle("REGEX3-R2D2"); + m_autoType->performGlobalAutoType(m_dbList); + QCOMPARE(m_test->actionChars(), QString("regex3")); + m_test->clearActions(); } diff --git a/tests/TestAutoType.h b/tests/TestAutoType.h index d46a5596..c12817b1 100644 --- a/tests/TestAutoType.h +++ b/tests/TestAutoType.h @@ -43,6 +43,7 @@ private Q_SLOTS: void testGlobalAutoTypeWithOneMatch(); void testGlobalAutoTypeTitleMatch(); void testGlobalAutoTypeTitleMatchDisabled(); + void testGlobalAutoTypeRegExp(); private: AutoTypePlatformInterface* m_platform; @@ -53,6 +54,7 @@ private: Group* m_group; Entry* m_entry1; Entry* m_entry2; + Entry* m_entry3; }; #endif // KEEPASSX_TESTAUTOTYPE_H diff --git a/tests/TestCryptoHash.cpp b/tests/TestCryptoHash.cpp index 4002aea6..c166f559 100644 --- a/tests/TestCryptoHash.cpp +++ b/tests/TestCryptoHash.cpp @@ -19,7 +19,6 @@ #include -#include "tests.h" #include "crypto/Crypto.h" #include "crypto/CryptoHash.h" diff --git a/tests/TestCsvExporter.cpp b/tests/TestCsvExporter.cpp new file mode 100644 index 00000000..1fa66347 --- /dev/null +++ b/tests/TestCsvExporter.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2015 Florian Geyer + * Copyright (C) 2015 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TestCsvExporter.h" + +#include +#include + +#include "core/Database.h" +#include "core/Entry.h" +#include "core/Group.h" +#include "crypto/Crypto.h" +#include "format/CsvExporter.h" + +QTEST_GUILESS_MAIN(TestCsvExporter) + +const QString TestCsvExporter::ExpectedHeaderLine = QString("\"Group\",\"Title\",\"Username\",\"Password\",\"URL\",\"Notes\"\n"); + +void TestCsvExporter::init() +{ + m_db = new Database(); + m_csvExporter = new CsvExporter(); +} + +void TestCsvExporter::initTestCase() +{ + Crypto::init(); +} + +void TestCsvExporter::cleanUp() +{ + delete m_db; + delete m_csvExporter; +} + +void TestCsvExporter::testExport() +{ + Group* groupRoot = m_db->rootGroup(); + Group* group = new Group(); + group->setName("Test Group Name"); + group->setParent(groupRoot); + Entry* entry = new Entry(); + entry->setGroup(group); + entry->setTitle("Test Entry Title"); + entry->setUsername("Test Username"); + entry->setPassword("Test Password"); + entry->setUrl("http://test.url"); + entry->setNotes("Test Notes"); + + QBuffer buffer; + QVERIFY(buffer.open(QIODevice::ReadWrite)); + m_csvExporter->exportDatabase(&buffer, m_db); + + QString expectedResult = QString().append(ExpectedHeaderLine).append("\"Test Group Name\",\"Test Entry Title\",\"Test Username\",\"Test Password\",\"http://test.url\",\"Test Notes\"\n"); + + QCOMPARE(QString::fromUtf8(buffer.buffer().constData()), expectedResult); +} + +void TestCsvExporter::testEmptyDatabase() +{ + QBuffer buffer; + QVERIFY(buffer.open(QIODevice::ReadWrite)); + m_csvExporter->exportDatabase(&buffer, m_db); + + QCOMPARE(QString::fromUtf8(buffer.buffer().constData()), ExpectedHeaderLine); +} + +void TestCsvExporter::testNestedGroups() +{ + Group* groupRoot = m_db->rootGroup(); + Group* group = new Group(); + group->setName("Test Group Name"); + group->setParent(groupRoot); + Group* childGroup = new Group(); + childGroup->setName("Test Sub Group Name"); + childGroup->setParent(group); + Entry* entry = new Entry(); + entry->setGroup(childGroup); + entry->setTitle("Test Entry Title"); + + QBuffer buffer; + QVERIFY(buffer.open(QIODevice::ReadWrite)); + m_csvExporter->exportDatabase(&buffer, m_db); + + QCOMPARE(QString::fromUtf8(buffer.buffer().constData()), QString().append(ExpectedHeaderLine).append("\"Test Group Name/Test Sub Group Name\",\"Test Entry Title\",\"\",\"\",\"\",\"\"\n")); +} diff --git a/tests/TestCsvExporter.h b/tests/TestCsvExporter.h new file mode 100644 index 00000000..c8cc4dc1 --- /dev/null +++ b/tests/TestCsvExporter.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 Florian Geyer + * Copyright (C) 2015 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_TESTCSVEXPORTER_H +#define KEEPASSX_TESTCSVEXPORTER_H + +#include + +class Database; +class CsvExporter; + +class TestCsvExporter : public QObject +{ + Q_OBJECT + +public: + static const QString ExpectedHeaderLine; + +private Q_SLOTS: + void init(); + void initTestCase(); + void cleanUp(); + void testExport(); + void testEmptyDatabase(); + void testNestedGroups(); + +private: + Database* m_db; + CsvExporter* m_csvExporter; +}; + +#endif // KEEPASSX_TESTCSVEXPORTER_H diff --git a/tests/TestDeletedObjects.cpp b/tests/TestDeletedObjects.cpp index cf9e3d10..5af01788 100644 --- a/tests/TestDeletedObjects.cpp +++ b/tests/TestDeletedObjects.cpp @@ -19,7 +19,6 @@ #include -#include "tests.h" #include "core/Database.h" #include "core/Group.h" #include "crypto/Crypto.h" diff --git a/tests/TestEntry.cpp b/tests/TestEntry.cpp index 477e83b8..1eaca324 100644 --- a/tests/TestEntry.cpp +++ b/tests/TestEntry.cpp @@ -19,7 +19,6 @@ #include -#include "tests.h" #include "core/Entry.h" #include "crypto/Crypto.h" @@ -120,6 +119,6 @@ void TestEntry::testClone() QCOMPARE(entryCloneNone->uuid(), entryOrg->uuid()); QCOMPARE(entryCloneHistory->title(), QString("New Title")); QCOMPARE(entryCloneHistory->historyItems().size(), 1); - QCOMPARE(entryCloneHistory->historyItems().first()->title(), QString("Original Title")); + QCOMPARE(entryCloneHistory->historyItems().at(0)->title(), QString("Original Title")); QCOMPARE(entryCloneHistory->timeInfo().creationTime(), entryOrg->timeInfo().creationTime()); } diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp index 7ba886bc..3f956d7f 100644 --- a/tests/TestEntryModel.cpp +++ b/tests/TestEntryModel.cpp @@ -21,7 +21,6 @@ #include #include "modeltest.h" -#include "tests.h" #include "core/DatabaseIcons.h" #include "core/Entry.h" #include "core/Group.h" @@ -210,17 +209,16 @@ void TestEntryModel::testCustomIconModel() QCOMPARE(model->rowCount(), 0); - QHash icons; + QHash icons; QList iconsOrder; Uuid iconUuid(QByteArray(16, '2')); - QImage icon; - icons.insert(iconUuid, icon); + icons.insert(iconUuid, QPixmap()); iconsOrder << iconUuid; Uuid iconUuid2(QByteArray(16, '1')); QImage icon2; - icons.insert(iconUuid2, icon2); + icons.insert(iconUuid2, QPixmap()); iconsOrder << iconUuid2; model->setIcons(icons, iconsOrder); diff --git a/tests/TestEntrySearcher.cpp b/tests/TestEntrySearcher.cpp index 9f7ca139..6b951c70 100644 --- a/tests/TestEntrySearcher.cpp +++ b/tests/TestEntrySearcher.cpp @@ -19,8 +19,6 @@ #include -#include "tests.h" - QTEST_GUILESS_MAIN(TestEntrySearcher) void TestEntrySearcher::initTestCase() diff --git a/tests/TestExporter.cpp b/tests/TestExporter.cpp index d703e02f..656b76c5 100644 --- a/tests/TestExporter.cpp +++ b/tests/TestExporter.cpp @@ -20,7 +20,6 @@ #include -#include "tests.h" #include "core/ToDbExporter.h" #include "core/Group.h" #include "core/Metadata.h" @@ -60,23 +59,20 @@ void TestExporter::testToDbExporter() Database* dbExp = ToDbExporter().exportGroup(groupOrg); QCOMPARE(dbExp->rootGroup()->children().size(), 1); - Group* groupExp = dbExp->rootGroup()->children().first(); + Group* groupExp = dbExp->rootGroup()->children().at(0); QVERIFY(groupExp != groupOrg); QCOMPARE(groupExp->name(), groupOrg->name()); QCOMPARE(groupExp->entries().size(), 1); - Entry* entryExp = groupExp->entries().first(); + Entry* entryExp = groupExp->entries().at(0); QCOMPARE(entryExp->title(), entryOrg->title()); QCOMPARE(dbExp->metadata()->customIcons().size(), 1); QVERIFY(dbExp->metadata()->containsCustomIcon(iconUuid)); QCOMPARE(entryExp->iconNumber(), entryOrg->iconNumber()); QCOMPARE(entryExp->historyItems().size(), 1); - QCOMPARE(entryExp->historyItems().first()->iconUuid(), iconUuid); + QCOMPARE(entryExp->historyItems().at(0)->iconUuid(), iconUuid); delete dbOrg; delete dbExp; } - - - diff --git a/tests/TestGroup.cpp b/tests/TestGroup.cpp index 507cf155..13ce82ea 100644 --- a/tests/TestGroup.cpp +++ b/tests/TestGroup.cpp @@ -21,7 +21,6 @@ #include #include -#include "tests.h" #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" diff --git a/tests/TestGroupModel.cpp b/tests/TestGroupModel.cpp index 32a4b8e9..3608cc47 100644 --- a/tests/TestGroupModel.cpp +++ b/tests/TestGroupModel.cpp @@ -21,7 +21,6 @@ #include #include "modeltest.h" -#include "tests.h" #include "core/Database.h" #include "core/Group.h" #include "crypto/Crypto.h" diff --git a/tests/TestHashedBlockStream.cpp b/tests/TestHashedBlockStream.cpp index 2a37d0aa..b78a46ba 100644 --- a/tests/TestHashedBlockStream.cpp +++ b/tests/TestHashedBlockStream.cpp @@ -20,7 +20,7 @@ #include #include -#include "tests.h" +#include "FailDevice.h" #include "crypto/Crypto.h" #include "streams/HashedBlockStream.h" @@ -71,3 +71,34 @@ void TestHashedBlockStream::testWriteRead() buffer.reset(); buffer.buffer().clear(); } + +void TestHashedBlockStream::testReset() +{ + QBuffer buffer; + QVERIFY(buffer.open(QIODevice::WriteOnly)); + + HashedBlockStream writer(&buffer, 16); + QVERIFY(writer.open(QIODevice::WriteOnly)); + QCOMPARE(writer.write(QByteArray(8, 'Z')), qint64(8)); + // test if reset() and close() write only one final block + QVERIFY(writer.reset()); + QVERIFY(writer.reset()); + writer.close(); + QCOMPARE(buffer.buffer().size(), 8 + (32 + 4 + 4) * 2); +} + +void TestHashedBlockStream::testWriteFailure() +{ + FailDevice failDevice(1500); + QVERIFY(failDevice.open(QIODevice::WriteOnly)); + + QByteArray input(2000, 'Z'); + + HashedBlockStream writer(&failDevice, 500); + QVERIFY(writer.open(QIODevice::WriteOnly)); + + QCOMPARE(writer.write(input.left(900)), qint64(900)); + writer.write(input.left(900)); + QVERIFY(!writer.reset()); + QCOMPARE(writer.errorString(), QString("FAILDEVICE")); +} diff --git a/tests/TestHashedBlockStream.h b/tests/TestHashedBlockStream.h index d672664c..9aeac141 100644 --- a/tests/TestHashedBlockStream.h +++ b/tests/TestHashedBlockStream.h @@ -27,6 +27,8 @@ class TestHashedBlockStream : public QObject private Q_SLOTS: void initTestCase(); void testWriteRead(); + void testReset(); + void testWriteFailure(); }; #endif // KEEPASSX_TESTHASHEDBLOCKSTREAM_H diff --git a/tests/TestKeePass1Reader.cpp b/tests/TestKeePass1Reader.cpp index 249a3657..f60846d2 100644 --- a/tests/TestKeePass1Reader.cpp +++ b/tests/TestKeePass1Reader.cpp @@ -21,7 +21,6 @@ #include #include "config-keepassx-tests.h" -#include "tests.h" #include "core/Database.h" #include "core/Entry.h" #include "core/Group.h" @@ -71,7 +70,7 @@ void TestKeePass1Reader::testBasic() QVERIFY(entry11->timeInfo().expires()); QCOMPARE(entry11->timeInfo().expiryTime(), genDT(2012, 5, 9, 10, 32)); QCOMPARE(entry11->attachments()->keys().size(), 1); - QCOMPARE(entry11->attachments()->keys().first(), QString("attachment.txt")); + QCOMPARE(entry11->attachments()->keys().at(0), QString("attachment.txt")); QCOMPARE(entry11->attachments()->value("attachment.txt"), QByteArray("hello world\n")); Entry* entry12 = group1->entries().at(1); @@ -118,7 +117,7 @@ void TestKeePass1Reader::testCustomIcons() { QCOMPARE(m_db->metadata()->customIcons().size(), 1); - Entry* entry = m_db->rootGroup()->children().at(1)->entries().first(); + Entry* entry = m_db->rootGroup()->children().at(1)->entries().at(0); QCOMPARE(entry->icon().width(), 16); QCOMPARE(entry->icon().height(), 16); diff --git a/tests/TestKeePass2RandomStream.cpp b/tests/TestKeePass2RandomStream.cpp index cb881337..03dfbe50 100644 --- a/tests/TestKeePass2RandomStream.cpp +++ b/tests/TestKeePass2RandomStream.cpp @@ -19,7 +19,6 @@ #include -#include "tests.h" #include "crypto/Crypto.h" #include "crypto/CryptoHash.h" #include "crypto/SymmetricCipher.h" diff --git a/tests/TestKeePass2Reader.cpp b/tests/TestKeePass2Reader.cpp index d6cb70c7..22973ee0 100644 --- a/tests/TestKeePass2Reader.cpp +++ b/tests/TestKeePass2Reader.cpp @@ -20,7 +20,6 @@ #include #include "config-keepassx-tests.h" -#include "tests.h" #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" diff --git a/tests/TestKeePass2Writer.cpp b/tests/TestKeePass2Writer.cpp index cf4ab1c5..60b7b90e 100644 --- a/tests/TestKeePass2Writer.cpp +++ b/tests/TestKeePass2Writer.cpp @@ -20,13 +20,16 @@ #include #include -#include "tests.h" +#include "config-keepassx-tests.h" +#include "FailDevice.h" #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" #include "crypto/Crypto.h" #include "format/KeePass2Reader.h" +#include "format/KeePass2Repair.h" #include "format/KeePass2Writer.h" +#include "format/KeePass2XmlWriter.h" #include "keys/PasswordKey.h" QTEST_GUILESS_MAIN(TestKeePass2Writer) @@ -101,6 +104,58 @@ void TestKeePass2Writer::testNonAsciiPasswords() QCOMPARE(m_dbTest->rootGroup()->entries()[0]->password(), m_dbOrg->rootGroup()->entries()[0]->password()); } +void TestKeePass2Writer::testDeviceFailure() +{ + CompositeKey key; + key.addKey(PasswordKey("test")); + Database* db = new Database(); + db->setKey(key); + // Disable compression so we write a predictable number of bytes. + db->setCompressionAlgo(Database::CompressionNone); + + Entry* entry = new Entry(); + entry->setParent(db->rootGroup()); + QByteArray attachment(4096, 'Z'); + entry->attachments()->set("test", attachment); + + FailDevice failDevice(512); + QVERIFY(failDevice.open(QIODevice::WriteOnly)); + KeePass2Writer writer; + writer.writeDatabase(&failDevice, db); + QVERIFY(writer.hasError()); + QCOMPARE(writer.errorString(), QString("FAILDEVICE")); + + delete db; +} + +void TestKeePass2Writer::testRepair() +{ + QString brokenDbFilename = QString(KEEPASSX_TEST_DATA_DIR).append("/bug392.kdbx"); + // master password = test + // entry username: testuser\x10\x20AC + // entry password: testpw + CompositeKey key; + key.addKey(PasswordKey("test")); + + // test that we can't open the broken database + KeePass2Reader reader; + Database* dbBroken = reader.readDatabase(brokenDbFilename, key); + QVERIFY(!dbBroken); + QVERIFY(reader.hasError()); + + // test if we can repair the database + KeePass2Repair repair; + QFile file(brokenDbFilename); + file.open(QIODevice::ReadOnly); + QCOMPARE(repair.repairDatabase(&file, key), KeePass2Repair::RepairSuccess); + Database* dbRepaired = repair.database(); + QVERIFY(dbRepaired); + + QCOMPARE(dbRepaired->rootGroup()->entries().size(), 1); + QCOMPARE(dbRepaired->rootGroup()->entries().at(0)->username(), QString("testuser").append(QChar(0x20AC))); + QCOMPARE(dbRepaired->rootGroup()->entries().at(0)->password(), QString("testpw")); +} + void TestKeePass2Writer::cleanupTestCase() { delete m_dbOrg; diff --git a/tests/TestKeePass2Writer.h b/tests/TestKeePass2Writer.h index b6a08dc5..82288382 100644 --- a/tests/TestKeePass2Writer.h +++ b/tests/TestKeePass2Writer.h @@ -32,6 +32,8 @@ private Q_SLOTS: void testProtectedAttributes(); void testAttachments(); void testNonAsciiPasswords(); + void testDeviceFailure(); + void testRepair(); void cleanupTestCase(); private: diff --git a/tests/TestKeePass2XmlReader.cpp b/tests/TestKeePass2XmlReader.cpp index e88e990a..f04c5480 100644 --- a/tests/TestKeePass2XmlReader.cpp +++ b/tests/TestKeePass2XmlReader.cpp @@ -17,15 +17,16 @@ #include "TestKeePass2XmlReader.h" +#include #include #include -#include "tests.h" #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" #include "crypto/Crypto.h" #include "format/KeePass2XmlReader.h" +#include "format/KeePass2XmlWriter.h" #include "config-keepassx-tests.h" QTEST_GUILESS_MAIN(TestKeePass2XmlReader) @@ -66,6 +67,18 @@ QDateTime TestKeePass2XmlReader::genDT(int year, int month, int day, int hour, i return QDateTime(date, time, Qt::UTC); } +QByteArray TestKeePass2XmlReader::strToBytes(const QString& str) +{ + QByteArray result; + + for (int i = 0; i < str.size(); i++) { + result.append(str.at(i).unicode() >> 8); + result.append(str.at(i).unicode() & 0xFF); + } + + return result; +} + void TestKeePass2XmlReader::initTestCase() { QVERIFY(Crypto::init()); @@ -98,12 +111,12 @@ void TestKeePass2XmlReader::testMetadata() QCOMPARE(m_db->metadata()->protectUrl(), true); QCOMPARE(m_db->metadata()->protectNotes(), false); QCOMPARE(m_db->metadata()->recycleBinEnabled(), true); - QVERIFY(m_db->metadata()->recycleBin() != Q_NULLPTR); + QVERIFY(m_db->metadata()->recycleBin() != nullptr); QCOMPARE(m_db->metadata()->recycleBin()->name(), QString("Recycle Bin")); QCOMPARE(m_db->metadata()->recycleBinChanged(), genDT(2010, 8, 25, 16, 12, 57)); - QVERIFY(m_db->metadata()->entryTemplatesGroup() == Q_NULLPTR); + QVERIFY(m_db->metadata()->entryTemplatesGroup() == nullptr); QCOMPARE(m_db->metadata()->entryTemplatesGroupChanged(), genDT(2010, 8, 8, 17, 24, 19)); - QVERIFY(m_db->metadata()->lastSelectedGroup() != Q_NULLPTR); + QVERIFY(m_db->metadata()->lastSelectedGroup() != nullptr); QCOMPARE(m_db->metadata()->lastSelectedGroup()->name(), QString("NewDatabase")); QVERIFY(m_db->metadata()->lastTopVisibleGroup() == m_db->metadata()->lastSelectedGroup()); QCOMPARE(m_db->metadata()->historyMaxItems(), -1); @@ -315,7 +328,7 @@ void TestKeePass2XmlReader::testEntry2() void TestKeePass2XmlReader::testEntryHistory() { - const Entry* entryMain = m_db->rootGroup()->entries().first(); + const Entry* entryMain = m_db->rootGroup()->entries().at(0); QCOMPARE(entryMain->historyItems().size(), 2); { @@ -395,6 +408,84 @@ void TestKeePass2XmlReader::testBroken_data() QTest::newRow("BrokenDeletedObjects (not strict)") << "BrokenDeletedObjects" << false << false; } +void TestKeePass2XmlReader::testEmptyUuids() +{ + KeePass2XmlReader reader; + reader.setStrictMode(true); + QString xmlFile = QString("%1/%2.xml").arg(KEEPASSX_TEST_DATA_DIR, "EmptyUuids"); + QVERIFY(QFile::exists(xmlFile)); + QScopedPointer db(reader.readDatabase(xmlFile)); + if (reader.hasError()) { + qWarning("Reader error: %s", qPrintable(reader.errorString())); + } + QVERIFY(!reader.hasError()); +} + +void TestKeePass2XmlReader::testInvalidXmlChars() +{ + QScopedPointer dbWrite(new Database()); + + QString strPlainInvalid = QString().append(QChar(0x02)).append(QChar(0x19)) + .append(QChar(0xFFFE)).append(QChar(0xFFFF)); + QString strPlainValid = QString().append(QChar(0x09)).append(QChar(0x0A)) + .append(QChar(0x20)).append(QChar(0xD7FF)) + .append(QChar(0xE000)).append(QChar(0xFFFD)); + // U+10437 in UTF-16: D801 DC37 + // high low surrogate + QString strSingleHighSurrogate1 = QString().append(QChar(0xD801)); + QString strSingleHighSurrogate2 = QString().append(QChar(0x31)).append(QChar(0xD801)).append(QChar(0x32)); + QString strHighHighSurrogate = QString().append(QChar(0xD801)).append(QChar(0xD801)); + QString strSingleLowSurrogate1 = QString().append(QChar(0xDC37)); + QString strSingleLowSurrogate2 = QString().append(QChar((0x31))).append(QChar(0xDC37)).append(QChar(0x32)); + QString strLowLowSurrogate = QString().append(QChar(0xDC37)).append(QChar(0xDC37)); + QString strSurrogateValid1 = QString().append(QChar(0xD801)).append(QChar(0xDC37)); + QString strSurrogateValid2 = QString().append(QChar(0x31)).append(QChar(0xD801)).append(QChar(0xDC37)).append(QChar(0x32)); + + Entry* entry = new Entry(); + entry->setUuid(Uuid::random()); + entry->setGroup(dbWrite->rootGroup()); + entry->attributes()->set("PlainInvalid", strPlainInvalid); + entry->attributes()->set("PlainValid", strPlainValid); + entry->attributes()->set("SingleHighSurrogate1", strSingleHighSurrogate1); + entry->attributes()->set("SingleHighSurrogate2", strSingleHighSurrogate2); + entry->attributes()->set("HighHighSurrogate", strHighHighSurrogate); + entry->attributes()->set("SingleLowSurrogate1", strSingleLowSurrogate1); + entry->attributes()->set("SingleLowSurrogate2", strSingleLowSurrogate2); + entry->attributes()->set("LowLowSurrogate", strLowLowSurrogate); + entry->attributes()->set("SurrogateValid1", strSurrogateValid1); + entry->attributes()->set("SurrogateValid2", strSurrogateValid2); + + QBuffer buffer; + buffer.open(QIODevice::ReadWrite); + KeePass2XmlWriter writer; + writer.writeDatabase(&buffer, dbWrite.data()); + QVERIFY(!writer.hasError()); + buffer.seek(0); + + KeePass2XmlReader reader; + reader.setStrictMode(true); + QScopedPointer dbRead(reader.readDatabase(&buffer)); + if (reader.hasError()) { + qWarning("Database read error: %s", qPrintable(reader.errorString())); + } + QVERIFY(!reader.hasError()); + QVERIFY(!dbRead.isNull()); + QCOMPARE(dbRead->rootGroup()->entries().size(), 1); + Entry* entryRead = dbRead->rootGroup()->entries().at(0); + EntryAttributes* attrRead = entryRead->attributes(); + + QCOMPARE(strToBytes(attrRead->value("PlainInvalid")), QByteArray()); + QCOMPARE(strToBytes(attrRead->value("PlainValid")), strToBytes(strPlainValid)); + QCOMPARE(strToBytes(attrRead->value("SingleHighSurrogate1")), QByteArray()); + QCOMPARE(strToBytes(attrRead->value("SingleHighSurrogate2")), strToBytes(QString("12"))); + QCOMPARE(strToBytes(attrRead->value("HighHighSurrogate")), QByteArray()); + QCOMPARE(strToBytes(attrRead->value("SingleLowSurrogate1")), QByteArray()); + QCOMPARE(strToBytes(attrRead->value("SingleLowSurrogate2")), strToBytes(QString("12"))); + QCOMPARE(strToBytes(attrRead->value("LowLowSurrogate")), QByteArray()); + QCOMPARE(strToBytes(attrRead->value("SurrogateValid1")), strToBytes(strSurrogateValid1)); + QCOMPARE(strToBytes(attrRead->value("SurrogateValid2")), strToBytes(strSurrogateValid2)); +} + void TestKeePass2XmlReader::cleanupTestCase() { delete m_db; diff --git a/tests/TestKeePass2XmlReader.h b/tests/TestKeePass2XmlReader.h index 6a6c6195..b9be7b55 100644 --- a/tests/TestKeePass2XmlReader.h +++ b/tests/TestKeePass2XmlReader.h @@ -41,10 +41,13 @@ private Q_SLOTS: void testDeletedObjects(); void testBroken(); void testBroken_data(); + void testEmptyUuids(); + void testInvalidXmlChars(); void cleanupTestCase(); private: static QDateTime genDT(int year, int month, int day, int hour, int min, int second); + static QByteArray strToBytes(const QString& str); Database* m_db; }; diff --git a/tests/TestKeys.cpp b/tests/TestKeys.cpp index 770af52d..6c1953fa 100644 --- a/tests/TestKeys.cpp +++ b/tests/TestKeys.cpp @@ -21,7 +21,6 @@ #include #include "config-keepassx-tests.h" -#include "tests.h" #include "core/Database.h" #include "core/Metadata.h" #include "crypto/Crypto.h" @@ -113,6 +112,7 @@ void TestKeys::testFileKey_data() { QTest::addColumn("type"); QTest::newRow("Xml") << QString("Xml"); + QTest::newRow("XmlBrokenBase64") << QString("XmlBrokenBase64"); QTest::newRow("Binary") << QString("Binary"); QTest::newRow("Hex") << QString("Hex"); QTest::newRow("Hashed") << QString("Hashed"); @@ -176,7 +176,7 @@ void TestKeys::benchmarkTransformKey() QByteArray env = qgetenv("BENCHMARK"); if (env.isEmpty() || env == "0" || env == "no") { - QSKIP("Benchmark skipped. Set env variable BENCHMARK=1 to enable.", SkipAll); + QSKIP("Benchmark skipped. Set env variable BENCHMARK=1 to enable."); } PasswordKey pwKey; diff --git a/tests/TestModified.cpp b/tests/TestModified.cpp index e275e837..70a4a484 100644 --- a/tests/TestModified.cpp +++ b/tests/TestModified.cpp @@ -20,7 +20,6 @@ #include #include -#include "tests.h" #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" @@ -237,7 +236,7 @@ void TestModified::testEntrySets() entry->setExpires(entry->timeInfo().expires()); QCOMPARE(spyModified.count(), spyCount); - entry->setExpiryTime(Tools::currentDateTimeUtc().addYears(1)); + entry->setExpiryTime(QDateTime::currentDateTimeUtc().addYears(1)); QCOMPARE(spyModified.count(), ++spyCount); entry->setExpiryTime(entry->timeInfo().expiryTime()); QCOMPARE(spyModified.count(), spyCount); diff --git a/tests/TestQCommandLineParser.cpp b/tests/TestQCommandLineParser.cpp deleted file mode 100644 index 4e2c6350..00000000 --- a/tests/TestQCommandLineParser.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "TestQCommandLineParser.h" - -#include - -#include "tests.h" -#include "core/qcommandlineparser.h" - -QTEST_GUILESS_MAIN(TestQCommandLineParser) - -Q_DECLARE_METATYPE(char**) - -static char *empty_argv[] = { 0 }; -static int empty_argc = 1; - -void TestQCommandLineParser::initTestCase() -{ - Q_ASSERT(!empty_argv[0]); - empty_argv[0] = const_cast("TestQCommandLineParser"); -} - -Q_DECLARE_METATYPE(QCommandLineParser::SingleDashWordOptionMode) - -void TestQCommandLineParser::parsingModes_data() -{ - QTest::addColumn("parsingMode"); - - QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions; - QTest::newRow("implicitlylong") << QCommandLineParser::ParseAsLongOptions; -} - -void TestQCommandLineParser::testInvalidOptions() -{ - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - QTest::ignoreMessage(QtWarningMsg, "QCommandLineOption: Option names cannot start with a '-'"); - parser.addOption(QCommandLineOption("-v", "Displays version information.")); -} - -void TestQCommandLineParser::testPositionalArguments() -{ - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "file.txt")); - QCOMPARE(parser.positionalArguments(), QStringList() << "file.txt"); -} - -void TestQCommandLineParser::testBooleanOption_data() -{ - QTest::addColumn("args"); - QTest::addColumn("expectedOptionNames"); - QTest::addColumn("expectedIsSet"); - - QTest::newRow("set") << (QStringList() << "TestQCommandLineParser" << "-b") << (QStringList() << "b") << true; - QTest::newRow("unset") << (QStringList() << "TestQCommandLineParser") << QStringList() << false; -} - -void TestQCommandLineParser::testBooleanOption() -{ - QFETCH(QStringList, args); - QFETCH(QStringList, expectedOptionNames); - QFETCH(bool, expectedIsSet); - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - QVERIFY(parser.addOption(QCommandLineOption("b", "a boolean option"))); - QVERIFY(parser.parse(args)); - QCOMPARE(parser.optionNames(), expectedOptionNames); - QCOMPARE(parser.isSet("b"), expectedIsSet); - QCOMPARE(parser.values("b"), QStringList()); - QCOMPARE(parser.positionalArguments(), QStringList()); - // Should warn on typos - QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: option not defined: \"c\""); - QVERIFY(!parser.isSet("c")); -} - -void TestQCommandLineParser::testMultipleNames_data() -{ - QTest::addColumn("args"); - QTest::addColumn("expectedOptionNames"); - - QTest::newRow("short") << (QStringList() << "TestQCommandLineParser" << "-v") << (QStringList() << "v"); - QTest::newRow("long") << (QStringList() << "TestQCommandLineParser" << "--version") << (QStringList() << "version"); - QTest::newRow("not_set") << (QStringList() << "TestQCommandLineParser") << QStringList(); -} - -void TestQCommandLineParser::testMultipleNames() -{ - QFETCH(QStringList, args); - QFETCH(QStringList, expectedOptionNames); - QCoreApplication app(empty_argc, empty_argv); - QCommandLineOption option(QStringList() << "v" << "version", "Show version information"); - QCOMPARE(option.names(), QStringList() << "v" << "version"); - QCommandLineParser parser; - QVERIFY(parser.addOption(option)); - QVERIFY(parser.parse(args)); - QCOMPARE(parser.optionNames(), expectedOptionNames); - const bool expectedIsSet = !expectedOptionNames.isEmpty(); - QCOMPARE(parser.isSet("v"), expectedIsSet); - QCOMPARE(parser.isSet("version"), expectedIsSet); -} - -void TestQCommandLineParser::testSingleValueOption_data() -{ - QTest::addColumn("args"); - QTest::addColumn("defaults"); - QTest::addColumn("expectedIsSet"); - - QTest::newRow("short") << (QStringList() << "tst" << "-s" << "oxygen") << QStringList() << true; - QTest::newRow("long") << (QStringList() << "tst" << "--style" << "oxygen") << QStringList() << true; - QTest::newRow("longequal") << (QStringList() << "tst" << "--style=oxygen") << QStringList() << true; - QTest::newRow("default") << (QStringList() << "tst") << (QStringList() << "oxygen") << false; -} - -void TestQCommandLineParser::testSingleValueOption() -{ - QFETCH(QStringList, args); - QFETCH(QStringList, defaults); - QFETCH(bool, expectedIsSet); - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - QCommandLineOption option(QStringList() << "s" << "style", "style name", "styleName"); - option.setDefaultValues(defaults); - QVERIFY(parser.addOption(option)); - for (int mode = 0; mode < 2; ++mode) { - parser.setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode(mode)); - QVERIFY(parser.parse(args)); - QCOMPARE(parser.isSet("s"), expectedIsSet); - QCOMPARE(parser.isSet("style"), expectedIsSet); - QCOMPARE(parser.isSet(option), expectedIsSet); - QCOMPARE(parser.value("s"), QString("oxygen")); - QCOMPARE(parser.value("style"), QString("oxygen")); - QCOMPARE(parser.values("s"), QStringList() << "oxygen"); - QCOMPARE(parser.values("style"), QStringList() << "oxygen"); - QCOMPARE(parser.values(option), QStringList() << "oxygen"); - QCOMPARE(parser.positionalArguments(), QStringList()); - } - // Should warn on typos - QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: option not defined: \"c\""); - QVERIFY(parser.values("c").isEmpty()); -} - -void TestQCommandLineParser::testValueNotSet() -{ - QCoreApplication app(empty_argc, empty_argv); - // Not set, no default value - QCommandLineParser parser; - QCommandLineOption option(QStringList() << "s" << "style", "style name"); - option.setValueName("styleName"); - QVERIFY(parser.addOption(option)); - QVERIFY(parser.parse(QStringList() << "tst")); - QCOMPARE(parser.optionNames(), QStringList()); - QVERIFY(!parser.isSet("s")); - QVERIFY(!parser.isSet("style")); - QCOMPARE(parser.value("s"), QString()); - QCOMPARE(parser.value("style"), QString()); - QCOMPARE(parser.values("s"), QStringList()); - QCOMPARE(parser.values("style"), QStringList()); -} - -void TestQCommandLineParser::testMultipleValuesOption() -{ - QCoreApplication app(empty_argc, empty_argv); - QCommandLineOption option("param", "Pass parameter to the backend."); - option.setValueName("key=value"); - QCommandLineParser parser; - QVERIFY(parser.addOption(option)); - { - QVERIFY(parser.parse(QStringList() << "tst" << "--param" << "key1=value1")); - QVERIFY(parser.isSet("param")); - QCOMPARE(parser.values("param"), QStringList() << "key1=value1"); - QCOMPARE(parser.value("param"), QString("key1=value1")); - } - { - QVERIFY(parser.parse(QStringList() << "tst" << "--param" << "key1=value1" << "--param" << "key2=value2")); - QVERIFY(parser.isSet("param")); - QCOMPARE(parser.values("param"), QStringList() << "key1=value1" << "key2=value2"); - QCOMPARE(parser.value("param"), QString("key2=value2")); - } - - QString expected = - "Usage: TestQCommandLineParser [options]\n" - "\n" - "Options:\n" - " --param Pass parameter to the backend.\n"; - - const QString exeName = QCoreApplication::instance()->arguments().first(); // e.g. debug\tst_qcommandlineparser.exe on Windows - expected.replace("TestQCommandLineParser", exeName); - QCOMPARE(parser.helpText(), expected); -} - -void TestQCommandLineParser::testUnknownOptionErrorHandling_data() -{ - QTest::addColumn("parsingMode"); - QTest::addColumn("args"); - QTest::addColumn("expectedUnknownOptionNames"); - QTest::addColumn("expectedErrorText"); - - const QStringList args_hello = QStringList() << "TestQCommandLineParser" << "--hello"; - const QString error_hello("Unknown option 'hello'."); - QTest::newRow("unknown_name_collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << args_hello << QStringList("hello") << error_hello; - QTest::newRow("unknown_name_long") << QCommandLineParser::ParseAsLongOptions << args_hello << QStringList("hello") << error_hello; - - const QStringList args_value = QStringList() << "TestQCommandLineParser" << "-b=1"; - QTest::newRow("bool_with_value_collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << args_value << QStringList() << QString("Unexpected value after '-b'."); - QTest::newRow("bool_with_value_long") << QCommandLineParser::ParseAsLongOptions << args_value << QStringList() << QString("Unexpected value after '-b'."); - - const QStringList args_dash_long = QStringList() << "TestQCommandLineParser" << "-bool"; - const QString error_bool("Unknown options: o, o, l."); - QTest::newRow("unknown_name_long_collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << args_dash_long << (QStringList() << "o" << "o" << "l") << error_bool; -} - -void TestQCommandLineParser::testUnknownOptionErrorHandling() -{ - QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode); - QFETCH(QStringList, args); - QFETCH(QStringList, expectedUnknownOptionNames); - QFETCH(QString, expectedErrorText); - - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - parser.setSingleDashWordOptionMode(parsingMode); - QVERIFY(parser.addOption(QCommandLineOption(QStringList() << "b" << "bool", "a boolean option"))); - QCOMPARE(parser.parse(args), expectedErrorText.isEmpty()); - QCOMPARE(parser.unknownOptionNames(), expectedUnknownOptionNames); - QCOMPARE(parser.errorText(), expectedErrorText); -} - -void TestQCommandLineParser::testDoubleDash_data() -{ - parsingModes_data(); -} - -void TestQCommandLineParser::testDoubleDash() -{ - QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode); - - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - parser.addOption(QCommandLineOption(QStringList() << "o" << "output", "Output file", "filename")); - parser.setSingleDashWordOptionMode(parsingMode); - QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "--output" << "foo")); - QCOMPARE(parser.value("output"), QString("foo")); - QCOMPARE(parser.positionalArguments(), QStringList()); - QCOMPARE(parser.unknownOptionNames(), QStringList()); - QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "--" << "--output" << "bar" << "-b" << "bleh")); - QCOMPARE(parser.value("output"), QString()); - QCOMPARE(parser.positionalArguments(), QStringList() << "--output" << "bar" << "-b" << "bleh"); - QCOMPARE(parser.unknownOptionNames(), QStringList()); -} - -void TestQCommandLineParser::testDefaultValue() -{ - QCommandLineOption opt("name", "desc", - "valueName", "default"); - QCOMPARE(opt.defaultValues(), QStringList("default")); - opt.setDefaultValue(""); - QCOMPARE(opt.defaultValues(), QStringList()); - opt.setDefaultValue("default"); - QCOMPARE(opt.defaultValues(), QStringList("default")); -} - -void TestQCommandLineParser::testProcessNotCalled() -{ - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - QVERIFY(parser.addOption(QCommandLineOption("b", "a boolean option"))); - QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: call process() or parse() before isSet"); - QVERIFY(!parser.isSet("b")); - QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: call process() or parse() before values"); - QCOMPARE(parser.values("b"), QStringList()); -} - -void TestQCommandLineParser::testEmptyArgsList() -{ - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - QTest::ignoreMessage(QtWarningMsg, "QCommandLineParser: argument list cannot be empty, it should contain at least the executable name"); - QVERIFY(!parser.parse(QStringList())); // invalid call, argv[0] is missing -} - -void TestQCommandLineParser::testMissingOptionValue() -{ - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - parser.addOption(QCommandLineOption("option", "An option", "value")); - QVERIFY(!parser.parse(QStringList() << "argv0" << "--option")); // the user forgot to pass a value for --option - QCOMPARE(parser.value("option"), QString()); - QCOMPARE(parser.errorText(), QString("Missing value after '--option'.")); -} - -void TestQCommandLineParser::testStdinArgument_data() -{ - parsingModes_data(); -} - -void TestQCommandLineParser::testStdinArgument() -{ - QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode); - - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - parser.setSingleDashWordOptionMode(parsingMode); - parser.addOption(QCommandLineOption(QStringList() << "i" << "input", "Input file.", "filename")); - parser.addOption(QCommandLineOption("b", "Boolean option.")); - QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "--input" << "-")); - QCOMPARE(parser.value("input"), QString("-")); - QCOMPARE(parser.positionalArguments(), QStringList()); - QCOMPARE(parser.unknownOptionNames(), QStringList()); - - QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "--input" << "-" << "-b" << "arg")); - QCOMPARE(parser.value("input"), QString("-")); - QVERIFY(parser.isSet("b")); - QCOMPARE(parser.positionalArguments(), QStringList() << "arg"); - QCOMPARE(parser.unknownOptionNames(), QStringList()); - - QVERIFY(parser.parse(QStringList() << "TestQCommandLineParser" << "-")); - QCOMPARE(parser.value("input"), QString()); - QVERIFY(!parser.isSet("b")); - QCOMPARE(parser.positionalArguments(), QStringList() << "-"); - QCOMPARE(parser.unknownOptionNames(), QStringList()); -} - -void TestQCommandLineParser::testSingleDashWordOptionModes_data() -{ - QTest::addColumn("parsingMode"); - QTest::addColumn("commandLine"); - QTest::addColumn("expectedOptionNames"); - QTest::addColumn("expectedOptionValues"); - - QTest::newRow("collapsed") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-abc" << "val") - << (QStringList() << "a" << "b" << "c") << (QStringList() << QString() << QString() << "val"); - QTest::newRow("collapsed_with_equalsign_value") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-abc=val") - << (QStringList() << "a" << "b" << "c") << (QStringList() << QString() << QString() << "val"); - QTest::newRow("collapsed_explicit_longoption") << QCommandLineParser::ParseAsCompactedShortOptions << QStringList("--nn") - << QStringList("nn") << QStringList(); - QTest::newRow("collapsed_longoption_value") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "--abc" << "val") - << QStringList("abc") << QStringList("val"); - QTest::newRow("compiler") << QCommandLineParser::ParseAsCompactedShortOptions << QStringList("-cab") - << QStringList("c") << QStringList("ab"); - QTest::newRow("compiler_with_space") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-c" << "val") - << QStringList("c") << QStringList("val"); - - QTest::newRow("implicitlylong") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-abc" << "val") - << QStringList("abc") << QStringList("val"); - QTest::newRow("implicitlylong_equal") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "-abc=val") - << QStringList("abc") << QStringList("val"); - QTest::newRow("implicitlylong_longoption") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "--nn") - << QStringList("nn") << QStringList(); - QTest::newRow("implicitlylong_longoption_value") << QCommandLineParser::ParseAsLongOptions << (QStringList() << "--abc" << "val") - << QStringList("abc") << QStringList("val"); - QTest::newRow("implicitlylong_with_space") << QCommandLineParser::ParseAsCompactedShortOptions << (QStringList() << "-c" << "val") - << QStringList("c") << QStringList("val"); -} - -void TestQCommandLineParser::testSingleDashWordOptionModes() -{ - QFETCH(QCommandLineParser::SingleDashWordOptionMode, parsingMode); - QFETCH(QStringList, commandLine); - QFETCH(QStringList, expectedOptionNames); - QFETCH(QStringList, expectedOptionValues); - - commandLine.prepend("TestQCommandLineParser"); - - QCoreApplication app(empty_argc, empty_argv); - QCommandLineParser parser; - parser.setSingleDashWordOptionMode(parsingMode); - parser.addOption(QCommandLineOption("a", "a option.")); - parser.addOption(QCommandLineOption("b", "b option.")); - parser.addOption(QCommandLineOption(QStringList() << "c" << "abc", "c option.", "value")); - parser.addOption(QCommandLineOption("nn", "nn option.")); - QVERIFY(parser.parse(commandLine)); - QCOMPARE(parser.optionNames(), expectedOptionNames); - for (int i = 0; i < expectedOptionValues.count(); ++i) - QCOMPARE(parser.value(parser.optionNames().at(i)), expectedOptionValues.at(i)); - QCOMPARE(parser.unknownOptionNames(), QStringList()); -} diff --git a/tests/TestQCommandLineParser.h b/tests/TestQCommandLineParser.h deleted file mode 100644 index 46214cd8..00000000 --- a/tests/TestQCommandLineParser.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef KEEPASSX_TESTQCOMMANDLINEPARSER_H -#define KEEPASSX_TESTQCOMMANDLINEPARSER_H - -#include - -class TestQCommandLineParser : public QObject -{ - Q_OBJECT - -public Q_SLOTS: - void initTestCase(); - -private Q_SLOTS: - void parsingModes_data(); - - // In-process tests - void testInvalidOptions(); - void testPositionalArguments(); - void testBooleanOption_data(); - void testBooleanOption(); - void testMultipleNames_data(); - void testMultipleNames(); - void testSingleValueOption_data(); - void testSingleValueOption(); - void testValueNotSet(); - void testMultipleValuesOption(); - void testUnknownOptionErrorHandling_data(); - void testUnknownOptionErrorHandling(); - void testDoubleDash_data(); - void testDoubleDash(); - void testDefaultValue(); - void testProcessNotCalled(); - void testEmptyArgsList(); - void testMissingOptionValue(); - void testStdinArgument_data(); - void testStdinArgument(); - void testSingleDashWordOptionModes_data(); - void testSingleDashWordOptionModes(); -}; - -#endif // KEEPASSX_TESTQCOMMANDLINEPARSER_H diff --git a/tests/TestQSaveFile.cpp b/tests/TestQSaveFile.cpp deleted file mode 100644 index 443db529..00000000 --- a/tests/TestQSaveFile.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "TestQSaveFile.h" - -#include - -#include - -#if defined(Q_OS_WIN) -# include -#endif - -#include "tests.h" -#include "core/qsavefile.h" - -QTEST_GUILESS_MAIN(TestQSaveFile) - -class DirCleanup -{ -public: - DirCleanup(const QString& dir, const QString& filePrefix) : m_dir(dir), m_filePrefix(filePrefix) {} - ~DirCleanup() { - QDir dir(m_dir); - QStringList files = dir.entryList(QStringList() << (m_filePrefix + "*"), QDir::Files); - Q_FOREACH (const QString& file, files) { - QFile::remove(m_dir + "/" + file); - } - - QDir().rmdir(m_dir); - } - -private: - QString m_dir; - QString m_filePrefix; -}; - -void TestQSaveFile::transactionalWrite() -{ - const QString dir = tmpDir(); - QVERIFY(!dir.isEmpty()); - const QString targetFile = dir + QString::fromLatin1("/outfile"); - DirCleanup dirCleanup(dir, "outfile"); - QFile::remove(targetFile); - QSaveFile file(targetFile); - QVERIFY(file.open(QIODevice::WriteOnly)); - QVERIFY(file.isOpen()); - QCOMPARE(file.fileName(), targetFile); - QVERIFY(!QFile::exists(targetFile)); - - QTextStream ts(&file); - ts << "This is test data one.\n"; - ts.flush(); - QCOMPARE(file.error(), QFile::NoError); - QVERIFY(!QFile::exists(targetFile)); - - QVERIFY(file.commit()); - QVERIFY(QFile::exists(targetFile)); - QCOMPARE(file.fileName(), targetFile); - - // Check that we can reuse a QSaveFile object - // (and test the case of an existing target file) - QVERIFY(file.open(QIODevice::WriteOnly)); - QCOMPARE(file.write("Hello"), 5LL); - QVERIFY(file.commit()); - - QFile reader(targetFile); - QVERIFY(reader.open(QIODevice::ReadOnly)); - QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Hello")); - reader.close(); - - QVERIFY(QFile::remove(targetFile)); -} - -void TestQSaveFile::autoFlush() -{ - const QString dir = tmpDir(); - QVERIFY(!dir.isEmpty()); - const QString targetFile = dir + QString::fromLatin1("/outfile"); - DirCleanup dirCleanup(dir, "outfile"); - QFile::remove(targetFile); - QSaveFile file(targetFile); - QVERIFY(file.open(QIODevice::WriteOnly)); - - QTextStream ts(&file); - ts << "Auto-flush."; - // no flush - QVERIFY(file.commit()); // close will emit aboutToClose, which will flush the stream - QFile reader(targetFile); - QVERIFY(reader.open(QIODevice::ReadOnly)); - QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Auto-flush.")); - reader.close(); - - QVERIFY(QFile::remove(targetFile)); -} - -void TestQSaveFile::transactionalWriteNoPermissions() -{ -#ifdef Q_OS_UNIX - if (::geteuid() == 0) { - QSKIP("not valid running this test as root", SkipAll); - } - - // You can write into /dev/zero, but you can't create a /dev/zero.XXXXXX temp file. - QSaveFile file("/dev/zero"); - if (!QDir("/dev").exists()) { - QSKIP("/dev doesn't exist on this system", SkipAll); - } - - QVERIFY(!file.open(QIODevice::WriteOnly)); - QCOMPARE(static_cast(file.error()), static_cast(QFile::OpenError)); - QVERIFY(!file.commit()); -#endif -} - -void TestQSaveFile::transactionalWriteCanceled() -{ - const QString dir = tmpDir(); - QVERIFY(!dir.isEmpty()); - const QString targetFile = dir + QString::fromLatin1("/outfile"); - DirCleanup dirCleanup(dir, "outfile"); - QFile::remove(targetFile); - QSaveFile file(targetFile); - QVERIFY(file.open(QIODevice::WriteOnly)); - - QTextStream ts(&file); - ts << "This writing operation will soon be canceled.\n"; - ts.flush(); - QCOMPARE(file.error(), QFile::NoError); - QVERIFY(!QFile::exists(targetFile)); - - // We change our mind, let's abort writing - file.cancelWriting(); - - QVERIFY(!file.commit()); - - QVERIFY(!QFile::exists(targetFile)); // temp file was discarded - QCOMPARE(file.fileName(), targetFile); -} - -void TestQSaveFile::transactionalWriteErrorRenaming() -{ -#ifndef Q_OS_WIN - if (::geteuid() == 0) { - QSKIP("not valid running this test as root", SkipAll); - } - const QString dir = tmpDir(); - QVERIFY(!dir.isEmpty()); - const QString targetFile = dir + QString::fromLatin1("/outfile"); - DirCleanup dirCleanup(dir, "outfile"); - QSaveFile file(targetFile); - QVERIFY(file.open(QIODevice::WriteOnly)); - QCOMPARE(file.write("Hello"), qint64(5)); - QVERIFY(!QFile::exists(targetFile)); - -#ifdef Q_OS_UNIX - QFile dirAsFile(dir); // yay, I have to use QFile to change a dir's permissions... - QVERIFY(dirAsFile.setPermissions(QFile::Permissions(0))); // no permissions -#else - QVERIFY(file.setPermissions(QFile::ReadOwner)); -#endif - - QVERIFY(!file.commit()); - QVERIFY(!QFile::exists(targetFile)); // renaming failed - QCOMPARE(file.error(), QFile::RenameError); - - // Restore permissions so that the cleanup can happen -#ifdef Q_OS_UNIX - QVERIFY(dirAsFile.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner))); -#else - QVERIFY(file.setPermissions(QFile::ReadOwner | QFile::WriteOwner)); -#endif -#endif // !Q_OS_WIN -} - -QString TestQSaveFile::tmpDir() -{ - QTemporaryFile* tmpFile = new QTemporaryFile(QDir::tempPath() + "/qttest_temp.XXXXXX"); - if (!tmpFile->open()) { - return QString(); - } - QString dirName = tmpFile->fileName(); - delete tmpFile; - if (!QDir().mkdir(dirName)) { - return QString(); - } - - return dirName; -} diff --git a/tests/TestRandom.cpp b/tests/TestRandom.cpp index 40ab702d..6c5b1f72 100644 --- a/tests/TestRandom.cpp +++ b/tests/TestRandom.cpp @@ -17,8 +17,8 @@ #include "TestRandom.h" -#include "tests.h" #include "core/Endian.h" +#include "core/Global.h" #include diff --git a/tests/TestRandom.h b/tests/TestRandom.h index a308f36e..c879f945 100644 --- a/tests/TestRandom.h +++ b/tests/TestRandom.h @@ -18,7 +18,6 @@ #ifndef KEEPASSX_TESTRANDOM_H #define KEEPASSX_TESTRANDOM_H -#include "core/Global.h" #include "crypto/Random.h" #include @@ -27,7 +26,7 @@ class RandomBackendTest : public RandomBackend { public: RandomBackendTest(); - void randomize(void* data, int len) Q_DECL_OVERRIDE; + void randomize(void* data, int len) override; void setNextBytes(const QByteArray& nextBytes); private: diff --git a/tests/TestSymmetricCipher.cpp b/tests/TestSymmetricCipher.cpp index 55a1bbe3..698ecb20 100644 --- a/tests/TestSymmetricCipher.cpp +++ b/tests/TestSymmetricCipher.cpp @@ -20,7 +20,6 @@ #include #include -#include "tests.h" #include "crypto/Crypto.h" #include "crypto/SymmetricCipher.h" #include "streams/SymmetricCipherStream.h" @@ -207,3 +206,22 @@ void TestSymmetricCipher::testPadding() QByteArray decrypted = streamDec.readAll(); QCOMPARE(decrypted, plainText); } + +void TestSymmetricCipher::testStreamReset() +{ + QByteArray key = QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"); + QByteArray iv = QByteArray::fromHex("000102030405060708090a0b0c0d0e0f"); + + QBuffer buffer; + QVERIFY(buffer.open(QIODevice::WriteOnly)); + SymmetricCipherStream writer(&buffer, SymmetricCipher::Aes256, SymmetricCipher::Cbc, + SymmetricCipher::Encrypt); + QVERIFY(writer.init(key, iv)); + QVERIFY(writer.open(QIODevice::WriteOnly)); + QCOMPARE(writer.write(QByteArray(4, 'Z')), qint64(4)); + // test if reset() and close() write only one block + QVERIFY(writer.reset()); + QVERIFY(writer.reset()); + writer.close(); + QCOMPARE(buffer.buffer().size(), 16); +} diff --git a/tests/TestSymmetricCipher.h b/tests/TestSymmetricCipher.h index e90fe600..1ac45793 100644 --- a/tests/TestSymmetricCipher.h +++ b/tests/TestSymmetricCipher.h @@ -30,6 +30,7 @@ private Q_SLOTS: void testAes256CbcDecryption(); void testSalsa20(); void testPadding(); + void testStreamReset(); }; #endif // KEEPASSX_TESTSYMMETRICCIPHER_H diff --git a/tests/TestWildcardMatcher.cpp b/tests/TestWildcardMatcher.cpp index dc9991db..dffe1c85 100644 --- a/tests/TestWildcardMatcher.cpp +++ b/tests/TestWildcardMatcher.cpp @@ -19,7 +19,6 @@ #include -#include "tests.h" #include "autotype/WildcardMatcher.h" QTEST_GUILESS_MAIN(TestWildcardMatcher) diff --git a/tests/data/EmptyUuids.xml b/tests/data/EmptyUuids.xml new file mode 100644 index 00000000..8734acf8 --- /dev/null +++ b/tests/data/EmptyUuids.xml @@ -0,0 +1,44 @@ + + + + KeePass + ANAME + 2010-08-08T17:24:53Z + ADESC + 2010-08-08T17:27:12Z + DEFUSERNAME + 2010-08-08T17:27:45Z + 127 + #FFEF00 + 2012-04-05T17:09:34Z + 101 + -1 + + + True + + 2010-08-25T16:12:57Z + + 2010-08-08T17:24:19Z + + + -1 + 5242880 + + + + + + lmU+9n0aeESKZvcEze+bRg== + NewDatabase + + 49 + + True + + null + null + + + + \ No newline at end of file diff --git a/tests/data/FileKeyXmlBrokenBase64.kdbx b/tests/data/FileKeyXmlBrokenBase64.kdbx new file mode 100644 index 00000000..7c3ee30f Binary files /dev/null and b/tests/data/FileKeyXmlBrokenBase64.kdbx differ diff --git a/tests/data/FileKeyXmlBrokenBase64.key b/tests/data/FileKeyXmlBrokenBase64.key new file mode 100644 index 00000000..530ecec2 --- /dev/null +++ b/tests/data/FileKeyXmlBrokenBase64.key @@ -0,0 +1,9 @@ + + + + 1.00 + + + yy + + diff --git a/tests/data/bug392.kdbx b/tests/data/bug392.kdbx new file mode 100644 index 00000000..0953d867 Binary files /dev/null and b/tests/data/bug392.kdbx differ diff --git a/tests/gui/CMakeLists.txt b/tests/gui/CMakeLists.txt index 91fcd695..a1ca914f 100644 --- a/tests/gui/CMakeLists.txt +++ b/tests/gui/CMakeLists.txt @@ -13,6 +13,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -add_unit_test(NAME testgui SOURCES TestGui.cpp MOCS TestGui.h LIBS ${TEST_LIBRARIES}) +add_unit_test(NAME testgui SOURCES TestGui.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testguipixmaps SOURCES TestGuiPixmaps.cpp MOCS TestGuiPixmaps.h LIBS ${TEST_LIBRARIES}) +add_unit_test(NAME testguipixmaps SOURCES TestGuiPixmaps.cpp LIBS ${TEST_LIBRARIES}) diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index c3d95b35..1585c8a6 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include #include "config-keepassx-tests.h" -#include "tests.h" #include "core/Config.h" #include "core/Database.h" #include "core/Entry.h" @@ -56,12 +56,23 @@ void TestGui::initTestCase() m_mainWindow = new MainWindow(); m_tabWidget = m_mainWindow->findChild("tabWidget"); m_mainWindow->show(); + m_mainWindow->activateWindow(); Tools::wait(50); + + QByteArray tmpData; + QFile sourceDbFile(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.kdbx")); + QVERIFY(sourceDbFile.open(QIODevice::ReadOnly)); + QVERIFY(Tools::readAllFromDevice(&sourceDbFile, tmpData)); + + QVERIFY(m_orgDbFile.open()); + m_orgDbFileName = QFileInfo(m_orgDbFile.fileName()).fileName(); + QCOMPARE(m_orgDbFile.write(tmpData), static_cast((tmpData.size()))); + m_orgDbFile.close(); } void TestGui::testOpenDatabase() { - fileDialog()->setNextFileName(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.kdbx")); + fileDialog()->setNextFileName(m_orgDbFile.fileName()); triggerAction("actionDatabaseOpen"); QWidget* databaseOpenWidget = m_mainWindow->findChild("databaseOpenWidget"); @@ -75,7 +86,7 @@ void TestGui::testOpenDatabase() void TestGui::testTabs() { QCOMPARE(m_tabWidget->count(), 1); - QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("NewDatabase.kdbx")); + QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), m_orgDbFileName); m_dbWidget = m_tabWidget->currentDatabaseWidget(); m_db = m_dbWidget->database(); @@ -103,7 +114,7 @@ void TestGui::testEditEntry() QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); // make sure the database isn't marked as modified // wait for modified timer - QTRY_COMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("NewDatabase.kdbx")); + QTRY_COMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), m_orgDbFileName); } void TestGui::testAddEntry() @@ -134,7 +145,7 @@ void TestGui::testAddEntry() QCOMPARE(entry->title(), QString("test")); QCOMPARE(entry->historyItems().size(), 0); // wait for modified timer - QTRY_COMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("NewDatabase.kdbx*")); + QTRY_COMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("%1*").arg(m_orgDbFileName)); QAction* entryEditAction = m_mainWindow->findChild("actionEntryEdit"); QVERIFY(entryEditAction->isEnabled()); @@ -174,7 +185,7 @@ void TestGui::testSearch() QLineEdit* searchEdit = m_dbWidget->findChild("searchEdit"); QToolButton* clearSearch = m_dbWidget->findChild("clearButton"); - QVERIFY(!searchEdit->hasFocus()); + QVERIFY(!searchEdit->isVisible()); // Enter search QTest::mouseClick(searchActionWidget, Qt::LeftButton); @@ -200,6 +211,10 @@ void TestGui::testSearch() // Search for "some" QTest::keyClicks(searchEdit, "some"); QTRY_COMPARE(entryView->model()->rowCount(), 4); + // Press Down to focus on the entry view + QVERIFY(!entryView->hasFocus()); + QTest::keyClick(searchEdit, Qt::Key_Down); + QVERIFY(entryView->hasFocus()); clickIndex(entryView->model()->index(0, 1), entryView, Qt::LeftButton); QAction* entryEditAction = m_mainWindow->findChild("actionEntryEdit"); @@ -352,7 +367,7 @@ void TestGui::testDragAndDropGroup() void TestGui::testSaveAs() { - QFileInfo fileInfo(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.kdbx")); + QFileInfo fileInfo(m_orgDbFile.fileName()); QDateTime lastModified = fileInfo.lastModified(); m_db->metadata()->setName("SaveAs"); @@ -425,8 +440,8 @@ void TestGui::testDatabaseLocking() triggerAction("actionLockDatabases"); - QCOMPARE(m_tabWidget->tabText(0), QString("Save [locked]")); - QCOMPARE(m_tabWidget->tabText(1), QString("basic [New database]*")); + QCOMPARE(m_tabWidget->tabText(0).remove('&'), QString("Save [locked]")); + QCOMPARE(m_tabWidget->tabText(1).remove('&'), QString("basic [New database]*")); QWidget* dbWidget = m_tabWidget->currentDatabaseWidget(); QWidget* unlockDatabaseWidget = dbWidget->findChild("unlockDatabaseWidget"); @@ -436,7 +451,7 @@ void TestGui::testDatabaseLocking() QTest::keyClicks(editPassword, "masterpw"); QTest::keyClick(editPassword, Qt::Key_Enter); - QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("basic [New database]*")); + QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()).remove('&'), QString("basic [New database]*")); } void TestGui::cleanupTestCase() diff --git a/tests/gui/TestGui.h b/tests/gui/TestGui.h index 84167f0d..a7474ca5 100644 --- a/tests/gui/TestGui.h +++ b/tests/gui/TestGui.h @@ -20,6 +20,7 @@ #include #include +#include class Database; class DatabaseTabWidget; @@ -60,6 +61,8 @@ private: MainWindow* m_mainWindow; DatabaseTabWidget* m_tabWidget; DatabaseWidget* m_dbWidget; + QTemporaryFile m_orgDbFile; + QString m_orgDbFileName; QString m_tmpFileName; Database* m_db; }; diff --git a/tests/gui/TestGuiPixmaps.cpp b/tests/gui/TestGuiPixmaps.cpp index 87e3f248..36374947 100644 --- a/tests/gui/TestGuiPixmaps.cpp +++ b/tests/gui/TestGuiPixmaps.cpp @@ -19,7 +19,6 @@ #include -#include "tests.h" #include "core/Database.h" #include "core/DatabaseIcons.h" #include "core/Entry.h" diff --git a/tests/modeltest.cpp b/tests/modeltest.cpp index 19f02d9d..360a7bef 100644 --- a/tests/modeltest.cpp +++ b/tests/modeltest.cpp @@ -1,50 +1,40 @@ /**************************************************************************** ** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** ** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** ** $QT_END_LICENSE$ ** ****************************************************************************/ - #include "modeltest.h" -#include -#include - -Q_DECLARE_METATYPE ( QModelIndex ) +#include +#include /*! Connect to all of the models signals. Whenever anything happens recheck everything. @@ -54,50 +44,52 @@ ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( if (!model) qFatal("%s: model must not be null", Q_FUNC_INFO); - connect ( model, SIGNAL ( columnsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( columnsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( dataChanged ( const QModelIndex &, const QModelIndex & ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( headerDataChanged ( Qt::Orientation, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( layoutAboutToBeChanged () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( layoutChanged () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( modelReset () ), this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); - connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( runAllTests() ) ); + connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT(runAllTests()) ); + connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT(runAllTests()) ); + connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)), + this, SLOT(runAllTests()) ); + connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), + this, SLOT(runAllTests()) ); + connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(runAllTests()) ); + connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), + this, SLOT(runAllTests()) ); + connect(model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(runAllTests()) ); + connect(model, SIGNAL(layoutChanged()), this, SLOT(runAllTests()) ); + connect(model, SIGNAL(modelReset()), this, SLOT(runAllTests()) ); + connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT(runAllTests()) ); + connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT(runAllTests()) ); + connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(runAllTests()) ); + connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(runAllTests()) ); - // Special checks for inserting/removing - connect ( model, SIGNAL ( layoutAboutToBeChanged() ), - this, SLOT ( layoutAboutToBeChanged() ) ); - connect ( model, SIGNAL ( layoutChanged() ), - this, SLOT ( layoutChanged() ) ); - - connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsInserted ( const QModelIndex &, int, int ) ) ); - connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), - this, SLOT ( rowsRemoved ( const QModelIndex &, int, int ) ) ); - - connect ( model, SIGNAL (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) ); - connect ( model, SIGNAL (rowsMoved(QModelIndex,int,int,QModelIndex,int)), - this, SLOT (rowsMoved(QModelIndex,int,int,QModelIndex,int)) ); + // Special checks for changes + connect(model, SIGNAL(layoutAboutToBeChanged()), + this, SLOT(layoutAboutToBeChanged()) ); + connect(model, SIGNAL(layoutChanged()), + this, SLOT(layoutChanged()) ); + connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), + this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)) ); + connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)) ); + connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), + this, SLOT(rowsInserted(QModelIndex,int,int)) ); + connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), + this, SLOT(rowsRemoved(QModelIndex,int,int)) ); + connect(model, SIGNAL (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), + this, SLOT (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) ); + connect(model, SIGNAL (rowsMoved(QModelIndex,int,int,QModelIndex,int)), + this, SLOT (rowsMoved(QModelIndex,int,int,QModelIndex,int)) ); + connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + this, SLOT(dataChanged(QModelIndex,QModelIndex)) ); + connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), + this, SLOT(headerDataChanged(Qt::Orientation,int,int)) ); runAllTests(); } @@ -257,7 +249,7 @@ void ModelTest::index() void ModelTest::parent() { // qDebug() << "p"; - // Make sure the model wont crash and will return an invalid QModelIndex + // Make sure the model won't crash and will return an invalid QModelIndex // when asked for the parent of an invalid index. QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); @@ -339,6 +331,8 @@ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows // << "columns:" << columns << "parent column:" << parent.column(); + const QModelIndex topLeftChild = model->index( 0, 0, parent ); + QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) ); for ( int r = 0; r < rows; ++r ) { if ( model->canFetchMore ( parent ) ) { @@ -362,6 +356,15 @@ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) QModelIndex b = model->index ( r, c, parent ); QVERIFY( a == b ); + { + const QModelIndex sibling = model->sibling( r, c, topLeftChild ); + QVERIFY( index == sibling ); + } + { + const QModelIndex sibling = topLeftChild.sibling( r, c ); + QVERIFY( index == sibling ); + } + // Some basic checking on the index that is returned QVERIFY( index.model() == model ); QCOMPARE( index.row(), r ); @@ -474,9 +477,9 @@ void ModelTest::data() \sa rowsInserted() */ -void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end ) +void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int /* end */) { - Q_UNUSED(end); +// Q_UNUSED(end); // qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString() // << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) ); // qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) ); @@ -565,6 +568,30 @@ void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) ); } +void ModelTest::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) +{ + QVERIFY(topLeft.isValid()); + QVERIFY(bottomRight.isValid()); + QModelIndex commonParent = bottomRight.parent(); + QVERIFY(topLeft.parent() == commonParent); + QVERIFY(topLeft.row() <= bottomRight.row()); + QVERIFY(topLeft.column() <= bottomRight.column()); + int rowCount = model->rowCount(commonParent); + int columnCount = model->columnCount(commonParent); + QVERIFY(bottomRight.row() < rowCount); + QVERIFY(bottomRight.column() < columnCount); +} + +void ModelTest::headerDataChanged(Qt::Orientation orientation, int start, int end) +{ + QVERIFY(start >= 0); + QVERIFY(end >= 0); + QVERIFY(start <= end); + int itemCount = orientation == Qt::Vertical ? model->rowCount() : model->columnCount(); + QVERIFY(start < itemCount); + QVERIFY(end < itemCount); +} + void ModelTest::rowsAboutToBeMoved( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow ) { Changing cs; @@ -589,8 +616,8 @@ void ModelTest::rowsMoved( const QModelIndex &srcParent, int start, int end, con QVERIFY ( cd.oldSize == model->rowCount ( destParent ) ); // TODO: Find out what I can assert here about last and next. - // QVERIFY ( cd.last == model->data ( model->index ( destinationRow - 1, 0, cd.parent ) ) ); - // QVERIFY ( cd.next == model->data ( model->index ( destinationRow + (end - start + 1), 0, cd.parent ) ) ); + // Q_ASSERT ( cd.last == model->data ( model->index ( destinationRow - 1, 0, cd.parent ) ) ); + // Q_ASSERT ( cd.next == model->data ( model->index ( destinationRow + (end - start + 1), 0, cd.parent ) ) ); } else { QVERIFY ( cd.oldSize + ( end - start + 1 ) == model->rowCount ( destParent ) ); @@ -602,12 +629,12 @@ void ModelTest::rowsMoved( const QModelIndex &srcParent, int start, int end, con Changing cs = remove.pop(); QVERIFY ( cs.parent == srcParent ); if (srcParent == destParent) { - QVERIFY ( cs.oldSize == model->rowCount ( srcParent ) ); + QVERIFY ( cs.oldSize == model->rowCount ( srcParent ) ); } else { - QVERIFY ( cs.oldSize - ( end - start + 1 ) == model->rowCount ( srcParent ) ); + QVERIFY ( cs.oldSize - ( end - start + 1 ) == model->rowCount ( srcParent ) ); - QVERIFY ( cs.last == model->data ( model->index ( start - 1, 0, srcParent ) ) ); - QVERIFY ( cs.next == model->data ( model->index ( start, 0, srcParent ) ) ); + QVERIFY ( cs.last == model->data ( model->index ( start - 1, 0, srcParent ) ) ); + QVERIFY ( cs.next == model->data ( model->index ( start, 0, srcParent ) ) ); } } diff --git a/tests/modeltest.h b/tests/modeltest.h index 9eb343d7..3dcf18ce 100644 --- a/tests/modeltest.h +++ b/tests/modeltest.h @@ -1,40 +1,32 @@ /**************************************************************************** ** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** ** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -43,8 +35,8 @@ #ifndef MODELTEST_H #define MODELTEST_H -#include #include +#include #include class ModelTest : public QObject @@ -73,7 +65,8 @@ protected Q_SLOTS: void rowsRemoved( const QModelIndex & parent, int start, int end ); void rowsAboutToBeMoved ( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow ); void rowsMoved ( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow ); - + void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void headerDataChanged(Qt::Orientation orientation, int start, int end); private: void checkChildren( const QModelIndex &parent, int currentDepth = 0 ); diff --git a/tests/tests.h b/tests/tests.h deleted file mode 100644 index e719a0bf..00000000 --- a/tests/tests.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2011 Felix Geyer - * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef KEEPASSX_TESTS_H -#define KEEPASSX_TESTS_H - -#include - -// backport QTEST_GUILESS_MAIN, QTRY_VERIFY and QTRY_COMPARE from Qt 5 - -#ifndef QTEST_GUILESS_MAIN -#define QTEST_GUILESS_MAIN(TestObject) \ -int main(int argc, char* argv[]) \ -{ \ - QCoreApplication app(argc, argv); \ - TestObject tc; \ - return QTest::qExec(&tc, argc, argv); \ -} -#endif // QTEST_GUILESS_MAIN - - -#ifndef QTRY_VERIFY -#define KEEPASSX_VERIFY_WITH_TIMEOUT(__expr, __timeout) \ -do { \ - const int __step = 50; \ - const int __timeoutValue = __timeout; \ - if (!(__expr)) { \ - QTest::qWait(0); \ - } \ - for (int __i = 0; __i < __timeoutValue && !(__expr); __i+=__step) { \ - QTest::qWait(__step); \ - } \ - QVERIFY(__expr); \ -} while (0) - -#define QTRY_VERIFY(__expr) KEEPASSX_VERIFY_WITH_TIMEOUT(__expr, 5000) -#endif // QTRY_VERIFY - - -#ifndef QTRY_COMPARE -#define KEEPASSX_COMPARE_WITH_TIMEOUT(__expr, __expected, __timeout) \ -do { \ - const int __step = 50; \ - const int __timeoutValue = __timeout; \ - if ((__expr) != (__expected)) { \ - QTest::qWait(0); \ - } \ - for (int __i = 0; __i < __timeoutValue && ((__expr) != (__expected)); __i+=__step) { \ - QTest::qWait(__step); \ - } \ - QCOMPARE(__expr, __expected); \ -} while (0) - -#define QTRY_COMPARE(__expr, __expected) KEEPASSX_COMPARE_WITH_TIMEOUT(__expr, __expected, 5000) -#endif // QTRY_COMPARE - -#endif // KEEPASSX_TESTS_H diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index c4aa5fa9..7988467f 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -18,7 +18,8 @@ include_directories(../src) add_executable(kdbx-extract kdbx-extract.cpp) target_link_libraries(kdbx-extract keepassx_core - ${QT_QTCORE_LIBRARY} - ${QT_QTGUI_LIBRARY} + Qt5::Core + Qt5::Concurrent + Qt5::Widgets ${GCRYPT_LIBRARIES} ${ZLIB_LIBRARIES})