Implemented remote credential storage via qtkeychain
Imported qtkeychain FossilOrigin-Name: 7c068aa8acdae1b86dee004d2d4cd7fb42904186
This commit is contained in:
parent
86af187c23
commit
e6fa4062d0
195
ext/qtkeychain/CMakeLists.txt
Normal file
195
ext/qtkeychain/CMakeLists.txt
Normal file
@ -0,0 +1,195 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
project(qtkeychain)
|
||||
|
||||
###
|
||||
|
||||
set(QTKEYCHAIN_VERSION 0.5.90)
|
||||
set(QTKEYCHAIN_SOVERSION 0)
|
||||
|
||||
###
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${PROJECT_SOURCE_DIR}/cmake/Modules")
|
||||
include(GNUInstallDirs)
|
||||
|
||||
option(BUILD_WITH_QT4 "Build qtkeychain with Qt4 no matter if Qt5 was found" OFF)
|
||||
|
||||
|
||||
if( NOT BUILD_WITH_QT4 )
|
||||
# try Qt5 first, and prefer that if found
|
||||
find_package(Qt5Core QUIET)
|
||||
endif()
|
||||
|
||||
if (Qt5Core_FOUND)
|
||||
set(QTKEYCHAIN_VERSION_INFIX 5)
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Qt5DBus REQUIRED)
|
||||
include_directories(${Qt5DBus_INCLUDE_DIRS})
|
||||
set(QTDBUS_LIBRARIES ${Qt5DBus_LIBRARIES})
|
||||
macro(qt_add_dbus_interface)
|
||||
qt5_add_dbus_interface(${ARGN})
|
||||
endmacro()
|
||||
endif()
|
||||
find_package(Qt5LinguistTools REQUIRED)
|
||||
macro(qt_add_translation)
|
||||
qt5_add_translation(${ARGN})
|
||||
endmacro(qt_add_translation)
|
||||
macro(qt_create_translation)
|
||||
qt5_create_translation(${ARGN})
|
||||
endmacro(qt_create_translation)
|
||||
macro(qt_wrap_cpp)
|
||||
qt5_wrap_cpp(${ARGN})
|
||||
endmacro()
|
||||
|
||||
set(QTCORE_LIBRARIES ${Qt5Core_LIBRARIES})
|
||||
include_directories(${Qt5Core_INCLUDE_DIRS})
|
||||
|
||||
if (Qt5_POSITION_INDEPENDENT_CODE)
|
||||
if (CMAKE_VERSION VERSION_LESS 2.8.9) # TODO remove once we increase the cmake requirement
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
else()
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
set(QTKEYCHAIN_VERSION_INFIX "")
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Qt4 COMPONENTS QtCore QtDBus REQUIRED)
|
||||
set(QTDBUS_LIBRARIES ${QT_QTDBUS_LIBRARY})
|
||||
macro(qt_add_dbus_interface)
|
||||
qt4_add_dbus_interface(${ARGN})
|
||||
endmacro()
|
||||
else()
|
||||
find_package(Qt4 COMPONENTS QtCore REQUIRED)
|
||||
endif()
|
||||
include_directories(${QT_INCLUDES})
|
||||
set(QTCORE_LIBRARIES ${QT_QTCORE_LIBRARY})
|
||||
macro(qt_add_translation)
|
||||
qt4_add_translation(${ARGN})
|
||||
endmacro(qt_add_translation)
|
||||
macro(qt_create_translation)
|
||||
qt4_create_translation(${ARGN})
|
||||
endmacro(qt_create_translation)
|
||||
macro(qt_wrap_cpp)
|
||||
qt4_wrap_cpp(${ARGN})
|
||||
endmacro()
|
||||
endif()
|
||||
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
list(APPEND qtkeychain_LIBRARIES ${QTCORE_LIBRARIES})
|
||||
set(qtkeychain_SOURCES
|
||||
keychain.cpp
|
||||
)
|
||||
|
||||
ADD_DEFINITIONS( -Wall )
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND qtkeychain_SOURCES keychain_win.cpp)
|
||||
list(APPEND qtkeychain_LIBRARIES crypt32)
|
||||
#FIXME: mingw bug; otherwise getting undefined refs to RtlSecureZeroMemory there
|
||||
if(MINGW)
|
||||
add_definitions( -O2 )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
list(APPEND qtkeychain_SOURCES keychain_mac.cpp)
|
||||
|
||||
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
||||
list(APPEND qtkeychain_LIBRARIES ${COREFOUNDATION_LIBRARY})
|
||||
|
||||
find_library(SECURITY_LIBRARY Security)
|
||||
list(APPEND qtkeychain_LIBRARIES ${SECURITY_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
list(APPEND qtkeychain_SOURCES keychain_unix.cpp gnomekeyring.cpp)
|
||||
qt_add_dbus_interface(qtkeychain_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/org.kde.KWallet.xml kwallet_interface KWalletInterface)
|
||||
list(APPEND qtkeychain_LIBRARIES ${QTDBUS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
QT_WRAP_CPP(qtkeychain_MOC_OUTFILES keychain.h keychain_p.h)
|
||||
|
||||
set(qtkeychain_TR_FILES
|
||||
translations/qtkeychain_de.ts
|
||||
translations/qtkeychain_ro.ts
|
||||
)
|
||||
|
||||
file(GLOB qtkeychain_TR_SOURCES *.cpp *.h *.ui)
|
||||
qt_create_translation(qtkeychain_MESSAGES ${qtkeychain_TR_SOURCES} ${qtkeychain_TR_FILES})
|
||||
qt_add_translation(qtkeychain_QM_FILES ${qtkeychain_TR_FILES})
|
||||
add_custom_target(messages DEPENDS ${qtkeychain_MESSAGES})
|
||||
add_custom_target(translations DEPENDS ${qtkeychain_QM_FILES})
|
||||
|
||||
if(NOT QT_TRANSLATIONS_DIR)
|
||||
# If this directory is missing, we are in a Qt5 environment.
|
||||
# Extract the qmake executable location
|
||||
get_target_property(QT5_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
|
||||
# Ask Qt5 where to put the translations
|
||||
execute_process( COMMAND ${QT5_QMAKE_EXECUTABLE} -query QT_INSTALL_TRANSLATIONS
|
||||
OUTPUT_VARIABLE qt_translations_dir OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
# make sure we have / and not \ as qmake gives on windows
|
||||
FILE(TO_CMAKE_PATH "${qt_translations_dir}" qt_translations_dir)
|
||||
SET(QT_TRANSLATIONS_DIR ${qt_translations_dir} CACHE PATH "The
|
||||
location of the Qt translations" FORCE)
|
||||
endif()
|
||||
|
||||
install(FILES ${qtkeychain_QM_FILES}
|
||||
DESTINATION ${QT_TRANSLATIONS_DIR})
|
||||
|
||||
set(QTKEYCHAIN_TARGET_NAME qt${QTKEYCHAIN_VERSION_INFIX}keychain)
|
||||
if(NOT QTKEYCHAIN_STATIC)
|
||||
add_library(${QTKEYCHAIN_TARGET_NAME} SHARED ${qtkeychain_SOURCES} ${qtkeychain_MOC_OUTFILES} ${qtkeychain_QM_FILES})
|
||||
set_target_properties(${QTKEYCHAIN_TARGET_NAME} PROPERTIES COMPILE_DEFINITIONS QKEYCHAIN_BUILD_QKEYCHAIN_LIB)
|
||||
target_link_libraries(${QTKEYCHAIN_TARGET_NAME} ${qtkeychain_LIBRARIES})
|
||||
else()
|
||||
add_library(${QTKEYCHAIN_TARGET_NAME} STATIC ${qtkeychain_SOURCES} ${qtkeychain_MOC_OUTFILES} ${qtkeychain_QM_FILES})
|
||||
set_target_properties(${QTKEYCHAIN_TARGET_NAME} PROPERTIES COMPILE_DEFINITIONS QKEYCHAIN_STATICLIB)
|
||||
endif()
|
||||
|
||||
set_target_properties(${QTKEYCHAIN_TARGET_NAME} PROPERTIES
|
||||
VERSION ${QTKEYCHAIN_VERSION}
|
||||
SOVERSION ${QTKEYCHAIN_SOVERSION}
|
||||
MACOSX_RPATH 1
|
||||
INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}"
|
||||
)
|
||||
|
||||
install(FILES keychain.h qkeychain_export.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/qt${QTKEYCHAIN_VERSION_INFIX}keychain/
|
||||
)
|
||||
|
||||
install(TARGETS ${QTKEYCHAIN_TARGET_NAME}
|
||||
EXPORT Qt${QTKEYCHAIN_VERSION_INFIX}KeychainLibraryDepends
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
add_executable( testclient testclient.cpp )
|
||||
target_link_libraries( testclient ${QTKEYCHAIN_TARGET_NAME})
|
||||
|
||||
|
||||
###
|
||||
### CMake config file
|
||||
###
|
||||
|
||||
export(TARGETS ${QTKEYCHAIN_TARGET_NAME} FILE "${PROJECT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainLibraryDepends.cmake")
|
||||
export(PACKAGE Qt${QTKEYCHAIN_VERSION_INFIX}Keychain)
|
||||
|
||||
configure_file(QtKeychainBuildTreeSettings.cmake.in
|
||||
"${PROJECT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainBuildTreeSettings.cmake" @ONLY)
|
||||
configure_file(QtKeychainConfig.cmake.in
|
||||
"${PROJECT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfig.cmake" @ONLY)
|
||||
configure_file(QtKeychainConfigVersion.cmake.in
|
||||
"${PROJECT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake" @ONLY)
|
||||
|
||||
install(EXPORT Qt${QTKEYCHAIN_VERSION_INFIX}KeychainLibraryDepends
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Qt${QTKEYCHAIN_VERSION_INFIX}Keychain"
|
||||
)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfig.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Qt${QTKEYCHAIN_VERSION_INFIX}Keychain
|
||||
)
|
||||
|
20
ext/qtkeychain/COPYING
Normal file
20
ext/qtkeychain/COPYING
Normal file
@ -0,0 +1,20 @@
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
23
ext/qtkeychain/ChangeLog
Normal file
23
ext/qtkeychain/ChangeLog
Normal file
@ -0,0 +1,23 @@
|
||||
ChangeLog
|
||||
=========
|
||||
|
||||
version 0.5.0 (release 2015-05-04)
|
||||
* Added support for KWallet5 (KDE5/KF)
|
||||
|
||||
version 0.4.0 (release 2014-09-01)
|
||||
* KWallet: Handle case where no wallet exists yet (Liviu Cristian Mirea Ghiban <contact@liviucmg.com>)
|
||||
* Improved desktop environment detection at runtime (Daniel Molkentin <daniel@molkentin.de>)
|
||||
|
||||
version 0.3.0 (release 2014-03-13)
|
||||
* Gnome Keyring supported added (Francois Ferrand <thetypz@gmail.com>)
|
||||
* Improved Qt 5 support
|
||||
* KWallet: Distinguish empty passwords from non-existing entries
|
||||
* KWallet: Do not use hardcoded wallet name
|
||||
* German translation (Daniel Molkentin <daniel@molkentin.de>)
|
||||
* Romanian translation (Arthur Țițeică <arthur@psw.ro>)
|
||||
|
||||
version 0.2.0: no official release
|
||||
|
||||
version 0.1.0 (release 2013-01-16)
|
||||
* Initial release
|
||||
|
4
ext/qtkeychain/QtKeychainBuildTreeSettings.cmake.in
Normal file
4
ext/qtkeychain/QtKeychainBuildTreeSettings.cmake.in
Normal file
@ -0,0 +1,4 @@
|
||||
set(QTKEYCHAIN_INCLUDE_DIRS
|
||||
"@PROJECT_SOURCE_DIR@"
|
||||
"@PROJECT_BINARY_DIR@"
|
||||
)
|
21
ext/qtkeychain/QtKeychainConfig.cmake.in
Normal file
21
ext/qtkeychain/QtKeychainConfig.cmake.in
Normal file
@ -0,0 +1,21 @@
|
||||
# - Config file for the QtKeychain package
|
||||
# It defines the following variables
|
||||
# QTKEYCHAIN_INCLUDE_DIRS - include directories for QtKeychain
|
||||
# QTKEYCHAIN_LIBRARIES - libraries to link against
|
||||
|
||||
# Compute paths
|
||||
get_filename_component(QTKEYCHAIN_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
if(EXISTS "${QTKEYCHAIN_CMAKE_DIR}/CMakeCache.txt")
|
||||
# In build tree
|
||||
include("${QTKEYCHAIN_CMAKE_DIR}/Qt@QTKEYCHAIN_VERSION_INFIX@KeychainBuildTreeSettings.cmake")
|
||||
else()
|
||||
set(QTKEYCHAIN_INCLUDE_DIRS "@CMAKE_INSTALL_FULL_INCLUDEDIR@")
|
||||
endif()
|
||||
|
||||
# Our library dependencies (contains definitions for IMPORTED targets)
|
||||
include("${QTKEYCHAIN_CMAKE_DIR}/Qt@QTKEYCHAIN_VERSION_INFIX@KeychainLibraryDepends.cmake")
|
||||
|
||||
# These are IMPORTED targets created by FooBarLibraryDepends.cmake
|
||||
set(QTKEYCHAIN_LIBRARIES "@QTKEYCHAIN_TARGET_NAME@")
|
||||
|
||||
set(QTKEYCHAIN_FOUND TRUE)
|
11
ext/qtkeychain/QtKeychainConfigVersion.cmake.in
Normal file
11
ext/qtkeychain/QtKeychainConfigVersion.cmake.in
Normal file
@ -0,0 +1,11 @@
|
||||
set(PACKAGE_VERSION "@QTKEYCHAIN_VERSION@")
|
||||
|
||||
# Check whether the requested PACKAGE_FIND_VERSION is compatible
|
||||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||
else()
|
||||
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||
set(PACKAGE_VERSION_EXACT TRUE)
|
||||
endif()
|
||||
endif()
|
15
ext/qtkeychain/ReadMe.markdown
Normal file
15
ext/qtkeychain/ReadMe.markdown
Normal file
@ -0,0 +1,15 @@
|
||||
QtKeychain
|
||||
==========
|
||||
|
||||
QtKeychain is a Qt API to store passwords and other secret data securely. How the data is stored depends on the platform:
|
||||
|
||||
* **Mac OS X:** Passwords are stored in the OS X Keychain.
|
||||
|
||||
* **Linux/Unix:** If running, GNOME Keyring is used, otherwise
|
||||
qtkeychain tries to use KWallet (via D-Bus), if available.
|
||||
|
||||
* **Windows:** Windows does not provide a service for secure storage. QtKeychain uses the Windows API function [CryptProtectData](http://msdn.microsoft.com/en-us/library/windows/desktop/aa380261%28v=vs.85%29.aspx "CryptProtectData function") to encrypt the password with the user's logon credentials. The encrypted data is then persisted via QSettings.
|
||||
|
||||
In unsupported environments QtKeychain will report an error. It will not store any data unencrypted unless explicitly requested (setInsecureFallback( true )).
|
||||
|
||||
**License:** QtKeychain is available under the [Modified BSD License](http://www.gnu.org/licenses/license-list.html#ModifiedBSD). See the file COPYING for details.
|
15
ext/qtkeychain/ReadMe.txt
Normal file
15
ext/qtkeychain/ReadMe.txt
Normal file
@ -0,0 +1,15 @@
|
||||
QtKeychain
|
||||
==========
|
||||
|
||||
QtKeychain is a Qt API to store passwords and other secret data securely. How the data is stored depends on the platform:
|
||||
|
||||
* **Mac OS X:** Passwords are stored in the OS X Keychain.
|
||||
|
||||
* **Linux/Unix:** If running, GNOME Keyring is used, otherwise
|
||||
qtkeychain tries to use KWallet (via D-Bus), if available.
|
||||
|
||||
* **Windows:** Windows does not provide a service for secure storage. QtKeychain uses the Windows API function [CryptProtectData](http://msdn.microsoft.com/en-us/library/windows/desktop/aa380261%28v=vs.85%29.aspx "CryptProtectData function") to encrypt the password with the user's logon credentials. The encrypted data is then persisted via QSettings.
|
||||
|
||||
In unsupported environments QtKeychain will report an error. It will not store any data unencrypted unless explicitly requested (setInsecureFallback( true )).
|
||||
|
||||
**License:** QtKeychain is available under the [Modified BSD License](http://www.gnu.org/licenses/license-list.html#ModifiedBSD). See the file COPYING for details.
|
188
ext/qtkeychain/cmake/Modules/GNUInstallDirs.cmake
Normal file
188
ext/qtkeychain/cmake/Modules/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"
|
||||
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()
|
71
ext/qtkeychain/gnomekeyring.cpp
Normal file
71
ext/qtkeychain/gnomekeyring.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include "gnomekeyring_p.h"
|
||||
|
||||
const char* GnomeKeyring::GNOME_KEYRING_DEFAULT = NULL;
|
||||
|
||||
bool GnomeKeyring::isAvailable()
|
||||
{
|
||||
const GnomeKeyring& keyring = instance();
|
||||
return keyring.isLoaded() &&
|
||||
keyring.NETWORK_PASSWORD &&
|
||||
keyring.is_available &&
|
||||
keyring.find_password &&
|
||||
keyring.store_password &&
|
||||
keyring.delete_password &&
|
||||
keyring.is_available();
|
||||
}
|
||||
|
||||
GnomeKeyring::gpointer GnomeKeyring::store_network_password( const gchar* keyring, const gchar* display_name,
|
||||
const gchar* user, const gchar* server, const gchar* password,
|
||||
OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data )
|
||||
{
|
||||
if ( !isAvailable() )
|
||||
return 0;
|
||||
return instance().store_password( instance().NETWORK_PASSWORD,
|
||||
keyring, display_name, password, callback, data, destroy_data,
|
||||
"user", user, "server", server, static_cast<char*>(0) );
|
||||
}
|
||||
|
||||
GnomeKeyring::gpointer GnomeKeyring::find_network_password( const gchar* user, const gchar* server,
|
||||
OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data )
|
||||
{
|
||||
if ( !isAvailable() )
|
||||
return 0;
|
||||
return instance().find_password( instance().NETWORK_PASSWORD,
|
||||
callback, data, destroy_data,
|
||||
"user", user, "server", server, static_cast<char*>(0) );
|
||||
}
|
||||
|
||||
GnomeKeyring::gpointer GnomeKeyring::delete_network_password( const gchar* user,
|
||||
const gchar* server,
|
||||
OperationDoneCallback callback,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy_data )
|
||||
{
|
||||
if ( !isAvailable() )
|
||||
return 0;
|
||||
return instance().delete_password( instance().NETWORK_PASSWORD,
|
||||
callback, data, destroy_data,
|
||||
"user", user, "server", server, static_cast<char*>(0) );
|
||||
}
|
||||
|
||||
GnomeKeyring::GnomeKeyring()
|
||||
: QLibrary("gnome-keyring", 0)
|
||||
{
|
||||
static const PasswordSchema schema = {
|
||||
ITEM_NETWORK_PASSWORD,
|
||||
{{ "user", ATTRIBUTE_TYPE_STRING },
|
||||
{ "server", ATTRIBUTE_TYPE_STRING },
|
||||
{ 0, static_cast<AttributeType>( 0 ) }}
|
||||
};
|
||||
|
||||
NETWORK_PASSWORD = &schema;
|
||||
is_available = reinterpret_cast<is_available_fn*>( resolve( "gnome_keyring_is_available" ) );
|
||||
find_password = reinterpret_cast<find_password_fn*>( resolve( "gnome_keyring_find_password" ) );
|
||||
store_password = reinterpret_cast<store_password_fn*>( resolve( "gnome_keyring_store_password" ) );
|
||||
delete_password = reinterpret_cast<delete_password_fn*>( resolve( "gnome_keyring_delete_password" ) );
|
||||
}
|
||||
|
||||
GnomeKeyring& GnomeKeyring::instance() {
|
||||
static GnomeKeyring keyring;
|
||||
return keyring;
|
||||
}
|
88
ext/qtkeychain/gnomekeyring_p.h
Normal file
88
ext/qtkeychain/gnomekeyring_p.h
Normal file
@ -0,0 +1,88 @@
|
||||
#ifndef QTKEYCHAIN_GNOME_P_H
|
||||
#define QTKEYCHAIN_GNOME_P_H
|
||||
|
||||
#include <QLibrary>
|
||||
|
||||
class GnomeKeyring : private QLibrary {
|
||||
public:
|
||||
enum Result {
|
||||
RESULT_OK,
|
||||
RESULT_DENIED,
|
||||
RESULT_NO_KEYRING_DAEMON,
|
||||
RESULT_ALREADY_UNLOCKED,
|
||||
RESULT_NO_SUCH_KEYRING,
|
||||
RESULT_BAD_ARGUMENTS,
|
||||
RESULT_IO_ERROR,
|
||||
RESULT_CANCELLED,
|
||||
RESULT_KEYRING_ALREADY_EXISTS,
|
||||
RESULT_NO_MATCH
|
||||
};
|
||||
|
||||
enum ItemType {
|
||||
ITEM_GENERIC_SECRET = 0,
|
||||
ITEM_NETWORK_PASSWORD,
|
||||
ITEM_NOTE,
|
||||
ITEM_CHAINED_KEYRING_PASSWORD,
|
||||
ITEM_ENCRYPTION_KEY_PASSWORD,
|
||||
ITEM_PK_STORAGE = 0x100
|
||||
};
|
||||
|
||||
enum AttributeType {
|
||||
ATTRIBUTE_TYPE_STRING,
|
||||
ATTRIBUTE_TYPE_UINT32
|
||||
};
|
||||
|
||||
typedef char gchar;
|
||||
typedef void* gpointer;
|
||||
typedef bool gboolean;
|
||||
typedef struct {
|
||||
ItemType item_type;
|
||||
struct {
|
||||
const gchar* name;
|
||||
AttributeType type;
|
||||
} attributes[32];
|
||||
} PasswordSchema;
|
||||
|
||||
typedef void ( *OperationGetStringCallback )( Result result, const char* string, gpointer data );
|
||||
typedef void ( *OperationDoneCallback )( Result result, gpointer data );
|
||||
typedef void ( *GDestroyNotify )( gpointer data );
|
||||
|
||||
static const char* GNOME_KEYRING_DEFAULT;
|
||||
|
||||
static bool isAvailable();
|
||||
|
||||
static gpointer store_network_password( const gchar* keyring, const gchar* display_name,
|
||||
const gchar* user, const gchar* server, const gchar* password,
|
||||
OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data );
|
||||
|
||||
static gpointer find_network_password( const gchar* user, const gchar* server,
|
||||
OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data );
|
||||
|
||||
static gpointer delete_network_password( const gchar* user, const gchar* server,
|
||||
OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data );
|
||||
private:
|
||||
GnomeKeyring();
|
||||
|
||||
static GnomeKeyring& instance();
|
||||
|
||||
const PasswordSchema* NETWORK_PASSWORD;
|
||||
typedef gboolean ( is_available_fn )( void );
|
||||
typedef gpointer ( store_password_fn )( const PasswordSchema* schema, const gchar* keyring,
|
||||
const gchar* display_name, const gchar* password,
|
||||
OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data,
|
||||
... );
|
||||
typedef gpointer ( find_password_fn )( const PasswordSchema* schema,
|
||||
OperationGetStringCallback callback, gpointer data, GDestroyNotify destroy_data,
|
||||
... );
|
||||
typedef gpointer ( delete_password_fn )( const PasswordSchema* schema,
|
||||
OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data,
|
||||
... );
|
||||
|
||||
is_available_fn* is_available;
|
||||
find_password_fn* find_password;
|
||||
store_password_fn* store_password;
|
||||
delete_password_fn* delete_password;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
229
ext/qtkeychain/keychain.cpp
Normal file
229
ext/qtkeychain/keychain.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> *
|
||||
* *
|
||||
* 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. For licensing and distribution *
|
||||
* details, check the accompanying file 'COPYING'. *
|
||||
*****************************************************************************/
|
||||
#include "keychain.h"
|
||||
#include "keychain_p.h"
|
||||
|
||||
using namespace QKeychain;
|
||||
|
||||
Job::Job( const QString& service, QObject *parent )
|
||||
: QObject( parent )
|
||||
, d ( new JobPrivate( service ) ) {
|
||||
}
|
||||
|
||||
Job::~Job() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
QString Job::service() const {
|
||||
return d->service;
|
||||
}
|
||||
|
||||
QSettings* Job::settings() const {
|
||||
return d->settings;
|
||||
}
|
||||
|
||||
void Job::setSettings( QSettings* settings ) {
|
||||
d->settings = settings;
|
||||
}
|
||||
|
||||
void Job::start() {
|
||||
QMetaObject::invokeMethod( this, "doStart", Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
bool Job::autoDelete() const {
|
||||
return d->autoDelete;
|
||||
}
|
||||
|
||||
void Job::setAutoDelete( bool autoDelete ) {
|
||||
d->autoDelete = autoDelete;
|
||||
}
|
||||
|
||||
bool Job::insecureFallback() const {
|
||||
return d->insecureFallback;
|
||||
}
|
||||
|
||||
void Job::setInsecureFallback( bool insecureFallback ) {
|
||||
d->insecureFallback = insecureFallback;
|
||||
}
|
||||
|
||||
void Job::emitFinished() {
|
||||
emit finished( this );
|
||||
if ( d->autoDelete )
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void Job::emitFinishedWithError( Error error, const QString& errorString ) {
|
||||
d->error = error;
|
||||
d->errorString = errorString;
|
||||
emitFinished();
|
||||
}
|
||||
|
||||
Error Job::error() const {
|
||||
return d->error;
|
||||
}
|
||||
|
||||
QString Job::errorString() const {
|
||||
return d->errorString;
|
||||
}
|
||||
|
||||
void Job::setError( Error error ) {
|
||||
d->error = error;
|
||||
}
|
||||
|
||||
void Job::setErrorString( const QString& errorString ) {
|
||||
d->errorString = errorString;
|
||||
}
|
||||
|
||||
ReadPasswordJob::ReadPasswordJob( const QString& service, QObject* parent )
|
||||
: Job( service, parent )
|
||||
, d( new ReadPasswordJobPrivate( this ) )
|
||||
{}
|
||||
|
||||
ReadPasswordJob::~ReadPasswordJob() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
QString ReadPasswordJob::textData() const {
|
||||
return QString::fromUtf8( d->data );
|
||||
}
|
||||
|
||||
QByteArray ReadPasswordJob::binaryData() const {
|
||||
return d->data;
|
||||
}
|
||||
|
||||
QString ReadPasswordJob::key() const {
|
||||
return d->key;
|
||||
}
|
||||
|
||||
void ReadPasswordJob::setKey( const QString& key ) {
|
||||
d->key = key;
|
||||
}
|
||||
|
||||
void ReadPasswordJob::doStart() {
|
||||
JobExecutor::instance()->enqueue( this );
|
||||
}
|
||||
|
||||
WritePasswordJob::WritePasswordJob( const QString& service, QObject* parent )
|
||||
: Job( service, parent )
|
||||
, d( new WritePasswordJobPrivate( this ) ) {
|
||||
}
|
||||
|
||||
WritePasswordJob::~WritePasswordJob() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
QString WritePasswordJob::key() const {
|
||||
return d->key;
|
||||
}
|
||||
|
||||
void WritePasswordJob::setKey( const QString& key ) {
|
||||
d->key = key;
|
||||
}
|
||||
|
||||
void WritePasswordJob::setBinaryData( const QByteArray& data ) {
|
||||
d->binaryData = data;
|
||||
d->mode = WritePasswordJobPrivate::Binary;
|
||||
}
|
||||
|
||||
void WritePasswordJob::setTextData( const QString& data ) {
|
||||
d->textData = data;
|
||||
d->mode = WritePasswordJobPrivate::Text;
|
||||
}
|
||||
|
||||
void WritePasswordJob::doStart() {
|
||||
JobExecutor::instance()->enqueue( this );
|
||||
}
|
||||
|
||||
DeletePasswordJob::DeletePasswordJob( const QString& service, QObject* parent )
|
||||
: Job( service, parent )
|
||||
, d( new DeletePasswordJobPrivate( this ) ) {
|
||||
}
|
||||
|
||||
DeletePasswordJob::~DeletePasswordJob() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
void DeletePasswordJob::doStart() {
|
||||
//Internally, to delete a password we just execute a write job with no data set (null byte array).
|
||||
//In all current implementations, this deletes the entry so this is sufficient
|
||||
WritePasswordJob* job = new WritePasswordJob( service(), this );
|
||||
connect( job, SIGNAL(finished(QKeychain::Job*)), d, SLOT(jobFinished(QKeychain::Job*)) );
|
||||
job->setInsecureFallback(true);
|
||||
job->setSettings(settings());
|
||||
job->setKey( d->key );
|
||||
job->doStart();
|
||||
}
|
||||
|
||||
QString DeletePasswordJob::key() const {
|
||||
return d->key;
|
||||
}
|
||||
|
||||
void DeletePasswordJob::setKey( const QString& key ) {
|
||||
d->key = key;
|
||||
}
|
||||
|
||||
void DeletePasswordJobPrivate::jobFinished( Job* job ) {
|
||||
q->setError( job->error() );
|
||||
q->setErrorString( job->errorString() );
|
||||
q->emitFinished();
|
||||
}
|
||||
|
||||
JobExecutor::JobExecutor()
|
||||
: QObject( 0 )
|
||||
, m_runningJob( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
void JobExecutor::enqueue( Job* job ) {
|
||||
m_queue.append( job );
|
||||
startNextIfNoneRunning();
|
||||
}
|
||||
|
||||
void JobExecutor::startNextIfNoneRunning() {
|
||||
if ( m_queue.isEmpty() || m_runningJob )
|
||||
return;
|
||||
QPointer<Job> next;
|
||||
while ( !next && !m_queue.isEmpty() ) {
|
||||
next = m_queue.first();
|
||||
m_queue.pop_front();
|
||||
}
|
||||
if ( next ) {
|
||||
connect( next, SIGNAL(finished(QKeychain::Job*)), this, SLOT(jobFinished(QKeychain::Job*)) );
|
||||
connect( next, SIGNAL(destroyed(QObject*)), this, SLOT(jobDestroyed(QObject*)) );
|
||||
m_runningJob = next;
|
||||
if ( ReadPasswordJob* rpj = qobject_cast<ReadPasswordJob*>( m_runningJob ) )
|
||||
rpj->d->scheduledStart();
|
||||
else if ( WritePasswordJob* wpj = qobject_cast<WritePasswordJob*>( m_runningJob) )
|
||||
wpj->d->scheduledStart();
|
||||
}
|
||||
}
|
||||
|
||||
void JobExecutor::jobDestroyed( QObject* object ) {
|
||||
Q_UNUSED( object ) // for release mode
|
||||
Q_ASSERT( object == m_runningJob );
|
||||
m_runningJob->disconnect( this );
|
||||
m_runningJob = 0;
|
||||
startNextIfNoneRunning();
|
||||
}
|
||||
|
||||
void JobExecutor::jobFinished( Job* job ) {
|
||||
Q_UNUSED( job ) // for release mode
|
||||
Q_ASSERT( job == m_runningJob );
|
||||
m_runningJob->disconnect( this );
|
||||
m_runningJob = 0;
|
||||
startNextIfNoneRunning();
|
||||
}
|
||||
|
||||
JobExecutor* JobExecutor::s_instance = 0;
|
||||
|
||||
JobExecutor* JobExecutor::instance() {
|
||||
if ( !s_instance )
|
||||
s_instance = new JobExecutor;
|
||||
return s_instance;
|
||||
}
|
145
ext/qtkeychain/keychain.h
Normal file
145
ext/qtkeychain/keychain.h
Normal file
@ -0,0 +1,145 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> *
|
||||
* *
|
||||
* 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. For licensing and distribution *
|
||||
* details, check the accompanying file 'COPYING'. *
|
||||
*****************************************************************************/
|
||||
#ifndef KEYCHAIN_H
|
||||
#define KEYCHAIN_H
|
||||
|
||||
#include "qkeychain_export.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QString>
|
||||
|
||||
class QSettings;
|
||||
|
||||
#define QTKEYCHAIN_VERSION 0x000100
|
||||
|
||||
namespace QKeychain {
|
||||
|
||||
/**
|
||||
* Error codes
|
||||
*/
|
||||
enum Error {
|
||||
NoError=0, /**< No error occurred, operation was successful */
|
||||
EntryNotFound, /**< For the given key no data was found */
|
||||
CouldNotDeleteEntry, /**< Could not delete existing secret data */
|
||||
AccessDeniedByUser, /**< User denied access to keychain */
|
||||
AccessDenied, /**< Access denied for other reasons */
|
||||
NoBackendAvailable, /**< No platform-specific keychain service available */
|
||||
NotImplemented, /**< Not implemented on platform */
|
||||
OtherError /**< Something else went wrong (errorString() might provide details) */
|
||||
};
|
||||
|
||||
class JobExecutor;
|
||||
class JobPrivate;
|
||||
|
||||
class QKEYCHAIN_EXPORT Job : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Job( const QString& service, QObject* parent=0 );
|
||||
~Job();
|
||||
|
||||
QSettings* settings() const;
|
||||
void setSettings( QSettings* settings );
|
||||
|
||||
void start();
|
||||
|
||||
QString service() const;
|
||||
|
||||
Error error() const;
|
||||
QString errorString() const;
|
||||
|
||||
bool autoDelete() const;
|
||||
void setAutoDelete( bool autoDelete );
|
||||
|
||||
bool insecureFallback() const;
|
||||
void setInsecureFallback( bool insecureFallback );
|
||||
|
||||
Q_SIGNALS:
|
||||
void finished( QKeychain::Job* );
|
||||
|
||||
protected:
|
||||
Q_INVOKABLE virtual void doStart() = 0;
|
||||
|
||||
void setError( Error error );
|
||||
void setErrorString( const QString& errorString );
|
||||
void emitFinished();
|
||||
void emitFinishedWithError(Error, const QString& errorString);
|
||||
|
||||
private:
|
||||
JobPrivate* const d;
|
||||
};
|
||||
|
||||
class ReadPasswordJobPrivate;
|
||||
|
||||
class QKEYCHAIN_EXPORT ReadPasswordJob : public Job {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ReadPasswordJob( const QString& service, QObject* parent=0 );
|
||||
~ReadPasswordJob();
|
||||
|
||||
QString key() const;
|
||||
void setKey( const QString& key );
|
||||
|
||||
QByteArray binaryData() const;
|
||||
QString textData() const;
|
||||
|
||||
protected:
|
||||
void doStart();
|
||||
|
||||
private:
|
||||
friend class QKeychain::ReadPasswordJobPrivate;
|
||||
friend class QKeychain::JobExecutor;
|
||||
ReadPasswordJobPrivate* const d;
|
||||
};
|
||||
|
||||
class WritePasswordJobPrivate;
|
||||
|
||||
class QKEYCHAIN_EXPORT WritePasswordJob : public Job {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WritePasswordJob( const QString& service, QObject* parent=0 );
|
||||
~WritePasswordJob();
|
||||
|
||||
QString key() const;
|
||||
void setKey( const QString& key );
|
||||
|
||||
void setBinaryData( const QByteArray& data );
|
||||
void setTextData( const QString& data );
|
||||
|
||||
protected:
|
||||
void doStart();
|
||||
|
||||
private:
|
||||
friend class QKeychain::JobExecutor;
|
||||
friend class QKeychain::WritePasswordJobPrivate;
|
||||
friend class DeletePasswordJob;
|
||||
WritePasswordJobPrivate* const d;
|
||||
};
|
||||
|
||||
class DeletePasswordJobPrivate;
|
||||
|
||||
class QKEYCHAIN_EXPORT DeletePasswordJob : public Job {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeletePasswordJob( const QString& service, QObject* parent=0 );
|
||||
~DeletePasswordJob();
|
||||
|
||||
QString key() const;
|
||||
void setKey( const QString& key );
|
||||
|
||||
protected:
|
||||
void doStart();
|
||||
|
||||
private:
|
||||
friend class QKeychain::DeletePasswordJobPrivate;
|
||||
DeletePasswordJobPrivate* const d;
|
||||
};
|
||||
|
||||
} // namespace QtKeychain
|
||||
|
||||
#endif
|
161
ext/qtkeychain/keychain_mac.cpp
Normal file
161
ext/qtkeychain/keychain_mac.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> *
|
||||
* *
|
||||
* 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. For licensing and distribution *
|
||||
* details, check the accompanying file 'COPYING'. *
|
||||
*****************************************************************************/
|
||||
#include "keychain_p.h"
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace QKeychain;
|
||||
|
||||
template <typename T>
|
||||
struct Releaser {
|
||||
explicit Releaser( const T& v ) : value( v ) {}
|
||||
~Releaser() {
|
||||
CFRelease( value );
|
||||
}
|
||||
|
||||
const T value;
|
||||
};
|
||||
|
||||
static QString strForStatus( OSStatus os ) {
|
||||
const Releaser<CFStringRef> str( SecCopyErrorMessageString( os, 0 ) );
|
||||
const char * const buf = CFStringGetCStringPtr( str.value, kCFStringEncodingUTF8 );
|
||||
if ( !buf )
|
||||
return QObject::tr( "%1 (OSStatus %2)" )
|
||||
.arg( "OSX Keychain Error" ).arg( os );
|
||||
return QObject::tr( "%1 (OSStatus %2)" )
|
||||
.arg( QString::fromUtf8( buf, strlen( buf ) ) ).arg( os );
|
||||
}
|
||||
|
||||
static OSStatus readPw( QByteArray* pw,
|
||||
const QString& service,
|
||||
const QString& account,
|
||||
SecKeychainItemRef* ref ) {
|
||||
Q_ASSERT( pw );
|
||||
pw->clear();
|
||||
const QByteArray serviceData = service.toUtf8();
|
||||
const QByteArray accountData = account.toUtf8();
|
||||
|
||||
void* data = 0;
|
||||
UInt32 len = 0;
|
||||
|
||||
const OSStatus ret = SecKeychainFindGenericPassword( NULL, // default keychain
|
||||
serviceData.size(),
|
||||
serviceData.constData(),
|
||||
accountData.size(),
|
||||
accountData.constData(),
|
||||
&len,
|
||||
&data,
|
||||
ref );
|
||||
if ( ret == noErr ) {
|
||||
*pw = QByteArray( reinterpret_cast<const char*>( data ), len );
|
||||
const OSStatus ret2 = SecKeychainItemFreeContent ( 0, data );
|
||||
if ( ret2 != noErr )
|
||||
qWarning() << "Could not free item content: " << strForStatus( ret2 );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ReadPasswordJobPrivate::scheduledStart()
|
||||
{
|
||||
QString errorString;
|
||||
Error error = NoError;
|
||||
const OSStatus ret = readPw( &data, q->service(), q->key(), 0 );
|
||||
|
||||
switch ( ret ) {
|
||||
case noErr:
|
||||
break;
|
||||
case errSecItemNotFound:
|
||||
errorString = tr("Password not found");
|
||||
error = EntryNotFound;
|
||||
break;
|
||||
default:
|
||||
errorString = strForStatus( ret );
|
||||
error = OtherError;
|
||||
break;
|
||||
}
|
||||
q->emitFinishedWithError( error, errorString );
|
||||
}
|
||||
|
||||
|
||||
static QKeychain::Error deleteEntryImpl( const QString& service, const QString& account, QString* err ) {
|
||||
SecKeychainItemRef ref;
|
||||
QByteArray pw;
|
||||
const OSStatus ret1 = readPw( &pw, service, account, &ref );
|
||||
if ( ret1 == errSecItemNotFound )
|
||||
return NoError; // No item stored, we're done
|
||||
if ( ret1 != noErr ) {
|
||||
*err = strForStatus( ret1 );
|
||||
//TODO map error code, set errstr
|
||||
return OtherError;
|
||||
}
|
||||
const Releaser<SecKeychainItemRef> releaser( ref );
|
||||
|
||||
const OSStatus ret2 = SecKeychainItemDelete( ref );
|
||||
|
||||
if ( ret2 == noErr )
|
||||
return NoError;
|
||||
//TODO map error code
|
||||
*err = strForStatus( ret2 );
|
||||
return CouldNotDeleteEntry;
|
||||
}
|
||||
|
||||
static QKeychain::Error writeEntryImpl( const QString& service,
|
||||
const QString& account,
|
||||
const QByteArray& data,
|
||||
QString* err ) {
|
||||
Q_ASSERT( err );
|
||||
err->clear();
|
||||
const QByteArray serviceData = service.toUtf8();
|
||||
const QByteArray accountData = account.toUtf8();
|
||||
const OSStatus ret = SecKeychainAddGenericPassword( NULL, //default keychain
|
||||
serviceData.size(),
|
||||
serviceData.constData(),
|
||||
accountData.size(),
|
||||
accountData.constData(),
|
||||
data.size(),
|
||||
data.constData(),
|
||||
NULL //item reference
|
||||
);
|
||||
if ( ret != noErr ) {
|
||||
switch ( ret ) {
|
||||
case errSecDuplicateItem:
|
||||
{
|
||||
Error derr = deleteEntryImpl( service, account, err );
|
||||
if ( derr != NoError )
|
||||
return CouldNotDeleteEntry;
|
||||
else
|
||||
return writeEntryImpl( service, account, data, err );
|
||||
}
|
||||
default:
|
||||
*err = strForStatus( ret );
|
||||
return OtherError;
|
||||
}
|
||||
}
|
||||
|
||||
return NoError;
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::scheduledStart()
|
||||
{
|
||||
QString errorString;
|
||||
Error error = NoError;
|
||||
|
||||
if ( mode == Delete ) {
|
||||
const Error derr = deleteEntryImpl( q->service(), key, &errorString );
|
||||
if ( derr != NoError )
|
||||
error = CouldNotDeleteEntry;
|
||||
q->emitFinishedWithError( error, errorString );
|
||||
return;
|
||||
}
|
||||
const QByteArray data = mode == Text ? textData.toUtf8() : binaryData;
|
||||
error = writeEntryImpl( q->service(), key, data, &errorString );
|
||||
q->emitFinishedWithError( error, errorString );
|
||||
}
|
163
ext/qtkeychain/keychain_p.h
Normal file
163
ext/qtkeychain/keychain_p.h
Normal file
@ -0,0 +1,163 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> *
|
||||
* *
|
||||
* 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. For licensing and distribution *
|
||||
* details, check the accompanying file 'COPYING'. *
|
||||
*****************************************************************************/
|
||||
#ifndef KEYCHAIN_P_H
|
||||
#define KEYCHAIN_P_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QObject>
|
||||
#include <QPointer>
|
||||
#include <QSettings>
|
||||
#include <QVector>
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||
|
||||
#include <QDBusPendingCallWatcher>
|
||||
|
||||
#include "kwallet_interface.h"
|
||||
#else
|
||||
|
||||
class QDBusPendingCallWatcher;
|
||||
|
||||
#endif
|
||||
|
||||
#include "keychain.h"
|
||||
|
||||
namespace QKeychain {
|
||||
|
||||
class JobExecutor;
|
||||
|
||||
class JobPrivate : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
JobPrivate( const QString& service_ )
|
||||
: error( NoError )
|
||||
, service( service_ )
|
||||
, autoDelete( true )
|
||||
, insecureFallback( false ) {}
|
||||
|
||||
QKeychain::Error error;
|
||||
QString errorString;
|
||||
QString service;
|
||||
bool autoDelete;
|
||||
bool insecureFallback;
|
||||
QPointer<QSettings> settings;
|
||||
};
|
||||
|
||||
class ReadPasswordJobPrivate : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ReadPasswordJobPrivate( ReadPasswordJob* qq ) : q( qq ), walletHandle( 0 ), dataType( Text ) {}
|
||||
void scheduledStart();
|
||||
|
||||
ReadPasswordJob* const q;
|
||||
QByteArray data;
|
||||
QString key;
|
||||
int walletHandle;
|
||||
enum DataType {
|
||||
Binary,
|
||||
Text
|
||||
};
|
||||
DataType dataType;
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||
org::kde::KWallet* iface;
|
||||
static void gnomeKeyring_cb( int result, const char* string, ReadPasswordJobPrivate* data );
|
||||
friend class QKeychain::JobExecutor;
|
||||
void fallbackOnError(const QDBusError& err);
|
||||
|
||||
private Q_SLOTS:
|
||||
void kwalletWalletFound( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletOpenFinished( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletReadFinished( QDBusPendingCallWatcher* watcher );
|
||||
#else //moc's too dumb to respect above macros, so just define empty slot implementations
|
||||
private Q_SLOTS:
|
||||
void kwalletWalletFound( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletOpenFinished( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletEntryTypeFinished( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletReadFinished( QDBusPendingCallWatcher* ) {}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class WritePasswordJobPrivate : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit WritePasswordJobPrivate( WritePasswordJob* qq ) : q( qq ), mode( Delete ) {}
|
||||
void scheduledStart();
|
||||
|
||||
enum Mode {
|
||||
Delete,
|
||||
Text,
|
||||
Binary
|
||||
};
|
||||
|
||||
static QString modeToString(Mode m);
|
||||
static Mode stringToMode(const QString& s);
|
||||
|
||||
WritePasswordJob* const q;
|
||||
Mode mode;
|
||||
QString key;
|
||||
QByteArray binaryData;
|
||||
QString textData;
|
||||
|
||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
|
||||
org::kde::KWallet* iface;
|
||||
static void gnomeKeyring_cb( int result, WritePasswordJobPrivate* self );
|
||||
friend class QKeychain::JobExecutor;
|
||||
void fallbackOnError(const QDBusError& err);
|
||||
|
||||
private Q_SLOTS:
|
||||
void kwalletWalletFound( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletOpenFinished( QDBusPendingCallWatcher* watcher );
|
||||
void kwalletWriteFinished( QDBusPendingCallWatcher* watcher );
|
||||
#else
|
||||
private Q_SLOTS:
|
||||
void kwalletWalletFound( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletOpenFinished( QDBusPendingCallWatcher* ) {}
|
||||
void kwalletWriteFinished( QDBusPendingCallWatcher* ) {}
|
||||
#endif
|
||||
};
|
||||
|
||||
class DeletePasswordJobPrivate : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeletePasswordJobPrivate( DeletePasswordJob* qq ) : q( qq ) {}
|
||||
void doStart();
|
||||
DeletePasswordJob* const q;
|
||||
QString key;
|
||||
private Q_SLOTS:
|
||||
void jobFinished( QKeychain::Job* );
|
||||
};
|
||||
|
||||
class JobExecutor : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
static JobExecutor* instance();
|
||||
|
||||
void enqueue( Job* job );
|
||||
|
||||
private:
|
||||
explicit JobExecutor();
|
||||
void startNextIfNoneRunning();
|
||||
|
||||
private Q_SLOTS:
|
||||
void jobFinished( QKeychain::Job* );
|
||||
void jobDestroyed( QObject* object );
|
||||
|
||||
private:
|
||||
static JobExecutor* s_instance;
|
||||
Job* m_runningJob;
|
||||
QVector<QPointer<Job> > m_queue;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // KEYCHAIN_P_H
|
510
ext/qtkeychain/keychain_unix.cpp
Normal file
510
ext/qtkeychain/keychain_unix.cpp
Normal file
@ -0,0 +1,510 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> *
|
||||
* *
|
||||
* 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. For licensing and distribution *
|
||||
* details, check the accompanying file 'COPYING'. *
|
||||
*****************************************************************************/
|
||||
#include "keychain_p.h"
|
||||
#include "gnomekeyring_p.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
#include <QScopedPointer>
|
||||
|
||||
using namespace QKeychain;
|
||||
|
||||
static QString typeKey( const QString& key )
|
||||
{
|
||||
return QString::fromLatin1( "%1/type" ).arg( key );
|
||||
}
|
||||
|
||||
static QString dataKey( const QString& key )
|
||||
{
|
||||
return QString::fromLatin1( "%1/data" ).arg( key );
|
||||
}
|
||||
|
||||
enum KeyringBackend {
|
||||
Backend_GnomeKeyring,
|
||||
Backend_Kwallet4,
|
||||
Backend_Kwallet5
|
||||
};
|
||||
|
||||
enum DesktopEnvironment {
|
||||
DesktopEnv_Gnome,
|
||||
DesktopEnv_Kde4,
|
||||
DesktopEnv_Plasma5,
|
||||
DesktopEnv_Unity,
|
||||
DesktopEnv_Xfce,
|
||||
DesktopEnv_Other
|
||||
};
|
||||
|
||||
// the following detection algorithm is derived from chromium,
|
||||
// licensed under BSD, see base/nix/xdg_util.cc
|
||||
|
||||
static DesktopEnvironment getKdeVersion() {
|
||||
QString value = qgetenv("KDE_SESSION_VERSION");
|
||||
if ( value == "5" ) {
|
||||
return DesktopEnv_Plasma5;
|
||||
} else if (value == "4" ) {
|
||||
return DesktopEnv_Kde4;
|
||||
} else {
|
||||
// most likely KDE3
|
||||
return DesktopEnv_Other;
|
||||
}
|
||||
}
|
||||
|
||||
static DesktopEnvironment detectDesktopEnvironment() {
|
||||
QByteArray xdgCurrentDesktop = qgetenv("XDG_CURRENT_DESKTOP");
|
||||
if ( xdgCurrentDesktop == "GNOME" ) {
|
||||
return DesktopEnv_Gnome;
|
||||
} else if ( xdgCurrentDesktop == "Unity" ) {
|
||||
return DesktopEnv_Unity;
|
||||
} else if ( xdgCurrentDesktop == "KDE" ) {
|
||||
return getKdeVersion();
|
||||
}
|
||||
|
||||
QByteArray desktopSession = qgetenv("DESKTOP_SESSION");
|
||||
if ( desktopSession == "gnome" ) {
|
||||
return DesktopEnv_Gnome;
|
||||
} else if ( desktopSession == "kde" ) {
|
||||
return getKdeVersion();
|
||||
} else if ( desktopSession == "kde4" ) {
|
||||
return DesktopEnv_Kde4;
|
||||
} else if ( desktopSession.contains("xfce") || desktopSession == "xubuntu" ) {
|
||||
return DesktopEnv_Xfce;
|
||||
}
|
||||
|
||||
if ( !qgetenv("GNOME_DESKTOP_SESSION_ID").isEmpty() ) {
|
||||
return DesktopEnv_Gnome;
|
||||
} else if ( !qgetenv("KDE_FULL_SESSION").isEmpty() ) {
|
||||
return getKdeVersion();
|
||||
}
|
||||
|
||||
return DesktopEnv_Other;
|
||||
}
|
||||
|
||||
static KeyringBackend detectKeyringBackend()
|
||||
{
|
||||
switch (detectDesktopEnvironment()) {
|
||||
case DesktopEnv_Kde4:
|
||||
return Backend_Kwallet4;
|
||||
break;
|
||||
case DesktopEnv_Plasma5:
|
||||
return Backend_Kwallet5;
|
||||
break;
|
||||
// fall through
|
||||
case DesktopEnv_Gnome:
|
||||
case DesktopEnv_Unity:
|
||||
case DesktopEnv_Xfce:
|
||||
case DesktopEnv_Other:
|
||||
default:
|
||||
if ( GnomeKeyring::isAvailable() ) {
|
||||
return Backend_GnomeKeyring;
|
||||
} else {
|
||||
return Backend_Kwallet4;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static KeyringBackend getKeyringBackend()
|
||||
{
|
||||
static KeyringBackend backend = detectKeyringBackend();
|
||||
return backend;
|
||||
}
|
||||
|
||||
static void kwalletReadPasswordScheduledStartImpl(const char * service, const char * path, ReadPasswordJobPrivate * priv) {
|
||||
if ( QDBusConnection::sessionBus().isConnected() )
|
||||
{
|
||||
priv->iface = new org::kde::KWallet( QLatin1String(service), QLatin1String(path), QDBusConnection::sessionBus(), priv );
|
||||
const QDBusPendingReply<QString> reply = priv->iface->networkWallet();
|
||||
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, priv );
|
||||
priv->connect( watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), priv, SLOT(kwalletWalletFound(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// D-Bus is not reachable so none can tell us something about KWalletd
|
||||
QDBusError err( QDBusError::NoServer, ReadPasswordJobPrivate::tr("D-Bus is not running") );
|
||||
priv->fallbackOnError( err );
|
||||
}
|
||||
}
|
||||
|
||||
void ReadPasswordJobPrivate::scheduledStart() {
|
||||
switch ( getKeyringBackend() ) {
|
||||
case Backend_GnomeKeyring:
|
||||
if ( !GnomeKeyring::find_network_password( key.toUtf8().constData(), q->service().toUtf8().constData(),
|
||||
reinterpret_cast<GnomeKeyring::OperationGetStringCallback>( &ReadPasswordJobPrivate::gnomeKeyring_cb ),
|
||||
this, 0 ) )
|
||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
||||
break;
|
||||
|
||||
case Backend_Kwallet4:
|
||||
kwalletReadPasswordScheduledStartImpl("org.kde.kwalletd", "/modules/kwalletd", this);
|
||||
break;
|
||||
case Backend_Kwallet5:
|
||||
kwalletReadPasswordScheduledStartImpl("org.kde.kwalletd5", "/modules/kwalletd5", this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ReadPasswordJobPrivate::kwalletWalletFound(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
watcher->deleteLater();
|
||||
const QDBusPendingReply<QString> reply = *watcher;
|
||||
const QDBusPendingReply<int> pendingReply = iface->open( reply.value(), 0, q->service() );
|
||||
QDBusPendingCallWatcher* pendingWatcher = new QDBusPendingCallWatcher( pendingReply, this );
|
||||
connect( pendingWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
|
||||
static QPair<Error, QString> mapGnomeKeyringError( int result )
|
||||
{
|
||||
Q_ASSERT( result != GnomeKeyring::RESULT_OK );
|
||||
|
||||
switch ( result ) {
|
||||
case GnomeKeyring::RESULT_DENIED:
|
||||
return qMakePair( AccessDenied, QObject::tr("Access to keychain denied") );
|
||||
case GnomeKeyring::RESULT_NO_KEYRING_DAEMON:
|
||||
return qMakePair( NoBackendAvailable, QObject::tr("No keyring daemon") );
|
||||
case GnomeKeyring::RESULT_ALREADY_UNLOCKED:
|
||||
return qMakePair( OtherError, QObject::tr("Already unlocked") );
|
||||
case GnomeKeyring::RESULT_NO_SUCH_KEYRING:
|
||||
return qMakePair( OtherError, QObject::tr("No such keyring") );
|
||||
case GnomeKeyring::RESULT_BAD_ARGUMENTS:
|
||||
return qMakePair( OtherError, QObject::tr("Bad arguments") );
|
||||
case GnomeKeyring::RESULT_IO_ERROR:
|
||||
return qMakePair( OtherError, QObject::tr("I/O error") );
|
||||
case GnomeKeyring::RESULT_CANCELLED:
|
||||
return qMakePair( OtherError, QObject::tr("Cancelled") );
|
||||
case GnomeKeyring::RESULT_KEYRING_ALREADY_EXISTS:
|
||||
return qMakePair( OtherError, QObject::tr("Keyring already exists") );
|
||||
case GnomeKeyring::RESULT_NO_MATCH:
|
||||
return qMakePair( EntryNotFound, QObject::tr("No match") );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return qMakePair( OtherError, QObject::tr("Unknown error") );
|
||||
}
|
||||
|
||||
void ReadPasswordJobPrivate::gnomeKeyring_cb( int result, const char* string, ReadPasswordJobPrivate* self )
|
||||
{
|
||||
if ( result == GnomeKeyring::RESULT_OK ) {
|
||||
if ( self->dataType == ReadPasswordJobPrivate::Text )
|
||||
self->data = string;
|
||||
else
|
||||
self->data = QByteArray::fromBase64( string );
|
||||
self->q->emitFinished();
|
||||
} else {
|
||||
const QPair<Error, QString> errorResult = mapGnomeKeyringError( result );
|
||||
self->q->emitFinishedWithError( errorResult.first, errorResult.second );
|
||||
}
|
||||
}
|
||||
|
||||
void ReadPasswordJobPrivate::fallbackOnError(const QDBusError& err )
|
||||
{
|
||||
QScopedPointer<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
QSettings* actual = q->settings() ? q->settings() : local.data();
|
||||
|
||||
if ( q->insecureFallback() && actual->contains( dataKey( key ) ) ) {
|
||||
|
||||
const WritePasswordJobPrivate::Mode mode = WritePasswordJobPrivate::stringToMode( actual->value( typeKey( key ) ).toString() );
|
||||
if (mode == WritePasswordJobPrivate::Binary)
|
||||
dataType = Binary;
|
||||
else
|
||||
dataType = Text;
|
||||
data = actual->value( dataKey( key ) ).toByteArray();
|
||||
|
||||
q->emitFinished();
|
||||
} else {
|
||||
if ( err.type() == QDBusError::ServiceUnknown ) //KWalletd not running
|
||||
q->emitFinishedWithError( NoBackendAvailable, tr("No keychain service available") );
|
||||
else
|
||||
q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void ReadPasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
watcher->deleteLater();
|
||||
const QDBusPendingReply<int> reply = *watcher;
|
||||
|
||||
QScopedPointer<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
QSettings* actual = q->settings() ? q->settings() : local.data();
|
||||
|
||||
if ( reply.isError() ) {
|
||||
fallbackOnError( reply.error() );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( actual->contains( dataKey( key ) ) ) {
|
||||
// We previously stored data in the insecure QSettings, but now have KWallet available.
|
||||
// Do the migration
|
||||
|
||||
data = actual->value( dataKey( key ) ).toByteArray();
|
||||
const WritePasswordJobPrivate::Mode mode = WritePasswordJobPrivate::stringToMode( actual->value( typeKey( key ) ).toString() );
|
||||
actual->remove( key );
|
||||
|
||||
q->emitFinished();
|
||||
|
||||
|
||||
WritePasswordJob* j = new WritePasswordJob( q->service(), 0 );
|
||||
j->setSettings( q->settings() );
|
||||
j->setKey( key );
|
||||
j->setAutoDelete( true );
|
||||
if ( mode == WritePasswordJobPrivate::Binary )
|
||||
j->setBinaryData( data );
|
||||
else if ( mode == WritePasswordJobPrivate::Text )
|
||||
j->setTextData( QString::fromUtf8( data ) );
|
||||
else
|
||||
Q_ASSERT( false );
|
||||
|
||||
j->start();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
walletHandle = reply.value();
|
||||
|
||||
if ( walletHandle < 0 ) {
|
||||
q->emitFinishedWithError( AccessDenied, tr("Access to keychain denied") );
|
||||
return;
|
||||
}
|
||||
|
||||
const QDBusPendingReply<int> nextReply = iface->entryType( walletHandle, q->service(), key, q->service() );
|
||||
QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this );
|
||||
connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletEntryTypeFinished(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
|
||||
//Must be in sync with KWallet::EntryType (kwallet.h)
|
||||
enum KWalletEntryType {
|
||||
Unknown=0,
|
||||
Password,
|
||||
Stream,
|
||||
Map
|
||||
};
|
||||
|
||||
void ReadPasswordJobPrivate::kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
watcher->deleteLater();
|
||||
if ( watcher->isError() ) {
|
||||
const QDBusError err = watcher->error();
|
||||
q->emitFinishedWithError( OtherError, tr("Could not determine data type: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
const QDBusPendingReply<int> reply = *watcher;
|
||||
const int value = reply.value();
|
||||
|
||||
switch ( value ) {
|
||||
case Unknown:
|
||||
q->emitFinishedWithError( EntryNotFound, tr("Entry not found") );
|
||||
return;
|
||||
case Password:
|
||||
dataType = Text;
|
||||
break;
|
||||
case Stream:
|
||||
dataType = Binary;
|
||||
break;
|
||||
case Map:
|
||||
q->emitFinishedWithError( EntryNotFound, tr("Unsupported entry type 'Map'") );
|
||||
return;
|
||||
default:
|
||||
q->emitFinishedWithError( OtherError, tr("Unknown kwallet entry type '%1'").arg( value ) );
|
||||
return;
|
||||
}
|
||||
|
||||
const QDBusPendingCall nextReply = dataType == Text
|
||||
? QDBusPendingCall( iface->readPassword( walletHandle, q->service(), key, q->service() ) )
|
||||
: QDBusPendingCall( iface->readEntry( walletHandle, q->service(), key, q->service() ) );
|
||||
QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this );
|
||||
connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletReadFinished(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
|
||||
void ReadPasswordJobPrivate::kwalletReadFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
watcher->deleteLater();
|
||||
if ( watcher->isError() ) {
|
||||
const QDBusError err = watcher->error();
|
||||
q->emitFinishedWithError( OtherError, tr("Could not read password: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( dataType == Binary ) {
|
||||
QDBusPendingReply<QByteArray> reply = *watcher;
|
||||
data = reply.value();
|
||||
} else {
|
||||
QDBusPendingReply<QString> reply = *watcher;
|
||||
data = reply.value().toUtf8();
|
||||
}
|
||||
q->emitFinished();
|
||||
}
|
||||
|
||||
static void kwalletWritePasswordScheduledStart( const char * service, const char * path, WritePasswordJobPrivate * priv ) {
|
||||
if ( QDBusConnection::sessionBus().isConnected() )
|
||||
{
|
||||
priv->iface = new org::kde::KWallet( QLatin1String(service), QLatin1String(path), QDBusConnection::sessionBus(), priv );
|
||||
const QDBusPendingReply<QString> reply = priv->iface->networkWallet();
|
||||
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, priv );
|
||||
priv->connect( watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), priv, SLOT(kwalletWalletFound(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// D-Bus is not reachable so none can tell us something about KWalletd
|
||||
QDBusError err( QDBusError::NoServer, WritePasswordJobPrivate::tr("D-Bus is not running") );
|
||||
priv->fallbackOnError( err );
|
||||
}
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::scheduledStart() {
|
||||
switch ( getKeyringBackend() ) {
|
||||
case Backend_GnomeKeyring:
|
||||
if ( mode == WritePasswordJobPrivate::Delete ) {
|
||||
if ( !GnomeKeyring::delete_network_password( key.toUtf8().constData(), q->service().toUtf8().constData(),
|
||||
reinterpret_cast<GnomeKeyring::OperationDoneCallback>( &WritePasswordJobPrivate::gnomeKeyring_cb ),
|
||||
this, 0 ) )
|
||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
||||
} else {
|
||||
QByteArray password = mode == WritePasswordJobPrivate::Text ? textData.toUtf8() : binaryData.toBase64();
|
||||
QByteArray service = q->service().toUtf8();
|
||||
if ( !GnomeKeyring::store_network_password( GnomeKeyring::GNOME_KEYRING_DEFAULT, service.constData(),
|
||||
key.toUtf8().constData(), service.constData(), password.constData(),
|
||||
reinterpret_cast<GnomeKeyring::OperationDoneCallback>( &WritePasswordJobPrivate::gnomeKeyring_cb ),
|
||||
this, 0 ) )
|
||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
||||
}
|
||||
break;
|
||||
|
||||
case Backend_Kwallet4:
|
||||
kwalletWritePasswordScheduledStart("org.kde.kwalletd", "/modules/kwalletd", this);
|
||||
break;
|
||||
case Backend_Kwallet5:
|
||||
kwalletWritePasswordScheduledStart("org.kde.kwalletd5", "/modules/kwalletd5", this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QString WritePasswordJobPrivate::modeToString(Mode m)
|
||||
{
|
||||
switch (m) {
|
||||
case Delete:
|
||||
return QLatin1String("Delete");
|
||||
case Text:
|
||||
return QLatin1String("Text");
|
||||
case Binary:
|
||||
return QLatin1String("Binary");
|
||||
}
|
||||
|
||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled Mode value");
|
||||
return QString();
|
||||
}
|
||||
|
||||
WritePasswordJobPrivate::Mode WritePasswordJobPrivate::stringToMode(const QString& s)
|
||||
{
|
||||
if (s == QLatin1String("Delete") || s == QLatin1String("0"))
|
||||
return Delete;
|
||||
if (s == QLatin1String("Text") || s == QLatin1String("1"))
|
||||
return Text;
|
||||
if (s == QLatin1String("Binary") || s == QLatin1String("2"))
|
||||
return Binary;
|
||||
|
||||
qCritical("Unexpected mode string '%s'", qPrintable(s));
|
||||
|
||||
return Text;
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::fallbackOnError(const QDBusError &err)
|
||||
{
|
||||
QScopedPointer<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
QSettings* actual = q->settings() ? q->settings() : local.data();
|
||||
|
||||
if ( !q->insecureFallback() ) {
|
||||
q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mode == Delete ) {
|
||||
actual->remove( key );
|
||||
actual->sync();
|
||||
|
||||
q->emitFinished();
|
||||
return;
|
||||
}
|
||||
|
||||
actual->setValue( QString::fromLatin1( "%1/type" ).arg( key ), mode );
|
||||
if ( mode == Text )
|
||||
actual->setValue( QString::fromLatin1( "%1/data" ).arg( key ), textData.toUtf8() );
|
||||
else if ( mode == Binary )
|
||||
actual->setValue( QString::fromLatin1( "%1/data" ).arg( key ), binaryData );
|
||||
actual->sync();
|
||||
|
||||
q->emitFinished();
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::gnomeKeyring_cb( int result, WritePasswordJobPrivate* self )
|
||||
{
|
||||
if ( result == GnomeKeyring::RESULT_OK ) {
|
||||
self->q->emitFinished();
|
||||
} else {
|
||||
const QPair<Error, QString> errorResult = mapGnomeKeyringError( result );
|
||||
self->q->emitFinishedWithError( errorResult.first, errorResult.second );
|
||||
}
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::kwalletWalletFound(QDBusPendingCallWatcher *watcher)
|
||||
{
|
||||
watcher->deleteLater();
|
||||
const QDBusPendingReply<QString> reply = *watcher;
|
||||
const QDBusPendingReply<int> pendingReply = iface->open( reply.value(), 0, q->service() );
|
||||
QDBusPendingCallWatcher* pendingWatcher = new QDBusPendingCallWatcher( pendingReply, this );
|
||||
connect( pendingWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletOpenFinished(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
watcher->deleteLater();
|
||||
QDBusPendingReply<int> reply = *watcher;
|
||||
|
||||
QScopedPointer<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
QSettings* actual = q->settings() ? q->settings() : local.data();
|
||||
|
||||
if ( reply.isError() ) {
|
||||
fallbackOnError( reply.error() );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( actual->contains( key ) )
|
||||
{
|
||||
// If we had previously written to QSettings, but we now have a kwallet available, migrate and delete old insecure data
|
||||
actual->remove( key );
|
||||
actual->sync();
|
||||
}
|
||||
|
||||
const int handle = reply.value();
|
||||
|
||||
if ( handle < 0 ) {
|
||||
q->emitFinishedWithError( AccessDenied, tr("Access to keychain denied") );
|
||||
return;
|
||||
}
|
||||
|
||||
QDBusPendingReply<int> nextReply;
|
||||
|
||||
if ( !textData.isEmpty() )
|
||||
nextReply = iface->writePassword( handle, q->service(), key, textData, q->service() );
|
||||
else if ( !binaryData.isEmpty() )
|
||||
nextReply = iface->writeEntry( handle, q->service(), key, binaryData, q->service() );
|
||||
else
|
||||
nextReply = iface->removeEntry( handle, q->service(), key, q->service() );
|
||||
|
||||
QDBusPendingCallWatcher* nextWatcher = new QDBusPendingCallWatcher( nextReply, this );
|
||||
connect( nextWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(kwalletWriteFinished(QDBusPendingCallWatcher*)) );
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::kwalletWriteFinished( QDBusPendingCallWatcher* watcher ) {
|
||||
watcher->deleteLater();
|
||||
QDBusPendingReply<int> reply = *watcher;
|
||||
if ( reply.isError() ) {
|
||||
const QDBusError err = reply.error();
|
||||
q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
q->emitFinished();
|
||||
}
|
107
ext/qtkeychain/keychain_win.cpp
Normal file
107
ext/qtkeychain/keychain_win.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> *
|
||||
* *
|
||||
* 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. For licensing and distribution *
|
||||
* details, check the accompanying file 'COPYING'. *
|
||||
*****************************************************************************/
|
||||
#include "keychain_p.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
using namespace QKeychain;
|
||||
|
||||
void ReadPasswordJobPrivate::scheduledStart() {
|
||||
//Use settings member if there, create local settings object if not
|
||||
std::auto_ptr<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
QSettings* actual = q->settings() ? q->settings() : local.get();
|
||||
|
||||
QByteArray encrypted = actual->value( key ).toByteArray();
|
||||
if ( encrypted.isNull() ) {
|
||||
q->emitFinishedWithError( EntryNotFound, tr("Entry not found") );
|
||||
return;
|
||||
}
|
||||
|
||||
DATA_BLOB blob_in, blob_out;
|
||||
|
||||
blob_in.pbData = reinterpret_cast<BYTE*>( encrypted.data() );
|
||||
blob_in.cbData = encrypted.size();
|
||||
|
||||
const BOOL ret = CryptUnprotectData( &blob_in,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
&blob_out );
|
||||
if ( !ret ) {
|
||||
q->emitFinishedWithError( OtherError, tr("Could not decrypt data") );
|
||||
return;
|
||||
}
|
||||
|
||||
data = QByteArray( reinterpret_cast<char*>( blob_out.pbData ), blob_out.cbData );
|
||||
SecureZeroMemory( blob_out.pbData, blob_out.cbData );
|
||||
LocalFree( blob_out.pbData );
|
||||
|
||||
q->emitFinished();
|
||||
}
|
||||
|
||||
void WritePasswordJobPrivate::scheduledStart() {
|
||||
if ( mode == Delete ) {
|
||||
//Use settings member if there, create local settings object if not
|
||||
std::auto_ptr<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
QSettings* actual = q->settings() ? q->settings() : local.get();
|
||||
actual->remove( key );
|
||||
actual->sync();
|
||||
if ( actual->status() != QSettings::NoError ) {
|
||||
const QString err = actual->status() == QSettings::AccessError
|
||||
? tr("Could not delete encrypted data from settings: access error")
|
||||
: tr("Could not delete encrypted data from settings: format error");
|
||||
q->emitFinishedWithError( OtherError, err );
|
||||
} else {
|
||||
q->emitFinished();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = mode == Binary ? binaryData : textData.toUtf8();
|
||||
DATA_BLOB blob_in, blob_out;
|
||||
blob_in.pbData = reinterpret_cast<BYTE*>( data.data() );
|
||||
blob_in.cbData = data.size();
|
||||
const BOOL res = CryptProtectData( &blob_in,
|
||||
L"QKeychain-encrypted data",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
&blob_out );
|
||||
if ( !res ) {
|
||||
q->emitFinishedWithError( OtherError, tr("Encryption failed") ); //TODO more details available?
|
||||
return;
|
||||
}
|
||||
|
||||
const QByteArray encrypted( reinterpret_cast<char*>( blob_out.pbData ), blob_out.cbData );
|
||||
LocalFree( blob_out.pbData );
|
||||
|
||||
//Use settings member if there, create local settings object if not
|
||||
std::auto_ptr<QSettings> local( !q->settings() ? new QSettings( q->service() ) : 0 );
|
||||
QSettings* actual = q->settings() ? q->settings() : local.get();
|
||||
actual->setValue( key, encrypted );
|
||||
actual->sync();
|
||||
if ( actual->status() != QSettings::NoError ) {
|
||||
|
||||
const QString errorString = actual->status() == QSettings::AccessError
|
||||
? tr("Could not store encrypted data in settings: access error")
|
||||
: tr("Could not store encrypted data in settings: format error");
|
||||
q->emitFinishedWithError( OtherError, errorString );
|
||||
return;
|
||||
}
|
||||
|
||||
q->emitFinished();
|
||||
}
|
276
ext/qtkeychain/org.kde.KWallet.xml
Normal file
276
ext/qtkeychain/org.kde.KWallet.xml
Normal file
@ -0,0 +1,276 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.KWallet">
|
||||
<signal name="walletListDirty">
|
||||
</signal>
|
||||
<signal name="walletCreated">
|
||||
<arg name="wallet" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="walletOpened">
|
||||
<arg name="wallet" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="walletAsyncOpened">
|
||||
<arg name="tId" type="i" direction="out"/>
|
||||
<arg name="handle" type="i" direction="out"/>
|
||||
</signal>
|
||||
<signal name="walletDeleted">
|
||||
<arg name="wallet" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="walletClosed">
|
||||
<arg name="wallet" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="walletClosed">
|
||||
<arg name="handle" type="i" direction="out"/>
|
||||
</signal>
|
||||
<signal name="allWalletsClosed">
|
||||
</signal>
|
||||
<signal name="folderListUpdated">
|
||||
<arg name="wallet" type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="folderUpdated">
|
||||
<arg type="s" direction="out"/>
|
||||
<arg type="s" direction="out"/>
|
||||
</signal>
|
||||
<signal name="applicationDisconnected">
|
||||
<arg name="wallet" type="s" direction="out"/>
|
||||
<arg name="application" type="s" direction="out"/>
|
||||
</signal>
|
||||
<method name="isEnabled">
|
||||
<arg type="b" direction="out"/>
|
||||
</method>
|
||||
<method name="open">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
<arg name="wId" type="x" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="openPath">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="path" type="s" direction="in"/>
|
||||
<arg name="wId" type="x" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="openAsync">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
<arg name="wId" type="x" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
<arg name="handleSession" type="b" direction="in"/>
|
||||
</method>
|
||||
<method name="openPathAsync">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="path" type="s" direction="in"/>
|
||||
<arg name="wId" type="x" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
<arg name="handleSession" type="b" direction="in"/>
|
||||
</method>
|
||||
<method name="close">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
<arg name="force" type="b" direction="in"/>
|
||||
</method>
|
||||
<method name="close">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="force" type="b" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="sync">
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
||||
</method>
|
||||
<method name="deleteWallet">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="isOpen">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="isOpen">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
</method>
|
||||
<method name="users">
|
||||
<arg type="as" direction="out"/>
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="changePassword">
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
<arg name="wId" type="x" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="wallets">
|
||||
<arg type="as" direction="out"/>
|
||||
</method>
|
||||
<method name="folderList">
|
||||
<arg type="as" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="hasFolder">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="createFolder">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="removeFolder">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="entryList">
|
||||
<arg type="as" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="readEntry">
|
||||
<arg type="ay" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="readMap">
|
||||
<arg type="ay" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="readPassword">
|
||||
<arg type="s" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="readEntryList">
|
||||
<arg type="a{sv}" direction="out"/>
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="readMapList">
|
||||
<arg type="a{sv}" direction="out"/>
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="readPasswordList">
|
||||
<arg type="a{sv}" direction="out"/>
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="renameEntry">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="oldName" type="s" direction="in"/>
|
||||
<arg name="newName" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="writeEntry">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="value" type="ay" direction="in"/>
|
||||
<arg name="entryType" type="i" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="writeEntry">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="value" type="ay" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="writeMap">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="value" type="ay" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="writePassword">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="value" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="hasEntry">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="entryType">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="removeEntry">
|
||||
<arg type="i" direction="out"/>
|
||||
<arg name="handle" type="i" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
<arg name="appid" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="disconnectApplication">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
<arg name="application" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="reconfigure">
|
||||
</method>
|
||||
<method name="folderDoesNotExist">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="keyDoesNotExist">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
<arg name="folder" type="s" direction="in"/>
|
||||
<arg name="key" type="s" direction="in"/>
|
||||
</method>
|
||||
<method name="closeAllWallets">
|
||||
</method>
|
||||
<method name="networkWallet">
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<method name="localWallet">
|
||||
<arg type="s" direction="out"/>
|
||||
</method>
|
||||
<method name="pamOpen">
|
||||
<arg name="wallet" type="s" direction="in"/>
|
||||
<arg name="passwordHash" type="ay" direction="in"/>
|
||||
<arg name="sessionTimeout" type="i" direction="in"/>
|
||||
<annotation name="org.freedesktop.DBus.Method.NoReply" value="true"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
17
ext/qtkeychain/qkeychain_export.h
Normal file
17
ext/qtkeychain/qkeychain_export.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef QKEYCHAIN_EXPORT_H
|
||||
#define QKEYCHAIN_EXPORT_H
|
||||
|
||||
#include <qglobal.h>
|
||||
|
||||
# ifdef QKEYCHAIN_STATICLIB
|
||||
# undef QKEYCHAIN_SHAREDLIB
|
||||
# define QKEYCHAIN_EXPORT
|
||||
# else
|
||||
# ifdef QKEYCHAIN_BUILD_QKEYCHAIN_LIB
|
||||
# define QKEYCHAIN_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define QKEYCHAIN_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#endif
|
98
ext/qtkeychain/testclient.cpp
Normal file
98
ext/qtkeychain/testclient.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> *
|
||||
* *
|
||||
* 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. For licensing and distribution *
|
||||
* details, check the accompanying file 'COPYING'. *
|
||||
*****************************************************************************/
|
||||
#include <QCoreApplication>
|
||||
#include <QStringList>
|
||||
|
||||
#include "keychain.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace QKeychain;
|
||||
|
||||
static int printUsage() {
|
||||
std::cerr << "testclient store <account> <password>" << std::endl;
|
||||
std::cerr << "testclient restore <account>" << std::endl;
|
||||
std::cerr << "testclient delete <account>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main( int argc, char** argv ) {
|
||||
QCoreApplication app( argc, argv );
|
||||
const QStringList args = app.arguments();
|
||||
if ( args.count() < 2 )
|
||||
return printUsage();
|
||||
|
||||
QStringList::ConstIterator it = args.constBegin();
|
||||
++it;
|
||||
|
||||
if ( *it == QLatin1String("store") ) {
|
||||
if ( ++it == args.constEnd() )
|
||||
return printUsage();
|
||||
const QString acc = *it;
|
||||
if ( ++it == args.constEnd() )
|
||||
return printUsage();
|
||||
const QString pass = *it;
|
||||
if ( ++it != args.constEnd() )
|
||||
return printUsage();
|
||||
WritePasswordJob job( QLatin1String("qtkeychain-testclient") );
|
||||
job.setAutoDelete( false );
|
||||
job.setKey( acc );
|
||||
job.setTextData( pass );
|
||||
QEventLoop loop;
|
||||
job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) );
|
||||
job.start();
|
||||
loop.exec();
|
||||
if ( job.error() ) {
|
||||
std::cerr << "Storing password failed: " << qPrintable(job.errorString()) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::cout << "Password stored successfully" << std::endl;
|
||||
} else if ( *it == QLatin1String("restore") ) {
|
||||
if ( ++it == args.constEnd() )
|
||||
return printUsage();
|
||||
const QString acc = *it;
|
||||
if ( ++it != args.constEnd() )
|
||||
return printUsage();
|
||||
ReadPasswordJob job( QLatin1String("qtkeychain-testclient") );
|
||||
job.setAutoDelete( false );
|
||||
job.setKey( acc );
|
||||
QEventLoop loop;
|
||||
job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) );
|
||||
job.start();
|
||||
loop.exec();
|
||||
|
||||
const QString pw = job.textData();
|
||||
if ( job.error() ) {
|
||||
std::cerr << "Restoring password failed: " << qPrintable(job.errorString()) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::cout << qPrintable(pw) << std::endl;
|
||||
} else if ( *it == QLatin1String("delete") ) {
|
||||
if ( ++it == args.constEnd() )
|
||||
return printUsage();
|
||||
const QString acc = *it;
|
||||
if ( ++it != args.constEnd() )
|
||||
return printUsage();
|
||||
DeletePasswordJob job( QLatin1String("qtkeychain-testclient") );
|
||||
job.setAutoDelete( false );
|
||||
job.setKey( acc );
|
||||
QEventLoop loop;
|
||||
job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) );
|
||||
job.start();
|
||||
loop.exec();
|
||||
|
||||
if ( job.error() ) {
|
||||
std::cerr << "Deleting password failed: " << qPrintable(job.errorString()) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::cout << "Password deleted successfully" << std::endl;
|
||||
} else {
|
||||
return printUsage();
|
||||
}
|
||||
}
|
||||
|
177
ext/qtkeychain/translations/qtkeychain_de.ts
Normal file
177
ext/qtkeychain/translations/qtkeychain_de.ts
Normal file
@ -0,0 +1,177 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="de_DE">
|
||||
<context>
|
||||
<name>QKeychain::ReadPasswordJobPrivate</name>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="140"/>
|
||||
<source>Unknown error</source>
|
||||
<translation>Unbekannter Fehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="129"/>
|
||||
<source>D-Bus is not running</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="222"/>
|
||||
<source>No keychain service available</source>
|
||||
<translation>Kein Schlüsselbund-Dienst verfügbar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="224"/>
|
||||
<source>Could not open wallet: %1; %2</source>
|
||||
<translation>Konnte Brieftasche nicht öffnen: %1; %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="270"/>
|
||||
<source>Access to keychain denied</source>
|
||||
<translation>Zugriff auf Schlüsselbund verweigert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="291"/>
|
||||
<source>Could not determine data type: %1; %2</source>
|
||||
<translation>Datentyp kann nicht ermittelt werden: %1: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="309"/>
|
||||
<source>Unsupported entry type 'Map'</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="312"/>
|
||||
<source>Unknown kwallet entry type '%1'</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="327"/>
|
||||
<source>Could not read password: %1; %2</source>
|
||||
<translation>Passwort konnte nicht ausgelesen werden: %1; %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_mac.cpp" line="76"/>
|
||||
<source>Password not found</source>
|
||||
<translation>Passwort nicht gefunden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="300"/>
|
||||
<location filename="../keychain_win.cpp" line="27"/>
|
||||
<source>Entry not found</source>
|
||||
<translation>Eintrag nicht gefunden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="44"/>
|
||||
<source>Could not decrypt data</source>
|
||||
<translation>Kann Daten nicht entschlüsseln</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QKeychain::WritePasswordJobPrivate</name>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="364"/>
|
||||
<location filename="../keychain_unix.cpp" line="372"/>
|
||||
<source>Unknown error</source>
|
||||
<translation>Unbekannter Fehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="352"/>
|
||||
<source>D-Bus is not running</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="420"/>
|
||||
<location filename="../keychain_unix.cpp" line="505"/>
|
||||
<source>Could not open wallet: %1; %2</source>
|
||||
<translation>Konnte Brieftasche nicht öffnen: %1; %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="483"/>
|
||||
<source>Access to keychain denied</source>
|
||||
<translation>Zugriff auf Schlüsselbund verweigert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="64"/>
|
||||
<source>Could not delete encrypted data from settings: access error</source>
|
||||
<translation>Kann verschlüsselte Daten nicht aus den Einstellungen entfernen: Zugriffsfehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="65"/>
|
||||
<source>Could not delete encrypted data from settings: format error</source>
|
||||
<translation>Kann verschlüsselte Daten nicht aus den Einstellungen entfernen: Formatfehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="85"/>
|
||||
<source>Encryption failed</source>
|
||||
<translation>Verschlüsselung fehlgeschlagen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="100"/>
|
||||
<source>Could not store encrypted data in settings: access error</source>
|
||||
<translation>Kann verschlüsselte Daten nicht in den Einstellungen speichern: Zugriffsfehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="101"/>
|
||||
<source>Could not store encrypted data in settings: format error</source>
|
||||
<translation>Kann verschlüsselte Daten nicht in den Einstellungen speichern: Formatfehler</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="167"/>
|
||||
<source>Access to keychain denied</source>
|
||||
<translation>Zugriff auf Schlüsselbund verweigert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="169"/>
|
||||
<source>No keyring daemon</source>
|
||||
<translation>Kein Schlüsselbund-Dienst </translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="171"/>
|
||||
<source>Already unlocked</source>
|
||||
<translation>Bereits entsperrt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="173"/>
|
||||
<source>No such keyring</source>
|
||||
<translation>Kein solcher Schlüsselbund</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="175"/>
|
||||
<source>Bad arguments</source>
|
||||
<translation>Ungültige Argumente</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="177"/>
|
||||
<source>I/O error</source>
|
||||
<translation>Ein-/Ausgabe-Fehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="179"/>
|
||||
<source>Cancelled</source>
|
||||
<translation>Abgebrochen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="181"/>
|
||||
<source>Keyring already exists</source>
|
||||
<translation>Schlüsselbund existiert bereits</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="183"/>
|
||||
<source>No match</source>
|
||||
<translation>Kein Treffer</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="188"/>
|
||||
<source>Unknown error</source>
|
||||
<translation>Unbekannter Fehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_mac.cpp" line="31"/>
|
||||
<location filename="../keychain_mac.cpp" line="33"/>
|
||||
<source>%1 (OSStatus %2)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
178
ext/qtkeychain/translations/qtkeychain_ro.ts
Normal file
178
ext/qtkeychain/translations/qtkeychain_ro.ts
Normal file
@ -0,0 +1,178 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1" language="ro_RO">
|
||||
<context>
|
||||
<name>QKeychain::ReadPasswordJobPrivate</name>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="140"/>
|
||||
<source>Unknown error</source>
|
||||
<translation>Eroare necunoscută</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="129"/>
|
||||
<source>D-Bus is not running</source>
|
||||
<translation>D-Bus nu rulează</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="222"/>
|
||||
<source>No keychain service available</source>
|
||||
<translatorcomment>Nu există niciun serviciu de chei disponibil</translatorcomment>
|
||||
<translation>Kein Schlüsselbund-Dienst verfügbar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="224"/>
|
||||
<source>Could not open wallet: %1; %2</source>
|
||||
<translation>Nu se poate deschide portofelul: %1; %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="270"/>
|
||||
<source>Access to keychain denied</source>
|
||||
<translation>Acces interzis la serviciul de chei</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="291"/>
|
||||
<source>Could not determine data type: %1; %2</source>
|
||||
<translation>Nu se poate stabili tipul de date: %1: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="309"/>
|
||||
<source>Unsupported entry type 'Map'</source>
|
||||
<translation>Tip de înregistrare nesuportat 'Map'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="312"/>
|
||||
<source>Unknown kwallet entry type '%1'</source>
|
||||
<translation>Tip de înregistrare kwallet necunoscut '%1'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="327"/>
|
||||
<source>Could not read password: %1; %2</source>
|
||||
<translation>Nu se poate citi parola: %1; %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_mac.cpp" line="76"/>
|
||||
<source>Password not found</source>
|
||||
<translation>Parola nu a fost găsită</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="300"/>
|
||||
<location filename="../keychain_win.cpp" line="27"/>
|
||||
<source>Entry not found</source>
|
||||
<translation>Înregistrarea nu a fost găsită</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="44"/>
|
||||
<source>Could not decrypt data</source>
|
||||
<translation>Nu se poate decripta data</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QKeychain::WritePasswordJobPrivate</name>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="364"/>
|
||||
<location filename="../keychain_unix.cpp" line="372"/>
|
||||
<source>Unknown error</source>
|
||||
<translation>Eroare necunoscută</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="352"/>
|
||||
<source>D-Bus is not running</source>
|
||||
<translation>D-Bus nu rulează</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="420"/>
|
||||
<location filename="../keychain_unix.cpp" line="505"/>
|
||||
<source>Could not open wallet: %1; %2</source>
|
||||
<translation>Nu se poate deschide portofelul: %1; %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="483"/>
|
||||
<source>Access to keychain denied</source>
|
||||
<translation>Acces interzis la serviciul de chei</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="64"/>
|
||||
<source>Could not delete encrypted data from settings: access error</source>
|
||||
<translation>Nu se pot șterge datele criptate din setări: eroare de acces</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="65"/>
|
||||
<source>Could not delete encrypted data from settings: format error</source>
|
||||
<translation>Nu se pot șterge datele criptate din setări: eroare de format</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="85"/>
|
||||
<source>Encryption failed</source>
|
||||
<translation>Criptarea a eșuat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="100"/>
|
||||
<source>Could not store encrypted data in settings: access error</source>
|
||||
<translation>Nu se pot stoca datele criptate în setări: eroare de acces</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_win.cpp" line="101"/>
|
||||
<source>Could not store encrypted data in settings: format error</source>
|
||||
<translation>Nu se pot stoca datele criptate în setări: eroare de format</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>QObject</name>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="167"/>
|
||||
<source>Access to keychain denied</source>
|
||||
<translation>Acces interzis la serviciul de chei</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="169"/>
|
||||
<source>No keyring daemon</source>
|
||||
<translation>Niciun demon pentru inelul de chei</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="171"/>
|
||||
<source>Already unlocked</source>
|
||||
<translation>Deja deblocat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="173"/>
|
||||
<source>No such keyring</source>
|
||||
<translation>Nu există astfel de inel de chei</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="175"/>
|
||||
<source>Bad arguments</source>
|
||||
<translation>Argumente greșite</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="177"/>
|
||||
<source>I/O error</source>
|
||||
<translation>Eroare de I/E</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="179"/>
|
||||
<source>Cancelled</source>
|
||||
<translation>Anulat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="181"/>
|
||||
<source>Keyring already exists</source>
|
||||
<translation>Inelul de chei deja există</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="183"/>
|
||||
<source>No match</source>
|
||||
<translation>Nicio potrivire</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_unix.cpp" line="188"/>
|
||||
<source>Unknown error</source>
|
||||
<translation>Eroare necunoscută</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../keychain_mac.cpp" line="31"/>
|
||||
<location filename="../keychain_mac.cpp" line="33"/>
|
||||
<source>%1 (OSStatus %2)</source>
|
||||
<translation>%1 (OSStatus %2)</translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
31
fuel.pro
31
fuel.pro
@ -7,6 +7,10 @@ QT = core gui webkit
|
||||
contains(QT_VERSION, ^5\\..*) {
|
||||
QT += widgets webkitwidgets
|
||||
QT -= quick multimediawidgets opengl printsupport qml multimedia positioning sensors
|
||||
|
||||
unix:!macx {
|
||||
QT += dbus
|
||||
}
|
||||
}
|
||||
|
||||
TARGET = Fuel
|
||||
@ -92,6 +96,33 @@ FORMS += ui/MainWindow.ui \
|
||||
RESOURCES += \
|
||||
rsrc/resources.qrc
|
||||
|
||||
# QtKeychain
|
||||
SOURCES += ext/qtkeychain/keychain.cpp
|
||||
|
||||
HEADERS += ext/qtkeychain/keychain.h \
|
||||
ext/qtkeychain/keychain_p.h \
|
||||
ext/qtkeychain/qkeychain_export.h
|
||||
|
||||
unix:!macx {
|
||||
SOURCES += ext/qtkeychain/keychain_unix.cpp \
|
||||
ext/qtkeychain/gnomekeyring.cpp
|
||||
|
||||
HEADERS += ext/qtkeychain/gnomekeyring_p.h
|
||||
|
||||
DBUS_INTERFACES += ext/qtkeychain/org.kde.KWallet.xml
|
||||
}
|
||||
|
||||
macx {
|
||||
SOURCES += ext/qtkeychain/keychain_mac.cpp
|
||||
}
|
||||
|
||||
win32 {
|
||||
SOURCES += ext/qtkeychain/keychain_win.cpp
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
CODECFORTR = UTF-8
|
||||
|
||||
TRANSLATIONS += \
|
||||
|
45
manifest
45
manifest
@ -1,5 +1,5 @@
|
||||
C Initial\swork\son\sremote\smanagement
|
||||
D 2015-05-25T12:27:27.983
|
||||
C Implemented\sremote\scredential\sstorage\svia\sqtkeychain\nImported\sqtkeychain
|
||||
D 2015-05-25T14:03:38.817
|
||||
F .travis.yml 77966888a81c4ceee1fcc79bce842c9667ad8a35
|
||||
F debian/changelog eb4304dfcb6bb66850ec740838090eb50ce1249b
|
||||
F debian/compat b6abd567fa79cbe0196d093a067271361dc6ca8b
|
||||
@ -15,7 +15,29 @@ F dist/win/fuel.iss ef3558dbba409eb194938b930377fc9ee27d319e
|
||||
F doc/Building.txt 17b43fa23da764b5d1b828cc48c5a95e612bbd8f
|
||||
F doc/Changes.txt b03302545e4a6c0b16a30d623a7627f8aef65ef6
|
||||
F doc/License.txt 4cc77b90af91e615a64ae04893fdffa7939db84c
|
||||
F fuel.pro 641f62716fc90c9430f5c4cbc415c9d63f833a52
|
||||
F ext/qtkeychain/CMakeLists.txt fc1afa05034f2765ba243ce758a7e9d6b6efe2d6
|
||||
F ext/qtkeychain/COPYING d0f83c8198fdd5464d2373015b7b64ce7cae607e
|
||||
F ext/qtkeychain/ChangeLog 1703279e17036995806ba1719033d14840a8a7e2
|
||||
F ext/qtkeychain/QtKeychainBuildTreeSettings.cmake.in a50c3b646181124f15b946c3297f13012e959341
|
||||
F ext/qtkeychain/QtKeychainConfig.cmake.in ac7c87e54854a06c51e00f833f21f8323d1e6884
|
||||
F ext/qtkeychain/QtKeychainConfigVersion.cmake.in 3b650037d5775f28802c0471afe2cf6dbe51084e
|
||||
F ext/qtkeychain/ReadMe.markdown 65fe7f400600aa98a9a7fa5c3fc842ad8699cc43
|
||||
F ext/qtkeychain/ReadMe.txt 65fe7f400600aa98a9a7fa5c3fc842ad8699cc43
|
||||
F ext/qtkeychain/cmake/Modules/GNUInstallDirs.cmake 7a2ccf81f25546e93a6f48c792cdebaae51857e9
|
||||
F ext/qtkeychain/gnomekeyring.cpp 7fa97bd4ffb7c9df00d25e56cd9173d34109afe6
|
||||
F ext/qtkeychain/gnomekeyring_p.h 7f6acaf6d00b36bd08f5f31ba9136efa969e9875
|
||||
F ext/qtkeychain/keychain.cpp 427cbda7c6a76de995b1f1b4caa700cd06a9d19a
|
||||
F ext/qtkeychain/keychain.h f084c671b481af6ac7ce00bf641055a3cfc9cf9b
|
||||
F ext/qtkeychain/keychain_mac.cpp a028f6fc5e40f9ab88c94ebe30b8b0ae417f2f34
|
||||
F ext/qtkeychain/keychain_p.h 36f4caee2cbdbde971a1105ab388681ad2924665
|
||||
F ext/qtkeychain/keychain_unix.cpp 8e657da9acd9e86b2fdec19dc40f1afa4a1c5191
|
||||
F ext/qtkeychain/keychain_win.cpp e52877828703650219c1c674e618c7211f588d0d
|
||||
F ext/qtkeychain/org.kde.KWallet.xml f3729fda9f8fa8031a6f69415dcc29455c3c9ae6
|
||||
F ext/qtkeychain/qkeychain_export.h d756528188ef9bf3c4461ecc80048f06c362b54b
|
||||
F ext/qtkeychain/testclient.cpp cb1290a9584b627306a7bfdf1c02a8bbae503f5f
|
||||
F ext/qtkeychain/translations/qtkeychain_de.ts 0a70c8205c066c30ed8172f0670942de1fc5eede
|
||||
F ext/qtkeychain/translations/qtkeychain_ro.ts f16939382fd1a047b0692426bc82847347f14b32
|
||||
F fuel.pro 0522a3f57fa34122d47ccd0a62bf14aeb1caeb03
|
||||
F intl/convert.bat 4222ae403418381452b843929d15259ea9850ab1 x
|
||||
F intl/convert.sh 2ca2179ff53e727f241925b75e19182607883c45 x
|
||||
F intl/de_DE.ts e2faceab920ac60c97bbc6fba038e261d51fc741
|
||||
@ -202,9 +224,9 @@ F src/FslSettingsDialog.cpp f5a34a70ecb0560d2b6eea6bf27e42048548aedd
|
||||
F src/FslSettingsDialog.h dfe2a61884a55a74cbb9206b6f6b482b979725e7
|
||||
F src/LoggedProcess.cpp 2a1e5c94bc1e57c8984563e66c210e43a14dc60c
|
||||
F src/LoggedProcess.h 85df7c635c807a5a0e8c4763f17a0752aaff7261
|
||||
F src/MainWindow.cpp 717ccd4c91127a08d8cc71d46d8df1a40db62146
|
||||
F src/MainWindow.cpp 2bfafff682c13a9176b4f4200c54c2c5c55b8ae8
|
||||
F src/MainWindow.h 6cb82a4fc337793a339ffef4728e6d30b7b74305
|
||||
F src/RemoteDialog.cpp f0ee2d05e6d6c079f2a00bb551431407eb9d783d
|
||||
F src/RemoteDialog.cpp 03a6cf213d6dde68ee0ceb8d122e05da2d491724
|
||||
F src/RemoteDialog.h 364e867210ec55d8d6d23d0c8078f2517b2389ec
|
||||
F src/RevisionDialog.cpp 51065c65a07c118dd1a7363da4a55a135d1c6c9c
|
||||
F src/RevisionDialog.h b718c3009342eaabad39c8a11a253a4e4fef7a73
|
||||
@ -214,8 +236,8 @@ F src/Settings.cpp 6ab826273b9693bfcd65f0f59b550ae2aa3577f1
|
||||
F src/Settings.h 1ff8bb71e19949150e8caa4f5e5f13f8810e496b
|
||||
F src/SettingsDialog.cpp 25be4c351dd21ea9132321944f42dc0bc22fb128
|
||||
F src/SettingsDialog.h b324dfd77ca3ad24fd83588aaf79a7e4c291e716
|
||||
F src/Utils.cpp c48e3316f3a0a5d735e8d4953710500358985e32
|
||||
F src/Utils.h c2a28611bd77fb35ea3dcf65fb60ed585f68aa3c
|
||||
F src/Utils.cpp abfd679b8a4a320207abe385b8f3a4af8f646a55
|
||||
F src/Utils.h c293175ea08801aa4f0513bf2820213f8958f704
|
||||
F src/Workspace.cpp f68a4ca05d1b7c5c345fbd89527691813593c663
|
||||
F src/Workspace.h d6649a3ae1cd0fbad55237030313e85530417271
|
||||
F src/main.cpp d8c65ea5e54102e4989fef9fd8cfd4f13ef8a8f0
|
||||
@ -230,10 +252,7 @@ F ui/MainWindow.ui 72d363caef1a9ce0484509cdf3e5f924af363381
|
||||
F ui/RemoteDialog.ui aa738503e4f6625ed8d7cc46169a319a39b0e575
|
||||
F ui/RevisionDialog.ui 27c3b98c665fec014a50cbf3352c0627f75e68cd
|
||||
F ui/SettingsDialog.ui 4c480cd595a32664d01c85bf74845c4282fc0068
|
||||
P 7ebac37b3255e6721889c070b7327a96c63b6c97
|
||||
R 70bbd6d1fd63555631752f47198d7051
|
||||
T *branch * remote-management
|
||||
T *sym-remote-management *
|
||||
T -sym-new-workspace *
|
||||
P 13d3a5222dfe24a33a72efffff0ecb0b5bfefe73
|
||||
R 9e773ad6f2945f8bd613b0b9f6e23acf
|
||||
U kostas
|
||||
Z a9dba47682969d430cd680d884c75123
|
||||
Z 96c30d4c2ad3ef32f51d03d388cfc133
|
||||
|
@ -1 +1 @@
|
||||
13d3a5222dfe24a33a72efffff0ecb0b5bfefe73
|
||||
7c068aa8acdae1b86dee004d2d4cd7fb42904186
|
@ -2505,12 +2505,18 @@ void MainWindow::on_actionEditRemote_triggered()
|
||||
{
|
||||
QStringList remotes;
|
||||
getSelectionRemotes(remotes);
|
||||
|
||||
if(remotes.empty())
|
||||
return;
|
||||
|
||||
QUrl url(remotes.first());
|
||||
bool exists = KeychainGet(this, url);
|
||||
|
||||
if(!RemoteDialog::run(this, url))
|
||||
return;
|
||||
|
||||
if(exists)
|
||||
KeychainDelete(this, url);
|
||||
|
||||
if(!KeychainSet(this, url))
|
||||
QMessageBox::critical(this, tr("Error"), tr("Could not store information to keychain."), QMessageBox::Ok );
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ bool RemoteDialog::run(QWidget *parent, QUrl &url)
|
||||
// Set URL components
|
||||
if(!url.isEmpty())
|
||||
{
|
||||
QString qq = url.toString(QUrl::PrettyDecoded|QUrl::RemoveUserInfo);
|
||||
dlg.ui->lineURL->setText(qq);
|
||||
QString url_no_credentials = url.toString(QUrl::PrettyDecoded|QUrl::RemoveUserInfo);
|
||||
dlg.ui->lineURL->setText(url_no_credentials);
|
||||
dlg.ui->lineUserName->setText(url.userName());
|
||||
dlg.ui->linePassword->setText(url.password());
|
||||
}
|
||||
|
@ -2,6 +2,9 @@
|
||||
#include <QMessageBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFileDialog>
|
||||
#include <QEventLoop>
|
||||
#include "ext/qtkeychain/keychain.h"
|
||||
#define KEYCHAIN_ROOT "Fuel-SCM"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
QMessageBox::StandardButton DialogQuery(QWidget *parent, const QString &title, const QString &query, QMessageBox::StandardButtons buttons)
|
||||
@ -388,4 +391,56 @@ void BuildNameToModelIndex(name_modelindex_map_t &map, const QStandardItemModel
|
||||
Q_ASSERT(item);
|
||||
BuildNameToModelIndex(map, *item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool KeychainSet(QObject *parent, const QUrl &url)
|
||||
{
|
||||
QEventLoop loop(parent);
|
||||
QKeychain::WritePasswordJob job(url.toString(QUrl::PrettyDecoded|QUrl::RemoveUserInfo));
|
||||
job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) );
|
||||
job.setAutoDelete( false );
|
||||
job.setInsecureFallback(false);
|
||||
job.setKey(url.userName());
|
||||
job.setTextData(url.password());
|
||||
job.start();
|
||||
loop.exec();
|
||||
return job.error() == QKeychain::NoError;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool KeychainGet(QObject *parent, QUrl &url)
|
||||
{
|
||||
QEventLoop loop(parent);
|
||||
QKeychain::ReadPasswordJob job(url.toString(QUrl::PrettyDecoded|QUrl::RemoveUserInfo));
|
||||
job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()));
|
||||
job.setAutoDelete( false );
|
||||
job.setInsecureFallback(false);
|
||||
job.setAutoDelete( false );
|
||||
job.setKey(url.userName());
|
||||
job.start();
|
||||
loop.exec();
|
||||
|
||||
if(job.error() != QKeychain::NoError)
|
||||
return false;
|
||||
|
||||
url.setUserName(job.key());
|
||||
url.setPassword(job.textData());
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool KeychainDelete(QObject* parent, const QUrl& url)
|
||||
{
|
||||
QEventLoop loop(parent);
|
||||
QKeychain::DeletePasswordJob job(url.toString(QUrl::PrettyDecoded|QUrl::RemoveUserInfo));
|
||||
job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()));
|
||||
job.setAutoDelete( false );
|
||||
job.setInsecureFallback(false);
|
||||
job.setAutoDelete( false );
|
||||
job.setKey(url.userName());
|
||||
job.start();
|
||||
loop.exec();
|
||||
|
||||
return job.error() == QKeychain::NoError;
|
||||
}
|
||||
|
@ -22,6 +22,9 @@ typedef QMap<QString, QModelIndex> name_modelindex_map_t;
|
||||
void GetStandardItemTextRecursive(QString &name, const QStandardItem &item, const QChar &separator='/');
|
||||
void BuildNameToModelIndex(name_modelindex_map_t &map, const QStandardItem &item);
|
||||
void BuildNameToModelIndex(name_modelindex_map_t &map, const QStandardItemModel &model);
|
||||
bool KeychainSet(QObject* parent, const QUrl& url);
|
||||
bool KeychainGet(QObject* parent, QUrl& url);
|
||||
bool KeychainDelete(QObject* parent, const QUrl& url);
|
||||
|
||||
|
||||
typedef QMap<QString, QString> QStringMap;
|
||||
|
Loading…
x
Reference in New Issue
Block a user