Compare commits
151 Commits
2.0-alpha4
...
2.0-alpha6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43a1d54bba | ||
|
|
2963752585 | ||
|
|
1decdc6c11 | ||
|
|
6659745e2b | ||
|
|
1e2d1a1b17 | ||
|
|
f300ca5b7b | ||
|
|
b9370c6e79 | ||
|
|
54bb7462f6 | ||
|
|
4a08101a60 | ||
|
|
809be5f89e | ||
|
|
bf9a755bea | ||
|
|
34b82da9aa | ||
|
|
e0c59395da | ||
|
|
b07de47e35 | ||
|
|
586de64293 | ||
|
|
9321943e64 | ||
|
|
c00550078c | ||
|
|
2190260a68 | ||
|
|
678c4a8ece | ||
|
|
c2781274a0 | ||
|
|
bc14898b13 | ||
|
|
b6497d9245 | ||
|
|
79d827ffa4 | ||
|
|
811eb2714f | ||
|
|
a914b837a1 | ||
|
|
04c9332a99 | ||
|
|
97f374a189 | ||
|
|
6f3648d63e | ||
|
|
350cf4b00a | ||
|
|
3af2307468 | ||
|
|
29c997e1bc | ||
|
|
223c5a1651 | ||
|
|
8b437821a2 | ||
|
|
4ded95a060 | ||
|
|
0b6b149351 | ||
|
|
eee909e948 | ||
|
|
8c7e655274 | ||
|
|
8e86437e89 | ||
|
|
a8edad1e27 | ||
|
|
41162ea2e8 | ||
|
|
0cbf59209b | ||
|
|
0f91e0d141 | ||
|
|
6a50a76466 | ||
|
|
1fce1ac905 | ||
|
|
b9a955c048 | ||
|
|
5a577e5e4c | ||
|
|
f648172625 | ||
|
|
4b41dd30e6 | ||
|
|
2a416d1f1d | ||
|
|
23f338b0c3 | ||
|
|
cdcea91b50 | ||
|
|
4549c97e51 | ||
|
|
fc3cc12038 | ||
|
|
62ea117f45 | ||
|
|
3d8ff5b585 | ||
|
|
a3b95c1c38 | ||
|
|
2308099260 | ||
|
|
4a3da3abe7 | ||
|
|
3e4811791a | ||
|
|
34f12ac39c | ||
|
|
af98c2636c | ||
|
|
f21b331844 | ||
|
|
ea628af580 | ||
|
|
9cae8a412a | ||
|
|
47b7befd2f | ||
|
|
2fcc369c41 | ||
|
|
66b3d22041 | ||
|
|
03e4b2d13c | ||
|
|
c83579ecdb | ||
|
|
a26119ea20 | ||
|
|
98c821df05 | ||
|
|
a992c76d6a | ||
|
|
f2dfef8c41 | ||
|
|
cb804eb143 | ||
|
|
74e912ccd3 | ||
|
|
1f47033835 | ||
|
|
3fcfc348ed | ||
|
|
6b33298a6e | ||
|
|
68e1fc0cd0 | ||
|
|
31796d33fb | ||
|
|
755241df5c | ||
|
|
9080864167 | ||
|
|
d25e883983 | ||
|
|
091e87aeb3 | ||
|
|
4a870f61f1 | ||
|
|
5daf0853c9 | ||
|
|
ef3d7b7772 | ||
|
|
7dde8a771f | ||
|
|
3dd4681e69 | ||
|
|
98d888063b | ||
|
|
9c788a6e84 | ||
|
|
e087baeb48 | ||
|
|
b64276c4e8 | ||
|
|
f7dd63a126 | ||
|
|
a68a86f19b | ||
|
|
984b23de70 | ||
|
|
d5b70b1bef | ||
|
|
551637f0c2 | ||
|
|
8778df5789 | ||
|
|
67338aac7b | ||
|
|
626351c5da | ||
|
|
6504b6f2bd | ||
|
|
035271d469 | ||
|
|
5c84aa308d | ||
|
|
e1c82a4453 | ||
|
|
db6ac26794 | ||
|
|
a505d85792 | ||
|
|
6df30df992 | ||
|
|
0ec29b2354 | ||
|
|
f1bebe904a | ||
|
|
e16720d06d | ||
|
|
3be7fa6b3b | ||
|
|
e99e3ae6ca | ||
|
|
d182586557 | ||
|
|
1f5564760f | ||
|
|
2be045eb8f | ||
|
|
7a89510916 | ||
|
|
5588792344 | ||
|
|
3acb33e05a | ||
|
|
61ee763515 | ||
|
|
3658a65380 | ||
|
|
fd18bc0330 | ||
|
|
b499a6df77 | ||
|
|
cabec57631 | ||
|
|
63f7a0685f | ||
|
|
94e6d3f89b | ||
|
|
94ac9c9ea1 | ||
|
|
bbf183bef7 | ||
|
|
6f92188323 | ||
|
|
f0985ff9d9 | ||
|
|
ba3baf3595 | ||
|
|
34c6b416b0 | ||
|
|
bf906a7867 | ||
|
|
5786e2620a | ||
|
|
fe42861bed | ||
|
|
5a96e19ce9 | ||
|
|
8ed0379136 | ||
|
|
4e2f5b1a5b | ||
|
|
317f603262 | ||
|
|
701013baab | ||
|
|
4b3bee6400 | ||
|
|
91868969ca | ||
|
|
ef46b3e8ad | ||
|
|
9e87230102 | ||
|
|
2558e6db79 | ||
|
|
bee570c3cf | ||
|
|
be288d26ca | ||
|
|
b055780984 | ||
|
|
e805a6ff82 | ||
|
|
60335452a4 | ||
|
|
3a822c24e2 |
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
CMakeLists.txt.*
|
CMakeLists.txt.*
|
||||||
|
build/
|
||||||
|
|||||||
27
CHANGELOG
@@ -1,3 +1,29 @@
|
|||||||
|
2.0 Alpha 6 (2014-04-06)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
- Add option to lock databases after user inactivity [#62]
|
||||||
|
- Add compatibility with libgcrypt 1.6 [#129]
|
||||||
|
- Display passwords in monospace font [#51]
|
||||||
|
- Use an icon for the button that shows/masks passwords [#38]
|
||||||
|
- Add an option to show passwords by default [#93]
|
||||||
|
- Improve password generator design [#122]
|
||||||
|
- On Linux link .kdbx files with KeePassX
|
||||||
|
- Remember window size [#154]
|
||||||
|
- Disallow global auto-typing when the database is locked
|
||||||
|
|
||||||
|
2.0 Alpha 5 (2013-12-20)
|
||||||
|
=========================
|
||||||
|
|
||||||
|
- Support copying entries and groups using drag'n'drop [#74]
|
||||||
|
- Open last used databases on startup [#36]
|
||||||
|
- Made the kdbx file parser more robust
|
||||||
|
- Only edit entries on doubleclick (not single) or with enter key
|
||||||
|
- Allow removing multiple entries
|
||||||
|
- Added option to minimize window when copying data to clipboard
|
||||||
|
- Save password generator settings
|
||||||
|
- Fixed auto-type producing wrong chars in some keyboard configurations [#116]
|
||||||
|
- Added some more actions to the toolbar
|
||||||
|
|
||||||
2.0 Alpha 4 (2013-03-29)
|
2.0 Alpha 4 (2013-03-29)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
@@ -29,7 +55,6 @@
|
|||||||
- Sortable entry view
|
- Sortable entry view
|
||||||
- Support building Mac OS X bundles
|
- Support building Mac OS X bundles
|
||||||
|
|
||||||
|
|
||||||
2.0 Alpha 1 (2012-05-07)
|
2.0 Alpha 1 (2012-05-07)
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,12 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
|
||||||
|
"Choose the type of build, options are: None Debug Release RelWithDebInfo Debug Debugfull Profile MinSizeRel."
|
||||||
|
FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
project(KeePassX)
|
project(KeePassX)
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 2.6.4)
|
cmake_minimum_required(VERSION 2.6.4)
|
||||||
@@ -28,8 +34,8 @@ option(WITH_GUI_TESTS "Enable building of GUI tests" OFF)
|
|||||||
option(WITH_LTO "Enable Link Time Optimization (LTO)" OFF)
|
option(WITH_LTO "Enable Link Time Optimization (LTO)" OFF)
|
||||||
option(WITH_CXX11 "Build with the C++ 11 standard" OFF)
|
option(WITH_CXX11 "Build with the C++ 11 standard" OFF)
|
||||||
|
|
||||||
set(KEEPASSX_VERSION "2.0 alpha 4")
|
set(KEEPASSX_VERSION "2.0 alpha 6")
|
||||||
set(KEEPASSX_VERSION_NUM "1.9.83")
|
set(KEEPASSX_VERSION_NUM "1.9.85")
|
||||||
|
|
||||||
if("${CMAKE_C_COMPILER}" MATCHES "clang$" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
if("${CMAKE_C_COMPILER}" MATCHES "clang$" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
|
||||||
set(CMAKE_COMPILER_IS_CLANG 1)
|
set(CMAKE_COMPILER_IS_CLANG 1)
|
||||||
@@ -58,14 +64,21 @@ 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_NO_STL -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII)
|
||||||
|
|
||||||
add_gcc_compiler_flags("-fno-common -fstack-protector -D_FORTIFY_SOURCE=2")
|
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")
|
add_gcc_compiler_flags("-Wall -Wextra -Wundef -Wpointer-arith -Wno-long-long")
|
||||||
add_gcc_compiler_flags("-Wformat=2 -Wmissing-format-attribute")
|
add_gcc_compiler_flags("-Wformat=2 -Wmissing-format-attribute")
|
||||||
|
add_gcc_compiler_flags("-fvisibility=hidden")
|
||||||
|
add_gcc_compiler_cxxflags("-fvisibility-inlines-hidden")
|
||||||
|
|
||||||
add_gcc_compiler_cxxflags("-fno-exceptions -fno-rtti")
|
add_gcc_compiler_cxxflags("-fno-exceptions -fno-rtti")
|
||||||
add_gcc_compiler_cxxflags("-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual")
|
add_gcc_compiler_cxxflags("-Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual")
|
||||||
add_gcc_compiler_cflags("-Wchar-subscripts -Wwrite-strings")
|
add_gcc_compiler_cflags("-Wchar-subscripts -Wwrite-strings")
|
||||||
|
|
||||||
|
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
|
||||||
|
if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
|
||||||
|
add_gcc_compiler_flags("-D_FORTIFY_SOURCE=2")
|
||||||
|
endif()
|
||||||
|
|
||||||
check_c_compiler_flag("-Werror=format-security -Werror=implicit-function-declaration" WERROR_C_AVAILABLE)
|
check_c_compiler_flag("-Werror=format-security -Werror=implicit-function-declaration" WERROR_C_AVAILABLE)
|
||||||
check_cxx_compiler_flag("-Werror=format-security" WERROR_CXX_AVAILABLE)
|
check_cxx_compiler_flag("-Werror=format-security" WERROR_CXX_AVAILABLE)
|
||||||
if(WERROR_C_AVAILABLE AND WERROR_CXX_AVAILABLE)
|
if(WERROR_C_AVAILABLE AND WERROR_CXX_AVAILABLE)
|
||||||
@@ -73,16 +86,12 @@ if(WERROR_C_AVAILABLE AND WERROR_CXX_AVAILABLE)
|
|||||||
add_gcc_compiler_cflags("-Werror=implicit-function-declaration")
|
add_gcc_compiler_cflags("-Werror=implicit-function-declaration")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_CLANGXX)
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -stack-protector-buffer-size=4")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align")
|
||||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wcast-align --param=ssp-buffer-size=4")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_CLANG)
|
if(CMAKE_COMPILER_IS_GNUCC)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mllvm -stack-protector-buffer-size=4")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align")
|
||||||
elseif(CMAKE_COMPILER_IS_GNUCC)
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-align --param=ssp-buffer-size=4")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
@@ -138,9 +147,11 @@ elseif(APPLE)
|
|||||||
set(PLUGIN_INSTALL_DIR ".")
|
set(PLUGIN_INSTALL_DIR ".")
|
||||||
set(DATA_INSTALL_DIR "${PROGNAME}.app/Contents/Resources")
|
set(DATA_INSTALL_DIR "${PROGNAME}.app/Contents/Resources")
|
||||||
else()
|
else()
|
||||||
set(BIN_INSTALL_DIR "bin")
|
include(GNUInstallDirs)
|
||||||
set(PLUGIN_INSTALL_DIR "lib/keepassx")
|
|
||||||
set(DATA_INSTALL_DIR "share/keepassx")
|
set(BIN_INSTALL_DIR "${CMAKE_INSTALL_BINDIR}")
|
||||||
|
set(PLUGIN_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/keepassx")
|
||||||
|
set(DATA_INSTALL_DIR "${CMAKE_INSTALL_DATAROOTDIR}/keepassx")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_TESTS)
|
if(WITH_TESTS)
|
||||||
@@ -153,16 +164,13 @@ if(UNIX AND NOT APPLE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Qt4 4.6.0 REQUIRED ${QT_REQUIRED_MODULES})
|
find_package(Qt4 4.6.0 REQUIRED ${QT_REQUIRED_MODULES})
|
||||||
add_definitions(${QT_DEFINITIONS} -DQT_CORE_LIB -DQT_GUI_LIB)
|
include(${QT_USE_FILE})
|
||||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG QT_DEBUG)
|
|
||||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG)
|
|
||||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG)
|
|
||||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG)
|
|
||||||
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
|
|
||||||
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS QT_NO_DEBUG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(Gcrypt REQUIRED)
|
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(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
|
|
||||||
@@ -201,7 +209,12 @@ if(UNIX)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(SYSTEM ${QT_INCLUDE_DIR} ${GCRYPT_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
|
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()
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(share)
|
add_subdirectory(share)
|
||||||
@@ -209,3 +222,7 @@ add_subdirectory(utils)
|
|||||||
if(WITH_TESTS)
|
if(WITH_TESTS)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif(WITH_TESTS)
|
endif(WITH_TESTS)
|
||||||
|
|
||||||
|
if(PRINT_SUMMARY)
|
||||||
|
feature_summary(WHAT ALL)
|
||||||
|
endif()
|
||||||
|
|||||||
11
COPYING
@@ -25,8 +25,15 @@ Copyright: 2010-2012, Felix Geyer <debfx@fobos.de>
|
|||||||
2012, Intel Corporation
|
2012, Intel Corporation
|
||||||
2012, Nokia Corporation and/or its subsidiary(-ies)
|
2012, Nokia Corporation and/or its subsidiary(-ies)
|
||||||
2000-2008, Tom Sato <VEF00200@nifty.ne.jp>
|
2000-2008, Tom Sato <VEF00200@nifty.ne.jp>
|
||||||
|
2013, Laszlo Papp <lpapp@kde.org>
|
||||||
|
2013, David Faure <faure@kde.org>
|
||||||
License: GPL-2 or GPL-3
|
License: GPL-2 or GPL-3
|
||||||
|
|
||||||
|
Files: cmake/GNUInstallDirs.cmake
|
||||||
|
Copyright: 2011 Nikita Krupen'ko <krnekit@gmail.com>
|
||||||
|
2011 Kitware, Inc.
|
||||||
|
License: BSD-3-clause
|
||||||
|
|
||||||
Files: share/icons/application/*/apps/keepassx.png
|
Files: share/icons/application/*/apps/keepassx.png
|
||||||
share/icons/application/scalable/apps/keepassx.svgz
|
share/icons/application/scalable/apps/keepassx.svgz
|
||||||
Copyright: 2006, Otto Salminen
|
Copyright: 2006, Otto Salminen
|
||||||
@@ -122,16 +129,20 @@ Files: share/icons/application/*/actions/application-exit.png
|
|||||||
share/icons/application/*/actions/dialog-ok.png
|
share/icons/application/*/actions/dialog-ok.png
|
||||||
share/icons/application/*/actions/document-close.png
|
share/icons/application/*/actions/document-close.png
|
||||||
share/icons/application/*/actions/document-edit.png
|
share/icons/application/*/actions/document-edit.png
|
||||||
|
share/icons/application/*/actions/document-encrypt.png
|
||||||
share/icons/application/*/actions/document-new.png
|
share/icons/application/*/actions/document-new.png
|
||||||
share/icons/application/*/actions/document-open.png
|
share/icons/application/*/actions/document-open.png
|
||||||
share/icons/application/*/actions/document-save.png
|
share/icons/application/*/actions/document-save.png
|
||||||
share/icons/application/*/actions/document-save-as.png
|
share/icons/application/*/actions/document-save-as.png
|
||||||
share/icons/application/*/actions/edit-clear-locationbar-ltr.png
|
share/icons/application/*/actions/edit-clear-locationbar-ltr.png
|
||||||
share/icons/application/*/actions/edit-clear-locationbar-rtl.png
|
share/icons/application/*/actions/edit-clear-locationbar-rtl.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/system-search.png
|
||||||
share/icons/application/*/status/dialog-error.png
|
share/icons/application/*/status/dialog-error.png
|
||||||
share/icons/application/*/status/dialog-information.png
|
share/icons/application/*/status/dialog-information.png
|
||||||
share/icons/application/*/status/dialog-warning.png
|
share/icons/application/*/status/dialog-warning.png
|
||||||
|
share/icons/application/*/status/username-copy.png
|
||||||
share/icons/svg/*.svgz
|
share/icons/svg/*.svgz
|
||||||
Copyright: 2007, Nuno Pinheiro <nuno@oxygen-icons.org>
|
Copyright: 2007, Nuno Pinheiro <nuno@oxygen-icons.org>
|
||||||
2007, David Vignoni <david@icon-king.com>
|
2007, David Vignoni <david@icon-king.com>
|
||||||
|
|||||||
14
INSTALL
@@ -16,15 +16,13 @@ Installing:
|
|||||||
===========
|
===========
|
||||||
make install [DESTDIR=X]
|
make install [DESTDIR=X]
|
||||||
|
|
||||||
|
Create a bundle on Mac:
|
||||||
|
make package
|
||||||
|
|
||||||
Run tests:
|
Run tests:
|
||||||
==========
|
==========
|
||||||
make test [CTEST_OUTPUT_ON_FAILURE=1] [ARGS+=-jX] [ARGS+="-E testgui"]
|
make test [CTEST_OUTPUT_ON_FAILURE=1] [ARGS+=-jX] [ARGS+="-E testgui"]
|
||||||
|
|
||||||
Building on Mac OS X:
|
OS specific instructions:
|
||||||
=====================
|
=========================
|
||||||
Install macports and cmake
|
https://www.keepassx.org/dev/projects/keepassx/wiki/Install_instructions
|
||||||
Open /opt/local/etc/macports/macports.conf and set the architecture(s) you want to build for.
|
|
||||||
Run: sudo port install qt4-mac libgcrypt zlib
|
|
||||||
If you want to build a universal binary append " +universal" to the above command.
|
|
||||||
Pass -DCMAKE_OSX_ARCHITECTURES="<ARCH1>;<ARCH2>" to cmake
|
|
||||||
Run: make package
|
|
||||||
|
|||||||
@@ -17,7 +17,15 @@ find_path(GCRYPT_INCLUDE_DIR gcrypt.h)
|
|||||||
|
|
||||||
find_library(GCRYPT_LIBRARIES gcrypt)
|
find_library(GCRYPT_LIBRARIES gcrypt)
|
||||||
|
|
||||||
|
mark_as_advanced(GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIR)
|
||||||
|
|
||||||
|
if(GCRYPT_INCLUDE_DIR AND EXISTS "${GCRYPT_INCLUDE_DIR}/gcrypt.h")
|
||||||
|
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" GCRYPT_H REGEX "^#define GCRYPT_VERSION \"[^\"]*\"$")
|
||||||
|
string(REGEX REPLACE "^.*GCRYPT_VERSION \"([0-9]+).*$" "\\1" GCRYPT_VERSION_MAJOR "${GCRYPT_H}")
|
||||||
|
string(REGEX REPLACE "^.*GCRYPT_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" GCRYPT_VERSION_MINOR "${GCRYPT_H}")
|
||||||
|
string(REGEX REPLACE "^.*GCRYPT_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" GCRYPT_VERSION_PATCH "${GCRYPT_H}")
|
||||||
|
set(GCRYPT_VERSION_STRING "${GCRYPT_VERSION_MAJOR}.${GCRYPT_VERSION_MINOR}.${GCRYPT_VERSION_PATCH}")
|
||||||
|
endif()
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
find_package_handle_standard_args(Gcrypt DEFAULT_MSG GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIR)
|
find_package_handle_standard_args(Gcrypt DEFAULT_MSG GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIR)
|
||||||
|
|
||||||
mark_as_advanced(GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIR)
|
|
||||||
|
|||||||
188
cmake/GNUInstallDirs.cmake
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
# - Define GNU standard installation directories
|
||||||
|
# Provides install directory variables as defined for GNU software:
|
||||||
|
# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
|
||||||
|
# Inclusion of this module defines the following variables:
|
||||||
|
# CMAKE_INSTALL_<dir> - destination for files of a given type
|
||||||
|
# CMAKE_INSTALL_FULL_<dir> - corresponding absolute path
|
||||||
|
# where <dir> is one of:
|
||||||
|
# BINDIR - user executables (bin)
|
||||||
|
# SBINDIR - system admin executables (sbin)
|
||||||
|
# LIBEXECDIR - program executables (libexec)
|
||||||
|
# SYSCONFDIR - read-only single-machine data (etc)
|
||||||
|
# SHAREDSTATEDIR - modifiable architecture-independent data (com)
|
||||||
|
# LOCALSTATEDIR - modifiable single-machine data (var)
|
||||||
|
# LIBDIR - object code libraries (lib or lib64 or lib/<multiarch-tuple> on Debian)
|
||||||
|
# INCLUDEDIR - C header files (include)
|
||||||
|
# OLDINCLUDEDIR - C header files for non-gcc (/usr/include)
|
||||||
|
# DATAROOTDIR - read-only architecture-independent data root (share)
|
||||||
|
# DATADIR - read-only architecture-independent data (DATAROOTDIR)
|
||||||
|
# INFODIR - info documentation (DATAROOTDIR/info)
|
||||||
|
# LOCALEDIR - locale-dependent data (DATAROOTDIR/locale)
|
||||||
|
# MANDIR - man documentation (DATAROOTDIR/man)
|
||||||
|
# DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME)
|
||||||
|
# Each CMAKE_INSTALL_<dir> value may be passed to the DESTINATION options of
|
||||||
|
# install() commands for the corresponding file type. If the includer does
|
||||||
|
# not define a value the above-shown default will be used and the value will
|
||||||
|
# appear in the cache for editing by the user.
|
||||||
|
# Each CMAKE_INSTALL_FULL_<dir> value contains an absolute path constructed
|
||||||
|
# from the corresponding destination by prepending (if necessary) the value
|
||||||
|
# of CMAKE_INSTALL_PREFIX.
|
||||||
|
|
||||||
|
#=============================================================================
|
||||||
|
# Copyright 2011 Nikita Krupen'ko <krnekit@gmail.com>
|
||||||
|
# Copyright 2011 Kitware, Inc.
|
||||||
|
#
|
||||||
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
|
# see accompanying file Copyright.txt for details.
|
||||||
|
#
|
||||||
|
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||||
|
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
# See the License for more information.
|
||||||
|
#=============================================================================
|
||||||
|
# (To distribute this file outside of CMake, substitute the full
|
||||||
|
# License text for the above reference.)
|
||||||
|
|
||||||
|
# Installation directories
|
||||||
|
#
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_BINDIR)
|
||||||
|
set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_SBINDIR)
|
||||||
|
set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR)
|
||||||
|
set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR)
|
||||||
|
set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR)
|
||||||
|
set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR)
|
||||||
|
set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
|
||||||
|
set(_LIBDIR_DEFAULT "lib")
|
||||||
|
# Override this default 'lib' with 'lib64' iff:
|
||||||
|
# - we are on Linux system but NOT cross-compiling
|
||||||
|
# - we are NOT on debian
|
||||||
|
# - we are on a 64 bits system
|
||||||
|
# reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
|
||||||
|
# For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if
|
||||||
|
# CMAKE_LIBRARY_ARCHITECTURE is set (which contains e.g. "i386-linux-gnu"
|
||||||
|
# See http://wiki.debian.org/Multiarch
|
||||||
|
if((CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU")
|
||||||
|
AND NOT CMAKE_CROSSCOMPILING)
|
||||||
|
if (EXISTS "/etc/debian_version") # is this a debian system ?
|
||||||
|
if(CMAKE_LIBRARY_ARCHITECTURE)
|
||||||
|
set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
|
||||||
|
endif()
|
||||||
|
else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
|
||||||
|
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
|
||||||
|
message(AUTHOR_WARNING
|
||||||
|
"Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
|
||||||
|
"Please enable at least one language before including GNUInstallDirs.")
|
||||||
|
else()
|
||||||
|
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
|
||||||
|
set(_LIBDIR_DEFAULT "lib64")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
|
||||||
|
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR)
|
||||||
|
set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR)
|
||||||
|
set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Values whose defaults are relative to DATAROOTDIR. Store empty values in
|
||||||
|
# the cache and store the defaults in local variables if the cache values are
|
||||||
|
# not set explicitly. This auto-updates the defaults as DATAROOTDIR changes.
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_DATADIR)
|
||||||
|
set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)")
|
||||||
|
set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_INFODIR)
|
||||||
|
set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)")
|
||||||
|
set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_LOCALEDIR)
|
||||||
|
set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)")
|
||||||
|
set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_MANDIR)
|
||||||
|
set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)")
|
||||||
|
set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_INSTALL_DOCDIR)
|
||||||
|
set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
|
||||||
|
set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
mark_as_advanced(
|
||||||
|
CMAKE_INSTALL_BINDIR
|
||||||
|
CMAKE_INSTALL_SBINDIR
|
||||||
|
CMAKE_INSTALL_LIBEXECDIR
|
||||||
|
CMAKE_INSTALL_SYSCONFDIR
|
||||||
|
CMAKE_INSTALL_SHAREDSTATEDIR
|
||||||
|
CMAKE_INSTALL_LOCALSTATEDIR
|
||||||
|
CMAKE_INSTALL_LIBDIR
|
||||||
|
CMAKE_INSTALL_INCLUDEDIR
|
||||||
|
CMAKE_INSTALL_OLDINCLUDEDIR
|
||||||
|
CMAKE_INSTALL_DATAROOTDIR
|
||||||
|
CMAKE_INSTALL_DATADIR
|
||||||
|
CMAKE_INSTALL_INFODIR
|
||||||
|
CMAKE_INSTALL_LOCALEDIR
|
||||||
|
CMAKE_INSTALL_MANDIR
|
||||||
|
CMAKE_INSTALL_DOCDIR
|
||||||
|
)
|
||||||
|
|
||||||
|
# Result directories
|
||||||
|
#
|
||||||
|
foreach(dir
|
||||||
|
BINDIR
|
||||||
|
SBINDIR
|
||||||
|
LIBEXECDIR
|
||||||
|
SYSCONFDIR
|
||||||
|
SHAREDSTATEDIR
|
||||||
|
LOCALSTATEDIR
|
||||||
|
LIBDIR
|
||||||
|
INCLUDEDIR
|
||||||
|
OLDINCLUDEDIR
|
||||||
|
DATAROOTDIR
|
||||||
|
DATADIR
|
||||||
|
INFODIR
|
||||||
|
LOCALEDIR
|
||||||
|
MANDIR
|
||||||
|
DOCDIR
|
||||||
|
)
|
||||||
|
if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
|
||||||
|
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
|
||||||
|
else()
|
||||||
|
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
@@ -20,6 +20,10 @@ install(FILES ${DATABASE_ICONS} DESTINATION ${DATA_INSTALL_DIR}/icons/database)
|
|||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
install(DIRECTORY icons/application/ DESTINATION share/icons/hicolor
|
install(DIRECTORY icons/application/ DESTINATION share/icons/hicolor
|
||||||
FILES_MATCHING PATTERN "keepassx.png" PATTERN "keepassx.svgz")
|
FILES_MATCHING PATTERN "keepassx.png" PATTERN "keepassx.svgz")
|
||||||
|
install(DIRECTORY icons/application/ DESTINATION share/icons/hicolor
|
||||||
|
FILES_MATCHING PATTERN "application-x-keepassx.png" PATTERN "application-x-keepassx.svgz")
|
||||||
|
install(FILES linux/keepassx.desktop DESTINATION share/applications)
|
||||||
|
install(FILES linux/keepassx.xml DESTINATION share/mime/packages)
|
||||||
endif(UNIX AND NOT APPLE)
|
endif(UNIX AND NOT APPLE)
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
|
|||||||
|
After Width: | Height: | Size: 9.0 KiB |
BIN
share/icons/application/16x16/actions/password-copy.png
Normal file
|
After Width: | Height: | Size: 670 B |
BIN
share/icons/application/16x16/actions/password-show-off.png
Normal file
|
After Width: | Height: | Size: 783 B |
BIN
share/icons/application/16x16/actions/password-show-on.png
Normal file
|
After Width: | Height: | Size: 838 B |
BIN
share/icons/application/16x16/actions/username-copy.png
Normal file
|
After Width: | Height: | Size: 766 B |
|
After Width: | Height: | Size: 711 B |
BIN
share/icons/application/22x22/actions/document-encrypt.png
Normal file
|
After Width: | Height: | Size: 604 B |
BIN
share/icons/application/22x22/actions/document-open.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
share/icons/application/22x22/actions/document-save.png
Normal file
|
After Width: | Height: | Size: 798 B |
BIN
share/icons/application/22x22/actions/password-copy.png
Normal file
|
After Width: | Height: | Size: 966 B |
BIN
share/icons/application/22x22/actions/username-copy.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
BIN
share/icons/svg/application-x-keepassx-16.svgz
Normal file
BIN
share/icons/svg/application-x-keepassx.svgz
Normal file
BIN
share/icons/svg/password-copy.svgz
Normal file
BIN
share/icons/svg/username-copy.svgz
Normal file
12
share/linux/keepassx.desktop
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=KeePassX
|
||||||
|
GenericName=Cross Platform Password Manager
|
||||||
|
GenericName[de]=Passwortverwaltung
|
||||||
|
GenericName[es]=Gestor de contraseñas multiplataforma
|
||||||
|
GenericName[fr]=Gestionnaire de mot de passe
|
||||||
|
Exec=keepassx %f
|
||||||
|
Icon=keepassx
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
Categories=Qt;Utility;
|
||||||
|
MimeType=application/x-keepass2;
|
||||||
8
share/linux/keepassx.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
|
||||||
|
<mime-type type="application/x-keepass2">
|
||||||
|
<comment>KeePass 2 database</comment>
|
||||||
|
<glob pattern="*.kdbx"/>
|
||||||
|
<icon name="application-x-keepassx"/>
|
||||||
|
</mime-type>
|
||||||
|
</mime-info>
|
||||||
@@ -20,11 +20,13 @@ configure_file(config-keepassx.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-keepas
|
|||||||
set(keepassx_SOURCES
|
set(keepassx_SOURCES
|
||||||
autotype/AutoType.cpp
|
autotype/AutoType.cpp
|
||||||
autotype/AutoTypeAction.cpp
|
autotype/AutoTypeAction.cpp
|
||||||
|
autotype/AutoTypePlatformPlugin.h
|
||||||
autotype/AutoTypeSelectDialog.cpp
|
autotype/AutoTypeSelectDialog.cpp
|
||||||
autotype/AutoTypeSelectView.cpp
|
autotype/AutoTypeSelectView.cpp
|
||||||
autotype/ShortcutWidget.cpp
|
autotype/ShortcutWidget.cpp
|
||||||
autotype/WildcardMatcher.cpp
|
autotype/WildcardMatcher.cpp
|
||||||
autotype/WindowSelectComboBox.cpp
|
autotype/WindowSelectComboBox.cpp
|
||||||
|
autotype/test/AutoTypeTestInterface.h
|
||||||
core/AutoTypeAssociations.cpp
|
core/AutoTypeAssociations.cpp
|
||||||
core/Config.cpp
|
core/Config.cpp
|
||||||
core/Database.cpp
|
core/Database.cpp
|
||||||
@@ -34,28 +36,27 @@ set(keepassx_SOURCES
|
|||||||
core/EntryAttachments.cpp
|
core/EntryAttachments.cpp
|
||||||
core/EntryAttributes.cpp
|
core/EntryAttributes.cpp
|
||||||
core/FilePath.cpp
|
core/FilePath.cpp
|
||||||
|
core/Global.h
|
||||||
core/Group.cpp
|
core/Group.cpp
|
||||||
|
core/InactivityTimer.cpp
|
||||||
core/ListDeleter.h
|
core/ListDeleter.h
|
||||||
core/Metadata.cpp
|
core/Metadata.cpp
|
||||||
core/PasswordGenerator.cpp
|
core/PasswordGenerator.cpp
|
||||||
core/qsavefile.cpp
|
core/qsavefile.cpp
|
||||||
|
core/qsavefile_p.h
|
||||||
core/SignalMultiplexer.cpp
|
core/SignalMultiplexer.cpp
|
||||||
core/TimeDelta.cpp
|
core/TimeDelta.cpp
|
||||||
core/TimeInfo.cpp
|
core/TimeInfo.cpp
|
||||||
core/Tools.cpp
|
core/Tools.cpp
|
||||||
core/Uuid.cpp
|
core/Uuid.cpp
|
||||||
|
core/qcommandlineoption.cpp
|
||||||
|
core/qcommandlineparser.cpp
|
||||||
crypto/Crypto.cpp
|
crypto/Crypto.cpp
|
||||||
crypto/CryptoHash.cpp
|
crypto/CryptoHash.cpp
|
||||||
crypto/Random.cpp
|
crypto/Random.cpp
|
||||||
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/SymmetricCipher.cpp
|
crypto/SymmetricCipher.cpp
|
||||||
crypto/SymmetricCipherBackend.h
|
crypto/SymmetricCipherBackend.h
|
||||||
crypto/SymmetricCipherGcrypt.cpp
|
crypto/SymmetricCipherGcrypt.cpp
|
||||||
crypto/SymmetricCipherSalsa20.cpp
|
|
||||||
format/KeePass1.h
|
format/KeePass1.h
|
||||||
format/KeePass1Reader.cpp
|
format/KeePass1Reader.cpp
|
||||||
format/KeePass2.h
|
format/KeePass2.h
|
||||||
@@ -82,13 +83,17 @@ set(keepassx_SOURCES
|
|||||||
gui/KeePass1OpenWidget.cpp
|
gui/KeePass1OpenWidget.cpp
|
||||||
gui/LineEdit.cpp
|
gui/LineEdit.cpp
|
||||||
gui/MainWindow.cpp
|
gui/MainWindow.cpp
|
||||||
|
gui/MessageBox.cpp
|
||||||
|
gui/PasswordEdit.cpp
|
||||||
gui/PasswordGeneratorWidget.cpp
|
gui/PasswordGeneratorWidget.cpp
|
||||||
|
gui/PasswordComboBox.cpp
|
||||||
gui/SettingsWidget.cpp
|
gui/SettingsWidget.cpp
|
||||||
gui/SortFilterHideProxyModel.cpp
|
gui/SortFilterHideProxyModel.cpp
|
||||||
gui/UnlockDatabaseWidget.cpp
|
gui/UnlockDatabaseWidget.cpp
|
||||||
gui/WelcomeWidget.cpp
|
gui/WelcomeWidget.cpp
|
||||||
gui/entry/AutoTypeAssociationsModel.cpp
|
gui/entry/AutoTypeAssociationsModel.cpp
|
||||||
gui/entry/EditEntryWidget.cpp
|
gui/entry/EditEntryWidget.cpp
|
||||||
|
gui/entry/EditEntryWidget_p.h
|
||||||
gui/entry/EntryAttachmentsModel.cpp
|
gui/entry/EntryAttachmentsModel.cpp
|
||||||
gui/entry/EntryAttributesModel.cpp
|
gui/entry/EntryAttributesModel.cpp
|
||||||
gui/entry/EntryHistoryModel.cpp
|
gui/entry/EntryHistoryModel.cpp
|
||||||
@@ -98,6 +103,7 @@ set(keepassx_SOURCES
|
|||||||
gui/group/GroupModel.cpp
|
gui/group/GroupModel.cpp
|
||||||
gui/group/GroupView.cpp
|
gui/group/GroupView.cpp
|
||||||
keys/CompositeKey.cpp
|
keys/CompositeKey.cpp
|
||||||
|
keys/CompositeKey_p.h
|
||||||
keys/FileKey.cpp
|
keys/FileKey.cpp
|
||||||
keys/Key.h
|
keys/Key.h
|
||||||
keys/PasswordKey.cpp
|
keys/PasswordKey.cpp
|
||||||
@@ -108,6 +114,18 @@ set(keepassx_SOURCES
|
|||||||
streams/SymmetricCipherStream.cpp
|
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()
|
||||||
|
|
||||||
set(keepassx_SOURCES_MAINEXE
|
set(keepassx_SOURCES_MAINEXE
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
@@ -125,6 +143,7 @@ set(keepassx_MOC
|
|||||||
core/EntryAttachments.h
|
core/EntryAttachments.h
|
||||||
core/EntryAttributes.h
|
core/EntryAttributes.h
|
||||||
core/Group.h
|
core/Group.h
|
||||||
|
core/InactivityTimer.h
|
||||||
core/Metadata.h
|
core/Metadata.h
|
||||||
core/qsavefile.h
|
core/qsavefile.h
|
||||||
gui/AboutDialog.h
|
gui/AboutDialog.h
|
||||||
@@ -144,7 +163,9 @@ set(keepassx_MOC
|
|||||||
gui/KeePass1OpenWidget.h
|
gui/KeePass1OpenWidget.h
|
||||||
gui/LineEdit.h
|
gui/LineEdit.h
|
||||||
gui/MainWindow.h
|
gui/MainWindow.h
|
||||||
|
gui/PasswordEdit.h
|
||||||
gui/PasswordGeneratorWidget.h
|
gui/PasswordGeneratorWidget.h
|
||||||
|
gui/PasswordComboBox.h
|
||||||
gui/SettingsWidget.h
|
gui/SettingsWidget.h
|
||||||
gui/SortFilterHideProxyModel.h
|
gui/SortFilterHideProxyModel.h
|
||||||
gui/UnlockDatabaseWidget.h
|
gui/UnlockDatabaseWidget.h
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
#include "AutoType.h"
|
#include "AutoType.h"
|
||||||
|
|
||||||
#include <QtCore/QPluginLoader>
|
#include <QApplication>
|
||||||
#include <QtGui/QApplication>
|
#include <QPluginLoader>
|
||||||
|
|
||||||
#include "autotype/AutoTypePlatformPlugin.h"
|
#include "autotype/AutoTypePlatformPlugin.h"
|
||||||
#include "autotype/AutoTypeSelectDialog.h"
|
#include "autotype/AutoTypeSelectDialog.h"
|
||||||
@@ -40,6 +40,7 @@ AutoType::AutoType(QObject* parent, bool test)
|
|||||||
, m_pluginLoader(new QPluginLoader(this))
|
, m_pluginLoader(new QPluginLoader(this))
|
||||||
, m_plugin(Q_NULLPTR)
|
, m_plugin(Q_NULLPTR)
|
||||||
, m_executor(Q_NULLPTR)
|
, m_executor(Q_NULLPTR)
|
||||||
|
, m_windowFromGlobal(0)
|
||||||
{
|
{
|
||||||
// prevent crash when the plugin has unresolved symbols
|
// prevent crash when the plugin has unresolved symbols
|
||||||
m_pluginLoader->setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
m_pluginLoader->setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
||||||
@@ -57,11 +58,16 @@ AutoType::AutoType(QObject* parent, bool test)
|
|||||||
if (!pluginPath.isEmpty()) {
|
if (!pluginPath.isEmpty()) {
|
||||||
loadPlugin(pluginPath);
|
loadPlugin(pluginPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
connect(qApp, SIGNAL(aboutToQuit()), SLOT(unloadPlugin()));
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoType::~AutoType()
|
AutoType::~AutoType()
|
||||||
{
|
{
|
||||||
delete m_executor;
|
if (m_executor) {
|
||||||
|
delete m_executor;
|
||||||
|
m_executor = Q_NULLPTR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoType::loadPlugin(const QString& pluginPath)
|
void AutoType::loadPlugin(const QString& pluginPath)
|
||||||
@@ -215,6 +221,19 @@ void AutoType::resetInAutoType()
|
|||||||
m_inAutoType = false;
|
m_inAutoType = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoType::unloadPlugin()
|
||||||
|
{
|
||||||
|
if (m_executor) {
|
||||||
|
delete m_executor;
|
||||||
|
m_executor = Q_NULLPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_plugin) {
|
||||||
|
m_plugin->unload();
|
||||||
|
m_plugin = Q_NULLPTR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool AutoType::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
|
bool AutoType::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
|
||||||
{
|
{
|
||||||
Q_ASSERT(key);
|
Q_ASSERT(key);
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
#ifndef KEEPASSX_AUTOTYPE_H
|
#ifndef KEEPASSX_AUTOTYPE_H
|
||||||
#define KEEPASSX_AUTOTYPE_H
|
#define KEEPASSX_AUTOTYPE_H
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QObject>
|
||||||
#include <QtCore/QStringList>
|
#include <QStringList>
|
||||||
#include <QtGui/QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
@@ -59,6 +59,7 @@ Q_SIGNALS:
|
|||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void performAutoTypeFromGlobal(Entry* entry, const QString& sequence);
|
void performAutoTypeFromGlobal(Entry* entry, const QString& sequence);
|
||||||
void resetInAutoType();
|
void resetInAutoType();
|
||||||
|
void unloadPlugin();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit AutoType(QObject* parent = Q_NULLPTR, bool test = false);
|
explicit AutoType(QObject* parent = Q_NULLPTR, bool test = false);
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#ifndef KEEPASSX_AUTOTYPEACTION_H
|
#ifndef KEEPASSX_AUTOTYPEACTION_H
|
||||||
#define KEEPASSX_AUTOTYPEACTION_H
|
#define KEEPASSX_AUTOTYPEACTION_H
|
||||||
|
|
||||||
#include <QtCore/QChar>
|
#include <QChar>
|
||||||
#include <QtCore/Qt>
|
#include <Qt>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef KEEPASSX_AUTOTYPEPLATFORMPLUGIN_H
|
#ifndef KEEPASSX_AUTOTYPEPLATFORMPLUGIN_H
|
||||||
#define KEEPASSX_AUTOTYPEPLATFORMPLUGIN_H
|
#define KEEPASSX_AUTOTYPEPLATFORMPLUGIN_H
|
||||||
|
|
||||||
#include <QtGui/QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "autotype/AutoTypeAction.h"
|
#include "autotype/AutoTypeAction.h"
|
||||||
|
|
||||||
@@ -33,6 +33,7 @@ public:
|
|||||||
virtual void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) = 0;
|
virtual void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) = 0;
|
||||||
virtual int platformEventFilter(void* event) = 0;
|
virtual int platformEventFilter(void* event) = 0;
|
||||||
virtual int initialTimeout() = 0;
|
virtual int initialTimeout() = 0;
|
||||||
|
virtual void unload() {}
|
||||||
|
|
||||||
virtual AutoTypeExecutor* createExecutor() = 0;
|
virtual AutoTypeExecutor* createExecutor() = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,11 @@
|
|||||||
|
|
||||||
#include "AutoTypeSelectDialog.h"
|
#include "AutoTypeSelectDialog.h"
|
||||||
|
|
||||||
#include <QtGui/QApplication>
|
#include <QApplication>
|
||||||
#include <QtGui/QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
#include <QtGui/QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QtGui/QLabel>
|
#include <QLabel>
|
||||||
#include <QtGui/QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include "autotype/AutoTypeSelectView.h"
|
#include "autotype/AutoTypeSelectView.h"
|
||||||
#include "core/FilePath.h"
|
#include "core/FilePath.h"
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
#ifndef KEEPASSX_AUTOTYPESELECTDIALOG_H
|
#ifndef KEEPASSX_AUTOTYPESELECTDIALOG_H
|
||||||
#define KEEPASSX_AUTOTYPESELECTDIALOG_H
|
#define KEEPASSX_AUTOTYPESELECTDIALOG_H
|
||||||
|
|
||||||
#include <QtCore/QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
#include <QtCore/QHash>
|
#include <QDialog>
|
||||||
#include <QtGui/QDialog>
|
#include <QHash>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "AutoTypeSelectView.h"
|
#include "AutoTypeSelectView.h"
|
||||||
|
|
||||||
#include <QtGui/QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
|
||||||
AutoTypeSelectView::AutoTypeSelectView(QWidget* parent)
|
AutoTypeSelectView::AutoTypeSelectView(QWidget* parent)
|
||||||
: EntryView(parent)
|
: EntryView(parent)
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
if(Q_WS_X11)
|
if(Q_WS_X11)
|
||||||
find_package(X11)
|
find_package(X11)
|
||||||
|
if(PRINT_SUMMARY)
|
||||||
|
add_feature_info(libXtest X11_XTest_FOUND "The X11 XTEST Protocol library is required for auto-type")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(X11_FOUND AND X11_XTest_FOUND)
|
if(X11_FOUND AND X11_XTest_FOUND)
|
||||||
add_subdirectory(x11)
|
add_subdirectory(x11)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "ShortcutWidget.h"
|
#include "ShortcutWidget.h"
|
||||||
|
|
||||||
#include <QtGui/QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
|
||||||
#include "autotype/AutoType.h"
|
#include "autotype/AutoType.h"
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef KEEPASSX_SHORTCUTWIDGET_H
|
#ifndef KEEPASSX_SHORTCUTWIDGET_H
|
||||||
#define KEEPASSX_SHORTCUTWIDGET_H
|
#define KEEPASSX_SHORTCUTWIDGET_H
|
||||||
|
|
||||||
#include <QtGui/QLineEdit>
|
#include <QLineEdit>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "WildcardMatcher.h"
|
#include "WildcardMatcher.h"
|
||||||
|
|
||||||
#include <QtCore/QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
const QChar WildcardMatcher::Wildcard = '*';
|
const QChar WildcardMatcher::Wildcard = '*';
|
||||||
const Qt::CaseSensitivity WildcardMatcher::Sensitivity = Qt::CaseInsensitive;
|
const Qt::CaseSensitivity WildcardMatcher::Sensitivity = Qt::CaseInsensitive;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef KEEPASSX_WILDCARDMATCHER_H
|
#ifndef KEEPASSX_WILDCARDMATCHER_H
|
||||||
#define KEEPASSX_WILDCARDMATCHER_H
|
#define KEEPASSX_WILDCARDMATCHER_H
|
||||||
|
|
||||||
#include <QtCore/QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
class WildcardMatcher
|
class WildcardMatcher
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "WindowSelectComboBox.h"
|
#include "WindowSelectComboBox.h"
|
||||||
|
|
||||||
#include <QtGui/QLineEdit>
|
#include <QLineEdit>
|
||||||
|
|
||||||
#include "autotype/AutoType.h"
|
#include "autotype/AutoType.h"
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef KEEPASSX_WINDOWSELECTCOMBOBOX_H
|
#ifndef KEEPASSX_WINDOWSELECTCOMBOBOX_H
|
||||||
#define KEEPASSX_WINDOWSELECTCOMBOBOX_H
|
#define KEEPASSX_WINDOWSELECTCOMBOBOX_H
|
||||||
|
|
||||||
#include <QtGui/QComboBox>
|
#include <QComboBox>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef KEEPASSX_AUTOTYPETEST_H
|
#ifndef KEEPASSX_AUTOTYPETEST_H
|
||||||
#define KEEPASSX_AUTOTYPETEST_H
|
#define KEEPASSX_AUTOTYPETEST_H
|
||||||
|
|
||||||
#include <QtCore/QtPlugin>
|
#include <QtPlugin>
|
||||||
|
|
||||||
#include "autotype/AutoTypePlatformPlugin.h"
|
#include "autotype/AutoTypePlatformPlugin.h"
|
||||||
#include "autotype/AutoTypeAction.h"
|
#include "autotype/AutoTypeAction.h"
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "AutoTypeX11.h"
|
#include "AutoTypeX11.h"
|
||||||
|
#include "KeySymMap.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
bool AutoTypePlatformX11::m_catchXErrors = false;
|
bool AutoTypePlatformX11::m_catchXErrors = false;
|
||||||
bool AutoTypePlatformX11::m_xErrorOccured = false;
|
bool AutoTypePlatformX11::m_xErrorOccured = false;
|
||||||
@@ -42,14 +45,32 @@ AutoTypePlatformX11::AutoTypePlatformX11()
|
|||||||
m_currentGlobalModifiers = 0;
|
m_currentGlobalModifiers = 0;
|
||||||
|
|
||||||
m_keysymTable = Q_NULLPTR;
|
m_keysymTable = Q_NULLPTR;
|
||||||
m_altMask = 0;
|
m_xkb = Q_NULLPTR;
|
||||||
m_metaMask = 0;
|
m_remapKeycode = 0;
|
||||||
m_altgrMask = 0;
|
m_currentRemapKeysym = NoSymbol;
|
||||||
m_altgrKeysym = NoSymbol;
|
m_modifierMask = ControlMask | ShiftMask | Mod1Mask | Mod4Mask;
|
||||||
|
|
||||||
|
m_loaded = true;
|
||||||
|
|
||||||
updateKeymap();
|
updateKeymap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AutoTypePlatformX11::unload()
|
||||||
|
{
|
||||||
|
// Restore the KeyboardMapping to its original state.
|
||||||
|
AddKeysym(NoSymbol);
|
||||||
|
|
||||||
|
if (m_keysymTable) {
|
||||||
|
XFree(m_keysymTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_xkb) {
|
||||||
|
XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_loaded = false;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList AutoTypePlatformX11::windowTitles()
|
QStringList AutoTypePlatformX11::windowTitles()
|
||||||
{
|
{
|
||||||
return windowTitlesRecursive(m_rootWindow);
|
return windowTitlesRecursive(m_rootWindow);
|
||||||
@@ -125,10 +146,10 @@ uint AutoTypePlatformX11::qtToNativeModifiers(Qt::KeyboardModifiers modifiers)
|
|||||||
nativeModifiers |= ControlMask;
|
nativeModifiers |= ControlMask;
|
||||||
}
|
}
|
||||||
if (modifiers & Qt::AltModifier) {
|
if (modifiers & Qt::AltModifier) {
|
||||||
nativeModifiers |= m_altMask;
|
nativeModifiers |= Mod1Mask;
|
||||||
}
|
}
|
||||||
if (modifiers & Qt::MetaModifier) {
|
if (modifiers & Qt::MetaModifier) {
|
||||||
nativeModifiers |= m_metaMask;
|
nativeModifiers |= Mod4Mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nativeModifiers;
|
return nativeModifiers;
|
||||||
@@ -158,13 +179,15 @@ int AutoTypePlatformX11::platformEventFilter(void* event)
|
|||||||
&& m_currentGlobalKey
|
&& m_currentGlobalKey
|
||||||
&& xevent->xkey.keycode == m_currentGlobalKeycode
|
&& xevent->xkey.keycode == m_currentGlobalKeycode
|
||||||
&& (xevent->xkey.state & m_modifierMask) == m_currentGlobalNativeModifiers
|
&& (xevent->xkey.state & m_modifierMask) == m_currentGlobalNativeModifiers
|
||||||
&& !QApplication::focusWidget()) {
|
&& !QApplication::focusWidget()
|
||||||
|
&& m_loaded) {
|
||||||
if (xevent->type == KeyPress) {
|
if (xevent->type == KeyPress) {
|
||||||
Q_EMIT globalShortcutTriggered();
|
Q_EMIT globalShortcutTriggered();
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (xevent->type == MappingNotify) {
|
if (xevent->type == MappingNotify && m_loaded) {
|
||||||
|
XRefreshKeyboardMapping(reinterpret_cast<XMappingEvent*>(xevent));
|
||||||
updateKeymap();
|
updateKeymap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,12 +349,21 @@ KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
|
|||||||
|| (unicode >= 0x00a0 && unicode <= 0x00ff)) {
|
|| (unicode >= 0x00a0 && unicode <= 0x00ff)) {
|
||||||
return unicode;
|
return unicode;
|
||||||
}
|
}
|
||||||
else if (unicode >= 0x0100) {
|
|
||||||
|
/* mapping table generated from keysymdef.h */
|
||||||
|
const uint* match = qBinaryFind(m_unicodeToKeysymKeys,
|
||||||
|
m_unicodeToKeysymKeys + m_unicodeToKeysymLen,
|
||||||
|
unicode);
|
||||||
|
int index = match - m_unicodeToKeysymKeys;
|
||||||
|
if (index != m_unicodeToKeysymLen) {
|
||||||
|
return m_unicodeToKeysymValues[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unicode >= 0x0100) {
|
||||||
return unicode | 0x01000000;
|
return unicode | 0x01000000;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return NoSymbol;
|
return NoSymbol;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
|
KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
|
||||||
@@ -387,24 +419,65 @@ KeySym AutoTypePlatformX11::keyToKeySym(Qt::Key key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the keyboard and modifier mapping.
|
||||||
|
* We need the KeyboardMapping for AddKeysym.
|
||||||
|
* Modifier mapping is required for clearing the modifiers.
|
||||||
|
*/
|
||||||
void AutoTypePlatformX11::updateKeymap()
|
void AutoTypePlatformX11::updateKeymap()
|
||||||
{
|
{
|
||||||
ReadKeymap();
|
int keycode, inx;
|
||||||
|
int mod_index, mod_key;
|
||||||
|
XModifierKeymap *modifiers;
|
||||||
|
|
||||||
if (!m_altgrMask) {
|
/* read keyboard map */
|
||||||
AddModifier(XK_Mode_switch);
|
if (m_xkb != NULL) XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
|
||||||
}
|
m_xkb = XkbGetKeyboard (m_dpy, XkbCompatMapMask | XkbGeometryMask, XkbUseCoreKbd);
|
||||||
if (!m_metaMask) {
|
|
||||||
m_metaMask = Mod4Mask;
|
XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
|
||||||
|
if (m_keysymTable != NULL) XFree(m_keysymTable);
|
||||||
|
m_keysymTable = XGetKeyboardMapping(m_dpy,
|
||||||
|
m_minKeycode, m_maxKeycode - m_minKeycode + 1,
|
||||||
|
&m_keysymPerKeycode);
|
||||||
|
|
||||||
|
/* determine the keycode to use for remapped keys */
|
||||||
|
inx = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
|
||||||
|
if (m_remapKeycode == 0 || !isRemapKeycodeValid()) {
|
||||||
|
for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) {
|
||||||
|
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
|
||||||
|
if (m_keysymTable[inx] == NoSymbol) {
|
||||||
|
m_remapKeycode = keycode;
|
||||||
|
m_currentRemapKeysym = NoSymbol;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_modifierMask = ControlMask | ShiftMask | m_altMask | m_metaMask;
|
/* determine the keycode to use for modifiers */
|
||||||
|
modifiers = XGetModifierMapping(m_dpy);
|
||||||
|
for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
|
||||||
|
m_modifier_keycode[mod_index] = 0;
|
||||||
|
for (mod_key = 0; mod_key < modifiers->max_keypermod; mod_key++) {
|
||||||
|
keycode = modifiers->modifiermap[mod_index * modifiers->max_keypermod + mod_key];
|
||||||
|
if (keycode) {
|
||||||
|
m_modifier_keycode[mod_index] = keycode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XFreeModifiermap(modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: figure out why this breaks after the first global auto-type
|
bool AutoTypePlatformX11::isRemapKeycodeValid()
|
||||||
/*if (m_currentGlobalKey && m_currentGlobalModifiers) {
|
{
|
||||||
unregisterGlobalShortcut(m_currentGlobalKey, m_currentGlobalModifiers);
|
int baseKeycode = (m_remapKeycode - m_minKeycode) * m_keysymPerKeycode;
|
||||||
registerGlobalShortcut(m_currentGlobalKey, m_currentGlobalModifiers);
|
for (int i = 0; i < m_keysymPerKeycode; i++) {
|
||||||
}*/
|
if (m_keysymTable[baseKeycode + i] == m_currentRemapKeysym) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoTypePlatformX11::startCatchXErrors()
|
void AutoTypePlatformX11::startCatchXErrors()
|
||||||
@@ -442,141 +515,31 @@ int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error)
|
|||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert a specified keysym to unused position in the keymap table.
|
* Insert a specified keysym on the dedicated position in the keymap
|
||||||
* This will be called to add required keysyms on-the-fly.
|
* table.
|
||||||
* if the second parameter is TRUE, the keysym will be added to the
|
|
||||||
* non-shifted position - this may be required for modifier keys
|
|
||||||
* (e.g. Mode_switch) and some special keys (e.g. F20).
|
|
||||||
*/
|
*/
|
||||||
int AutoTypePlatformX11::AddKeysym(KeySym keysym, bool top)
|
int AutoTypePlatformX11::AddKeysym(KeySym keysym)
|
||||||
{
|
{
|
||||||
int keycode, pos, max_pos, inx, phase;
|
if (m_remapKeycode == 0) {
|
||||||
|
return 0;
|
||||||
if (top) {
|
|
||||||
max_pos = 0;
|
|
||||||
} else {
|
|
||||||
max_pos = m_keysymPerKeycode - 1;
|
|
||||||
if (4 <= max_pos) max_pos = 3;
|
|
||||||
if (2 <= max_pos && m_altgrKeysym != XK_Mode_switch) max_pos = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (phase = 0; phase < 2; phase++) {
|
int inx = (m_remapKeycode- m_minKeycode) * m_keysymPerKeycode;
|
||||||
for (keycode = m_maxKeycode; m_minKeycode <= keycode; keycode--) {
|
m_keysymTable[inx] = keysym;
|
||||||
for (pos = max_pos; 0 <= pos; pos--) {
|
m_currentRemapKeysym = keysym;
|
||||||
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
|
|
||||||
if ((phase != 0 || m_keysymTable[inx] == NoSymbol) && m_keysymTable[inx] < 0xFF00) {
|
|
||||||
/* In the first phase, to avoid modifing existing keys, */
|
|
||||||
/* add the keysym only to the keys which has no keysym in the first position. */
|
|
||||||
/* If no place fuond in the first phase, add the keysym for any keys except */
|
|
||||||
/* for modifier keys and other special keys */
|
|
||||||
if (m_keysymTable[inx + pos] == NoSymbol) {
|
|
||||||
m_keysymTable[inx + pos] = keysym;
|
|
||||||
XChangeKeyboardMapping(m_dpy, keycode, m_keysymPerKeycode, &m_keysymTable[inx], 1);
|
|
||||||
XFlush(m_dpy);
|
|
||||||
return keycode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qWarning("Couldn't add \"%s\" to keymap", XKeysymToString(keysym));
|
|
||||||
return NoSymbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
XChangeKeyboardMapping(m_dpy, m_remapKeycode, m_keysymPerKeycode, &m_keysymTable[inx], 1);
|
||||||
* Add the specified key as a new modifier.
|
XFlush(m_dpy);
|
||||||
* This is used to use Mode_switch (AltGr) as a modifier.
|
updateKeymap();
|
||||||
*/
|
|
||||||
void AutoTypePlatformX11::AddModifier(KeySym keysym)
|
|
||||||
{
|
|
||||||
XModifierKeymap *modifiers;
|
|
||||||
int keycode, i, pos;
|
|
||||||
|
|
||||||
keycode = XKeysymToKeycode(m_dpy, keysym);
|
/* Xlib needs some time until the mapping is distributed to
|
||||||
if (keycode == NoSymbol) keycode = AddKeysym(keysym, TRUE);
|
all clients */
|
||||||
|
timespec ts;
|
||||||
|
ts.tv_sec = 0;
|
||||||
|
ts.tv_nsec = 10 * 1000 * 1000;
|
||||||
|
nanosleep(&ts, Q_NULLPTR);
|
||||||
|
|
||||||
modifiers = XGetModifierMapping(m_dpy);
|
return m_remapKeycode;
|
||||||
for (i = 7; 3 < i; i--) {
|
|
||||||
if (modifiers->modifiermap[i * modifiers->max_keypermod] == NoSymbol
|
|
||||||
|| ((m_keysymTable[(modifiers->modifiermap[i * modifiers->max_keypermod]
|
|
||||||
- m_minKeycode) * m_keysymPerKeycode]) == XK_ISO_Level3_Shift
|
|
||||||
&& keysym == XK_Mode_switch))
|
|
||||||
{
|
|
||||||
for (pos = 0; pos < modifiers->max_keypermod; pos++) {
|
|
||||||
if (modifiers->modifiermap[i * modifiers->max_keypermod + pos] == NoSymbol) {
|
|
||||||
modifiers->modifiermap[i * modifiers->max_keypermod + pos] = keycode;
|
|
||||||
XSetModifierMapping(m_dpy, modifiers);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qWarning("Couldn't add \"%s\" as modifier", XKeysymToString(keysym));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read keyboard mapping and modifier mapping.
|
|
||||||
* Keyboard mapping is used to know what keys are in shifted position.
|
|
||||||
* Modifier mapping is required because we should know Alt and Meta
|
|
||||||
* key are used as which modifier.
|
|
||||||
*/
|
|
||||||
void AutoTypePlatformX11::ReadKeymap()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int keycode, inx, pos;
|
|
||||||
KeySym keysym;
|
|
||||||
XModifierKeymap *modifiers;
|
|
||||||
|
|
||||||
XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
|
|
||||||
if (m_keysymTable != NULL) XFree(m_keysymTable);
|
|
||||||
m_keysymTable = XGetKeyboardMapping(m_dpy,
|
|
||||||
m_minKeycode, m_maxKeycode - m_minKeycode + 1,
|
|
||||||
&m_keysymPerKeycode);
|
|
||||||
for (keycode = m_minKeycode; keycode <= m_maxKeycode; keycode++) {
|
|
||||||
/* if the first keysym is alphabet and the second keysym is NoSymbol,
|
|
||||||
it is equivalent to pair of lowercase and uppercase alphabet */
|
|
||||||
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
|
|
||||||
if (m_keysymTable[inx + 1] == NoSymbol
|
|
||||||
&& ((XK_A <= m_keysymTable[inx] && m_keysymTable[inx] <= XK_Z)
|
|
||||||
|| (XK_a <= m_keysymTable[inx] && m_keysymTable[inx] <= XK_z)))
|
|
||||||
{
|
|
||||||
if (XK_A <= m_keysymTable[inx] && m_keysymTable[inx] <= XK_Z)
|
|
||||||
m_keysymTable[inx] = m_keysymTable[inx] - XK_A + XK_a;
|
|
||||||
m_keysymTable[inx + 1] = m_keysymTable[inx] - XK_a + XK_A;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_altMask = 0;
|
|
||||||
m_metaMask = 0;
|
|
||||||
m_altgrMask = 0;
|
|
||||||
m_altgrKeysym = NoSymbol;
|
|
||||||
modifiers = XGetModifierMapping(m_dpy);
|
|
||||||
for (i = 0; i < 8; i++) {
|
|
||||||
for (pos = 0; pos < modifiers->max_keypermod; pos++) {
|
|
||||||
keycode = modifiers->modifiermap[i * modifiers->max_keypermod + pos];
|
|
||||||
if (keycode < m_minKeycode || m_maxKeycode < keycode) continue;
|
|
||||||
|
|
||||||
keysym = m_keysymTable[(keycode - m_minKeycode) * m_keysymPerKeycode];
|
|
||||||
if (keysym == XK_Alt_L || keysym == XK_Alt_R) {
|
|
||||||
m_altMask = 1 << i;
|
|
||||||
} else if (keysym == XK_Meta_L || keysym == XK_Meta_R) {
|
|
||||||
m_metaMask = 1 << i;
|
|
||||||
} else if (keysym == XK_Mode_switch) {
|
|
||||||
if (m_altgrKeysym == XK_ISO_Level3_Shift) {
|
|
||||||
} else {
|
|
||||||
m_altgrMask = 0x0101 << i;
|
|
||||||
/* I don't know why, but 0x2000 was required for mod3 on my Linux box */
|
|
||||||
m_altgrKeysym = keysym;
|
|
||||||
}
|
|
||||||
} else if (keysym == XK_ISO_Level3_Shift) {
|
|
||||||
/* if no Mode_switch, try to use ISO_Level3_Shift instead */
|
|
||||||
/* however, it may not work as intended - I don't know why */
|
|
||||||
m_altgrMask = 1 << i;
|
|
||||||
m_altgrKeysym = keysym;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
XFreeModifiermap(modifiers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -584,80 +547,101 @@ void AutoTypePlatformX11::ReadKeymap()
|
|||||||
* If input focus is specified explicitly, select the window
|
* If input focus is specified explicitly, select the window
|
||||||
* before send event to the window.
|
* before send event to the window.
|
||||||
*/
|
*/
|
||||||
void AutoTypePlatformX11::SendEvent(XKeyEvent* event)
|
void AutoTypePlatformX11::SendEvent(XKeyEvent* event, int event_type)
|
||||||
{
|
{
|
||||||
XSync(event->display, FALSE);
|
XSync(event->display, FALSE);
|
||||||
int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
|
int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
|
||||||
|
|
||||||
|
event->type = event_type;
|
||||||
XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0);
|
XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0);
|
||||||
XFlush(event->display);
|
XFlush(event->display);
|
||||||
|
|
||||||
XSetErrorHandler(oldHandler);
|
XSetErrorHandler(oldHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send a modifier press/release event for all modifiers
|
||||||
|
* which are set in the mask variable.
|
||||||
|
*/
|
||||||
|
void AutoTypePlatformX11::SendModifier(XKeyEvent *event, unsigned int mask, int event_type)
|
||||||
|
{
|
||||||
|
int mod_index;
|
||||||
|
for (mod_index = ShiftMapIndex; mod_index <= Mod5MapIndex; mod_index ++) {
|
||||||
|
if (mask & (1 << mod_index)) {
|
||||||
|
event->keycode = m_modifier_keycode[mod_index];
|
||||||
|
SendEvent(event, event_type);
|
||||||
|
if (event_type == KeyPress)
|
||||||
|
event->state |= (1 << mod_index);
|
||||||
|
else
|
||||||
|
event->state &= (1 << mod_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determines the keycode and modifier mask for the given
|
||||||
|
* keysym.
|
||||||
|
*/
|
||||||
|
int AutoTypePlatformX11::GetKeycode(KeySym keysym, unsigned int *mask)
|
||||||
|
{
|
||||||
|
int keycode = XKeysymToKeycode(m_dpy, keysym);
|
||||||
|
|
||||||
|
if (keycode && keysymModifiers(keysym, keycode, mask)) {
|
||||||
|
return keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no modifier matches => resort to remapping */
|
||||||
|
keycode = AddKeysym(keysym);
|
||||||
|
if (keycode && keysymModifiers(keysym, keycode, mask)) {
|
||||||
|
return keycode;
|
||||||
|
}
|
||||||
|
|
||||||
|
*mask = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AutoTypePlatformX11::keysymModifiers(KeySym keysym, int keycode, unsigned int *mask)
|
||||||
|
{
|
||||||
|
int shift, mod;
|
||||||
|
unsigned int mods_rtrn;
|
||||||
|
|
||||||
|
/* determine whether there is a combination of the modifiers
|
||||||
|
(Mod1-Mod5) with or without shift which returns keysym */
|
||||||
|
for (shift = 0; shift < 2; shift ++) {
|
||||||
|
for (mod = ControlMapIndex; mod <= Mod5MapIndex; mod ++) {
|
||||||
|
KeySym keysym_rtrn;
|
||||||
|
*mask = (mod == ControlMapIndex) ? shift : shift | (1 << mod);
|
||||||
|
XkbTranslateKeyCode(m_xkb, keycode, *mask, &mods_rtrn, &keysym_rtrn);
|
||||||
|
if (keysym_rtrn == keysym) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send sequence of KeyPressed/KeyReleased events to the focused
|
* Send sequence of KeyPressed/KeyReleased events to the focused
|
||||||
* window to simulate keyboard. If modifiers (shift, control, etc)
|
* window to simulate keyboard. If modifiers (shift, control, etc)
|
||||||
* are set ON, many events will be sent.
|
* are set ON, many events will be sent.
|
||||||
*/
|
*/
|
||||||
void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym, unsigned int shift)
|
void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym)
|
||||||
{
|
{
|
||||||
Window cur_focus;
|
Window cur_focus;
|
||||||
int revert_to;
|
int revert_to;
|
||||||
XKeyEvent event;
|
XKeyEvent event;
|
||||||
int keycode;
|
int keycode;
|
||||||
int phase, inx;
|
|
||||||
bool found;
|
if (keysym == NoSymbol) {
|
||||||
|
qWarning("No such key: keysym=0x%lX", static_cast<long>(keysym));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
XGetInputFocus(m_dpy, &cur_focus, &revert_to);
|
XGetInputFocus(m_dpy, &cur_focus, &revert_to);
|
||||||
|
|
||||||
found = FALSE;
|
|
||||||
keycode = 0;
|
|
||||||
if (keysym != NoSymbol) {
|
|
||||||
for (phase = 0; phase < 2; phase++) {
|
|
||||||
for (keycode = m_minKeycode; !found && (keycode <= m_maxKeycode); keycode++) {
|
|
||||||
/* Determine keycode for the keysym: we use this instead
|
|
||||||
of XKeysymToKeycode() because we must know shift_state, too */
|
|
||||||
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
|
|
||||||
if (m_keysymTable[inx] == keysym) {
|
|
||||||
shift &= ~m_altgrMask;
|
|
||||||
if (m_keysymTable[inx + 1] != NoSymbol) shift &= ~ShiftMask;
|
|
||||||
found = TRUE;
|
|
||||||
break;
|
|
||||||
} else if (m_keysymTable[inx + 1] == keysym) {
|
|
||||||
shift &= ~m_altgrMask;
|
|
||||||
shift |= ShiftMask;
|
|
||||||
found = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found && m_altgrMask && 3 <= m_keysymPerKeycode) {
|
|
||||||
for (keycode = m_minKeycode; !found && (keycode <= m_maxKeycode); keycode++) {
|
|
||||||
inx = (keycode - m_minKeycode) * m_keysymPerKeycode;
|
|
||||||
if (m_keysymTable[inx + 2] == keysym) {
|
|
||||||
shift &= ~ShiftMask;
|
|
||||||
shift |= m_altgrMask;
|
|
||||||
found = TRUE;
|
|
||||||
break;
|
|
||||||
} else if (4 <= m_keysymPerKeycode && m_keysymTable[inx + 3] == keysym) {
|
|
||||||
shift |= ShiftMask | m_altgrMask;
|
|
||||||
found = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found) break;
|
|
||||||
|
|
||||||
if (0xF000 <= keysym) {
|
|
||||||
/* for special keys such as function keys,
|
|
||||||
first try to add it in the non-shifted position of the keymap */
|
|
||||||
if (AddKeysym(keysym, TRUE) == NoSymbol) AddKeysym(keysym, FALSE);
|
|
||||||
} else {
|
|
||||||
AddKeysym(keysym, FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
event.display = m_dpy;
|
event.display = m_dpy;
|
||||||
event.window = cur_focus;
|
event.window = cur_focus;
|
||||||
event.root = m_rootWindow;
|
event.root = m_rootWindow;
|
||||||
@@ -672,106 +656,33 @@ void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym, unsigned int shift)
|
|||||||
Window root, child;
|
Window root, child;
|
||||||
int root_x, root_y, x, y;
|
int root_x, root_y, x, y;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
|
unsigned int saved_mask;
|
||||||
|
|
||||||
XQueryPointer(m_dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &mask);
|
XQueryPointer(m_dpy, event.root, &root, &child, &root_x, &root_y, &x, &y, &mask);
|
||||||
|
saved_mask = mask;
|
||||||
|
|
||||||
event.type = KeyRelease;
|
/* determine keycode and mask for the given keysym */
|
||||||
event.state = 0;
|
keycode = GetKeycode(keysym, &mask);
|
||||||
if (mask & ControlMask) {
|
if (keycode < 8 || keycode > 255) {
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Control_L);
|
qWarning("Unable to get valid keycode for key: keysym=0x%lX", static_cast<long>(keysym));
|
||||||
SendEvent(&event);
|
return;
|
||||||
}
|
|
||||||
if (mask & m_altMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Alt_L);
|
|
||||||
SendEvent(&event);
|
|
||||||
}
|
|
||||||
if (mask & m_metaMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Meta_L);
|
|
||||||
SendEvent(&event);
|
|
||||||
}
|
|
||||||
if (mask & m_altgrMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, m_altgrKeysym);
|
|
||||||
SendEvent(&event);
|
|
||||||
}
|
|
||||||
if (mask & ShiftMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Shift_L);
|
|
||||||
SendEvent(&event);
|
|
||||||
}
|
|
||||||
if (mask & LockMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Caps_Lock);
|
|
||||||
SendEvent(&event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
event.type = KeyPress;
|
/* release all modifiers */
|
||||||
event.state = 0;
|
SendModifier(&event, mask, KeyRelease);
|
||||||
if (shift & ControlMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Control_L);
|
|
||||||
SendEvent(&event);
|
|
||||||
event.state |= ControlMask;
|
|
||||||
}
|
|
||||||
if (shift & m_altMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Alt_L);
|
|
||||||
SendEvent(&event);
|
|
||||||
event.state |= m_altMask;
|
|
||||||
}
|
|
||||||
if (shift & m_metaMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Meta_L);
|
|
||||||
SendEvent(&event);
|
|
||||||
event.state |= m_metaMask;
|
|
||||||
}
|
|
||||||
if (shift & m_altgrMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, m_altgrKeysym);
|
|
||||||
SendEvent(&event);
|
|
||||||
event.state |= m_altgrMask;
|
|
||||||
}
|
|
||||||
if (shift & ShiftMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Shift_L);
|
|
||||||
SendEvent(&event);
|
|
||||||
event.state |= ShiftMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keysym != NoSymbol) { /* send event for the key itself */
|
SendModifier(&event, mask, KeyPress);
|
||||||
event.keycode = found ? keycode : XKeysymToKeycode(m_dpy, keysym);
|
|
||||||
if (event.keycode == NoSymbol) {
|
|
||||||
if ((keysym & ~0x7f) == 0 && QChar(static_cast<char>(keysym)).isPrint())
|
|
||||||
qWarning("No such key: %c", static_cast<char>(keysym));
|
|
||||||
else if (XKeysymToString(keysym) != NULL)
|
|
||||||
qWarning("No such key: keysym=%s (0x%lX)", XKeysymToString(keysym), static_cast<long>(keysym));
|
|
||||||
else
|
|
||||||
qWarning("No such key: keysym=0x%lX", static_cast<long>(keysym));
|
|
||||||
} else {
|
|
||||||
SendEvent(&event);
|
|
||||||
event.type = KeyRelease;
|
|
||||||
SendEvent(&event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
event.type = KeyRelease;
|
/* press and release key */
|
||||||
if (shift & ShiftMask) {
|
event.keycode = keycode;
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Shift_L);
|
SendEvent(&event, KeyPress);
|
||||||
SendEvent(&event);
|
SendEvent(&event, KeyRelease);
|
||||||
event.state &= ~ShiftMask;
|
|
||||||
}
|
/* release the modifiers */
|
||||||
if (shift & m_altgrMask) {
|
SendModifier(&event, mask, KeyRelease);
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, m_altgrKeysym);
|
|
||||||
SendEvent(&event);
|
/* restore the old keyboard mask */
|
||||||
event.state &= ~m_altgrMask;
|
SendModifier(&event, saved_mask, KeyPress);
|
||||||
}
|
|
||||||
if (shift & m_metaMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Meta_L);
|
|
||||||
SendEvent(&event);
|
|
||||||
event.state &= ~m_metaMask;
|
|
||||||
}
|
|
||||||
if (shift & m_altMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Alt_L);
|
|
||||||
SendEvent(&event);
|
|
||||||
event.state &= ~m_altMask;
|
|
||||||
}
|
|
||||||
if (shift & ControlMask) {
|
|
||||||
event.keycode = XKeysymToKeycode(m_dpy, XK_Control_L);
|
|
||||||
SendEvent(&event);
|
|
||||||
event.state &= ~ControlMask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
|
int AutoTypePlatformX11::MyErrorHandler(Display* my_dpy, XErrorEvent* event)
|
||||||
|
|||||||
@@ -19,19 +19,22 @@
|
|||||||
#ifndef KEEPASSX_AUTOTYPEX11_H
|
#ifndef KEEPASSX_AUTOTYPEX11_H
|
||||||
#define KEEPASSX_AUTOTYPEX11_H
|
#define KEEPASSX_AUTOTYPEX11_H
|
||||||
|
|
||||||
#include <QtCore/QSet>
|
#include <QApplication>
|
||||||
#include <QtCore/QtPlugin>
|
#include <QSet>
|
||||||
#include <QtGui/QApplication>
|
#include <QtPlugin>
|
||||||
#include <QtGui/QWidget>
|
#include <QWidget>
|
||||||
#include <QtGui/QX11Info>
|
#include <QX11Info>
|
||||||
|
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
#include <X11/extensions/XTest.h>
|
#include <X11/extensions/XTest.h>
|
||||||
|
#include <X11/XKBlib.h>
|
||||||
|
|
||||||
#include "autotype/AutoTypePlatformPlugin.h"
|
#include "autotype/AutoTypePlatformPlugin.h"
|
||||||
#include "autotype/AutoTypeAction.h"
|
#include "autotype/AutoTypeAction.h"
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
#define N_MOD_INDICES (Mod5MapIndex + 1)
|
||||||
|
|
||||||
class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface
|
class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -39,6 +42,7 @@ class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
AutoTypePlatformX11();
|
AutoTypePlatformX11();
|
||||||
|
void unload() Q_DECL_OVERRIDE;
|
||||||
QStringList windowTitles();
|
QStringList windowTitles();
|
||||||
WId activeWindow();
|
WId activeWindow();
|
||||||
QString activeWindowTitle();
|
QString activeWindowTitle();
|
||||||
@@ -51,7 +55,7 @@ public:
|
|||||||
KeySym charToKeySym(const QChar& ch);
|
KeySym charToKeySym(const QChar& ch);
|
||||||
KeySym keyToKeySym(Qt::Key key);
|
KeySym keyToKeySym(Qt::Key key);
|
||||||
|
|
||||||
void SendKeyPressedEvent(KeySym keysym, unsigned int shift = 0);
|
void SendKeyPressedEvent(KeySym keysym);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void globalShortcutTriggered();
|
void globalShortcutTriggered();
|
||||||
@@ -68,10 +72,14 @@ private:
|
|||||||
static int x11ErrorHandler(Display* display, XErrorEvent* error);
|
static int x11ErrorHandler(Display* display, XErrorEvent* error);
|
||||||
|
|
||||||
void updateKeymap();
|
void updateKeymap();
|
||||||
int AddKeysym(KeySym keysym, bool top);
|
bool isRemapKeycodeValid();
|
||||||
|
int AddKeysym(KeySym keysym);
|
||||||
void AddModifier(KeySym keysym);
|
void AddModifier(KeySym keysym);
|
||||||
void ReadKeymap();
|
void SendEvent(XKeyEvent* event, int event_type);
|
||||||
void SendEvent(XKeyEvent* event);
|
void SendModifier(XKeyEvent *event, unsigned int mask, int event_type);
|
||||||
|
int GetKeycode(KeySym keysym, unsigned int *mask);
|
||||||
|
bool keysymModifiers(KeySym keysym, int keycode, unsigned int *mask);
|
||||||
|
|
||||||
static int MyErrorHandler(Display* my_dpy, XErrorEvent* event);
|
static int MyErrorHandler(Display* my_dpy, XErrorEvent* event);
|
||||||
|
|
||||||
Display* m_dpy;
|
Display* m_dpy;
|
||||||
@@ -91,14 +99,20 @@ private:
|
|||||||
static bool m_xErrorOccured;
|
static bool m_xErrorOccured;
|
||||||
static int (*m_oldXErrorHandler)(Display*, XErrorEvent*);
|
static int (*m_oldXErrorHandler)(Display*, XErrorEvent*);
|
||||||
|
|
||||||
|
static const int m_unicodeToKeysymLen;
|
||||||
|
static const uint m_unicodeToKeysymKeys[];
|
||||||
|
static const uint m_unicodeToKeysymValues[];
|
||||||
|
|
||||||
|
XkbDescPtr m_xkb;
|
||||||
KeySym* m_keysymTable;
|
KeySym* m_keysymTable;
|
||||||
int m_minKeycode;
|
int m_minKeycode;
|
||||||
int m_maxKeycode;
|
int m_maxKeycode;
|
||||||
int m_keysymPerKeycode;
|
int m_keysymPerKeycode;
|
||||||
int m_altMask;
|
/* dedicated keycode for remapped keys */
|
||||||
int m_metaMask;
|
unsigned int m_remapKeycode;
|
||||||
int m_altgrMask;
|
KeySym m_currentRemapKeysym;
|
||||||
KeySym m_altgrKeysym;
|
KeyCode m_modifier_keycode[N_MOD_INDICES];
|
||||||
|
bool m_loaded;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AutoTypeExecturorX11 : public AutoTypeExecutor
|
class AutoTypeExecturorX11 : public AutoTypeExecutor
|
||||||
|
|||||||
169
src/autotype/x11/KeySymMap.h
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Automatically generated by keysymmap.py from parsing keysymdef.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const int AutoTypePlatformX11::m_unicodeToKeysymLen = 632;
|
||||||
|
|
||||||
|
const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {
|
||||||
|
0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107,
|
||||||
|
0x0108, 0x0109, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f,
|
||||||
|
0x0110, 0x0111, 0x0112, 0x0113, 0x0116, 0x0117, 0x0118, 0x0119,
|
||||||
|
0x011a, 0x011b, 0x011c, 0x011d, 0x011e, 0x011f, 0x0120, 0x0121,
|
||||||
|
0x0122, 0x0123, 0x0124, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129,
|
||||||
|
0x012a, 0x012b, 0x012e, 0x012f, 0x0130, 0x0131, 0x0134, 0x0135,
|
||||||
|
0x0136, 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d,
|
||||||
|
0x013e, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0147,
|
||||||
|
0x0148, 0x014a, 0x014b, 0x014c, 0x014d, 0x0150, 0x0151, 0x0152,
|
||||||
|
0x0153, 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159, 0x015a,
|
||||||
|
0x015b, 0x015c, 0x015d, 0x015e, 0x015f, 0x0160, 0x0161, 0x0162,
|
||||||
|
0x0163, 0x0164, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169, 0x016a,
|
||||||
|
0x016b, 0x016c, 0x016d, 0x016e, 0x016f, 0x0170, 0x0171, 0x0172,
|
||||||
|
0x0173, 0x0178, 0x0179, 0x017a, 0x017b, 0x017c, 0x017d, 0x017e,
|
||||||
|
0x0192, 0x02c7, 0x02d8, 0x02d9, 0x02db, 0x02dd, 0x0385, 0x0386,
|
||||||
|
0x0388, 0x0389, 0x038a, 0x038c, 0x038e, 0x038f, 0x0390, 0x0391,
|
||||||
|
0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399,
|
||||||
|
0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1,
|
||||||
|
0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa,
|
||||||
|
0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03b0, 0x03b1, 0x03b2,
|
||||||
|
0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba,
|
||||||
|
0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c0, 0x03c1, 0x03c2,
|
||||||
|
0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca,
|
||||||
|
0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0401, 0x0402, 0x0403, 0x0404,
|
||||||
|
0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c,
|
||||||
|
0x040e, 0x040f, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
|
||||||
|
0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d,
|
||||||
|
0x041e, 0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425,
|
||||||
|
0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d,
|
||||||
|
0x042e, 0x042f, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435,
|
||||||
|
0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d,
|
||||||
|
0x043e, 0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445,
|
||||||
|
0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d,
|
||||||
|
0x044e, 0x044f, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456,
|
||||||
|
0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045e, 0x045f,
|
||||||
|
0x0490, 0x0491, 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5,
|
||||||
|
0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd,
|
||||||
|
0x05de, 0x05df, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
|
||||||
|
0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x060c, 0x061b, 0x061f,
|
||||||
|
0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628,
|
||||||
|
0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, 0x0630,
|
||||||
|
0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638,
|
||||||
|
0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645,
|
||||||
|
0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d,
|
||||||
|
0x064e, 0x064f, 0x0650, 0x0651, 0x0652, 0x0e01, 0x0e02, 0x0e03,
|
||||||
|
0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b,
|
||||||
|
0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, 0x0e10, 0x0e11, 0x0e12, 0x0e13,
|
||||||
|
0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b,
|
||||||
|
0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, 0x0e20, 0x0e21, 0x0e22, 0x0e23,
|
||||||
|
0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b,
|
||||||
|
0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, 0x0e30, 0x0e31, 0x0e32, 0x0e33,
|
||||||
|
0x0e34, 0x0e35, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0e3f,
|
||||||
|
0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
|
||||||
|
0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e50, 0x0e51,
|
||||||
|
0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59,
|
||||||
|
0x2002, 0x2003, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, 0x200a,
|
||||||
|
0x2012, 0x2013, 0x2014, 0x2015, 0x2017, 0x2018, 0x2019, 0x201a,
|
||||||
|
0x201c, 0x201d, 0x201e, 0x2020, 0x2021, 0x2025, 0x2026, 0x2030,
|
||||||
|
0x2032, 0x2033, 0x2038, 0x203e, 0x20ac, 0x2105, 0x2116, 0x2117,
|
||||||
|
0x211e, 0x2122, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158,
|
||||||
|
0x2159, 0x215a, 0x215b, 0x215c, 0x215d, 0x215e, 0x2190, 0x2191,
|
||||||
|
0x2192, 0x2193, 0x21d2, 0x21d4, 0x2202, 0x2207, 0x2218, 0x221a,
|
||||||
|
0x221d, 0x221e, 0x2227, 0x2228, 0x2229, 0x222a, 0x222b, 0x2234,
|
||||||
|
0x223c, 0x2243, 0x2260, 0x2261, 0x2264, 0x2265, 0x2282, 0x2283,
|
||||||
|
0x22a2, 0x22a3, 0x22a4, 0x22a5, 0x2308, 0x230a, 0x2315, 0x2320,
|
||||||
|
0x2321, 0x2395, 0x239b, 0x239d, 0x239e, 0x23a0, 0x23a1, 0x23a3,
|
||||||
|
0x23a4, 0x23a6, 0x23a8, 0x23ac, 0x23b7, 0x23ba, 0x23bb, 0x23bc,
|
||||||
|
0x23bd, 0x2409, 0x240a, 0x240b, 0x240c, 0x240d, 0x2424, 0x2500,
|
||||||
|
0x2502, 0x250c, 0x2510, 0x2514, 0x2518, 0x251c, 0x2524, 0x252c,
|
||||||
|
0x2534, 0x253c, 0x2592, 0x25c6, 0x25cb, 0x260e, 0x2640, 0x2642,
|
||||||
|
0x2663, 0x2665, 0x2666, 0x266d, 0x266f, 0x2713, 0x2717, 0x271d,
|
||||||
|
0x2720, 0x3001, 0x3002, 0x300c, 0x300d, 0x309b, 0x309c, 0x30a1,
|
||||||
|
0x30a2, 0x30a3, 0x30a4, 0x30a5, 0x30a6, 0x30a7, 0x30a8, 0x30a9,
|
||||||
|
0x30aa, 0x30ab, 0x30ad, 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7,
|
||||||
|
0x30b9, 0x30bb, 0x30bd, 0x30bf, 0x30c1, 0x30c3, 0x30c4, 0x30c6,
|
||||||
|
0x30c8, 0x30ca, 0x30cb, 0x30cc, 0x30cd, 0x30ce, 0x30cf, 0x30d2,
|
||||||
|
0x30d5, 0x30d8, 0x30db, 0x30de, 0x30df, 0x30e0, 0x30e1, 0x30e2,
|
||||||
|
0x30e3, 0x30e4, 0x30e5, 0x30e6, 0x30e7, 0x30e8, 0x30e9, 0x30ea,
|
||||||
|
0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f2, 0x30f3, 0x30fb, 0x30fc
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {
|
||||||
|
0x03c0, 0x03e0, 0x01c3, 0x01e3, 0x01a1, 0x01b1, 0x01c6, 0x01e6,
|
||||||
|
0x02c6, 0x02e6, 0x02c5, 0x02e5, 0x01c8, 0x01e8, 0x01cf, 0x01ef,
|
||||||
|
0x01d0, 0x01f0, 0x03aa, 0x03ba, 0x03cc, 0x03ec, 0x01ca, 0x01ea,
|
||||||
|
0x01cc, 0x01ec, 0x02d8, 0x02f8, 0x02ab, 0x02bb, 0x02d5, 0x02f5,
|
||||||
|
0x03ab, 0x03bb, 0x02a6, 0x02b6, 0x02a1, 0x02b1, 0x03a5, 0x03b5,
|
||||||
|
0x03cf, 0x03ef, 0x03c7, 0x03e7, 0x02a9, 0x02b9, 0x02ac, 0x02bc,
|
||||||
|
0x03d3, 0x03f3, 0x03a2, 0x01c5, 0x01e5, 0x03a6, 0x03b6, 0x01a5,
|
||||||
|
0x01b5, 0x01a3, 0x01b3, 0x01d1, 0x01f1, 0x03d1, 0x03f1, 0x01d2,
|
||||||
|
0x01f2, 0x03bd, 0x03bf, 0x03d2, 0x03f2, 0x01d5, 0x01f5, 0x13bc,
|
||||||
|
0x13bd, 0x01c0, 0x01e0, 0x03a3, 0x03b3, 0x01d8, 0x01f8, 0x01a6,
|
||||||
|
0x01b6, 0x02de, 0x02fe, 0x01aa, 0x01ba, 0x01a9, 0x01b9, 0x01de,
|
||||||
|
0x01fe, 0x01ab, 0x01bb, 0x03ac, 0x03bc, 0x03dd, 0x03fd, 0x03de,
|
||||||
|
0x03fe, 0x02dd, 0x02fd, 0x01d9, 0x01f9, 0x01db, 0x01fb, 0x03d9,
|
||||||
|
0x03f9, 0x13be, 0x01ac, 0x01bc, 0x01af, 0x01bf, 0x01ae, 0x01be,
|
||||||
|
0x08f6, 0x01b7, 0x01a2, 0x01ff, 0x01b2, 0x01bd, 0x07ae, 0x07a1,
|
||||||
|
0x07a2, 0x07a3, 0x07a4, 0x07a7, 0x07a8, 0x07ab, 0x07b6, 0x07c1,
|
||||||
|
0x07c2, 0x07c3, 0x07c4, 0x07c5, 0x07c6, 0x07c7, 0x07c8, 0x07c9,
|
||||||
|
0x07ca, 0x07cb, 0x07cc, 0x07cd, 0x07ce, 0x07cf, 0x07d0, 0x07d1,
|
||||||
|
0x07d2, 0x07d4, 0x07d5, 0x07d6, 0x07d7, 0x07d8, 0x07d9, 0x07a5,
|
||||||
|
0x07a9, 0x07b1, 0x07b2, 0x07b3, 0x07b4, 0x07ba, 0x07e1, 0x07e2,
|
||||||
|
0x07e3, 0x07e4, 0x07e5, 0x07e6, 0x07e7, 0x07e8, 0x07e9, 0x07ea,
|
||||||
|
0x07eb, 0x07ec, 0x07ed, 0x07ee, 0x07ef, 0x07f0, 0x07f1, 0x07f3,
|
||||||
|
0x07f2, 0x07f4, 0x07f5, 0x07f6, 0x07f7, 0x07f8, 0x07f9, 0x07b5,
|
||||||
|
0x07b9, 0x07b7, 0x07b8, 0x07bb, 0x06b3, 0x06b1, 0x06b2, 0x06b4,
|
||||||
|
0x06b5, 0x06b6, 0x06b7, 0x06b8, 0x06b9, 0x06ba, 0x06bb, 0x06bc,
|
||||||
|
0x06be, 0x06bf, 0x06e1, 0x06e2, 0x06f7, 0x06e7, 0x06e4, 0x06e5,
|
||||||
|
0x06f6, 0x06fa, 0x06e9, 0x06ea, 0x06eb, 0x06ec, 0x06ed, 0x06ee,
|
||||||
|
0x06ef, 0x06f0, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06e6, 0x06e8,
|
||||||
|
0x06e3, 0x06fe, 0x06fb, 0x06fd, 0x06ff, 0x06f9, 0x06f8, 0x06fc,
|
||||||
|
0x06e0, 0x06f1, 0x06c1, 0x06c2, 0x06d7, 0x06c7, 0x06c4, 0x06c5,
|
||||||
|
0x06d6, 0x06da, 0x06c9, 0x06ca, 0x06cb, 0x06cc, 0x06cd, 0x06ce,
|
||||||
|
0x06cf, 0x06d0, 0x06d2, 0x06d3, 0x06d4, 0x06d5, 0x06c6, 0x06c8,
|
||||||
|
0x06c3, 0x06de, 0x06db, 0x06dd, 0x06df, 0x06d9, 0x06d8, 0x06dc,
|
||||||
|
0x06c0, 0x06d1, 0x06a3, 0x06a1, 0x06a2, 0x06a4, 0x06a5, 0x06a6,
|
||||||
|
0x06a7, 0x06a8, 0x06a9, 0x06aa, 0x06ab, 0x06ac, 0x06ae, 0x06af,
|
||||||
|
0x06bd, 0x06ad, 0x0ce0, 0x0ce1, 0x0ce2, 0x0ce3, 0x0ce4, 0x0ce5,
|
||||||
|
0x0ce6, 0x0ce7, 0x0ce8, 0x0ce9, 0x0cea, 0x0ceb, 0x0cec, 0x0ced,
|
||||||
|
0x0cee, 0x0cef, 0x0cf0, 0x0cf1, 0x0cf2, 0x0cf3, 0x0cf4, 0x0cf5,
|
||||||
|
0x0cf6, 0x0cf7, 0x0cf8, 0x0cf9, 0x0cfa, 0x05ac, 0x05bb, 0x05bf,
|
||||||
|
0x05c1, 0x05c2, 0x05c3, 0x05c4, 0x05c5, 0x05c6, 0x05c7, 0x05c8,
|
||||||
|
0x05c9, 0x05ca, 0x05cb, 0x05cc, 0x05cd, 0x05ce, 0x05cf, 0x05d0,
|
||||||
|
0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8,
|
||||||
|
0x05d9, 0x05da, 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5,
|
||||||
|
0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x05eb, 0x05ec, 0x05ed,
|
||||||
|
0x05ee, 0x05ef, 0x05f0, 0x05f1, 0x05f2, 0x0da1, 0x0da2, 0x0da3,
|
||||||
|
0x0da4, 0x0da5, 0x0da6, 0x0da7, 0x0da8, 0x0da9, 0x0daa, 0x0dab,
|
||||||
|
0x0dac, 0x0dad, 0x0dae, 0x0daf, 0x0db0, 0x0db1, 0x0db2, 0x0db3,
|
||||||
|
0x0db4, 0x0db5, 0x0db6, 0x0db7, 0x0db8, 0x0db9, 0x0dba, 0x0dbb,
|
||||||
|
0x0dbc, 0x0dbd, 0x0dbe, 0x0dbf, 0x0dc0, 0x0dc1, 0x0dc2, 0x0dc3,
|
||||||
|
0x0dc4, 0x0dc5, 0x0dc6, 0x0dc7, 0x0dc8, 0x0dc9, 0x0dca, 0x0dcb,
|
||||||
|
0x0dcc, 0x0dcd, 0x0dce, 0x0dcf, 0x0dd0, 0x0dd1, 0x0dd2, 0x0dd3,
|
||||||
|
0x0dd4, 0x0dd5, 0x0dd6, 0x0dd7, 0x0dd8, 0x0dd9, 0x0dda, 0x0ddf,
|
||||||
|
0x0de0, 0x0de1, 0x0de2, 0x0de3, 0x0de4, 0x0de5, 0x0de6, 0x0de7,
|
||||||
|
0x0de8, 0x0de9, 0x0dea, 0x0deb, 0x0dec, 0x0ded, 0x0df0, 0x0df1,
|
||||||
|
0x0df2, 0x0df3, 0x0df4, 0x0df5, 0x0df6, 0x0df7, 0x0df8, 0x0df9,
|
||||||
|
0x0aa2, 0x0aa1, 0x0aa3, 0x0aa4, 0x0aa5, 0x0aa6, 0x0aa7, 0x0aa8,
|
||||||
|
0x0abb, 0x0aaa, 0x0aa9, 0x07af, 0x0cdf, 0x0ad0, 0x0ad1, 0x0afd,
|
||||||
|
0x0ad2, 0x0ad3, 0x0afe, 0x0af1, 0x0af2, 0x0aaf, 0x0aae, 0x0ad5,
|
||||||
|
0x0ad6, 0x0ad7, 0x0afc, 0x047e, 0x20ac, 0x0ab8, 0x06b0, 0x0afb,
|
||||||
|
0x0ad4, 0x0ac9, 0x0ab0, 0x0ab1, 0x0ab2, 0x0ab3, 0x0ab4, 0x0ab5,
|
||||||
|
0x0ab6, 0x0ab7, 0x0ac3, 0x0ac4, 0x0ac5, 0x0ac6, 0x08fb, 0x08fc,
|
||||||
|
0x08fd, 0x08fe, 0x08ce, 0x08cd, 0x08ef, 0x08c5, 0x0bca, 0x08d6,
|
||||||
|
0x08c1, 0x08c2, 0x08de, 0x08df, 0x08dc, 0x08dd, 0x08bf, 0x08c0,
|
||||||
|
0x08c8, 0x08c9, 0x08bd, 0x08cf, 0x08bc, 0x08be, 0x08da, 0x08db,
|
||||||
|
0x0bfc, 0x0bdc, 0x0bc2, 0x0bce, 0x0bd3, 0x0bc4, 0x0afa, 0x08a4,
|
||||||
|
0x08a5, 0x0bcc, 0x08ab, 0x08ac, 0x08ad, 0x08ae, 0x08a7, 0x08a8,
|
||||||
|
0x08a9, 0x08aa, 0x08af, 0x08b0, 0x08a1, 0x09ef, 0x09f0, 0x09f2,
|
||||||
|
0x09f3, 0x09e2, 0x09e5, 0x09e9, 0x09e3, 0x09e4, 0x09e8, 0x09f1,
|
||||||
|
0x09f8, 0x09ec, 0x09eb, 0x09ed, 0x09ea, 0x09f4, 0x09f5, 0x09f7,
|
||||||
|
0x09f6, 0x09ee, 0x09e1, 0x09e0, 0x0bcf, 0x0af9, 0x0af8, 0x0af7,
|
||||||
|
0x0aec, 0x0aee, 0x0aed, 0x0af6, 0x0af5, 0x0af3, 0x0af4, 0x0ad9,
|
||||||
|
0x0af0, 0x04a4, 0x04a1, 0x04a2, 0x04a3, 0x04de, 0x04df, 0x04a7,
|
||||||
|
0x04b1, 0x04a8, 0x04b2, 0x04a9, 0x04b3, 0x04aa, 0x04b4, 0x04ab,
|
||||||
|
0x04b5, 0x04b6, 0x04b7, 0x04b8, 0x04b9, 0x04ba, 0x04bb, 0x04bc,
|
||||||
|
0x04bd, 0x04be, 0x04bf, 0x04c0, 0x04c1, 0x04af, 0x04c2, 0x04c3,
|
||||||
|
0x04c4, 0x04c5, 0x04c6, 0x04c7, 0x04c8, 0x04c9, 0x04ca, 0x04cb,
|
||||||
|
0x04cc, 0x04cd, 0x04ce, 0x04cf, 0x04d0, 0x04d1, 0x04d2, 0x04d3,
|
||||||
|
0x04ac, 0x04d4, 0x04ad, 0x04d5, 0x04ae, 0x04d6, 0x04d7, 0x04d8,
|
||||||
|
0x04d9, 0x04da, 0x04db, 0x04dc, 0x04a6, 0x04dd, 0x04a5, 0x04b0
|
||||||
|
};
|
||||||
107
src/autotype/x11/keysymmap.py
Executable file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 Felix Geyer <debfx@fobos.de>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 2 or (at your option)
|
||||||
|
# version 3 of the License.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Parses keysymdef.h to construct a unicode symbol -> keysym mapping table.
|
||||||
|
#
|
||||||
|
# The lines that are parsed look like this:
|
||||||
|
# #define XK_Aogonek 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */
|
||||||
|
#
|
||||||
|
# This would create a 0x0104 -> 0x01a1 mapping.
|
||||||
|
#
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import collections
|
||||||
|
|
||||||
|
cols = 8
|
||||||
|
|
||||||
|
if len(sys.argv) >= 2:
|
||||||
|
keysymdef = sys.argv[1]
|
||||||
|
else:
|
||||||
|
keysymdef = "/usr/include/X11/keysymdef.h"
|
||||||
|
|
||||||
|
keysymMap = {}
|
||||||
|
|
||||||
|
f = open(keysymdef, "r")
|
||||||
|
for line in f:
|
||||||
|
match = re.search(r'0x([0-9a-fA-F]+)\s+/\* U\+([0-9a-fA-F]+)', line)
|
||||||
|
if match:
|
||||||
|
keysym = int(match.group(1), 16)
|
||||||
|
unicodeVal = int(match.group(2), 16)
|
||||||
|
|
||||||
|
# ignore 1:1 mappings
|
||||||
|
if keysym >= 0x0020 and keysym <= 0x007e:
|
||||||
|
continue
|
||||||
|
if keysym >= 0x00a0 and keysym <= 0x00ff:
|
||||||
|
continue
|
||||||
|
# ignore unicode | 0x01000000 mappings
|
||||||
|
if keysym >= 0x1000000:
|
||||||
|
continue
|
||||||
|
|
||||||
|
keysymMap[unicodeVal] = keysym
|
||||||
|
|
||||||
|
keysymMap = collections.OrderedDict(sorted(keysymMap.items(), key=lambda t: t[0]))
|
||||||
|
|
||||||
|
print("""/*
|
||||||
|
* Automatically generated by keysymmap.py from parsing keysymdef.h.
|
||||||
|
*/
|
||||||
|
""")
|
||||||
|
|
||||||
|
print("const int AutoTypePlatformX11::m_unicodeToKeysymLen = " + str(len(keysymMap)) + ";")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("const uint AutoTypePlatformX11::m_unicodeToKeysymKeys[] = {")
|
||||||
|
keys = keysymMap.keys()
|
||||||
|
keyLen = len(keys)
|
||||||
|
i = 1
|
||||||
|
for val in keys:
|
||||||
|
hexVal = "{0:#0{1}x}".format(val, 6)
|
||||||
|
|
||||||
|
if i == keyLen:
|
||||||
|
print(hexVal)
|
||||||
|
elif (i % cols) == 0:
|
||||||
|
print(hexVal + ",")
|
||||||
|
elif ((i - 1) % cols) == 0:
|
||||||
|
print(" " + hexVal + ", ", end="")
|
||||||
|
else:
|
||||||
|
print(hexVal + ", ", end="")
|
||||||
|
i += 1
|
||||||
|
print("};")
|
||||||
|
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("const uint AutoTypePlatformX11::m_unicodeToKeysymValues[] = {")
|
||||||
|
values = keysymMap.values()
|
||||||
|
valuesLen = len(values)
|
||||||
|
i = 1
|
||||||
|
for val in values:
|
||||||
|
hexVal = "{0:#0{1}x}".format(val, 6)
|
||||||
|
|
||||||
|
if i == valuesLen:
|
||||||
|
print(hexVal)
|
||||||
|
elif (i % cols) == 0:
|
||||||
|
print(hexVal + ",")
|
||||||
|
elif ((i - 1) % cols) == 0:
|
||||||
|
print(" " + hexVal + ", ", end="")
|
||||||
|
else:
|
||||||
|
print(hexVal + ", ", end="")
|
||||||
|
i += 1
|
||||||
|
print("};")
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
/* config-keepassx.h. Generated by cmake from config-keepassx.h.cmake */
|
/* config-keepassx.h. Generated by cmake from config-keepassx.h.cmake */
|
||||||
|
|
||||||
#ifndef KEEPASSX_CONFIG_H
|
#ifndef KEEPASSX_CONFIG_KEEPASSX_H
|
||||||
#define KEEPASSX_CONFIG_H
|
#define KEEPASSX_CONFIG_KEEPASSX_H
|
||||||
|
|
||||||
#define KEEPASSX_VERSION "${KEEPASSX_VERSION}"
|
#define KEEPASSX_VERSION "${KEEPASSX_VERSION}"
|
||||||
|
|
||||||
#define KEEPASSX_SOURCE_DIR "${CMAKE_SOURCE_DIR}"
|
#define KEEPASSX_SOURCE_DIR "${CMAKE_SOURCE_DIR}"
|
||||||
|
|
||||||
|
#define KEEPASSX_PLUGIN_DIR "${PLUGIN_INSTALL_DIR}"
|
||||||
|
|
||||||
#cmakedefine HAVE_PR_SET_DUMPABLE 1
|
#cmakedefine HAVE_PR_SET_DUMPABLE 1
|
||||||
#cmakedefine HAVE_RLIMIT_CORE 1
|
#cmakedefine HAVE_RLIMIT_CORE 1
|
||||||
#cmakedefine HAVE_PT_DENY_ATTACH 1
|
#cmakedefine HAVE_PT_DENY_ATTACH 1
|
||||||
|
|
||||||
#endif // KEEPASSX_CONFIG_H
|
#cmakedefine GCRYPT_HAS_SALSA20
|
||||||
|
|
||||||
|
#endif // KEEPASSX_CONFIG_KEEPASSX_H
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef KEEPASSX_AUTOTYPEASSOCIATIONS_H
|
#ifndef KEEPASSX_AUTOTYPEASSOCIATIONS_H
|
||||||
#define KEEPASSX_AUTOTYPEASSOCIATIONS_H
|
#define KEEPASSX_AUTOTYPEASSOCIATIONS_H
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,11 @@
|
|||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#include <QtCore/QDir>
|
#include <QCoreApplication>
|
||||||
#include <QtCore/QSettings>
|
#include <QDesktopServices>
|
||||||
#include <QtCore/QTemporaryFile>
|
#include <QDir>
|
||||||
#include <QtGui/QApplication>
|
#include <QSettings>
|
||||||
#include <QtGui/QDesktopServices>
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
Config* Config::m_instance(Q_NULLPTR);
|
Config* Config::m_instance(Q_NULLPTR);
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ Config::Config(QObject* parent)
|
|||||||
userPath += "/keepassx/";
|
userPath += "/keepassx/";
|
||||||
#else
|
#else
|
||||||
userPath = QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
|
userPath = QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
|
||||||
userPath += "/keepassx/";
|
// storageLocation() appends the application name ("/keepassx/") to the end
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
userPath += "keepassx2.ini";
|
userPath += "keepassx2.ini";
|
||||||
@@ -88,12 +88,17 @@ void Config::init(const QString& fileName)
|
|||||||
m_settings.reset(new QSettings(fileName, QSettings::IniFormat));
|
m_settings.reset(new QSettings(fileName, QSettings::IniFormat));
|
||||||
|
|
||||||
m_defaults.insert("RememberLastDatabases", true);
|
m_defaults.insert("RememberLastDatabases", true);
|
||||||
|
m_defaults.insert("OpenPreviousDatabasesOnStartup", true);
|
||||||
m_defaults.insert("ModifiedOnExpandedStateChanges", true);
|
m_defaults.insert("ModifiedOnExpandedStateChanges", true);
|
||||||
m_defaults.insert("AutoSaveAfterEveryChange", false);
|
m_defaults.insert("AutoSaveAfterEveryChange", false);
|
||||||
m_defaults.insert("AutoSaveOnExit", false);
|
m_defaults.insert("AutoSaveOnExit", false);
|
||||||
m_defaults.insert("ShowToolbar", true);
|
m_defaults.insert("ShowToolbar", true);
|
||||||
|
m_defaults.insert("MinimizeOnCopy", false);
|
||||||
m_defaults.insert("security/clearclipboard", true);
|
m_defaults.insert("security/clearclipboard", true);
|
||||||
m_defaults.insert("security/clearclipboardtimeout", 10);
|
m_defaults.insert("security/clearclipboardtimeout", 10);
|
||||||
|
m_defaults.insert("security/lockdatabaseidle", false);
|
||||||
|
m_defaults.insert("security/lockdatabaseidlesec", 10);
|
||||||
|
m_defaults.insert("security/passwordscleartext", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Config* Config::instance()
|
Config* Config::instance()
|
||||||
@@ -105,6 +110,12 @@ Config* Config::instance()
|
|||||||
return m_instance;
|
return m_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Config::createConfigFromFile(QString file)
|
||||||
|
{
|
||||||
|
Q_ASSERT(!m_instance);
|
||||||
|
m_instance = new Config(file, qApp);
|
||||||
|
}
|
||||||
|
|
||||||
void Config::createTempFileInstance()
|
void Config::createTempFileInstance()
|
||||||
{
|
{
|
||||||
Q_ASSERT(!m_instance);
|
Q_ASSERT(!m_instance);
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#ifndef KEEPASSX_CONFIG_H
|
#ifndef KEEPASSX_CONFIG_H
|
||||||
#define KEEPASSX_CONFIG_H
|
#define KEEPASSX_CONFIG_H
|
||||||
|
|
||||||
#include <QtCore/QScopedPointer>
|
#include <QScopedPointer>
|
||||||
#include <QtCore/QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
@@ -36,6 +36,7 @@ public:
|
|||||||
void set(const QString& key, const QVariant& value);
|
void set(const QString& key, const QVariant& value);
|
||||||
|
|
||||||
static Config* instance();
|
static Config* instance();
|
||||||
|
static void createConfigFromFile(QString file);
|
||||||
static void createTempFileInstance();
|
static void createTempFileInstance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
|
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
|
|
||||||
#include <QtCore/QFile>
|
#include <QFile>
|
||||||
#include <QtCore/QTimer>
|
#include <QTimer>
|
||||||
#include <QtCore/QXmlStreamReader>
|
#include <QXmlStreamReader>
|
||||||
|
|
||||||
#include "core/Group.h"
|
#include "core/Group.h"
|
||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
@@ -32,13 +32,14 @@ QHash<Uuid, Database*> Database::m_uuidMap;
|
|||||||
Database::Database()
|
Database::Database()
|
||||||
: m_metadata(new Metadata(this))
|
: m_metadata(new Metadata(this))
|
||||||
, m_timer(new QTimer(this))
|
, m_timer(new QTimer(this))
|
||||||
, m_cipher(KeePass2::CIPHER_AES)
|
|
||||||
, m_compressionAlgo(CompressionGZip)
|
|
||||||
, m_transformRounds(50000)
|
|
||||||
, m_hasKey(false)
|
|
||||||
, m_emitModified(false)
|
, m_emitModified(false)
|
||||||
, m_uuid(Uuid::random())
|
, m_uuid(Uuid::random())
|
||||||
{
|
{
|
||||||
|
m_data.cipher = KeePass2::CIPHER_AES;
|
||||||
|
m_data.compressionAlgo = CompressionGZip;
|
||||||
|
m_data.transformRounds = 50000;
|
||||||
|
m_data.hasKey = false;
|
||||||
|
|
||||||
setRootGroup(new Group());
|
setRootGroup(new Group());
|
||||||
rootGroup()->setUuid(Uuid::random());
|
rootGroup()->setUuid(Uuid::random());
|
||||||
m_timer->setSingleShot(true);
|
m_timer->setSingleShot(true);
|
||||||
@@ -150,60 +151,60 @@ void Database::addDeletedObject(const Uuid& uuid)
|
|||||||
|
|
||||||
Uuid Database::cipher() const
|
Uuid Database::cipher() const
|
||||||
{
|
{
|
||||||
return m_cipher;
|
return m_data.cipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::CompressionAlgorithm Database::compressionAlgo() const
|
Database::CompressionAlgorithm Database::compressionAlgo() const
|
||||||
{
|
{
|
||||||
return m_compressionAlgo;
|
return m_data.compressionAlgo;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Database::transformSeed() const
|
QByteArray Database::transformSeed() const
|
||||||
{
|
{
|
||||||
return m_transformSeed;
|
return m_data.transformSeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 Database::transformRounds() const
|
quint64 Database::transformRounds() const
|
||||||
{
|
{
|
||||||
return m_transformRounds;
|
return m_data.transformRounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Database::transformedMasterKey() const
|
QByteArray Database::transformedMasterKey() const
|
||||||
{
|
{
|
||||||
return m_transformedMasterKey;
|
return m_data.transformedMasterKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::setCipher(const Uuid& cipher)
|
void Database::setCipher(const Uuid& cipher)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!cipher.isNull());
|
Q_ASSERT(!cipher.isNull());
|
||||||
|
|
||||||
m_cipher = cipher;
|
m_data.cipher = cipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::setCompressionAlgo(Database::CompressionAlgorithm algo)
|
void Database::setCompressionAlgo(Database::CompressionAlgorithm algo)
|
||||||
{
|
{
|
||||||
Q_ASSERT(static_cast<quint32>(algo) <= CompressionAlgorithmMax);
|
Q_ASSERT(static_cast<quint32>(algo) <= CompressionAlgorithmMax);
|
||||||
|
|
||||||
m_compressionAlgo = algo;
|
m_data.compressionAlgo = algo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::setTransformRounds(quint64 rounds)
|
void Database::setTransformRounds(quint64 rounds)
|
||||||
{
|
{
|
||||||
if (m_transformRounds != rounds) {
|
if (m_data.transformRounds != rounds) {
|
||||||
m_transformRounds = rounds;
|
m_data.transformRounds = rounds;
|
||||||
|
|
||||||
if (m_hasKey) {
|
if (m_data.hasKey) {
|
||||||
setKey(m_key);
|
setKey(m_data.key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::setKey(const CompositeKey& key, const QByteArray& transformSeed, bool updateChangedTime)
|
void Database::setKey(const CompositeKey& key, const QByteArray& transformSeed, bool updateChangedTime)
|
||||||
{
|
{
|
||||||
m_key = key;
|
m_data.key = key;
|
||||||
m_transformSeed = transformSeed;
|
m_data.transformSeed = transformSeed;
|
||||||
m_transformedMasterKey = key.transform(transformSeed, transformRounds());
|
m_data.transformedMasterKey = key.transform(transformSeed, transformRounds());
|
||||||
m_hasKey = true;
|
m_data.hasKey = true;
|
||||||
if (updateChangedTime) {
|
if (updateChangedTime) {
|
||||||
m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc());
|
m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc());
|
||||||
}
|
}
|
||||||
@@ -212,19 +213,19 @@ void Database::setKey(const CompositeKey& key, const QByteArray& transformSeed,
|
|||||||
|
|
||||||
void Database::setKey(const CompositeKey& key)
|
void Database::setKey(const CompositeKey& key)
|
||||||
{
|
{
|
||||||
setKey(key, Random::randomArray(32));
|
setKey(key, randomGen()->randomArray(32));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::hasKey() const
|
bool Database::hasKey() const
|
||||||
{
|
{
|
||||||
return m_hasKey;
|
return m_data.hasKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Database::verifyKey(const CompositeKey& key) const
|
bool Database::verifyKey(const CompositeKey& key) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(hasKey());
|
Q_ASSERT(hasKey());
|
||||||
|
|
||||||
return (m_key.rawKey() == key.rawKey());
|
return (m_data.key.rawKey() == key.rawKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::createRecycleBin()
|
void Database::createRecycleBin()
|
||||||
@@ -269,6 +270,12 @@ void Database::setEmitModified(bool value)
|
|||||||
m_emitModified = value;
|
m_emitModified = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Database::copyAttributesFrom(const Database* other)
|
||||||
|
{
|
||||||
|
m_data = other->m_data;
|
||||||
|
m_metadata->copyAttributesFrom(other->m_metadata);
|
||||||
|
}
|
||||||
|
|
||||||
Uuid Database::uuid()
|
Uuid Database::uuid()
|
||||||
{
|
{
|
||||||
return m_uuid;
|
return m_uuid;
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#ifndef KEEPASSX_DATABASE_H
|
#ifndef KEEPASSX_DATABASE_H
|
||||||
#define KEEPASSX_DATABASE_H
|
#define KEEPASSX_DATABASE_H
|
||||||
|
|
||||||
#include <QtCore/QDateTime>
|
#include <QDateTime>
|
||||||
#include <QtCore/QHash>
|
#include <QHash>
|
||||||
|
|
||||||
#include "core/Uuid.h"
|
#include "core/Uuid.h"
|
||||||
#include "keys/CompositeKey.h"
|
#include "keys/CompositeKey.h"
|
||||||
@@ -49,6 +49,17 @@ public:
|
|||||||
};
|
};
|
||||||
static const quint32 CompressionAlgorithmMax = CompressionGZip;
|
static const quint32 CompressionAlgorithmMax = CompressionGZip;
|
||||||
|
|
||||||
|
struct DatabaseData
|
||||||
|
{
|
||||||
|
Uuid cipher;
|
||||||
|
CompressionAlgorithm compressionAlgo;
|
||||||
|
QByteArray transformSeed;
|
||||||
|
quint64 transformRounds;
|
||||||
|
QByteArray transformedMasterKey;
|
||||||
|
CompositeKey key;
|
||||||
|
bool hasKey;
|
||||||
|
};
|
||||||
|
|
||||||
Database();
|
Database();
|
||||||
~Database();
|
~Database();
|
||||||
Group* rootGroup();
|
Group* rootGroup();
|
||||||
@@ -91,6 +102,7 @@ public:
|
|||||||
void recycleEntry(Entry* entry);
|
void recycleEntry(Entry* entry);
|
||||||
void recycleGroup(Group* group);
|
void recycleGroup(Group* group);
|
||||||
void setEmitModified(bool value);
|
void setEmitModified(bool value);
|
||||||
|
void copyAttributesFrom(const Database* other);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a unique id that is only valid as long as the Database exists.
|
* Returns a unique id that is only valid as long as the Database exists.
|
||||||
@@ -124,15 +136,7 @@ private:
|
|||||||
Group* m_rootGroup;
|
Group* m_rootGroup;
|
||||||
QList<DeletedObject> m_deletedObjects;
|
QList<DeletedObject> m_deletedObjects;
|
||||||
QTimer* m_timer;
|
QTimer* m_timer;
|
||||||
|
DatabaseData m_data;
|
||||||
Uuid m_cipher;
|
|
||||||
CompressionAlgorithm m_compressionAlgo;
|
|
||||||
QByteArray m_transformSeed;
|
|
||||||
quint64 m_transformRounds;
|
|
||||||
QByteArray m_transformedMasterKey;
|
|
||||||
|
|
||||||
CompositeKey m_key;
|
|
||||||
bool m_hasKey;
|
|
||||||
bool m_emitModified;
|
bool m_emitModified;
|
||||||
|
|
||||||
Uuid m_uuid;
|
Uuid m_uuid;
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
#ifndef KEEPASSX_DATABASEICONS_H
|
#ifndef KEEPASSX_DATABASEICONS_H
|
||||||
#define KEEPASSX_DATABASEICONS_H
|
#define KEEPASSX_DATABASEICONS_H
|
||||||
|
|
||||||
#include <QtCore/QVector>
|
#include <QImage>
|
||||||
#include <QtGui/QImage>
|
#include <QPixmap>
|
||||||
#include <QtGui/QPixmap>
|
#include <QPixmapCache>
|
||||||
#include <QtGui/QPixmapCache>
|
#include <QVector>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
#include "Endian.h"
|
#include "Endian.h"
|
||||||
|
|
||||||
#include <QtCore/QtEndian>
|
#include <QtEndian>
|
||||||
#include <QtCore/QIODevice>
|
#include <QIODevice>
|
||||||
|
|
||||||
namespace Endian {
|
namespace Endian {
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#ifndef KEEPASSX_ENDIAN_H
|
#ifndef KEEPASSX_ENDIAN_H
|
||||||
#define KEEPASSX_ENDIAN_H
|
#define KEEPASSX_ENDIAN_H
|
||||||
|
|
||||||
#include <QtCore/QByteArray>
|
#include <QByteArray>
|
||||||
#include <QtCore/QSysInfo>
|
#include <QSysInfo>
|
||||||
|
|
||||||
class QIODevice;
|
class QIODevice;
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ Entry::Entry()
|
|||||||
, m_attachments(new EntryAttachments(this))
|
, m_attachments(new EntryAttachments(this))
|
||||||
, m_autoTypeAssociations(new AutoTypeAssociations(this))
|
, m_autoTypeAssociations(new AutoTypeAssociations(this))
|
||||||
, m_tmpHistoryItem(Q_NULLPTR)
|
, m_tmpHistoryItem(Q_NULLPTR)
|
||||||
|
, m_modifiedSinceBegin(false)
|
||||||
, m_updateTimeinfo(true)
|
, m_updateTimeinfo(true)
|
||||||
{
|
{
|
||||||
m_data.iconNumber = DefaultIconNumber;
|
m_data.iconNumber = DefaultIconNumber;
|
||||||
@@ -94,8 +95,14 @@ QImage Entry::icon() const
|
|||||||
return databaseIcons()->icon(m_data.iconNumber);
|
return databaseIcons()->icon(m_data.iconNumber);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: check if database() is 0
|
Q_ASSERT(database());
|
||||||
return database()->metadata()->customIcon(m_data.customIcon);
|
|
||||||
|
if (database()) {
|
||||||
|
return database()->metadata()->customIcon(m_data.customIcon);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return QImage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,9 +112,10 @@ QPixmap Entry::iconPixmap() const
|
|||||||
return databaseIcons()->iconPixmap(m_data.iconNumber);
|
return databaseIcons()->iconPixmap(m_data.iconNumber);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
Q_ASSERT(database());
|
||||||
|
|
||||||
QPixmap pixmap;
|
QPixmap pixmap;
|
||||||
if (!QPixmapCache::find(m_pixmapCacheKey, &pixmap)) {
|
if (database() && !QPixmapCache::find(m_pixmapCacheKey, &pixmap)) {
|
||||||
// TODO: check if database() is 0
|
|
||||||
pixmap = QPixmap::fromImage(database()->metadata()->customIcon(m_data.customIcon));
|
pixmap = QPixmap::fromImage(database()->metadata()->customIcon(m_data.customIcon));
|
||||||
m_pixmapCacheKey = QPixmapCache::insert(pixmap);
|
m_pixmapCacheKey = QPixmapCache::insert(pixmap);
|
||||||
}
|
}
|
||||||
@@ -178,27 +186,27 @@ const AutoTypeAssociations* Entry::autoTypeAssociations() const
|
|||||||
|
|
||||||
QString Entry::title() const
|
QString Entry::title() const
|
||||||
{
|
{
|
||||||
return m_attributes->value("Title");
|
return m_attributes->value(EntryAttributes::TitleKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Entry::url() const
|
QString Entry::url() const
|
||||||
{
|
{
|
||||||
return m_attributes->value("URL");
|
return m_attributes->value(EntryAttributes::URLKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Entry::username() const
|
QString Entry::username() const
|
||||||
{
|
{
|
||||||
return m_attributes->value("UserName");
|
return m_attributes->value(EntryAttributes::UserNameKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Entry::password() const
|
QString Entry::password() const
|
||||||
{
|
{
|
||||||
return m_attributes->value("Password");
|
return m_attributes->value(EntryAttributes::PasswordKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Entry::notes() const
|
QString Entry::notes() const
|
||||||
{
|
{
|
||||||
return m_attributes->value("Notes");
|
return m_attributes->value(EntryAttributes::NotesKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Entry::isExpired() const
|
bool Entry::isExpired() const
|
||||||
@@ -304,27 +312,27 @@ void Entry::setDefaultAutoTypeSequence(const QString& sequence)
|
|||||||
|
|
||||||
void Entry::setTitle(const QString& title)
|
void Entry::setTitle(const QString& title)
|
||||||
{
|
{
|
||||||
m_attributes->set("Title", title, m_attributes->isProtected("Title"));
|
m_attributes->set(EntryAttributes::TitleKey, title, m_attributes->isProtected(EntryAttributes::TitleKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entry::setUrl(const QString& url)
|
void Entry::setUrl(const QString& url)
|
||||||
{
|
{
|
||||||
m_attributes->set("URL", url, m_attributes->isProtected("URL"));
|
m_attributes->set(EntryAttributes::URLKey, url, m_attributes->isProtected(EntryAttributes::URLKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entry::setUsername(const QString& username)
|
void Entry::setUsername(const QString& username)
|
||||||
{
|
{
|
||||||
m_attributes->set("UserName", username, m_attributes->isProtected("UserName"));
|
m_attributes->set(EntryAttributes::UserNameKey, username, m_attributes->isProtected(EntryAttributes::UserNameKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entry::setPassword(const QString& password)
|
void Entry::setPassword(const QString& password)
|
||||||
{
|
{
|
||||||
m_attributes->set("Password", password, m_attributes->isProtected("Password"));
|
m_attributes->set(EntryAttributes::PasswordKey, password, m_attributes->isProtected(EntryAttributes::PasswordKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entry::setNotes(const QString& notes)
|
void Entry::setNotes(const QString& notes)
|
||||||
{
|
{
|
||||||
m_attributes->set("Notes", notes, m_attributes->isProtected("Notes"));
|
m_attributes->set(EntryAttributes::NotesKey, notes, m_attributes->isProtected(EntryAttributes::NotesKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entry::setExpires(const bool& value)
|
void Entry::setExpires(const bool& value)
|
||||||
@@ -432,26 +440,54 @@ void Entry::truncateHistory()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* Entry::clone() const
|
Entry* Entry::clone(CloneFlags flags) const
|
||||||
{
|
{
|
||||||
Entry* entry = new Entry();
|
Entry* entry = new Entry();
|
||||||
entry->setUpdateTimeinfo(false);
|
entry->setUpdateTimeinfo(false);
|
||||||
entry->m_uuid = m_uuid;
|
if (flags & CloneNewUuid) {
|
||||||
|
entry->m_uuid = Uuid::random();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry->m_uuid = m_uuid;
|
||||||
|
}
|
||||||
entry->m_data = m_data;
|
entry->m_data = m_data;
|
||||||
entry->m_attributes->copyDataFrom(m_attributes);
|
entry->m_attributes->copyDataFrom(m_attributes);
|
||||||
entry->m_attachments->copyDataFrom(m_attachments);
|
entry->m_attachments->copyDataFrom(m_attachments);
|
||||||
entry->m_autoTypeAssociations->copyDataFrom(this->m_autoTypeAssociations);
|
entry->m_autoTypeAssociations->copyDataFrom(this->m_autoTypeAssociations);
|
||||||
|
if (flags & CloneIncludeHistory) {
|
||||||
|
Q_FOREACH (Entry* historyItem, m_history) {
|
||||||
|
Entry* historyItemClone = historyItem->clone(flags & ~CloneIncludeHistory & ~CloneNewUuid);
|
||||||
|
historyItemClone->setUpdateTimeinfo(false);
|
||||||
|
historyItemClone->setUuid(entry->uuid());
|
||||||
|
historyItemClone->setUpdateTimeinfo(true);
|
||||||
|
entry->addHistoryItem(historyItemClone);
|
||||||
|
}
|
||||||
|
}
|
||||||
entry->setUpdateTimeinfo(true);
|
entry->setUpdateTimeinfo(true);
|
||||||
|
|
||||||
QDateTime now = Tools::currentDateTimeUtc();
|
if (flags & CloneResetTimeInfo) {
|
||||||
entry->m_data.timeInfo.setCreationTime(now);
|
QDateTime now = Tools::currentDateTimeUtc();
|
||||||
entry->m_data.timeInfo.setLastModificationTime(now);
|
entry->m_data.timeInfo.setCreationTime(now);
|
||||||
entry->m_data.timeInfo.setLastAccessTime(now);
|
entry->m_data.timeInfo.setLastModificationTime(now);
|
||||||
entry->m_data.timeInfo.setLocationChanged(now);
|
entry->m_data.timeInfo.setLastAccessTime(now);
|
||||||
|
entry->m_data.timeInfo.setLocationChanged(now);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Entry::copyDataFrom(const Entry* other)
|
||||||
|
{
|
||||||
|
setUpdateTimeinfo(false);
|
||||||
|
m_data = other->m_data;
|
||||||
|
m_attributes->copyDataFrom(other->m_attributes);
|
||||||
|
m_attachments->copyDataFrom(other->m_attachments);
|
||||||
|
m_autoTypeAssociations->copyDataFrom(other->m_autoTypeAssociations);
|
||||||
|
setUpdateTimeinfo(true);
|
||||||
|
}
|
||||||
|
|
||||||
void Entry::beginUpdate()
|
void Entry::beginUpdate()
|
||||||
{
|
{
|
||||||
Q_ASSERT(!m_tmpHistoryItem);
|
Q_ASSERT(!m_tmpHistoryItem);
|
||||||
|
|||||||
@@ -18,14 +18,14 @@
|
|||||||
#ifndef KEEPASSX_ENTRY_H
|
#ifndef KEEPASSX_ENTRY_H
|
||||||
#define KEEPASSX_ENTRY_H
|
#define KEEPASSX_ENTRY_H
|
||||||
|
|
||||||
#include <QtCore/QMap>
|
#include <QColor>
|
||||||
#include <QtCore/QPointer>
|
#include <QImage>
|
||||||
#include <QtCore/QSet>
|
#include <QMap>
|
||||||
#include <QtCore/QUrl>
|
#include <QPixmap>
|
||||||
#include <QtGui/QColor>
|
#include <QPixmapCache>
|
||||||
#include <QtGui/QImage>
|
#include <QPointer>
|
||||||
#include <QtGui/QPixmap>
|
#include <QSet>
|
||||||
#include <QtGui/QPixmapCache>
|
#include <QUrl>
|
||||||
|
|
||||||
#include "core/AutoTypeAssociations.h"
|
#include "core/AutoTypeAssociations.h"
|
||||||
#include "core/EntryAttachments.h"
|
#include "core/EntryAttachments.h"
|
||||||
@@ -110,7 +110,23 @@ public:
|
|||||||
void addHistoryItem(Entry* entry);
|
void addHistoryItem(Entry* entry);
|
||||||
void removeHistoryItems(const QList<Entry*>& historyEntries);
|
void removeHistoryItems(const QList<Entry*>& historyEntries);
|
||||||
void truncateHistory();
|
void truncateHistory();
|
||||||
Entry* clone() const;
|
|
||||||
|
enum CloneFlag {
|
||||||
|
CloneNoFlags = 0,
|
||||||
|
CloneNewUuid = 1, // generate a random uuid for the clone
|
||||||
|
CloneResetTimeInfo = 2, // set all TimeInfo attributes to the current time
|
||||||
|
CloneIncludeHistory = 4 // clone the history items
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(CloneFlags, CloneFlag)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a duplicate of this entry except that the returned entry isn't
|
||||||
|
* part of any group.
|
||||||
|
* Note that you need to copy the custom icons manually when inserting the
|
||||||
|
* new entry into another database.
|
||||||
|
*/
|
||||||
|
Entry* clone(CloneFlags flags) const;
|
||||||
|
void copyDataFrom(const Entry* other);
|
||||||
QString resolvePlaceholders(const QString& str) const;
|
QString resolvePlaceholders(const QString& str) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -159,4 +175,6 @@ private:
|
|||||||
bool m_updateTimeinfo;
|
bool m_updateTimeinfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(Entry::CloneFlags)
|
||||||
|
|
||||||
#endif // KEEPASSX_ENTRY_H
|
#endif // KEEPASSX_ENTRY_H
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#ifndef KEEPASSX_ENTRYATTACHMENTS_H
|
#ifndef KEEPASSX_ENTRYATTACHMENTS_H
|
||||||
#define KEEPASSX_ENTRYATTACHMENTS_H
|
#define KEEPASSX_ENTRYATTACHMENTS_H
|
||||||
|
|
||||||
#include <QtCore/QMap>
|
#include <QMap>
|
||||||
#include <QtCore/QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,13 @@
|
|||||||
|
|
||||||
#include "EntryAttributes.h"
|
#include "EntryAttributes.h"
|
||||||
|
|
||||||
const QStringList EntryAttributes::DefaultAttributes(QStringList() << "Title" << "UserName"
|
const QString EntryAttributes::TitleKey = "Title";
|
||||||
<< "Password" << "URL" << "Notes");
|
const QString EntryAttributes::UserNameKey = "UserName";
|
||||||
|
const QString EntryAttributes::PasswordKey = "Password";
|
||||||
|
const QString EntryAttributes::URLKey = "URL";
|
||||||
|
const QString EntryAttributes::NotesKey = "Notes";
|
||||||
|
const QStringList EntryAttributes::DefaultAttributes(QStringList() << TitleKey << UserNameKey
|
||||||
|
<< PasswordKey << URLKey << NotesKey);
|
||||||
|
|
||||||
EntryAttributes::EntryAttributes(QObject* parent)
|
EntryAttributes::EntryAttributes(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
#ifndef KEEPASSX_ENTRYATTRIBUTES_H
|
#ifndef KEEPASSX_ENTRYATTRIBUTES_H
|
||||||
#define KEEPASSX_ENTRYATTRIBUTES_H
|
#define KEEPASSX_ENTRYATTRIBUTES_H
|
||||||
|
|
||||||
#include <QtCore/QMap>
|
#include <QMap>
|
||||||
#include <QtCore/QSet>
|
#include <QObject>
|
||||||
#include <QtCore/QObject>
|
#include <QSet>
|
||||||
#include <QtCore/QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
@@ -46,6 +46,11 @@ public:
|
|||||||
bool operator==(const EntryAttributes& other) const;
|
bool operator==(const EntryAttributes& other) const;
|
||||||
bool operator!=(const EntryAttributes& other) const;
|
bool operator!=(const EntryAttributes& other) const;
|
||||||
|
|
||||||
|
static const QString TitleKey;
|
||||||
|
static const QString UserNameKey;
|
||||||
|
static const QString PasswordKey;
|
||||||
|
static const QString URLKey;
|
||||||
|
static const QString NotesKey;
|
||||||
static const QStringList DefaultAttributes;
|
static const QStringList DefaultAttributes;
|
||||||
static bool isDefaultAttribute(const QString& key);
|
static bool isDefaultAttribute(const QString& key);
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
|
|
||||||
#include "FilePath.h"
|
#include "FilePath.h"
|
||||||
|
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QtCore/QDir>
|
#include <QDir>
|
||||||
#include <QtCore/QLibrary>
|
#include <QLibrary>
|
||||||
|
|
||||||
#include "config-keepassx.h"
|
#include "config-keepassx.h"
|
||||||
|
|
||||||
@@ -48,7 +48,15 @@ QString FilePath::pluginPath(const QString& name)
|
|||||||
pluginPaths << QCoreApplication::applicationDirPath() + "/../src/autotype/test";
|
pluginPaths << QCoreApplication::applicationDirPath() + "/../src/autotype/test";
|
||||||
|
|
||||||
pluginPaths << QCoreApplication::applicationDirPath();
|
pluginPaths << QCoreApplication::applicationDirPath();
|
||||||
pluginPaths << QCoreApplication::applicationDirPath() + "/../lib/keepassx";
|
|
||||||
|
QString systemPluginDir = KEEPASSX_PLUGIN_DIR;
|
||||||
|
if (systemPluginDir != ".") {
|
||||||
|
if (!QDir(systemPluginDir).isAbsolute()) {
|
||||||
|
systemPluginDir = QCoreApplication::applicationDirPath() + "/../" + systemPluginDir;
|
||||||
|
systemPluginDir = QDir(systemPluginDir).canonicalPath();
|
||||||
|
}
|
||||||
|
pluginPaths << systemPluginDir;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList dirFilter;
|
QStringList dirFilter;
|
||||||
dirFilter << QString("*%1*").arg(name);
|
dirFilter << QString("*%1*").arg(name);
|
||||||
@@ -109,6 +117,51 @@ QIcon FilePath::icon(const QString& category, const QString& name, bool fromThem
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QIcon FilePath::onOffIcon(const QString& category, const QString& name)
|
||||||
|
{
|
||||||
|
QString combinedName = category + "/" + name;
|
||||||
|
QString cacheName = "onoff/" + combinedName;
|
||||||
|
|
||||||
|
QIcon icon = m_iconCache.value(cacheName);
|
||||||
|
|
||||||
|
if (!icon.isNull()) {
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
QIcon::State state;
|
||||||
|
QString stateName;
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
state = QIcon::Off;
|
||||||
|
stateName = "off";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
state = QIcon::On;
|
||||||
|
stateName = "on";
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<int> pngSizes;
|
||||||
|
pngSizes << 16 << 22 << 24 << 32 << 48 << 64 << 128;
|
||||||
|
QString filename;
|
||||||
|
Q_FOREACH (int size, pngSizes) {
|
||||||
|
filename = QString("%1/icons/application/%2x%2/%3-%4.png").arg(m_dataPath, QString::number(size),
|
||||||
|
combinedName, stateName);
|
||||||
|
if (QFile::exists(filename)) {
|
||||||
|
icon.addFile(filename, QSize(size, size), QIcon::Normal, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filename = QString("%1/icons/application/scalable/%3-%4.svgz").arg(m_dataPath, combinedName, stateName);
|
||||||
|
if (QFile::exists(filename)) {
|
||||||
|
icon.addFile(filename, QSize(), QIcon::Normal, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_iconCache.insert(cacheName, icon);
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
FilePath::FilePath()
|
FilePath::FilePath()
|
||||||
{
|
{
|
||||||
if (false) {
|
if (false) {
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
#ifndef KEEPASSX_FILEPATH_H
|
#ifndef KEEPASSX_FILEPATH_H
|
||||||
#define KEEPASSX_FILEPATH_H
|
#define KEEPASSX_FILEPATH_H
|
||||||
|
|
||||||
#include <QtCore/QHash>
|
#include <QHash>
|
||||||
#include <QtCore/QString>
|
#include <QIcon>
|
||||||
#include <QtGui/QIcon>
|
#include <QString>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
@@ -31,6 +31,7 @@ public:
|
|||||||
QString pluginPath(const QString& name);
|
QString pluginPath(const QString& name);
|
||||||
QIcon applicationIcon();
|
QIcon applicationIcon();
|
||||||
QIcon icon(const QString& category, const QString& name, bool fromTheme = true);
|
QIcon icon(const QString& category, const QString& name, bool fromTheme = true);
|
||||||
|
QIcon onOffIcon(const QString& category, const QString& name);
|
||||||
|
|
||||||
static FilePath* instance();
|
static FilePath* instance();
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
// mostly copied from qcompilerdetection.h which is part of Qt 5
|
// mostly copied from qcompilerdetection.h which is part of Qt 5
|
||||||
|
|
||||||
#include <QtCore/QtGlobal>
|
#include <QtGlobal>
|
||||||
|
|
||||||
#ifdef Q_CC_CLANG
|
#ifdef Q_CC_CLANG
|
||||||
# if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
# if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||||
@@ -125,7 +125,11 @@ template <> class QStaticAssertFailure<true> {};
|
|||||||
# define KEEPASSX_EXPORT Q_DECL_IMPORT
|
# define KEEPASSX_EXPORT Q_DECL_IMPORT
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# define KEEPASSX_EXPORT
|
# define KEEPASSX_EXPORT Q_DECL_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef QUINT32_MAX
|
||||||
|
#define QUINT32_MAX 4294967295U
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // KEEPASSX_GLOBAL_H
|
#endif // KEEPASSX_GLOBAL_H
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ const int Group::DefaultIconNumber = 48;
|
|||||||
const int Group::RecycleBinIconNumber = 43;
|
const int Group::RecycleBinIconNumber = 43;
|
||||||
|
|
||||||
Group::Group()
|
Group::Group()
|
||||||
: m_iconNumber(DefaultIconNumber)
|
: m_updateTimeinfo(true)
|
||||||
, m_isExpanded(true)
|
|
||||||
, m_autoTypeEnabled(Inherit)
|
|
||||||
, m_searchingEnabled(Inherit)
|
|
||||||
, m_updateTimeinfo(true)
|
|
||||||
{
|
{
|
||||||
|
m_data.iconNumber = DefaultIconNumber;
|
||||||
|
m_data.isExpanded = true;
|
||||||
|
m_data.autoTypeEnabled = Inherit;
|
||||||
|
m_data.searchingEnabled = Inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group::~Group()
|
Group::~Group()
|
||||||
@@ -84,8 +84,8 @@ template <class P, class V> inline bool Group::set(P& property, const V& value)
|
|||||||
void Group::updateTimeinfo()
|
void Group::updateTimeinfo()
|
||||||
{
|
{
|
||||||
if (m_updateTimeinfo) {
|
if (m_updateTimeinfo) {
|
||||||
m_timeInfo.setLastModificationTime(Tools::currentDateTimeUtc());
|
m_data.timeInfo.setLastModificationTime(Tools::currentDateTimeUtc());
|
||||||
m_timeInfo.setLastAccessTime(Tools::currentDateTimeUtc());
|
m_data.timeInfo.setLastAccessTime(Tools::currentDateTimeUtc());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,35 +101,42 @@ Uuid Group::uuid() const
|
|||||||
|
|
||||||
QString Group::name() const
|
QString Group::name() const
|
||||||
{
|
{
|
||||||
return m_name;
|
return m_data.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Group::notes() const
|
QString Group::notes() const
|
||||||
{
|
{
|
||||||
return m_notes;
|
return m_data.notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage Group::icon() const
|
QImage Group::icon() const
|
||||||
{
|
{
|
||||||
if (m_customIcon.isNull()) {
|
if (m_data.customIcon.isNull()) {
|
||||||
return databaseIcons()->icon(m_iconNumber);
|
return databaseIcons()->icon(m_data.iconNumber);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO: check if m_db is 0
|
Q_ASSERT(m_db);
|
||||||
return m_db->metadata()->customIcon(m_customIcon);
|
|
||||||
|
if (m_db) {
|
||||||
|
return m_db->metadata()->customIcon(m_data.customIcon);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return QImage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap Group::iconPixmap() const
|
QPixmap Group::iconPixmap() const
|
||||||
{
|
{
|
||||||
if (m_customIcon.isNull()) {
|
if (m_data.customIcon.isNull()) {
|
||||||
return databaseIcons()->iconPixmap(m_iconNumber);
|
return databaseIcons()->iconPixmap(m_data.iconNumber);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
Q_ASSERT(m_db);
|
||||||
|
|
||||||
QPixmap pixmap;
|
QPixmap pixmap;
|
||||||
if (!QPixmapCache::find(m_pixmapCacheKey, &pixmap)) {
|
if (m_db && !QPixmapCache::find(m_pixmapCacheKey, &pixmap)) {
|
||||||
// TODO: check if m_db is 0
|
pixmap = QPixmap::fromImage(m_db->metadata()->customIcon(m_data.customIcon));
|
||||||
pixmap = QPixmap::fromImage(m_db->metadata()->customIcon(m_customIcon));
|
|
||||||
m_pixmapCacheKey = QPixmapCache::insert(pixmap);
|
m_pixmapCacheKey = QPixmapCache::insert(pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,37 +146,37 @@ QPixmap Group::iconPixmap() const
|
|||||||
|
|
||||||
int Group::iconNumber() const
|
int Group::iconNumber() const
|
||||||
{
|
{
|
||||||
return m_iconNumber;
|
return m_data.iconNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
Uuid Group::iconUuid() const
|
Uuid Group::iconUuid() const
|
||||||
{
|
{
|
||||||
return m_customIcon;
|
return m_data.customIcon;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeInfo Group::timeInfo() const
|
TimeInfo Group::timeInfo() const
|
||||||
{
|
{
|
||||||
return m_timeInfo;
|
return m_data.timeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Group::isExpanded() const
|
bool Group::isExpanded() const
|
||||||
{
|
{
|
||||||
return m_isExpanded;
|
return m_data.isExpanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Group::defaultAutoTypeSequence() const
|
QString Group::defaultAutoTypeSequence() const
|
||||||
{
|
{
|
||||||
return m_defaultAutoTypeSequence;
|
return m_data.defaultAutoTypeSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group::TriState Group::autoTypeEnabled() const
|
Group::TriState Group::autoTypeEnabled() const
|
||||||
{
|
{
|
||||||
return m_autoTypeEnabled;
|
return m_data.autoTypeEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group::TriState Group::searchingEnabled() const
|
Group::TriState Group::searchingEnabled() const
|
||||||
{
|
{
|
||||||
return m_searchingEnabled;
|
return m_data.searchingEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry* Group::lastTopVisibleEntry() const
|
Entry* Group::lastTopVisibleEntry() const
|
||||||
@@ -179,7 +186,7 @@ Entry* Group::lastTopVisibleEntry() const
|
|||||||
|
|
||||||
bool Group::isExpired() const
|
bool Group::isExpired() const
|
||||||
{
|
{
|
||||||
return m_timeInfo.expires() && m_timeInfo.expiryTime() < Tools::currentDateTimeUtc();
|
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Tools::currentDateTimeUtc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::setUuid(const Uuid& uuid)
|
void Group::setUuid(const Uuid& uuid)
|
||||||
@@ -189,23 +196,23 @@ void Group::setUuid(const Uuid& uuid)
|
|||||||
|
|
||||||
void Group::setName(const QString& name)
|
void Group::setName(const QString& name)
|
||||||
{
|
{
|
||||||
if (set(m_name, name)) {
|
if (set(m_data.name, name)) {
|
||||||
Q_EMIT dataChanged(this);
|
Q_EMIT dataChanged(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::setNotes(const QString& notes)
|
void Group::setNotes(const QString& notes)
|
||||||
{
|
{
|
||||||
set(m_notes, notes);
|
set(m_data.notes, notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::setIcon(int iconNumber)
|
void Group::setIcon(int iconNumber)
|
||||||
{
|
{
|
||||||
Q_ASSERT(iconNumber >= 0);
|
Q_ASSERT(iconNumber >= 0);
|
||||||
|
|
||||||
if (m_iconNumber != iconNumber || !m_customIcon.isNull()) {
|
if (m_data.iconNumber != iconNumber || !m_data.customIcon.isNull()) {
|
||||||
m_iconNumber = iconNumber;
|
m_data.iconNumber = iconNumber;
|
||||||
m_customIcon = Uuid();
|
m_data.customIcon = Uuid();
|
||||||
|
|
||||||
m_pixmapCacheKey = QPixmapCache::Key();
|
m_pixmapCacheKey = QPixmapCache::Key();
|
||||||
|
|
||||||
@@ -219,9 +226,9 @@ void Group::setIcon(const Uuid& uuid)
|
|||||||
{
|
{
|
||||||
Q_ASSERT(!uuid.isNull());
|
Q_ASSERT(!uuid.isNull());
|
||||||
|
|
||||||
if (m_customIcon != uuid) {
|
if (m_data.customIcon != uuid) {
|
||||||
m_customIcon = uuid;
|
m_data.customIcon = uuid;
|
||||||
m_iconNumber = 0;
|
m_data.iconNumber = 0;
|
||||||
|
|
||||||
m_pixmapCacheKey = QPixmapCache::Key();
|
m_pixmapCacheKey = QPixmapCache::Key();
|
||||||
|
|
||||||
@@ -233,13 +240,13 @@ void Group::setIcon(const Uuid& uuid)
|
|||||||
|
|
||||||
void Group::setTimeInfo(const TimeInfo& timeInfo)
|
void Group::setTimeInfo(const TimeInfo& timeInfo)
|
||||||
{
|
{
|
||||||
m_timeInfo = timeInfo;
|
m_data.timeInfo = timeInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::setExpanded(bool expanded)
|
void Group::setExpanded(bool expanded)
|
||||||
{
|
{
|
||||||
if (m_isExpanded != expanded) {
|
if (m_data.isExpanded != expanded) {
|
||||||
m_isExpanded = expanded;
|
m_data.isExpanded = expanded;
|
||||||
updateTimeinfo();
|
updateTimeinfo();
|
||||||
if (config()->get("ModifiedOnExpandedStateChanges").toBool()) {
|
if (config()->get("ModifiedOnExpandedStateChanges").toBool()) {
|
||||||
Q_EMIT modified();
|
Q_EMIT modified();
|
||||||
@@ -249,17 +256,17 @@ void Group::setExpanded(bool expanded)
|
|||||||
|
|
||||||
void Group::setDefaultAutoTypeSequence(const QString& sequence)
|
void Group::setDefaultAutoTypeSequence(const QString& sequence)
|
||||||
{
|
{
|
||||||
set(m_defaultAutoTypeSequence, sequence);
|
set(m_data.defaultAutoTypeSequence, sequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::setAutoTypeEnabled(TriState enable)
|
void Group::setAutoTypeEnabled(TriState enable)
|
||||||
{
|
{
|
||||||
set(m_autoTypeEnabled, enable);
|
set(m_data.autoTypeEnabled, enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::setSearchingEnabled(TriState enable)
|
void Group::setSearchingEnabled(TriState enable)
|
||||||
{
|
{
|
||||||
set(m_searchingEnabled, enable);
|
set(m_data.searchingEnabled, enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Group::setLastTopVisibleEntry(Entry* entry)
|
void Group::setLastTopVisibleEntry(Entry* entry)
|
||||||
@@ -269,8 +276,8 @@ void Group::setLastTopVisibleEntry(Entry* entry)
|
|||||||
|
|
||||||
void Group::setExpires(bool value)
|
void Group::setExpires(bool value)
|
||||||
{
|
{
|
||||||
if (m_timeInfo.expires() != value) {
|
if (m_data.timeInfo.expires() != value) {
|
||||||
m_timeInfo.setExpires(value);
|
m_data.timeInfo.setExpires(value);
|
||||||
updateTimeinfo();
|
updateTimeinfo();
|
||||||
Q_EMIT modified();
|
Q_EMIT modified();
|
||||||
}
|
}
|
||||||
@@ -278,8 +285,8 @@ void Group::setExpires(bool value)
|
|||||||
|
|
||||||
void Group::setExpiryTime(const QDateTime& dateTime)
|
void Group::setExpiryTime(const QDateTime& dateTime)
|
||||||
{
|
{
|
||||||
if (m_timeInfo.expiryTime() != dateTime) {
|
if (m_data.timeInfo.expiryTime() != dateTime) {
|
||||||
m_timeInfo.setExpiryTime(dateTime);
|
m_data.timeInfo.setExpiryTime(dateTime);
|
||||||
updateTimeinfo();
|
updateTimeinfo();
|
||||||
Q_EMIT modified();
|
Q_EMIT modified();
|
||||||
}
|
}
|
||||||
@@ -347,7 +354,7 @@ void Group::setParent(Group* parent, int index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_updateTimeinfo) {
|
if (m_updateTimeinfo) {
|
||||||
m_timeInfo.setLocationChanged(Tools::currentDateTimeUtc());
|
m_data.timeInfo.setLocationChanged(Tools::currentDateTimeUtc());
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_EMIT modified();
|
Q_EMIT modified();
|
||||||
@@ -436,6 +443,79 @@ QList<const Group*> Group::groupsRecursive(bool includeSelf) const
|
|||||||
return groupList;
|
return groupList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSet<Uuid> Group::customIconsRecursive() const
|
||||||
|
{
|
||||||
|
QSet<Uuid> result;
|
||||||
|
|
||||||
|
if (!iconUuid().isNull()) {
|
||||||
|
result.insert(iconUuid());
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_FOREACH (Entry* entry, entriesRecursive(true)) {
|
||||||
|
if (!entry->iconUuid().isNull()) {
|
||||||
|
result.insert(entry->iconUuid());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_FOREACH (Group* group, m_children) {
|
||||||
|
result.unite(group->customIconsRecursive());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Group* Group::clone(Entry::CloneFlags entryFlags) const
|
||||||
|
{
|
||||||
|
Group* clonedGroup = new Group();
|
||||||
|
|
||||||
|
clonedGroup->setUpdateTimeinfo(false);
|
||||||
|
|
||||||
|
clonedGroup->setUuid(Uuid::random());
|
||||||
|
clonedGroup->m_data = m_data;
|
||||||
|
|
||||||
|
Q_FOREACH (Entry* entry, entries()) {
|
||||||
|
Entry* clonedEntry = entry->clone(entryFlags);
|
||||||
|
clonedEntry->setGroup(clonedGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_FOREACH (Group* groupChild, children()) {
|
||||||
|
Group* clonedGroupChild = groupChild->clone();
|
||||||
|
clonedGroupChild->setParent(clonedGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
clonedGroup->setUpdateTimeinfo(true);
|
||||||
|
|
||||||
|
QDateTime now = Tools::currentDateTimeUtc();
|
||||||
|
clonedGroup->m_data.timeInfo.setCreationTime(now);
|
||||||
|
clonedGroup->m_data.timeInfo.setLastModificationTime(now);
|
||||||
|
clonedGroup->m_data.timeInfo.setLastAccessTime(now);
|
||||||
|
clonedGroup->m_data.timeInfo.setLocationChanged(now);
|
||||||
|
|
||||||
|
return clonedGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Group::copyDataFrom(const Group* other)
|
||||||
|
{
|
||||||
|
m_data = other->m_data;
|
||||||
|
m_lastTopVisibleEntry = other->m_lastTopVisibleEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
Database* Group::exportToDb()
|
||||||
|
{
|
||||||
|
Q_ASSERT(database());
|
||||||
|
|
||||||
|
Database* db = new Database();
|
||||||
|
Group* clonedGroup = clone(Entry::CloneNewUuid | Entry::CloneIncludeHistory);
|
||||||
|
clonedGroup->setParent(db->rootGroup());
|
||||||
|
|
||||||
|
QSet<Uuid> customIcons = customIconsRecursive();
|
||||||
|
db->metadata()->copyCustomIcons(customIcons, database()->metadata());
|
||||||
|
|
||||||
|
db->copyAttributesFrom(database());
|
||||||
|
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
void Group::addEntry(Entry* entry)
|
void Group::addEntry(Entry* entry)
|
||||||
{
|
{
|
||||||
Q_ASSERT(entry);
|
Q_ASSERT(entry);
|
||||||
@@ -551,7 +631,7 @@ QList<Entry*> Group::search(const QString& searchTerm, Qt::CaseSensitivity caseS
|
|||||||
|
|
||||||
bool Group::includeInSearch(bool resolveInherit)
|
bool Group::includeInSearch(bool resolveInherit)
|
||||||
{
|
{
|
||||||
switch (m_searchingEnabled) {
|
switch (m_data.searchingEnabled) {
|
||||||
case Inherit:
|
case Inherit:
|
||||||
if (!m_parent) {
|
if (!m_parent) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
#ifndef KEEPASSX_GROUP_H
|
#ifndef KEEPASSX_GROUP_H
|
||||||
#define KEEPASSX_GROUP_H
|
#define KEEPASSX_GROUP_H
|
||||||
|
|
||||||
#include <QtCore/QPointer>
|
#include <QImage>
|
||||||
#include <QtGui/QImage>
|
#include <QPixmap>
|
||||||
#include <QtGui/QPixmap>
|
#include <QPixmapCache>
|
||||||
#include <QtGui/QPixmapCache>
|
#include <QPointer>
|
||||||
|
|
||||||
#include "core/Database.h"
|
#include "core/Database.h"
|
||||||
#include "core/Entry.h"
|
#include "core/Entry.h"
|
||||||
@@ -35,6 +35,19 @@ class Group : public QObject
|
|||||||
public:
|
public:
|
||||||
enum TriState { Inherit, Enable, Disable };
|
enum TriState { Inherit, Enable, Disable };
|
||||||
|
|
||||||
|
struct GroupData
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
QString notes;
|
||||||
|
int iconNumber;
|
||||||
|
Uuid customIcon;
|
||||||
|
TimeInfo timeInfo;
|
||||||
|
bool isExpanded;
|
||||||
|
QString defaultAutoTypeSequence;
|
||||||
|
Group::TriState autoTypeEnabled;
|
||||||
|
Group::TriState searchingEnabled;
|
||||||
|
};
|
||||||
|
|
||||||
Group();
|
Group();
|
||||||
~Group();
|
~Group();
|
||||||
|
|
||||||
@@ -86,6 +99,17 @@ public:
|
|||||||
const QList<Entry*>& entries() const;
|
const QList<Entry*>& entries() const;
|
||||||
QList<Entry*> entriesRecursive(bool includeHistoryItems = false) const;
|
QList<Entry*> entriesRecursive(bool includeHistoryItems = false) const;
|
||||||
QList<const Group*> groupsRecursive(bool includeSelf) const;
|
QList<const Group*> groupsRecursive(bool includeSelf) const;
|
||||||
|
QSet<Uuid> customIconsRecursive() const;
|
||||||
|
/**
|
||||||
|
* Creates a duplicate of this group including all child entries and groups.
|
||||||
|
* The exceptions are that the returned group doesn't have a parent group
|
||||||
|
* and all TimeInfo attributes are set to the current time.
|
||||||
|
* Note that you need to copy the custom icons manually when inserting the
|
||||||
|
* new group into another database.
|
||||||
|
*/
|
||||||
|
Group* clone(Entry::CloneFlags entryFlags = Entry::CloneNewUuid | Entry::CloneResetTimeInfo) const;
|
||||||
|
void copyDataFrom(const Group* other);
|
||||||
|
Database* exportToDb();
|
||||||
|
|
||||||
QList<Entry*> search(const QString& searchTerm, Qt::CaseSensitivity caseSensitivity,
|
QList<Entry*> search(const QString& searchTerm, Qt::CaseSensitivity caseSensitivity,
|
||||||
bool resolveInherit = true);
|
bool resolveInherit = true);
|
||||||
@@ -127,15 +151,7 @@ private:
|
|||||||
|
|
||||||
QPointer<Database> m_db;
|
QPointer<Database> m_db;
|
||||||
Uuid m_uuid;
|
Uuid m_uuid;
|
||||||
QString m_name;
|
GroupData m_data;
|
||||||
QString m_notes;
|
|
||||||
int m_iconNumber;
|
|
||||||
Uuid m_customIcon;
|
|
||||||
TimeInfo m_timeInfo;
|
|
||||||
bool m_isExpanded;
|
|
||||||
QString m_defaultAutoTypeSequence;
|
|
||||||
TriState m_autoTypeEnabled;
|
|
||||||
TriState m_searchingEnabled;
|
|
||||||
QPointer<Entry> m_lastTopVisibleEntry;
|
QPointer<Entry> m_lastTopVisibleEntry;
|
||||||
QList<Group*> m_children;
|
QList<Group*> m_children;
|
||||||
QList<Entry*> m_entries;
|
QList<Entry*> m_entries;
|
||||||
|
|||||||
73
src/core/InactivityTimer.cpp
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Felix Geyer <debfx@fobos.de>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "InactivityTimer.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
InactivityTimer::InactivityTimer(QObject* parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_timer(new QTimer(this))
|
||||||
|
, m_active(false)
|
||||||
|
{
|
||||||
|
m_timer->setSingleShot(true);
|
||||||
|
connect(m_timer, SIGNAL(timeout()), SLOT(timeout()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InactivityTimer::setInactivityTimeout(int inactivityTimeout)
|
||||||
|
{
|
||||||
|
Q_ASSERT(inactivityTimeout > 0);
|
||||||
|
|
||||||
|
m_timer->setInterval(inactivityTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InactivityTimer::activate()
|
||||||
|
{
|
||||||
|
if (!m_active) {
|
||||||
|
qApp->installEventFilter(this);
|
||||||
|
}
|
||||||
|
m_active = true;
|
||||||
|
m_timer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InactivityTimer::deactivate()
|
||||||
|
{
|
||||||
|
qApp->removeEventFilter(this);
|
||||||
|
m_active = false;
|
||||||
|
m_timer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InactivityTimer::eventFilter(QObject* watched, QEvent* event)
|
||||||
|
{
|
||||||
|
const QEvent::Type type = event->type();
|
||||||
|
|
||||||
|
if ( (type >= QEvent::MouseButtonPress && type <= QEvent::KeyRelease)
|
||||||
|
|| (type >= QEvent::HoverEnter && type <= QEvent::HoverMove)
|
||||||
|
|| (type == QEvent::Wheel) ) {
|
||||||
|
m_timer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QObject::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InactivityTimer::timeout()
|
||||||
|
{
|
||||||
|
if (m_active && !m_timer->isActive()) {
|
||||||
|
Q_EMIT inactivityDetected();
|
||||||
|
}
|
||||||
|
}
|
||||||
51
src/core/InactivityTimer.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Felix Geyer <debfx@fobos.de>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 2 or (at your option)
|
||||||
|
* version 3 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEEPASSX_INACTIVITYTIMER_H
|
||||||
|
#define KEEPASSX_INACTIVITYTIMER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
class QTimer;
|
||||||
|
|
||||||
|
class InactivityTimer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit InactivityTimer(QObject* parent = Q_NULLPTR);
|
||||||
|
void setInactivityTimeout(int inactivityTimeout);
|
||||||
|
void activate();
|
||||||
|
void deactivate();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void inactivityDetected();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject* watched, QEvent* event);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void timeout();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTimer* m_timer;
|
||||||
|
bool m_active;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KEEPASSX_INACTIVITYTIMER_H
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef KEEPASSX_LISTDELETER_H
|
#ifndef KEEPASSX_LISTDELETER_H
|
||||||
#define KEEPASSX_LISTDELETER_H
|
#define KEEPASSX_LISTDELETER_H
|
||||||
|
|
||||||
#include <QtCore/QList>
|
#include <QList>
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ListDeleter
|
class ListDeleter
|
||||||
|
|||||||
@@ -26,25 +26,26 @@ const int Metadata::DefaultHistoryMaxSize = 6 * 1024 * 1024;
|
|||||||
|
|
||||||
Metadata::Metadata(QObject* parent)
|
Metadata::Metadata(QObject* parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, m_generator("KeePassX")
|
|
||||||
, m_maintenanceHistoryDays(365)
|
|
||||||
, m_protectTitle(false)
|
|
||||||
, m_protectUsername(false)
|
|
||||||
, m_protectPassword(true)
|
|
||||||
, m_protectUrl(false)
|
|
||||||
, m_protectNotes(false)
|
|
||||||
// , m_autoEnableVisualHiding(false)
|
|
||||||
, m_recycleBinEnabled(true)
|
|
||||||
, m_masterKeyChangeRec(-1)
|
|
||||||
, m_masterKeyChangeForce(-1)
|
|
||||||
, m_historyMaxItems(DefaultHistoryMaxItems)
|
|
||||||
, m_historyMaxSize(DefaultHistoryMaxSize)
|
|
||||||
, m_updateDatetime(true)
|
, m_updateDatetime(true)
|
||||||
{
|
{
|
||||||
|
m_data.generator = "KeePassX";
|
||||||
|
m_data.maintenanceHistoryDays = 365;
|
||||||
|
m_data.masterKeyChangeRec = -1;
|
||||||
|
m_data.masterKeyChangeForce = -1;
|
||||||
|
m_data.historyMaxItems = DefaultHistoryMaxItems;
|
||||||
|
m_data.historyMaxSize = DefaultHistoryMaxSize;
|
||||||
|
m_data.recycleBinEnabled = true;
|
||||||
|
m_data.protectTitle = false;
|
||||||
|
m_data.protectUsername = false;
|
||||||
|
m_data.protectPassword = true;
|
||||||
|
m_data.protectUrl = false;
|
||||||
|
m_data.protectNotes = false;
|
||||||
|
// m_data.autoEnableVisualHiding = false;
|
||||||
|
|
||||||
QDateTime now = Tools::currentDateTimeUtc();
|
QDateTime now = Tools::currentDateTimeUtc();
|
||||||
m_nameChanged = now;
|
m_data.nameChanged = now;
|
||||||
m_descriptionChanged = now;
|
m_data.descriptionChanged = now;
|
||||||
m_defaultUserNameChanged = now;
|
m_data.defaultUserNameChanged = now;
|
||||||
m_recycleBinChanged = now;
|
m_recycleBinChanged = now;
|
||||||
m_entryTemplatesGroupChanged = now;
|
m_entryTemplatesGroupChanged = now;
|
||||||
m_masterKeyChanged = now;
|
m_masterKeyChanged = now;
|
||||||
@@ -81,74 +82,79 @@ void Metadata::setUpdateDatetime(bool value)
|
|||||||
m_updateDatetime = value;
|
m_updateDatetime = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Metadata::copyAttributesFrom(const Metadata* other)
|
||||||
|
{
|
||||||
|
m_data = other->m_data;
|
||||||
|
}
|
||||||
|
|
||||||
QString Metadata::generator() const
|
QString Metadata::generator() const
|
||||||
{
|
{
|
||||||
return m_generator;
|
return m_data.generator;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Metadata::name() const
|
QString Metadata::name() const
|
||||||
{
|
{
|
||||||
return m_name;
|
return m_data.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime Metadata::nameChanged() const
|
QDateTime Metadata::nameChanged() const
|
||||||
{
|
{
|
||||||
return m_nameChanged;
|
return m_data.nameChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Metadata::description() const
|
QString Metadata::description() const
|
||||||
{
|
{
|
||||||
return m_description;
|
return m_data.description;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime Metadata::descriptionChanged() const
|
QDateTime Metadata::descriptionChanged() const
|
||||||
{
|
{
|
||||||
return m_descriptionChanged;
|
return m_data.descriptionChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Metadata::defaultUserName() const
|
QString Metadata::defaultUserName() const
|
||||||
{
|
{
|
||||||
return m_defaultUserName;
|
return m_data.defaultUserName;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDateTime Metadata::defaultUserNameChanged() const
|
QDateTime Metadata::defaultUserNameChanged() const
|
||||||
{
|
{
|
||||||
return m_defaultUserNameChanged;
|
return m_data.defaultUserNameChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Metadata::maintenanceHistoryDays() const
|
int Metadata::maintenanceHistoryDays() const
|
||||||
{
|
{
|
||||||
return m_maintenanceHistoryDays;
|
return m_data.maintenanceHistoryDays;
|
||||||
}
|
}
|
||||||
|
|
||||||
QColor Metadata::color() const
|
QColor Metadata::color() const
|
||||||
{
|
{
|
||||||
return m_color;
|
return m_data.color;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Metadata::protectTitle() const
|
bool Metadata::protectTitle() const
|
||||||
{
|
{
|
||||||
return m_protectTitle;
|
return m_data.protectTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Metadata::protectUsername() const
|
bool Metadata::protectUsername() const
|
||||||
{
|
{
|
||||||
return m_protectUsername;
|
return m_data.protectUsername;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Metadata::protectPassword() const
|
bool Metadata::protectPassword() const
|
||||||
{
|
{
|
||||||
return m_protectPassword;
|
return m_data.protectPassword;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Metadata::protectUrl() const
|
bool Metadata::protectUrl() const
|
||||||
{
|
{
|
||||||
return m_protectUrl;
|
return m_data.protectUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Metadata::protectNotes() const
|
bool Metadata::protectNotes() const
|
||||||
{
|
{
|
||||||
return m_protectNotes;
|
return m_data.protectNotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*bool Metadata::autoEnableVisualHiding() const
|
/*bool Metadata::autoEnableVisualHiding() const
|
||||||
@@ -178,7 +184,7 @@ QList<Uuid> Metadata::customIconsOrder() const
|
|||||||
|
|
||||||
bool Metadata::recycleBinEnabled() const
|
bool Metadata::recycleBinEnabled() const
|
||||||
{
|
{
|
||||||
return m_recycleBinEnabled;
|
return m_data.recycleBinEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
Group* Metadata::recycleBin()
|
Group* Metadata::recycleBin()
|
||||||
@@ -223,22 +229,22 @@ QDateTime Metadata::masterKeyChanged() const
|
|||||||
|
|
||||||
int Metadata::masterKeyChangeRec() const
|
int Metadata::masterKeyChangeRec() const
|
||||||
{
|
{
|
||||||
return m_masterKeyChangeRec;
|
return m_data.masterKeyChangeRec;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Metadata::masterKeyChangeForce() const
|
int Metadata::masterKeyChangeForce() const
|
||||||
{
|
{
|
||||||
return m_masterKeyChangeForce;
|
return m_data.masterKeyChangeForce;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Metadata::historyMaxItems() const
|
int Metadata::historyMaxItems() const
|
||||||
{
|
{
|
||||||
return m_historyMaxItems;
|
return m_data.historyMaxItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Metadata::historyMaxSize() const
|
int Metadata::historyMaxSize() const
|
||||||
{
|
{
|
||||||
return m_historyMaxSize;
|
return m_data.historyMaxSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<QString, QString> Metadata::customFields() const
|
QHash<QString, QString> Metadata::customFields() const
|
||||||
@@ -248,12 +254,12 @@ QHash<QString, QString> Metadata::customFields() const
|
|||||||
|
|
||||||
void Metadata::setGenerator(const QString& value)
|
void Metadata::setGenerator(const QString& value)
|
||||||
{
|
{
|
||||||
set(m_generator, value);
|
set(m_data.generator, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setName(const QString& value)
|
void Metadata::setName(const QString& value)
|
||||||
{
|
{
|
||||||
if (set(m_name, value, m_nameChanged)) {
|
if (set(m_data.name, value, m_data.nameChanged)) {
|
||||||
Q_EMIT nameTextChanged();
|
Q_EMIT nameTextChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,64 +267,64 @@ void Metadata::setName(const QString& value)
|
|||||||
void Metadata::setNameChanged(const QDateTime& value)
|
void Metadata::setNameChanged(const QDateTime& value)
|
||||||
{
|
{
|
||||||
Q_ASSERT(value.timeSpec() == Qt::UTC);
|
Q_ASSERT(value.timeSpec() == Qt::UTC);
|
||||||
m_nameChanged = value;
|
m_data.nameChanged = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setDescription(const QString& value)
|
void Metadata::setDescription(const QString& value)
|
||||||
{
|
{
|
||||||
set(m_description, value, m_descriptionChanged);
|
set(m_data.description, value, m_data.descriptionChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setDescriptionChanged(const QDateTime& value)
|
void Metadata::setDescriptionChanged(const QDateTime& value)
|
||||||
{
|
{
|
||||||
Q_ASSERT(value.timeSpec() == Qt::UTC);
|
Q_ASSERT(value.timeSpec() == Qt::UTC);
|
||||||
m_descriptionChanged = value;
|
m_data.descriptionChanged = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setDefaultUserName(const QString& value)
|
void Metadata::setDefaultUserName(const QString& value)
|
||||||
{
|
{
|
||||||
set(m_defaultUserName, value, m_defaultUserNameChanged);
|
set(m_data.defaultUserName, value, m_data.defaultUserNameChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setDefaultUserNameChanged(const QDateTime& value)
|
void Metadata::setDefaultUserNameChanged(const QDateTime& value)
|
||||||
{
|
{
|
||||||
Q_ASSERT(value.timeSpec() == Qt::UTC);
|
Q_ASSERT(value.timeSpec() == Qt::UTC);
|
||||||
m_defaultUserNameChanged = value;
|
m_data.defaultUserNameChanged = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setMaintenanceHistoryDays(int value)
|
void Metadata::setMaintenanceHistoryDays(int value)
|
||||||
{
|
{
|
||||||
set(m_maintenanceHistoryDays, value);
|
set(m_data.maintenanceHistoryDays, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setColor(const QColor& value)
|
void Metadata::setColor(const QColor& value)
|
||||||
{
|
{
|
||||||
set(m_color, value);
|
set(m_data.color, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setProtectTitle(bool value)
|
void Metadata::setProtectTitle(bool value)
|
||||||
{
|
{
|
||||||
set(m_protectTitle, value);
|
set(m_data.protectTitle, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setProtectUsername(bool value)
|
void Metadata::setProtectUsername(bool value)
|
||||||
{
|
{
|
||||||
set(m_protectUsername, value);
|
set(m_data.protectUsername, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setProtectPassword(bool value)
|
void Metadata::setProtectPassword(bool value)
|
||||||
{
|
{
|
||||||
set(m_protectPassword, value);
|
set(m_data.protectPassword, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setProtectUrl(bool value)
|
void Metadata::setProtectUrl(bool value)
|
||||||
{
|
{
|
||||||
set(m_protectUrl, value);
|
set(m_data.protectUrl, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setProtectNotes(bool value)
|
void Metadata::setProtectNotes(bool value)
|
||||||
{
|
{
|
||||||
set(m_protectNotes, value);
|
set(m_data.protectNotes, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void Metadata::setAutoEnableVisualHiding(bool value)
|
/*void Metadata::setAutoEnableVisualHiding(bool value)
|
||||||
@@ -348,9 +354,20 @@ void Metadata::removeCustomIcon(const Uuid& uuid)
|
|||||||
Q_EMIT modified();
|
Q_EMIT modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Metadata::copyCustomIcons(const QSet<Uuid>& iconList, const Metadata* otherMetadata)
|
||||||
|
{
|
||||||
|
Q_FOREACH (const Uuid& uuid, iconList) {
|
||||||
|
Q_ASSERT(otherMetadata->containsCustomIcon(uuid));
|
||||||
|
|
||||||
|
if (!containsCustomIcon(uuid) && otherMetadata->containsCustomIcon(uuid)) {
|
||||||
|
addCustomIcon(uuid, otherMetadata->customIcon(uuid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Metadata::setRecycleBinEnabled(bool value)
|
void Metadata::setRecycleBinEnabled(bool value)
|
||||||
{
|
{
|
||||||
set(m_recycleBinEnabled, value);
|
set(m_data.recycleBinEnabled, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setRecycleBin(Group* group)
|
void Metadata::setRecycleBin(Group* group)
|
||||||
@@ -393,22 +410,22 @@ void Metadata::setMasterKeyChanged(const QDateTime& value)
|
|||||||
|
|
||||||
void Metadata::setMasterKeyChangeRec(int value)
|
void Metadata::setMasterKeyChangeRec(int value)
|
||||||
{
|
{
|
||||||
set(m_masterKeyChangeRec, value);
|
set(m_data.masterKeyChangeRec, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setMasterKeyChangeForce(int value)
|
void Metadata::setMasterKeyChangeForce(int value)
|
||||||
{
|
{
|
||||||
set(m_masterKeyChangeForce, value);
|
set(m_data.masterKeyChangeForce, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setHistoryMaxItems(int value)
|
void Metadata::setHistoryMaxItems(int value)
|
||||||
{
|
{
|
||||||
set(m_historyMaxItems, value);
|
set(m_data.historyMaxItems, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::setHistoryMaxSize(int value)
|
void Metadata::setHistoryMaxSize(int value)
|
||||||
{
|
{
|
||||||
set(m_historyMaxSize, value);
|
set(m_data.historyMaxSize, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metadata::addCustomField(const QString& key, const QString& value)
|
void Metadata::addCustomField(const QString& key, const QString& value)
|
||||||
|
|||||||
@@ -18,11 +18,11 @@
|
|||||||
#ifndef KEEPASSX_METADATA_H
|
#ifndef KEEPASSX_METADATA_H
|
||||||
#define KEEPASSX_METADATA_H
|
#define KEEPASSX_METADATA_H
|
||||||
|
|
||||||
#include <QtCore/QDateTime>
|
#include <QColor>
|
||||||
#include <QtCore/QHash>
|
#include <QDateTime>
|
||||||
#include <QtCore/QPointer>
|
#include <QHash>
|
||||||
#include <QtGui/QColor>
|
#include <QImage>
|
||||||
#include <QtGui/QImage>
|
#include <QPointer>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
#include "core/Uuid.h"
|
#include "core/Uuid.h"
|
||||||
@@ -37,6 +37,31 @@ class Metadata : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit Metadata(QObject* parent = Q_NULLPTR);
|
explicit Metadata(QObject* parent = Q_NULLPTR);
|
||||||
|
|
||||||
|
struct MetadataData
|
||||||
|
{
|
||||||
|
QString generator;
|
||||||
|
QString name;
|
||||||
|
QDateTime nameChanged;
|
||||||
|
QString description;
|
||||||
|
QDateTime descriptionChanged;
|
||||||
|
QString defaultUserName;
|
||||||
|
QDateTime defaultUserNameChanged;
|
||||||
|
int maintenanceHistoryDays;
|
||||||
|
QColor color;
|
||||||
|
bool recycleBinEnabled;
|
||||||
|
int historyMaxItems;
|
||||||
|
int historyMaxSize;
|
||||||
|
int masterKeyChangeRec;
|
||||||
|
int masterKeyChangeForce;
|
||||||
|
|
||||||
|
bool protectTitle;
|
||||||
|
bool protectUsername;
|
||||||
|
bool protectPassword;
|
||||||
|
bool protectUrl;
|
||||||
|
bool protectNotes;
|
||||||
|
// bool autoEnableVisualHiding;
|
||||||
|
};
|
||||||
|
|
||||||
QString generator() const;
|
QString generator() const;
|
||||||
QString name() const;
|
QString name() const;
|
||||||
QDateTime nameChanged() const;
|
QDateTime nameChanged() const;
|
||||||
@@ -91,6 +116,7 @@ public:
|
|||||||
// void setAutoEnableVisualHiding(bool value);
|
// void setAutoEnableVisualHiding(bool value);
|
||||||
void addCustomIcon(const Uuid& uuid, const QImage& icon);
|
void addCustomIcon(const Uuid& uuid, const QImage& icon);
|
||||||
void removeCustomIcon(const Uuid& uuid);
|
void removeCustomIcon(const Uuid& uuid);
|
||||||
|
void copyCustomIcons(const QSet<Uuid>& iconList, const Metadata* otherMetadata);
|
||||||
void setRecycleBinEnabled(bool value);
|
void setRecycleBinEnabled(bool value);
|
||||||
void setRecycleBin(Group* group);
|
void setRecycleBin(Group* group);
|
||||||
void setRecycleBinChanged(const QDateTime& value);
|
void setRecycleBinChanged(const QDateTime& value);
|
||||||
@@ -106,6 +132,14 @@ public:
|
|||||||
void addCustomField(const QString& key, const QString& value);
|
void addCustomField(const QString& key, const QString& value);
|
||||||
void removeCustomField(const QString& key);
|
void removeCustomField(const QString& key);
|
||||||
void setUpdateDatetime(bool value);
|
void setUpdateDatetime(bool value);
|
||||||
|
/*
|
||||||
|
* Copy all attributes from other except:
|
||||||
|
* - Group pointers/uuids
|
||||||
|
* - Master key changed date
|
||||||
|
* - Custom icons
|
||||||
|
* - Custom fields
|
||||||
|
*/
|
||||||
|
void copyAttributesFrom(const Metadata* other);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void nameTextChanged();
|
void nameTextChanged();
|
||||||
@@ -115,27 +149,11 @@ private:
|
|||||||
template <class P, class V> bool set(P& property, const V& value);
|
template <class P, class V> bool set(P& property, const V& value);
|
||||||
template <class P, class V> bool set(P& property, const V& value, QDateTime& dateTime);
|
template <class P, class V> bool set(P& property, const V& value, QDateTime& dateTime);
|
||||||
|
|
||||||
QString m_generator;
|
MetadataData m_data;
|
||||||
QString m_name;
|
|
||||||
QDateTime m_nameChanged;
|
|
||||||
QString m_description;
|
|
||||||
QDateTime m_descriptionChanged;
|
|
||||||
QString m_defaultUserName;
|
|
||||||
QDateTime m_defaultUserNameChanged;
|
|
||||||
int m_maintenanceHistoryDays;
|
|
||||||
QColor m_color;
|
|
||||||
|
|
||||||
bool m_protectTitle;
|
|
||||||
bool m_protectUsername;
|
|
||||||
bool m_protectPassword;
|
|
||||||
bool m_protectUrl;
|
|
||||||
bool m_protectNotes;
|
|
||||||
// bool m_autoEnableVisualHiding;
|
|
||||||
|
|
||||||
QHash<Uuid, QImage> m_customIcons;
|
QHash<Uuid, QImage> m_customIcons;
|
||||||
QList<Uuid> m_customIconsOrder;
|
QList<Uuid> m_customIconsOrder;
|
||||||
|
|
||||||
bool m_recycleBinEnabled;
|
|
||||||
QPointer<Group> m_recycleBin;
|
QPointer<Group> m_recycleBin;
|
||||||
QDateTime m_recycleBinChanged;
|
QDateTime m_recycleBinChanged;
|
||||||
QPointer<Group> m_entryTemplatesGroup;
|
QPointer<Group> m_entryTemplatesGroup;
|
||||||
@@ -144,10 +162,6 @@ private:
|
|||||||
QPointer<Group> m_lastTopVisibleGroup;
|
QPointer<Group> m_lastTopVisibleGroup;
|
||||||
|
|
||||||
QDateTime m_masterKeyChanged;
|
QDateTime m_masterKeyChanged;
|
||||||
int m_masterKeyChangeRec;
|
|
||||||
int m_masterKeyChangeForce;
|
|
||||||
int m_historyMaxItems;
|
|
||||||
int m_historyMaxSize;
|
|
||||||
|
|
||||||
QHash<QString, QString> m_customFields;
|
QHash<QString, QString> m_customFields;
|
||||||
|
|
||||||
|
|||||||
@@ -19,15 +19,33 @@
|
|||||||
|
|
||||||
#include "crypto/Random.h"
|
#include "crypto/Random.h"
|
||||||
|
|
||||||
PasswordGenerator* PasswordGenerator::m_instance = Q_NULLPTR;
|
PasswordGenerator::PasswordGenerator()
|
||||||
|
: m_length(0)
|
||||||
QString PasswordGenerator::generatePassword(int length,
|
, m_classes(0)
|
||||||
const PasswordGenerator::CharClasses& classes,
|
, m_flags(0)
|
||||||
const PasswordGenerator::GeneratorFlags& flags)
|
|
||||||
{
|
{
|
||||||
Q_ASSERT(isValidCombination(length, classes, flags));
|
}
|
||||||
|
|
||||||
QVector<PasswordGroup> groups = passwordGroups(classes, flags);
|
void PasswordGenerator::setLength(int length)
|
||||||
|
{
|
||||||
|
m_length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PasswordGenerator::setCharClasses(const CharClasses& classes)
|
||||||
|
{
|
||||||
|
m_classes = classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PasswordGenerator::setFlags(const GeneratorFlags& flags)
|
||||||
|
{
|
||||||
|
m_flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PasswordGenerator::generatePassword() const
|
||||||
|
{
|
||||||
|
Q_ASSERT(isValid());
|
||||||
|
|
||||||
|
QVector<PasswordGroup> groups = passwordGroups();
|
||||||
|
|
||||||
QVector<QChar> passwordChars;
|
QVector<QChar> passwordChars;
|
||||||
Q_FOREACH (const PasswordGroup& group, groups) {
|
Q_FOREACH (const PasswordGroup& group, groups) {
|
||||||
@@ -38,22 +56,22 @@ QString PasswordGenerator::generatePassword(int length,
|
|||||||
|
|
||||||
QString password;
|
QString password;
|
||||||
|
|
||||||
if (flags & CharFromEveryGroup) {
|
if (m_flags & CharFromEveryGroup) {
|
||||||
for (int i = 0; i < groups.size(); i++) {
|
for (int i = 0; i < groups.size(); i++) {
|
||||||
int pos = Random::randomUInt(groups[i].size());
|
int pos = randomGen()->randomUInt(groups[i].size());
|
||||||
|
|
||||||
password.append(groups[i][pos]);
|
password.append(groups[i][pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = groups.size(); i < length; i++) {
|
for (int i = groups.size(); i < m_length; i++) {
|
||||||
int pos = Random::randomUInt(passwordChars.size());
|
int pos = randomGen()->randomUInt(passwordChars.size());
|
||||||
|
|
||||||
password.append(passwordChars[pos]);
|
password.append(passwordChars[pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// shuffle chars
|
// shuffle chars
|
||||||
for (int i = (password.size() - 1); i >= 1; i--) {
|
for (int i = (password.size() - 1); i >= 1; i--) {
|
||||||
int j = Random::randomUInt(i + 1);
|
int j = randomGen()->randomUInt(i + 1);
|
||||||
|
|
||||||
QChar tmp = password[i];
|
QChar tmp = password[i];
|
||||||
password[i] = password[j];
|
password[i] = password[j];
|
||||||
@@ -61,8 +79,8 @@ QString PasswordGenerator::generatePassword(int length,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < m_length; i++) {
|
||||||
int pos = Random::randomUInt(passwordChars.size());
|
int pos = randomGen()->randomUInt(passwordChars.size());
|
||||||
|
|
||||||
password.append(passwordChars[pos]);
|
password.append(passwordChars[pos]);
|
||||||
}
|
}
|
||||||
@@ -71,34 +89,31 @@ QString PasswordGenerator::generatePassword(int length,
|
|||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PasswordGenerator::isValidCombination(int length,
|
bool PasswordGenerator::isValid() const
|
||||||
const PasswordGenerator::CharClasses& classes,
|
|
||||||
const PasswordGenerator::GeneratorFlags& flags)
|
|
||||||
{
|
{
|
||||||
if (classes == 0) {
|
if (m_classes == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (length == 0) {
|
else if (m_length == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((flags & CharFromEveryGroup) && (length < numCharClasses(classes))) {
|
if ((m_flags & CharFromEveryGroup) && (m_length < numCharClasses())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator::CharClasses& classes,
|
QVector<PasswordGroup> PasswordGenerator::passwordGroups() const
|
||||||
const PasswordGenerator::GeneratorFlags& flags)
|
|
||||||
{
|
{
|
||||||
QVector<PasswordGroup> passwordGroups;
|
QVector<PasswordGroup> passwordGroups;
|
||||||
|
|
||||||
if (classes & LowerLetters) {
|
if (m_classes & LowerLetters) {
|
||||||
PasswordGroup group;
|
PasswordGroup group;
|
||||||
|
|
||||||
for (int i = 97; i < (97 + 26); i++) {
|
for (int i = 97; i < (97 + 26); i++) {
|
||||||
if ((flags & ExcludeLookAlike) && (i == 108)) { // "l"
|
if ((m_flags & ExcludeLookAlike) && (i == 108)) { // "l"
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,11 +122,11 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator
|
|||||||
|
|
||||||
passwordGroups.append(group);
|
passwordGroups.append(group);
|
||||||
}
|
}
|
||||||
if (classes & UpperLetters) {
|
if (m_classes & UpperLetters) {
|
||||||
PasswordGroup group;
|
PasswordGroup group;
|
||||||
|
|
||||||
for (int i = 65; i < (65 + 26); i++) {
|
for (int i = 65; i < (65 + 26); i++) {
|
||||||
if ((flags & ExcludeLookAlike) && (i == 73 || i == 79)) { // "I" and "O"
|
if ((m_flags & ExcludeLookAlike) && (i == 73 || i == 79)) { // "I" and "O"
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,11 +135,11 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator
|
|||||||
|
|
||||||
passwordGroups.append(group);
|
passwordGroups.append(group);
|
||||||
}
|
}
|
||||||
if (classes & Numbers) {
|
if (m_classes & Numbers) {
|
||||||
PasswordGroup group;
|
PasswordGroup group;
|
||||||
|
|
||||||
for (int i = 48; i < (48 + 10); i++) {
|
for (int i = 48; i < (48 + 10); i++) {
|
||||||
if ((flags & ExcludeLookAlike) && (i == 48 || i == 49)) { // "0" and "1"
|
if ((m_flags & ExcludeLookAlike) && (i == 48 || i == 49)) { // "0" and "1"
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +148,7 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator
|
|||||||
|
|
||||||
passwordGroups.append(group);
|
passwordGroups.append(group);
|
||||||
}
|
}
|
||||||
if (classes & SpecialCharacters) {
|
if (m_classes & SpecialCharacters) {
|
||||||
PasswordGroup group;
|
PasswordGroup group;
|
||||||
|
|
||||||
for (int i = 33; i <= 47; i++) {
|
for (int i = 33; i <= 47; i++) {
|
||||||
@@ -149,7 +164,7 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 123; i <= 126; i++) {
|
for (int i = 123; i <= 126; i++) {
|
||||||
if ((flags & ExcludeLookAlike) && (i == 124)) { // "|"
|
if ((m_flags & ExcludeLookAlike) && (i == 124)) { // "|"
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,35 +177,22 @@ QVector<PasswordGroup> PasswordGenerator::passwordGroups(const PasswordGenerator
|
|||||||
return passwordGroups;
|
return passwordGroups;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PasswordGenerator::numCharClasses(const PasswordGenerator::CharClasses& classes)
|
int PasswordGenerator::numCharClasses() const
|
||||||
{
|
{
|
||||||
int numClasses = 0;
|
int numClasses = 0;
|
||||||
|
|
||||||
if (classes & LowerLetters) {
|
if (m_classes & LowerLetters) {
|
||||||
numClasses++;
|
numClasses++;
|
||||||
}
|
}
|
||||||
if (classes & UpperLetters) {
|
if (m_classes & UpperLetters) {
|
||||||
numClasses++;
|
numClasses++;
|
||||||
}
|
}
|
||||||
if (classes & Numbers) {
|
if (m_classes & Numbers) {
|
||||||
numClasses++;
|
numClasses++;
|
||||||
}
|
}
|
||||||
if (classes & SpecialCharacters) {
|
if (m_classes & SpecialCharacters) {
|
||||||
numClasses++;
|
numClasses++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return numClasses;
|
return numClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
PasswordGenerator* PasswordGenerator::instance()
|
|
||||||
{
|
|
||||||
if (!m_instance) {
|
|
||||||
m_instance = new PasswordGenerator();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
PasswordGenerator::PasswordGenerator()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
#ifndef KEEPASSX_PASSWORDGENERATOR_H
|
#ifndef KEEPASSX_PASSWORDGENERATOR_H
|
||||||
#define KEEPASSX_PASSWORDGENERATOR_H
|
#define KEEPASSX_PASSWORDGENERATOR_H
|
||||||
|
|
||||||
#include <QtCore/QFlags>
|
#include <QFlags>
|
||||||
#include <QtCore/QString>
|
#include <QString>
|
||||||
#include <QtCore/QVector>
|
#include <QVector>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
@@ -45,29 +45,28 @@ public:
|
|||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag)
|
Q_DECLARE_FLAGS(GeneratorFlags, GeneratorFlag)
|
||||||
|
|
||||||
QString generatePassword(int length, const PasswordGenerator::CharClasses& classes,
|
public:
|
||||||
const PasswordGenerator::GeneratorFlags& flags);
|
|
||||||
bool isValidCombination(int length, const PasswordGenerator::CharClasses& classes,
|
|
||||||
const PasswordGenerator::GeneratorFlags& flags);
|
|
||||||
|
|
||||||
static PasswordGenerator* instance();
|
|
||||||
|
|
||||||
private:
|
|
||||||
PasswordGenerator();
|
PasswordGenerator();
|
||||||
|
|
||||||
QVector<PasswordGroup> passwordGroups(const PasswordGenerator::CharClasses& classes,
|
void setLength(int length);
|
||||||
const PasswordGenerator::GeneratorFlags& flags);
|
void setCharClasses(const CharClasses& classes);
|
||||||
int numCharClasses(const PasswordGenerator::CharClasses& classes);
|
void setFlags(const GeneratorFlags& flags);
|
||||||
|
|
||||||
static PasswordGenerator* m_instance;
|
bool isValid() const;
|
||||||
|
|
||||||
|
QString generatePassword() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<PasswordGroup> passwordGroups() const;
|
||||||
|
int numCharClasses() const;
|
||||||
|
|
||||||
|
int m_length;
|
||||||
|
CharClasses m_classes;
|
||||||
|
GeneratorFlags m_flags;
|
||||||
|
|
||||||
Q_DISABLE_COPY(PasswordGenerator)
|
Q_DISABLE_COPY(PasswordGenerator)
|
||||||
};
|
};
|
||||||
|
|
||||||
inline PasswordGenerator* passwordGenerator() {
|
|
||||||
return PasswordGenerator::instance();
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(PasswordGenerator::CharClasses)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(PasswordGenerator::CharClasses)
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(PasswordGenerator::GeneratorFlags)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(PasswordGenerator::GeneratorFlags)
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#ifndef KEEPASSX_SIGNALMULTIPLEXER_H
|
#ifndef KEEPASSX_SIGNALMULTIPLEXER_H
|
||||||
#define KEEPASSX_SIGNALMULTIPLEXER_H
|
#define KEEPASSX_SIGNALMULTIPLEXER_H
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QObject>
|
||||||
#include <QtCore/QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "TimeDelta.h"
|
#include "TimeDelta.h"
|
||||||
|
|
||||||
#include <QtCore/QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta) {
|
QDateTime operator+(const QDateTime& dateTime, const TimeDelta& delta) {
|
||||||
return dateTime.addDays(delta.getDays())
|
return dateTime.addDays(delta.getDays())
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef KEEPASSX_TIMEDELTA_H
|
#ifndef KEEPASSX_TIMEDELTA_H
|
||||||
#define KEEPASSX_TIMEDELTA_H
|
#define KEEPASSX_TIMEDELTA_H
|
||||||
|
|
||||||
#include <QtCore/QMetaType>
|
#include <QMetaType>
|
||||||
|
|
||||||
class QDateTime;
|
class QDateTime;
|
||||||
class TimeDelta;
|
class TimeDelta;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef KEEPASSX_TIMEINFO_H
|
#ifndef KEEPASSX_TIMEINFO_H
|
||||||
#define KEEPASSX_TIMEINFO_H
|
#define KEEPASSX_TIMEINFO_H
|
||||||
|
|
||||||
#include <QtCore/QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
class TimeInfo
|
class TimeInfo
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,16 +17,16 @@
|
|||||||
|
|
||||||
#include "Tools.h"
|
#include "Tools.h"
|
||||||
|
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QtCore/QIODevice>
|
#include <QImageReader>
|
||||||
#include <QtCore/QLocale>
|
#include <QIODevice>
|
||||||
#include <QtCore/QStringList>
|
#include <QLocale>
|
||||||
#include <QtGui/QImageReader>
|
#include <QStringList>
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
|
||||||
#include <QtCore/QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
#else
|
#else
|
||||||
#include <QtCore/QTime>
|
#include <QTime>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
@@ -141,7 +141,7 @@ QString imageReaderFilter()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatsStringList.append("*." + QString::fromAscii(format).toLower());
|
formatsStringList.append("*." + QString::fromLatin1(format).toLower());
|
||||||
}
|
}
|
||||||
|
|
||||||
return formatsStringList.join(" ");
|
return formatsStringList.join(" ");
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
#ifndef KEEPASSX_TOOLS_H
|
#ifndef KEEPASSX_TOOLS_H
|
||||||
#define KEEPASSX_TOOLS_H
|
#define KEEPASSX_TOOLS_H
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QDateTime>
|
||||||
#include <QtCore/QString>
|
#include <QObject>
|
||||||
#include <QtCore/QDateTime>
|
#include <QString>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#include "Uuid.h"
|
#include "Uuid.h"
|
||||||
|
|
||||||
#include <QtCore/QHash>
|
#include <QHash>
|
||||||
|
|
||||||
#include "crypto/Random.h"
|
#include "crypto/Random.h"
|
||||||
|
|
||||||
@@ -37,17 +37,17 @@ Uuid::Uuid(const QByteArray& data)
|
|||||||
|
|
||||||
Uuid Uuid::random()
|
Uuid Uuid::random()
|
||||||
{
|
{
|
||||||
return Uuid(Random::randomArray(Length));
|
return Uuid(randomGen()->randomArray(Length));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Uuid::toBase64() const
|
QString Uuid::toBase64() const
|
||||||
{
|
{
|
||||||
return QString::fromAscii(m_data.toBase64());
|
return QString::fromLatin1(m_data.toBase64());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Uuid::toHex() const
|
QString Uuid::toHex() const
|
||||||
{
|
{
|
||||||
return QString::fromAscii(m_data.toHex());
|
return QString::fromLatin1(m_data.toHex());
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Uuid::toByteArray() const
|
QByteArray Uuid::toByteArray() const
|
||||||
@@ -85,7 +85,7 @@ bool Uuid::operator!=(const Uuid& other) const
|
|||||||
|
|
||||||
Uuid Uuid::fromBase64(const QString& str)
|
Uuid Uuid::fromBase64(const QString& str)
|
||||||
{
|
{
|
||||||
QByteArray data = QByteArray::fromBase64(str.toAscii());
|
QByteArray data = QByteArray::fromBase64(str.toLatin1());
|
||||||
return Uuid(data);
|
return Uuid(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#ifndef KEEPASSX_UUID_H
|
#ifndef KEEPASSX_UUID_H
|
||||||
#define KEEPASSX_UUID_H
|
#define KEEPASSX_UUID_H
|
||||||
|
|
||||||
#include <QtCore/QByteArray>
|
#include <QByteArray>
|
||||||
#include <QtCore/QString>
|
#include <QString>
|
||||||
|
|
||||||
class Uuid
|
class Uuid
|
||||||
{
|
{
|
||||||
|
|||||||
305
src/core/qcommandlineoption.cpp
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
|
||||||
|
** Copyright (C) 2013 David Faure <faure@kde.org>
|
||||||
|
** 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 <QSet>
|
||||||
|
|
||||||
|
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 <file>" 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 <file>}.
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
81
src/core/qcommandlineoption.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
|
||||||
|
** 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 <QStringList>
|
||||||
|
#include <QSharedData>
|
||||||
|
|
||||||
|
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<QCommandLineOptionPrivate> d;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QCOMMANDLINEOPTION_H
|
||||||
944
src/core/qcommandlineparser.cpp
Normal file
@@ -0,0 +1,944 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
|
||||||
|
** Copyright (C) 2013 David Faure <faure@kde.org>
|
||||||
|
** 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 <QCoreApplication>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QVector>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef QHash<QString, int> 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<QCommandLineOption> 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<int, QStringList> 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<PositionalArgumentDefinition> 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;
|
||||||
|
}
|
||||||
102
src/core/qcommandlineparser.h
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
|
||||||
|
** 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 <QStringList>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
#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
|
||||||
@@ -42,9 +42,9 @@
|
|||||||
#include "qsavefile.h"
|
#include "qsavefile.h"
|
||||||
#include "qsavefile_p.h"
|
#include "qsavefile_p.h"
|
||||||
|
|
||||||
#include <QtCore/QAbstractFileEngine>
|
#include <QAbstractFileEngine>
|
||||||
#include <QtCore/QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QtCore/QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
QSaveFilePrivate::QSaveFilePrivate()
|
QSaveFilePrivate::QSaveFilePrivate()
|
||||||
: tempFile(0), error(QFile::NoError)
|
: tempFile(0), error(QFile::NoError)
|
||||||
|
|||||||
@@ -42,8 +42,8 @@
|
|||||||
#ifndef QSAVEFILE_H
|
#ifndef QSAVEFILE_H
|
||||||
#define QSAVEFILE_H
|
#define QSAVEFILE_H
|
||||||
|
|
||||||
#include <QtCore/QFile>
|
#include <QFile>
|
||||||
#include <QtCore/QString>
|
#include <QString>
|
||||||
|
|
||||||
#ifdef open
|
#ifdef open
|
||||||
#error qsavefile.h must be included before any header file that defines open
|
#error qsavefile.h must be included before any header file that defines open
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
// We mean it.
|
// We mean it.
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <QtCore/QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
|
|
||||||
class QSaveFilePrivate
|
class QSaveFilePrivate
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,12 +17,13 @@
|
|||||||
|
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
|
|
||||||
#include <QtCore/QMutex>
|
#include <QMutex>
|
||||||
|
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
|
|
||||||
bool Crypto::m_initalized(false);
|
bool Crypto::m_initalized(false);
|
||||||
|
|
||||||
|
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
||||||
static int gcry_qt_mutex_init(void** p_sys)
|
static int gcry_qt_mutex_init(void** p_sys)
|
||||||
{
|
{
|
||||||
*p_sys = new QMutex();
|
*p_sys = new QMutex();
|
||||||
@@ -57,6 +58,7 @@ static const struct gcry_thread_cbs gcry_threads_qt =
|
|||||||
gcry_qt_mutex_unlock,
|
gcry_qt_mutex_unlock,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
Crypto::Crypto()
|
Crypto::Crypto()
|
||||||
{
|
{
|
||||||
@@ -69,7 +71,10 @@ void Crypto::init()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_qt);
|
||||||
|
#endif
|
||||||
gcry_check_version(0);
|
gcry_check_version(0);
|
||||||
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#ifndef KEEPASSX_CRYPTOHASH_H
|
#ifndef KEEPASSX_CRYPTOHASH_H
|
||||||
#define KEEPASSX_CRYPTOHASH_H
|
#define KEEPASSX_CRYPTOHASH_H
|
||||||
|
|
||||||
#include <QtCore/QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
class CryptoHashPrivate;
|
class CryptoHashPrivate;
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,17 @@
|
|||||||
|
|
||||||
#include "crypto/Crypto.h"
|
#include "crypto/Crypto.h"
|
||||||
|
|
||||||
|
class RandomBackendGcrypt : public RandomBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void randomize(void* data, int len) Q_DECL_OVERRIDE;
|
||||||
|
};
|
||||||
|
|
||||||
|
Random* Random::m_instance(Q_NULLPTR);
|
||||||
|
|
||||||
void Random::randomize(QByteArray& ba)
|
void Random::randomize(QByteArray& ba)
|
||||||
{
|
{
|
||||||
randomize(ba.data(), ba.size());
|
m_backend->randomize(ba.data(), ba.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray Random::randomArray(int len)
|
QByteArray Random::randomArray(int len)
|
||||||
@@ -38,8 +46,18 @@ QByteArray Random::randomArray(int len)
|
|||||||
|
|
||||||
quint32 Random::randomUInt(quint32 limit)
|
quint32 Random::randomUInt(quint32 limit)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(limit != 0);
|
||||||
|
Q_ASSERT(limit <= QUINT32_MAX);
|
||||||
|
|
||||||
quint32 rand;
|
quint32 rand;
|
||||||
randomize(&rand, 4);
|
const quint32 ceil = QUINT32_MAX - (QUINT32_MAX % limit) - 1;
|
||||||
|
|
||||||
|
// To avoid modulo bias:
|
||||||
|
// Make sure rand is below the largest number where rand%limit==0
|
||||||
|
do {
|
||||||
|
m_backend->randomize(&rand, 4);
|
||||||
|
} while (rand > ceil);
|
||||||
|
|
||||||
return (rand % limit);
|
return (rand % limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,13 +66,32 @@ quint32 Random::randomUIntRange(quint32 min, quint32 max)
|
|||||||
return min + randomUInt(max - min);
|
return min + randomUInt(max - min);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Random::randomize(void* data, int len)
|
Random* Random::instance()
|
||||||
|
{
|
||||||
|
if (!m_instance) {
|
||||||
|
m_instance = new Random(new RandomBackendGcrypt());
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Random::createWithBackend(RandomBackend* backend)
|
||||||
|
{
|
||||||
|
Q_ASSERT(backend);
|
||||||
|
Q_ASSERT(!m_instance);
|
||||||
|
|
||||||
|
m_instance = new Random(backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
Random::Random(RandomBackend* backend)
|
||||||
|
: m_backend(backend)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RandomBackendGcrypt::randomize(void* data, int len)
|
||||||
{
|
{
|
||||||
Q_ASSERT(Crypto::initalized());
|
Q_ASSERT(Crypto::initalized());
|
||||||
|
|
||||||
gcry_randomize(data, len, GCRY_STRONG_RANDOM);
|
gcry_randomize(data, len, GCRY_STRONG_RANDOM);
|
||||||
}
|
}
|
||||||
|
|
||||||
Random::Random()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -18,27 +18,46 @@
|
|||||||
#ifndef KEEPASSX_RANDOM_H
|
#ifndef KEEPASSX_RANDOM_H
|
||||||
#define KEEPASSX_RANDOM_H
|
#define KEEPASSX_RANDOM_H
|
||||||
|
|
||||||
#include <QtCore/QByteArray>
|
#include <QByteArray>
|
||||||
|
#include <QScopedPointer>
|
||||||
|
|
||||||
|
class RandomBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void randomize(void* data, int len) = 0;
|
||||||
|
virtual ~RandomBackend() {}
|
||||||
|
};
|
||||||
|
|
||||||
class Random
|
class Random
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void randomize(QByteArray& ba);
|
void randomize(QByteArray& ba);
|
||||||
static QByteArray randomArray(int len);
|
QByteArray randomArray(int len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a random quint32 in the range [0, @p limit)
|
* Generate a random quint32 in the range [0, @p limit)
|
||||||
*/
|
*/
|
||||||
static quint32 randomUInt(quint32 limit);
|
quint32 randomUInt(quint32 limit);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a random quint32 in the range [@p min, @p max)
|
* Generate a random quint32 in the range [@p min, @p max)
|
||||||
*/
|
*/
|
||||||
static quint32 randomUIntRange(quint32 min, quint32 max);
|
quint32 randomUIntRange(quint32 min, quint32 max);
|
||||||
|
|
||||||
|
static Random* instance();
|
||||||
|
static void createWithBackend(RandomBackend* backend);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void randomize(void* data, int len);
|
explicit Random(RandomBackend* backend);
|
||||||
Random();
|
|
||||||
|
QScopedPointer<RandomBackend> m_backend;
|
||||||
|
static Random* m_instance;
|
||||||
|
|
||||||
|
Q_DISABLE_COPY(Random)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline Random* randomGen() {
|
||||||
|
return Random::instance();
|
||||||
|
}
|
||||||
|
|
||||||
#endif // KEEPASSX_RANDOM_H
|
#endif // KEEPASSX_RANDOM_H
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "SymmetricCipher.h"
|
#include "SymmetricCipher.h"
|
||||||
|
|
||||||
|
#include "config-keepassx.h"
|
||||||
#include "crypto/SymmetricCipherGcrypt.h"
|
#include "crypto/SymmetricCipherGcrypt.h"
|
||||||
#include "crypto/SymmetricCipherSalsa20.h"
|
#include "crypto/SymmetricCipherSalsa20.h"
|
||||||
|
|
||||||
@@ -24,7 +25,6 @@ SymmetricCipher::SymmetricCipher(SymmetricCipher::Algorithm algo, SymmetricCiphe
|
|||||||
SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv)
|
SymmetricCipher::Direction direction, const QByteArray& key, const QByteArray& iv)
|
||||||
: m_backend(createBackend(algo, mode, direction))
|
: m_backend(createBackend(algo, mode, direction))
|
||||||
{
|
{
|
||||||
m_backend->init();
|
|
||||||
m_backend->setKey(key);
|
m_backend->setKey(key);
|
||||||
m_backend->setIv(iv);
|
m_backend->setIv(iv);
|
||||||
}
|
}
|
||||||
@@ -39,10 +39,15 @@ SymmetricCipherBackend* SymmetricCipher::createBackend(SymmetricCipher::Algorith
|
|||||||
switch (algo) {
|
switch (algo) {
|
||||||
case SymmetricCipher::Aes256:
|
case SymmetricCipher::Aes256:
|
||||||
case SymmetricCipher::Twofish:
|
case SymmetricCipher::Twofish:
|
||||||
|
#if defined(GCRYPT_HAS_SALSA20)
|
||||||
|
case SymmetricCipher::Salsa20:
|
||||||
|
#endif
|
||||||
return new SymmetricCipherGcrypt(algo, mode, direction);
|
return new SymmetricCipherGcrypt(algo, mode, direction);
|
||||||
|
|
||||||
|
#if !defined(GCRYPT_HAS_SALSA20)
|
||||||
case SymmetricCipher::Salsa20:
|
case SymmetricCipher::Salsa20:
|
||||||
return new SymmetricCipherSalsa20(algo, mode, direction);
|
return new SymmetricCipherSalsa20(algo, mode, direction);
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
#ifndef KEEPASSX_SYMMETRICCIPHER_H
|
#ifndef KEEPASSX_SYMMETRICCIPHER_H
|
||||||
#define KEEPASSX_SYMMETRICCIPHER_H
|
#define KEEPASSX_SYMMETRICCIPHER_H
|
||||||
|
|
||||||
#include <QtCore/QByteArray>
|
#include <QByteArray>
|
||||||
#include <QtCore/QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
#include "crypto/SymmetricCipherBackend.h"
|
#include "crypto/SymmetricCipherBackend.h"
|
||||||
|
|||||||
@@ -18,13 +18,12 @@
|
|||||||
#ifndef KEEPASSX_SYMMETRICCIPHERBACKEND_H
|
#ifndef KEEPASSX_SYMMETRICCIPHERBACKEND_H
|
||||||
#define KEEPASSX_SYMMETRICCIPHERBACKEND_H
|
#define KEEPASSX_SYMMETRICCIPHERBACKEND_H
|
||||||
|
|
||||||
#include <QtCore/QByteArray>
|
#include <QByteArray>
|
||||||
|
|
||||||
class SymmetricCipherBackend
|
class SymmetricCipherBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~SymmetricCipherBackend() {}
|
virtual ~SymmetricCipherBackend() {}
|
||||||
virtual void init() = 0;
|
|
||||||
virtual void setKey(const QByteArray& key) = 0;
|
virtual void setKey(const QByteArray& key) = 0;
|
||||||
virtual void setIv(const QByteArray& iv) = 0;
|
virtual void setIv(const QByteArray& iv) = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "SymmetricCipherGcrypt.h"
|
#include "SymmetricCipherGcrypt.h"
|
||||||
|
|
||||||
|
#include "config-keepassx.h"
|
||||||
#include "crypto/Crypto.h"
|
#include "crypto/Crypto.h"
|
||||||
|
|
||||||
SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
|
SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
|
||||||
@@ -24,8 +25,19 @@ SymmetricCipherGcrypt::SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, Sy
|
|||||||
: m_algo(gcryptAlgo(algo))
|
: m_algo(gcryptAlgo(algo))
|
||||||
, m_mode(gcryptMode(mode))
|
, m_mode(gcryptMode(mode))
|
||||||
, m_direction(direction)
|
, m_direction(direction)
|
||||||
|
, m_blockSize(-1)
|
||||||
{
|
{
|
||||||
Q_ASSERT(Crypto::initalized());
|
Q_ASSERT(Crypto::initalized());
|
||||||
|
|
||||||
|
gcry_error_t error;
|
||||||
|
|
||||||
|
error = gcry_cipher_open(&m_ctx, m_algo, m_mode, 0);
|
||||||
|
Q_ASSERT(error == 0); // TODO: real error checking
|
||||||
|
|
||||||
|
size_t blockSizeT;
|
||||||
|
error = gcry_cipher_algo_info(m_algo, GCRYCTL_GET_BLKLEN, Q_NULLPTR, &blockSizeT);
|
||||||
|
Q_ASSERT(error == 0);
|
||||||
|
m_blockSize = blockSizeT;
|
||||||
}
|
}
|
||||||
|
|
||||||
SymmetricCipherGcrypt::~SymmetricCipherGcrypt()
|
SymmetricCipherGcrypt::~SymmetricCipherGcrypt()
|
||||||
@@ -42,6 +54,11 @@ int SymmetricCipherGcrypt::gcryptAlgo(SymmetricCipher::Algorithm algo)
|
|||||||
case SymmetricCipher::Twofish:
|
case SymmetricCipher::Twofish:
|
||||||
return GCRY_CIPHER_TWOFISH;
|
return GCRY_CIPHER_TWOFISH;
|
||||||
|
|
||||||
|
#ifdef GCRYPT_HAS_SALSA20
|
||||||
|
case SymmetricCipher::Salsa20:
|
||||||
|
return GCRY_CIPHER_SALSA20;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -57,25 +74,15 @@ int SymmetricCipherGcrypt::gcryptMode(SymmetricCipher::Mode mode)
|
|||||||
case SymmetricCipher::Cbc:
|
case SymmetricCipher::Cbc:
|
||||||
return GCRY_CIPHER_MODE_CBC;
|
return GCRY_CIPHER_MODE_CBC;
|
||||||
|
|
||||||
|
case SymmetricCipher::Stream:
|
||||||
|
return GCRY_CIPHER_MODE_STREAM;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymmetricCipherGcrypt::init()
|
|
||||||
{
|
|
||||||
gcry_error_t error;
|
|
||||||
|
|
||||||
error = gcry_cipher_open(&m_ctx, m_algo, m_mode, 0);
|
|
||||||
Q_ASSERT(error == 0); // TODO: real error checking
|
|
||||||
|
|
||||||
size_t blockSizeT;
|
|
||||||
error = gcry_cipher_algo_info(m_algo, GCRYCTL_GET_BLKLEN, Q_NULLPTR, &blockSizeT);
|
|
||||||
Q_ASSERT(error == 0);
|
|
||||||
m_blockSize = blockSizeT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SymmetricCipherGcrypt::setKey(const QByteArray& key)
|
void SymmetricCipherGcrypt::setKey(const QByteArray& key)
|
||||||
{
|
{
|
||||||
m_key = key;
|
m_key = key;
|
||||||
@@ -133,15 +140,18 @@ void SymmetricCipherGcrypt::processInPlace(QByteArray& data, quint64 rounds)
|
|||||||
|
|
||||||
gcry_error_t error;
|
gcry_error_t error;
|
||||||
|
|
||||||
|
char* rawData = data.data();
|
||||||
|
int size = data.size();
|
||||||
|
|
||||||
if (m_direction == SymmetricCipher::Decrypt) {
|
if (m_direction == SymmetricCipher::Decrypt) {
|
||||||
for (quint64 i = 0; i != rounds; ++i) {
|
for (quint64 i = 0; i != rounds; ++i) {
|
||||||
error = gcry_cipher_decrypt(m_ctx, data.data(), data.size(), Q_NULLPTR, 0);
|
error = gcry_cipher_decrypt(m_ctx, rawData, size, Q_NULLPTR, 0);
|
||||||
Q_ASSERT(error == 0);
|
Q_ASSERT(error == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (quint64 i = 0; i != rounds; ++i) {
|
for (quint64 i = 0; i != rounds; ++i) {
|
||||||
error = gcry_cipher_encrypt(m_ctx, data.data(), data.size(), Q_NULLPTR, 0);
|
error = gcry_cipher_encrypt(m_ctx, rawData, size, Q_NULLPTR, 0);
|
||||||
Q_ASSERT(error == 0);
|
Q_ASSERT(error == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ public:
|
|||||||
SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
|
SymmetricCipherGcrypt(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
|
||||||
SymmetricCipher::Direction direction);
|
SymmetricCipher::Direction direction);
|
||||||
~SymmetricCipherGcrypt();
|
~SymmetricCipherGcrypt();
|
||||||
void init();
|
|
||||||
void setKey(const QByteArray& key);
|
void setKey(const QByteArray& key);
|
||||||
void setIv(const QByteArray& iv);
|
void setIv(const QByteArray& iv);
|
||||||
|
|
||||||
|
|||||||
@@ -33,10 +33,6 @@ SymmetricCipherSalsa20::~SymmetricCipherSalsa20()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymmetricCipherSalsa20::init()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SymmetricCipherSalsa20::setKey(const QByteArray& key)
|
void SymmetricCipherSalsa20::setKey(const QByteArray& key)
|
||||||
{
|
{
|
||||||
Q_ASSERT((key.size() == 16) || (key.size() == 32));
|
Q_ASSERT((key.size() == 16) || (key.size() == 32));
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ public:
|
|||||||
void setAlgorithm(SymmetricCipher::Algorithm algo);
|
void setAlgorithm(SymmetricCipher::Algorithm algo);
|
||||||
void setMode(SymmetricCipher::Mode mode);
|
void setMode(SymmetricCipher::Mode mode);
|
||||||
void setDirection(SymmetricCipher::Direction direction);
|
void setDirection(SymmetricCipher::Direction direction);
|
||||||
void init();
|
|
||||||
void setKey(const QByteArray& key);
|
void setKey(const QByteArray& key);
|
||||||
void setIv(const QByteArray& iv);
|
void setIv(const QByteArray& iv);
|
||||||
|
|
||||||
|
|||||||