🔨 Use system qtkeychain instead of vendoring it
This commit is contained in:
parent
4b91df5f81
commit
f34ec61276
59
.github/workflows/build.yml
vendored
59
.github/workflows/build.yml
vendored
@ -7,30 +7,31 @@ jobs:
|
|||||||
build-msvc:
|
build-msvc:
|
||||||
name: Build Windows
|
name: Build Windows
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
env:
|
|
||||||
BUILD_TOOLS_PATH: C:\apps\build-tools\
|
|
||||||
steps:
|
steps:
|
||||||
- run: echo $env:BUILD_TOOLS_PATH | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
- name: Add Conan to path
|
||||||
|
run: echo "C:\Program Files\Conan\conan\" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
|
||||||
- uses: actions/checkout@v2.3.4
|
- uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Install JOM
|
- name: Install deps
|
||||||
shell: cmake -P {0}
|
run: choco install jom conan -y
|
||||||
run: |
|
|
||||||
file(MAKE_DIRECTORY $ENV{BUILD_TOOLS_PATH})
|
|
||||||
file(DOWNLOAD http://prdownloads.sourceforge.net/rigs-of-rods/build-tools.zip "$ENV{TMP}/build-tools.zip" SHOW_PROGRESS)
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xzf "$ENV{TMP}/build-tools.zip" WORKING_DIRECTORY "$ENV{BUILD_TOOLS_PATH}")
|
|
||||||
|
|
||||||
- name: Enable Developer Command Prompt
|
- name: Enable Developer Command Prompt
|
||||||
uses: ilammy/msvc-dev-cmd@v1.9.0
|
uses: ilammy/msvc-dev-cmd@v1.9.0
|
||||||
|
|
||||||
|
- name: Cache conan packages
|
||||||
|
uses: actions/cache@v2.1.6
|
||||||
|
with:
|
||||||
|
key: win-conan-${{ hashFiles('**/conanfile.txt') }}
|
||||||
|
path: ~/.conan/
|
||||||
|
|
||||||
- name: Cache Qt
|
- name: Cache Qt
|
||||||
id: cache-qt
|
id: cache-qt
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.6
|
||||||
with:
|
with:
|
||||||
path: ../Qt
|
path: '${{ github.workspace }}/qt/'
|
||||||
key: ${{ runner.os }}-QtCache
|
key: ${{ runner.os }}-QtCache
|
||||||
|
|
||||||
- name: Install Qt
|
- name: Install Qt
|
||||||
@ -38,15 +39,33 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
||||||
modules: qtwebengine
|
modules: qtwebengine
|
||||||
|
dir: '${{ github.workspace }}/qt/'
|
||||||
|
|
||||||
|
- name: Export qtkeychain
|
||||||
|
run: |
|
||||||
|
conan export recipes/qtkeychain
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake -G"NMake Makefiles JOM" ..
|
conan install .. --build=missing
|
||||||
|
cmake -G"NMake Makefiles JOM" -DCMAKE_INSTALL_PREFIX=redist ..
|
||||||
jom
|
jom
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: |
|
||||||
|
cd build
|
||||||
|
jom install
|
||||||
|
shell: cmd
|
||||||
|
|
||||||
|
- name: Upload redist folder
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: fuel-win
|
||||||
|
path: build/redist
|
||||||
|
|
||||||
build-gcc:
|
build-gcc:
|
||||||
name: Build Linux
|
name: Build Linux
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -55,23 +74,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Cache Qt
|
- name: Install qt
|
||||||
id: cache-qt
|
run: |
|
||||||
uses: actions/cache@v2.1.6
|
sudo apt-get update
|
||||||
with:
|
sudo apt-get install qt5keychain-dev qtwebengine5-dev -y
|
||||||
path: ../Qt
|
|
||||||
key: ${{ runner.os }}-QtCache
|
|
||||||
|
|
||||||
- name: Install Qt
|
|
||||||
uses: jurplel/install-qt-action@v2
|
|
||||||
with:
|
|
||||||
cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
|
||||||
modules: qtwebengine
|
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||||
make -j8
|
make -j4
|
||||||
shell: bash
|
shell: bash
|
@ -1,5 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
cmake_policy(SET CMP0087 NEW)
|
cmake_policy(SET CMP0087 NEW)
|
||||||
|
set(CMAKE_MODULE_PATH "${CMAKE_BINARY_DIR}" ${CMAKE_MODULE_PATH})
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
|
|
||||||
# Setup paths
|
# Setup paths
|
||||||
@ -24,6 +25,7 @@ set(CMAKE_AUTOUIC ON)
|
|||||||
set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_SOURCE_DIR}/ui")
|
set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_SOURCE_DIR}/ui")
|
||||||
|
|
||||||
find_package(Qt5 COMPONENTS Core Gui WebEngineWidgets REQUIRED)
|
find_package(Qt5 COMPONENTS Core Gui WebEngineWidgets REQUIRED)
|
||||||
|
find_package(Qt5Keychain REQUIRED)
|
||||||
|
|
||||||
set(FORMS
|
set(FORMS
|
||||||
ui/MainWindow.ui
|
ui/MainWindow.ui
|
||||||
@ -118,8 +120,6 @@ elseif (APPLE)
|
|||||||
list(APPEND SOURCES "${CMAKE_SOURCE_DIR}/rsrc/icons/fuel.icns")
|
list(APPEND SOURCES "${CMAKE_SOURCE_DIR}/rsrc/icons/fuel.icns")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_subdirectory("${CMAKE_SOURCE_DIR}/ext/qtkeychain" EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
${PROJECT_NAME}
|
${PROJECT_NAME}
|
||||||
${FORMS}
|
${FORMS}
|
||||||
@ -135,7 +135,14 @@ target_include_directories(
|
|||||||
${CMAKE_SOURCE_DIR}/src/
|
${CMAKE_SOURCE_DIR}/src/
|
||||||
|
|
||||||
)
|
)
|
||||||
target_link_libraries(${PROJECT_NAME} Qt5::Widgets Qt5::WebEngineCore Qt5::WebEngineWidgets qt5keychain)
|
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets Qt5::WebEngineCore Qt5::WebEngineWidgets)
|
||||||
|
if (TARGET Qt5Keychain::Qt5Keychain)
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5Keychain::Qt5Keychain)
|
||||||
|
else ()
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE qt5keychain)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE FUEL_VERSION="${PROJECT_VERSION}")
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------------------------#
|
# ------------------------------------------------------------------------------------------------#
|
||||||
# Cpack
|
# Cpack
|
||||||
@ -157,9 +164,15 @@ if (WIN32)
|
|||||||
get_target_property(Qt5_Core_Location Qt5::Core LOCATION)
|
get_target_property(Qt5_Core_Location Qt5::Core LOCATION)
|
||||||
get_filename_component(QT_BIN_DIR ${Qt5_Core_Location} DIRECTORY)
|
get_filename_component(QT_BIN_DIR ${Qt5_Core_Location} DIRECTORY)
|
||||||
|
|
||||||
|
# Fix for windeployqt not being able to find qt5keychain
|
||||||
|
if (EXISTS ${RUNTIME_OUTPUT_DIRECTORY}/qt5keychain.dll AND NOT EXISTS ${QT_BIN_DIR}/qt5keychain.dll)
|
||||||
|
message("Copying ${RUNTIME_OUTPUT_DIRECTORY}/qt5keychain.dll to ${QT_BIN_DIR}")
|
||||||
|
file(COPY ${RUNTIME_OUTPUT_DIRECTORY}/qt5keychain.dll DESTINATION ${QT_BIN_DIR})
|
||||||
|
endif ()
|
||||||
|
|
||||||
add_custom_target(
|
add_custom_target(
|
||||||
copy_dll
|
copy_dll
|
||||||
COMMAND ${QT_BIN_DIR}/windeployqt.exe $<TARGET_FILE:${PROJECT_NAME}> --release --no-compiler-runtime --no-translations --no-opengl-sw
|
COMMAND ${QT_BIN_DIR}/windeployqt.exe $<TARGET_FILE:${PROJECT_NAME}> --release --no-compiler-runtime --no-opengl-sw
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -168,7 +181,7 @@ if (WIN32)
|
|||||||
RUNTIME DESTINATION .
|
RUNTIME DESTINATION .
|
||||||
)
|
)
|
||||||
|
|
||||||
install(CODE "execute_process(COMMAND ${QT_BIN_DIR}/windeployqt.exe $<TARGET_FILE:${PROJECT_NAME}> --release --no-compiler-runtime --no-translations --no-opengl-sw --dir \${CMAKE_INSTALL_PREFIX})")
|
install(CODE "execute_process(COMMAND ${QT_BIN_DIR}/windeployqt.exe $<TARGET_FILE:${PROJECT_NAME}> --release --no-opengl-sw --dir \${CMAKE_INSTALL_PREFIX})")
|
||||||
|
|
||||||
# For Windows Desktop shortcuts
|
# For Windows Desktop shortcuts
|
||||||
set(CPACK_CREATE_DESKTOP_LINKS "${PROJECT_NAME}" "${PROJECT_NAME}")
|
set(CPACK_CREATE_DESKTOP_LINKS "${PROJECT_NAME}" "${PROJECT_NAME}")
|
||||||
@ -182,7 +195,7 @@ if (WIN32)
|
|||||||
set(CPACK_WIX_PRODUCT_ICON "${CMAKE_SOURCE_DIR}/rsrc/icons/fuel.ico")
|
set(CPACK_WIX_PRODUCT_ICON "${CMAKE_SOURCE_DIR}/rsrc/icons/fuel.ico")
|
||||||
|
|
||||||
set(CPACK_WIX_LICENSE_RTF "${CPACK_RESOURCE_FILE_LICENSE}")
|
set(CPACK_WIX_LICENSE_RTF "${CPACK_RESOURCE_FILE_LICENSE}")
|
||||||
set(CPACK_WIX_UPGRADE_GUID "f33967d1-0bdd-4a4b-ba1a-d859bce8927a")
|
set(CPACK_WIX_UPGRADE_GUID "462522bf-36e4-4ce9-93e1-a4200f23096e")
|
||||||
|
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}")
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${PROJECT_NAME}")
|
||||||
set(CPACK_GENERATOR ${CPACK_GENERATOR};WIX)
|
set(CPACK_GENERATOR ${CPACK_GENERATOR};WIX)
|
||||||
|
11
conanfile.txt
Normal file
11
conanfile.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[requires]
|
||||||
|
qtkeychain/0.12.0
|
||||||
|
|
||||||
|
[generators]
|
||||||
|
qmake
|
||||||
|
cmake_find_package
|
||||||
|
|
||||||
|
[imports]
|
||||||
|
bin, *.dll -> ./bin @ keep_path=False
|
||||||
|
share, *.qm -> ./bin/translations @ keep_path=False
|
||||||
|
lib, *.so* -> ./bin @ keep_path=False
|
4
dist/arch/PKGBUILD
vendored
4
dist/arch/PKGBUILD
vendored
@ -1,6 +1,6 @@
|
|||||||
# Maintainer: Kostas Karanikolas <lastname[at]gmail[dot]com>
|
# Maintainer: Kostas Karanikolas <lastname[at]gmail[dot]com>
|
||||||
pkgname=fuel
|
pkgname=fuel
|
||||||
pkgver=1.0.0
|
pkgver=2.0.1
|
||||||
pkgrel=3
|
pkgrel=3
|
||||||
pkgdesc="A GUI front-end to Fossil SCM"
|
pkgdesc="A GUI front-end to Fossil SCM"
|
||||||
arch=(i686 x86_64)
|
arch=(i686 x86_64)
|
||||||
@ -16,7 +16,7 @@ build() {
|
|||||||
[ -d build ] && rm -r build
|
[ -d build ] && rm -r build
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
qmake-qt5 "${srcdir}/${pkgname}-${pkgver}/fuel.pro"
|
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||||
make
|
make
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
freebsd {
|
|
||||||
INCLUDEPATH += /usr/local/include/qt5keychain
|
|
||||||
LIBS += -lqt5keychain
|
|
||||||
} else {
|
|
||||||
unix:!android:!macx:!ios {
|
|
||||||
DEFINES += KEYCHAIN_DBUS
|
|
||||||
}
|
|
||||||
include(qtkeychain/qt5keychain.pri)
|
|
||||||
}
|
|
50
ext/qtkeychain/.gitignore
vendored
50
ext/qtkeychain/.gitignore
vendored
@ -1,50 +0,0 @@
|
|||||||
#CMake files
|
|
||||||
CMakeCache.txt
|
|
||||||
CMakeFiles
|
|
||||||
CMakeScripts
|
|
||||||
cmake_install.cmake
|
|
||||||
|
|
||||||
#Keychain temporary files
|
|
||||||
Qt5KeychainBuildTreeSettings.cmake
|
|
||||||
Qt5KeychainConfig.cmake
|
|
||||||
Qt5KeychainConfigVersion.cmake
|
|
||||||
QtKeychainBuildTreeSettings.cmake
|
|
||||||
QtKeychainConfig.cmake
|
|
||||||
QtKeychainConfigVersion.cmake
|
|
||||||
kwallet_interface.cpp
|
|
||||||
kwallet_interface.h
|
|
||||||
kwallet_interface.moc
|
|
||||||
moc_keychain.*
|
|
||||||
moc_keychain_p.*
|
|
||||||
moc_gnomekeyring_p.*
|
|
||||||
qkeychain_export.h
|
|
||||||
qt_Qt5Keychain.pri
|
|
||||||
|
|
||||||
#Qt files
|
|
||||||
*_parameters
|
|
||||||
*.qm
|
|
||||||
|
|
||||||
#General build files
|
|
||||||
Debug
|
|
||||||
Release
|
|
||||||
Makefile
|
|
||||||
|
|
||||||
#Linux build files
|
|
||||||
libqt5keychain.*
|
|
||||||
testclient
|
|
||||||
|
|
||||||
#Windows build files
|
|
||||||
install_manifest.txt
|
|
||||||
*.manifest
|
|
||||||
*.lib
|
|
||||||
*.exe
|
|
||||||
|
|
||||||
#Mac build files
|
|
||||||
qtkeychain.xcodeproj
|
|
||||||
qtkeychain.build
|
|
||||||
|
|
||||||
#Temporary files
|
|
||||||
*.sw?
|
|
||||||
*~
|
|
||||||
|
|
||||||
|
|
@ -1,307 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.3)
|
|
||||||
|
|
||||||
set(QTKEYCHAIN_VERSION 0.12.90)
|
|
||||||
set(QTKEYCHAIN_SOVERSION 1)
|
|
||||||
|
|
||||||
project(qtkeychain VERSION ${QTKEYCHAIN_VERSION} LANGUAGES CXX)
|
|
||||||
|
|
||||||
# Enable C++11
|
|
||||||
SET(CMAKE_CXX_STANDARD 11)
|
|
||||||
|
|
||||||
include(FindPkgConfig)
|
|
||||||
|
|
||||||
###
|
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${PROJECT_SOURCE_DIR}/cmake/Modules")
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
include(GenerateExportHeader)
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
include(ECMSetupVersion)
|
|
||||||
include(ECMGeneratePriFile)
|
|
||||||
|
|
||||||
option(BUILD_WITH_QT6 "Build qtkeychain with Qt 6" OFF)
|
|
||||||
option(BUILD_TEST_APPLICATION "Build test application" ON)
|
|
||||||
option(BUILD_TRANSLATIONS "Build translations" ON)
|
|
||||||
option(QTKEYCHAIN_STATIC "Build static library" OFF)
|
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL Android)
|
|
||||||
set(ANDROID 1)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL Haiku)
|
|
||||||
set(HAIKU 1)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
option(USE_CREDENTIAL_STORE "Build with windows CredentialStore support" ON)
|
|
||||||
|
|
||||||
if (USE_CREDENTIAL_STORE)
|
|
||||||
add_definitions(-DUSE_CREDENTIAL_STORE=1)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (NOT BUILD_WITH_QT6)
|
|
||||||
find_package(Qt5 COMPONENTS Core REQUIRED)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (Qt5Core_FOUND AND NOT BUILD_WITH_QT6)
|
|
||||||
set(QTKEYCHAIN_VERSION_INFIX 5)
|
|
||||||
|
|
||||||
if (ANDROID)
|
|
||||||
if (Qt5Core_VERSION VERSION_LESS 5.7)
|
|
||||||
find_package(Qt5 COMPONENTS Core REQUIRED Private)
|
|
||||||
include_directories(${Qt5Core_PRIVATE_INCLUDE_DIRS})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
find_package(Qt5 COMPONENTS AndroidExtras REQUIRED)
|
|
||||||
include_directories(${Qt5AndroidExtras_INCLUDE_DIRS})
|
|
||||||
set(QTANDROIDEXTRAS_LIBRARIES ${Qt5AndroidExtras_LIBRARIES})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU)
|
|
||||||
find_package(Qt5 COMPONENTS DBus REQUIRED)
|
|
||||||
include_directories(${Qt5DBus_INCLUDE_DIRS})
|
|
||||||
set(QTDBUS_LIBRARIES ${Qt5DBus_LIBRARIES})
|
|
||||||
macro(qt_add_dbus_interface)
|
|
||||||
qt5_add_dbus_interface(${ARGN})
|
|
||||||
endmacro()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (BUILD_TRANSLATIONS)
|
|
||||||
find_package(Qt5 COMPONENTS LinguistTools 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)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
macro(qt_wrap_cpp)
|
|
||||||
qt5_wrap_cpp(${ARGN})
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
set(QTCORE_LIBRARIES ${Qt5Core_LIBRARIES})
|
|
||||||
include_directories(${Qt5Core_INCLUDE_DIRS})
|
|
||||||
else ()
|
|
||||||
find_package(Qt6 COMPONENTS Core REQUIRED)
|
|
||||||
set(QTKEYCHAIN_VERSION_INFIX 6)
|
|
||||||
|
|
||||||
if (ANDROID)
|
|
||||||
find_package(Qt6 COMPONENTS AndroidExtras REQUIRED)
|
|
||||||
include_directories(${Qt6AndroidExtras_INCLUDE_DIRS})
|
|
||||||
set(QTANDROIDEXTRAS_LIBRARIES ${Qt6AndroidExtras_LIBRARIES})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU)
|
|
||||||
find_package(Qt6 COMPONENTS DBus REQUIRED)
|
|
||||||
include_directories(${Qt6DBus_INCLUDE_DIRS})
|
|
||||||
set(QTDBUS_LIBRARIES ${Qt6DBus_LIBRARIES})
|
|
||||||
macro(qt_add_dbus_interface)
|
|
||||||
qt6_add_dbus_interface(${ARGN})
|
|
||||||
endmacro()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (BUILD_TRANSLATIONS)
|
|
||||||
find_package(Qt6 COMPONENTS LinguistTools REQUIRED)
|
|
||||||
macro(qt_add_translation)
|
|
||||||
qt6_add_translation(${ARGN})
|
|
||||||
endmacro(qt_add_translation)
|
|
||||||
macro(qt_create_translation)
|
|
||||||
qt6_create_translation(${ARGN})
|
|
||||||
endmacro(qt_create_translation)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
macro(qt_wrap_cpp)
|
|
||||||
qt6_wrap_cpp(${ARGN})
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
set(QTCORE_LIBRARIES ${Qt6Core_LIBRARIES})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
||||||
list(APPEND qtkeychain_LIBRARIES ${QTCORE_LIBRARIES})
|
|
||||||
set(qtkeychain_SOURCES
|
|
||||||
keychain.cpp
|
|
||||||
qkeychain_export.h
|
|
||||||
keychain.h
|
|
||||||
)
|
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
|
||||||
# CMake < 3.15 sneaks in /W# flags for us, so we need a replacement,
|
|
||||||
# or we'll get a warning (cf. CMP0092)
|
|
||||||
if (CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
|
||||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
|
||||||
else ()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
|
||||||
endif ()
|
|
||||||
else ()
|
|
||||||
# MSVC's STL / Qt headers are not MSVC -Wall clean, so don't enable it there
|
|
||||||
add_definitions(-Wall)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
list(APPEND qtkeychain_SOURCES keychain_win.cpp)
|
|
||||||
if (NOT USE_CREDENTIAL_STORE)
|
|
||||||
list(APPEND qtkeychain_LIBRARIES crypt32)
|
|
||||||
list(APPEND qtkeychain_SOURCES plaintextstore.cpp)
|
|
||||||
endif ()
|
|
||||||
#FIXME: mingw bug; otherwise getting undefined refs to RtlSecureZeroMemory there
|
|
||||||
if (MINGW)
|
|
||||||
add_definitions(-O2)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (APPLE)
|
|
||||||
list(APPEND qtkeychain_SOURCES keychain_apple.mm)
|
|
||||||
list(APPEND qtkeychain_LIBRARIES "-framework Foundation" "-framework Security")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (HAIKU)
|
|
||||||
list(APPEND qtkeychain_SOURCES keychain_haiku.cpp)
|
|
||||||
|
|
||||||
find_library(BE_LIBRARY be REQUIRED)
|
|
||||||
list(APPEND qtkeychain_LIBRARIES ${BE_LIBRARY})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU)
|
|
||||||
option(LIBSECRET_SUPPORT "Build with libsecret support" ON)
|
|
||||||
|
|
||||||
if (LIBSECRET_SUPPORT)
|
|
||||||
pkg_check_modules(LIBSECRET libsecret-1)
|
|
||||||
|
|
||||||
if (LIBSECRET_FOUND)
|
|
||||||
add_definitions(-DHAVE_LIBSECRET=1)
|
|
||||||
endif ()
|
|
||||||
INCLUDE_DIRECTORIES(${LIBSECRET_INCLUDE_DIRS})
|
|
||||||
LINK_DIRECTORIES(${LIBSECRET_LIBRARY_DIRS})
|
|
||||||
list(APPEND qtkeychain_LIBRARIES_PRIVATE ${LIBSECRET_LIBRARIES})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
add_definitions(-DKEYCHAIN_DBUS=1)
|
|
||||||
list(APPEND qtkeychain_SOURCES keychain_unix.cpp gnomekeyring.cpp libsecret.cpp plaintextstore.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 ()
|
|
||||||
|
|
||||||
if (ANDROID)
|
|
||||||
list(APPEND qtkeychain_SOURCES keychain_android.cpp androidkeystore.cpp plaintextstore.cpp)
|
|
||||||
list(APPEND qtkeychain_LIBRARIES ${QTANDROIDEXTRAS_LIBRARIES})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
QT_WRAP_CPP(qtkeychain_MOC_OUTFILES keychain.h keychain_p.h gnomekeyring_p.h)
|
|
||||||
|
|
||||||
set(qtkeychain_TR_FILES
|
|
||||||
translations/qtkeychain_de.ts
|
|
||||||
translations/qtkeychain_fr.ts
|
|
||||||
translations/qtkeychain_ro.ts
|
|
||||||
translations/qtkeychain_ru.ts
|
|
||||||
translations/qtkeychain_zh.ts
|
|
||||||
)
|
|
||||||
|
|
||||||
file(GLOB qtkeychain_TR_SOURCES *.cpp *.h *.ui)
|
|
||||||
if (BUILD_TRANSLATIONS)
|
|
||||||
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 (QTKEYCHAIN_VERSION_INFIX EQUAL 5 AND QT_TRANSLATIONS_DIR AND NOT QTKEYCHAIN_TRANSLATIONS_DIR)
|
|
||||||
# Back compatibility with pre-0.11 versions
|
|
||||||
message(WARNING "QT_TRANSLATIONS_DIR is deprecated, use QTKEYCHAIN_TRANSLATIONS_DIR instead")
|
|
||||||
set(QTKEYCHAIN_TRANSLATIONS_DIR ${QT_TRANSLATIONS_DIR}
|
|
||||||
CACHE PATH "The location of the QtKeychain translations" FORCE)
|
|
||||||
else ()
|
|
||||||
set(QTKEYCHAIN_TRANSLATIONS_DIR
|
|
||||||
${CMAKE_INSTALL_DATADIR}/qt${QTKEYCHAIN_VERSION_INFIX}keychain/translations
|
|
||||||
CACHE PATH "The location of the QtKeychain translations")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
install(FILES ${qtkeychain_QM_FILES}
|
|
||||||
DESTINATION ${QTKEYCHAIN_TRANSLATIONS_DIR})
|
|
||||||
endif (BUILD_TRANSLATIONS)
|
|
||||||
|
|
||||||
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})
|
|
||||||
else ()
|
|
||||||
add_library(${QTKEYCHAIN_TARGET_NAME} STATIC ${qtkeychain_SOURCES} ${qtkeychain_MOC_OUTFILES} ${qtkeychain_QM_FILES})
|
|
||||||
endif ()
|
|
||||||
if (WIN32)
|
|
||||||
set_target_properties(${QTKEYCHAIN_TARGET_NAME} PROPERTIES DEBUG_POSTFIX "d")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
target_link_libraries(${QTKEYCHAIN_TARGET_NAME} PUBLIC ${qtkeychain_LIBRARIES} PRIVATE ${qtkeychain_LIBRARIES_PRIVATE})
|
|
||||||
if (NOT INTERFACE_INCLUDE_SUFFIX)
|
|
||||||
set(INTERFACE_INCLUDE_SUFFIX include)
|
|
||||||
endif ()
|
|
||||||
target_include_directories(${QTKEYCHAIN_TARGET_NAME} PUBLIC
|
|
||||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR}>"
|
|
||||||
$<INSTALL_INTERFACE:${INTERFACE_INCLUDE_SUFFIX}/>
|
|
||||||
)
|
|
||||||
|
|
||||||
generate_export_header(${QTKEYCHAIN_TARGET_NAME}
|
|
||||||
EXPORT_FILE_NAME qkeychain_export.h
|
|
||||||
EXPORT_MACRO_NAME QKEYCHAIN_EXPORT
|
|
||||||
)
|
|
||||||
|
|
||||||
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_RPATH_USE_LINK_PATH TRUE
|
|
||||||
)
|
|
||||||
|
|
||||||
install(FILES keychain.h ${CMAKE_CURRENT_BINARY_DIR}/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}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (BUILD_TEST_APPLICATION)
|
|
||||||
add_executable(testclient testclient.cpp)
|
|
||||||
target_link_libraries(testclient ${QTKEYCHAIN_TARGET_NAME})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### CMake config file
|
|
||||||
###
|
|
||||||
|
|
||||||
configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/QtKeychainConfig.cmake.in"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfig.cmake"
|
|
||||||
INSTALL_DESTINATION Qt${QTKEYCHAIN_VERSION_INFIX}Keychain)
|
|
||||||
|
|
||||||
ecm_setup_version("${QTKEYCHAIN_VERSION}" VARIABLE_PREFIX SNORE
|
|
||||||
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/Qt${QTKEYCHAIN_VERSION_INFIX}KeychainConfigVersion.cmake"
|
|
||||||
SOVERSION ${QTKEYCHAIN_VERSION})
|
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU)
|
|
||||||
set(PRI_EXTRA_DEPS "dbus")
|
|
||||||
endif ()
|
|
||||||
ecm_generate_pri_file(BASE_NAME Qt${QTKEYCHAIN_VERSION_INFIX}Keychain
|
|
||||||
LIB_NAME ${QTKEYCHAIN_TARGET_NAME}
|
|
||||||
DEPS "core ${PRI_EXTRA_DEPS}"
|
|
||||||
INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}
|
|
||||||
FILENAME_VAR pri_filename)
|
|
||||||
|
|
||||||
install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR})
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
|||||||
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.
|
|
||||||
3. The name of the author may not be used to
|
|
||||||
endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
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.
|
|
@ -1,82 +0,0 @@
|
|||||||
ChangeLog
|
|
||||||
=========
|
|
||||||
|
|
||||||
version 0.12.0 (release 2020-12-16)
|
|
||||||
|
|
||||||
* Add Qt 6 support, drop Qt 4 support
|
|
||||||
* Require C++11
|
|
||||||
* Add Android support (Mathias Hasselmann)
|
|
||||||
|
|
||||||
version 0.11.1 (release 2020-09-08)
|
|
||||||
|
|
||||||
* Build system fixes
|
|
||||||
|
|
||||||
version 0.11.0 (release 2020-09-08)
|
|
||||||
|
|
||||||
* Important: Debug builds on Windows now get the "d" suffix
|
|
||||||
* Various build system fixes
|
|
||||||
* Add Haiku support (François Revol <revol@free.fr>)
|
|
||||||
* Translation: Russian (Alexander Gorishnyak <kefir500@gmail.com>)
|
|
||||||
* Translation: Update French (David Geiger <david.david@mageialinux-online.org>)
|
|
||||||
|
|
||||||
version 0.10.0 (release 2019-12-17)
|
|
||||||
|
|
||||||
* Detect XFCE desktop correctly. (Sandro Knauß <hefee@debian.org>)
|
|
||||||
* Windows Use CRED_PERSIST_ENTERPRISE (Olivier Goffart <ogoffart@woboq.com>)
|
|
||||||
* Windows: Improve CredWrite() error handling (Christian Kamm <mail@ckamm.de>)
|
|
||||||
* Fix build with Qt 5.12.x (Sergey Ilinykh <rion4ik@gmail.com>)
|
|
||||||
* Fix Qt 4 build (Robert-André Mauchin <zebob.m@gmail.com>)
|
|
||||||
* Translation: Mandarin (Taiwan) (Poren Chiang <ren.chiang@gmail.com>)
|
|
||||||
* Translation: French (François Revol <revol@free.fr>)
|
|
||||||
|
|
||||||
version 0.9.1 (release 2018-08-20)
|
|
||||||
* Windows Credential Store: Use CRED_PERSIST_ENTERPRISE (Olivier Goffart <ogoffart@woboq.com>)
|
|
||||||
* Secret: Don't match the schema name #114 (Christian Kamm <mail@ckamm.de>)
|
|
||||||
* Fix qmake build on Windows (Alexander Gorishnyak <kefir500@gmail.com>)
|
|
||||||
|
|
||||||
version 0.9.0 (release 2018-07-13)
|
|
||||||
* Fall back on libsecret if kwallet is not available (Christian Kamm <mail@ckamm.de>)
|
|
||||||
* Only require QtLinguist if building translations (Victor Kropp <victor.kropp@jetbrains.com>)
|
|
||||||
* Fix building on Windows without credential store (Dmitry Ivanov <dm.vl.ivanov@gmail.com>)
|
|
||||||
* Fix Qt 4 build (Sandro Knauß <hefee@debian.org>)
|
|
||||||
* Make build of test application optional (Boris Pek <tehnick-8@yandex.ru>)
|
|
||||||
|
|
||||||
version 0.8.0 (release 2017-04-19)
|
|
||||||
* Buildsystem improvements (Kristofer Tingdahl <kristofer.tingdahl@dgbes.com>, Hannah von Reth <hannah.vonreth@kdab.com>, Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>)
|
|
||||||
* Enable C++11 support for Qt >= 5.7 (Dmitry Ivanov <dm.vl.ivanov@gmail.com>)
|
|
||||||
* Doxygen documentation ( Elvis Angelaccio <elvis.angelaccio@kdemail.net>)
|
|
||||||
* Libsecret support (Armin Novak <armin.novak@thincast.com>)
|
|
||||||
* iOS support (Mathias Hasselmann <mathias.hasselmann@kdab.com>)
|
|
||||||
|
|
||||||
version 0.7.0 (release 2016-05-23)
|
|
||||||
* Bump SO version due to 0.6 being binary-incompatible to previous releases
|
|
||||||
|
|
||||||
version 0.6.2 (release 2016-04-04)
|
|
||||||
* KWallet: Fixes a crash when storing passwords, seen on Debian/KDE4
|
|
||||||
|
|
||||||
version 0.6.1 (release 2016-03-31)
|
|
||||||
* Fix KWallet not working (regressions in 0.6.0)
|
|
||||||
|
|
||||||
version 0.6.0 (release 2016-03-18)
|
|
||||||
* Added support for the Windows Credential Store
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
# - Config file for the QtKeychain package
|
|
||||||
# It defines the following variables
|
|
||||||
# QTKEYCHAIN_INCLUDE_DIRS - include directories for QtKeychain
|
|
||||||
# QTKEYCHAIN_LIBRARIES - libraries to link against
|
|
||||||
|
|
||||||
@PACKAGE_INIT@
|
|
||||||
|
|
||||||
include("${CMAKE_CURRENT_LIST_DIR}/Qt@QTKEYCHAIN_VERSION_INFIX@KeychainLibraryDepends.cmake")
|
|
||||||
|
|
||||||
include(CMakeFindDependencyMacro)
|
|
||||||
|
|
||||||
find_dependency(Qt@QTKEYCHAIN_VERSION_INFIX@Core)
|
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
find_dependency(Qt@QTKEYCHAIN_VERSION_INFIX@DBus)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(QTKEYCHAIN_LIBRARIES "@QTKEYCHAIN_TARGET_NAME@")
|
|
||||||
get_target_property(QTKEYCHAIN_INCLUDE_DIRS "@QTKEYCHAIN_TARGET_NAME@" INTERFACE_INCLUDE_DIRECTORIES)
|
|
@ -1,35 +0,0 @@
|
|||||||
QtKeychain
|
|
||||||
==========
|
|
||||||
|
|
||||||
QtKeychain is a Qt API to store passwords and other secret data securely. How the data is stored depends on the platform:
|
|
||||||
|
|
||||||
* **macOS:** Passwords are stored in the macOS Keychain.
|
|
||||||
|
|
||||||
* **Linux/Unix:** If running, GNOME Keyring is used, otherwise QtKeychain tries to use KWallet (via D-Bus), if available. Libsecret (common API for desktop-specific solutions)
|
|
||||||
is also supported.
|
|
||||||
|
|
||||||
* **Windows:** By default, the Windows Credential Store is used (requires Windows 7 or newer).
|
|
||||||
Pass `-DUSE_CREDENTIAL_STORE=OFF` to cmake to disable it. If disabled, 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.
|
|
||||||
|
|
||||||
* **Android and iOS:** Passwords are stored in the Android keystore system and iOS keychain, respectively.
|
|
||||||
|
|
||||||
In unsupported environments QtKeychain will report an error. It will not store any data unencrypted unless explicitly requested (`setInsecureFallback( true )`).
|
|
||||||
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
------------
|
|
||||||
|
|
||||||
QtKeychain 0.12 and newer supports Qt 5 and Qt 6 and requires a compiler with C++11 support. Older versions support Qt 4 and Qt 5.
|
|
||||||
|
|
||||||
License
|
|
||||||
-------
|
|
||||||
|
|
||||||
QtKeychain is available under the [Modified BSD License](http://www.gnu.org/licenses/license-list.html#ModifiedBSD). See the file COPYING for details.
|
|
||||||
|
|
||||||
Changes made in this fork (Chatterino/qtkeychain)
|
|
||||||
-------
|
|
||||||
|
|
||||||
Updated the .pri file to point to the right mac/apple-specific file
|
|
||||||
Added `#undef singals` in libsecret.cpp to fix compilation.
|
|
@ -1,302 +0,0 @@
|
|||||||
#include "androidkeystore_p.h"
|
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
|
||||||
#include "private/qjni_p.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <QAndroidJniEnvironment>
|
|
||||||
|
|
||||||
using namespace QKeychain;
|
|
||||||
|
|
||||||
using namespace android::content;
|
|
||||||
using namespace android::security;
|
|
||||||
|
|
||||||
using namespace java::io;
|
|
||||||
using namespace java::lang;
|
|
||||||
using namespace java::math;
|
|
||||||
using namespace java::util;
|
|
||||||
using namespace java::security;
|
|
||||||
using namespace java::security::spec;
|
|
||||||
|
|
||||||
using namespace javax::crypto;
|
|
||||||
using namespace javax::security::auth::x500;
|
|
||||||
using namespace javax::security::cert;
|
|
||||||
|
|
||||||
const BigInteger BigInteger::ONE = BigInteger::getStaticObjectField("java/math/BigInteger", "ONE", "Ljava/math/BigInteger;");
|
|
||||||
|
|
||||||
const int Calendar::YEAR = Calendar::getStaticField<jint>("java/util/Calendar", "YEAR");
|
|
||||||
|
|
||||||
const int Cipher::DECRYPT_MODE = Cipher::getStaticField<jint>("javax/crypto/Cipher", "DECRYPT_MODE");
|
|
||||||
const int Cipher::ENCRYPT_MODE = Cipher::getStaticField<jint>("javax/crypto/Cipher", "ENCRYPT_MODE");
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
|
||||||
|
|
||||||
struct JNIObject
|
|
||||||
{
|
|
||||||
JNIObject(QSharedPointer<QJNIObjectPrivate> d): d(d) {}
|
|
||||||
|
|
||||||
static JNIObject fromLocalRef(jobject o)
|
|
||||||
{
|
|
||||||
return JNIObject(QSharedPointer<QJNIObjectPrivate>::create(QJNIObjectPrivate::fromLocalRef(o)));
|
|
||||||
}
|
|
||||||
|
|
||||||
jobject object() const { return d->object(); }
|
|
||||||
QSharedPointer<QJNIObjectPrivate> d;
|
|
||||||
};
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
using JNIObject = QAndroidJniObject;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QByteArray fromArray(const jbyteArray array)
|
|
||||||
{
|
|
||||||
QAndroidJniEnvironment env;
|
|
||||||
jbyte *const bytes = env->GetByteArrayElements(array, Q_NULLPTR);
|
|
||||||
const QByteArray result(reinterpret_cast<const char *>(bytes), env->GetArrayLength(array));
|
|
||||||
env->ReleaseByteArrayElements(array, bytes, JNI_ABORT);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIObject toArray(const QByteArray &bytes)
|
|
||||||
{
|
|
||||||
QAndroidJniEnvironment env;
|
|
||||||
const int length = bytes.length();
|
|
||||||
JNIObject array = JNIObject::fromLocalRef(env->NewByteArray(length));
|
|
||||||
env->SetByteArrayRegion(static_cast<jbyteArray>(array.object()),
|
|
||||||
0, length, reinterpret_cast<const jbyte *>(bytes.constData()));
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Object::handleExceptions()
|
|
||||||
{
|
|
||||||
QAndroidJniEnvironment env;
|
|
||||||
|
|
||||||
if (env->ExceptionCheck()) {
|
|
||||||
env->ExceptionDescribe();
|
|
||||||
env->ExceptionClear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
KeyPairGenerator KeyPairGenerator::getInstance(const QString &algorithm, const QString &provider)
|
|
||||||
{
|
|
||||||
return handleExceptions(callStaticObjectMethod("java/security/KeyPairGenerator", "getInstance",
|
|
||||||
"(Ljava/lang/String;Ljava/lang/String;)Ljava/security/KeyPairGenerator;",
|
|
||||||
fromString(algorithm).object(), fromString(provider).object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPair KeyPairGenerator::generateKeyPair() const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("generateKeyPair", "()Ljava/security/KeyPair;"));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KeyPairGenerator::initialize(const AlgorithmParameterSpec &spec) const
|
|
||||||
{
|
|
||||||
callMethod<void>("initialize", "(Ljava/security/spec/AlgorithmParameterSpec;)V", spec.object());
|
|
||||||
return handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KeyStore::containsAlias(const QString &alias) const
|
|
||||||
{
|
|
||||||
return handleExceptions(callMethod<jboolean>("containsAlias", "(Ljava/lang/String;)Z",
|
|
||||||
fromString(alias).object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KeyStore::deleteEntry(const QString &alias) const
|
|
||||||
{
|
|
||||||
callMethod<void>("deleteEntry", "(Ljava/lang/String;)Z", fromString(alias).object());
|
|
||||||
return handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyStore KeyStore::getInstance(const QString &type)
|
|
||||||
{
|
|
||||||
return handleExceptions(callStaticObjectMethod("java/security/KeyStore", "getInstance",
|
|
||||||
"(Ljava/lang/String;)Ljava/security/KeyStore;",
|
|
||||||
fromString(type).object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyStore::Entry KeyStore::getEntry(const QString &alias, const KeyStore::ProtectionParameter ¶m) const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("getEntry",
|
|
||||||
"(Ljava/lang/String;Ljava/security/KeyStore$ProtectionParameter;)Ljava/security/KeyStore$Entry;",
|
|
||||||
fromString(alias).object(), param.object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool KeyStore::load(const KeyStore::LoadStoreParameter ¶m) const
|
|
||||||
{
|
|
||||||
callMethod<void>("load", "(Ljava/security/KeyStore$LoadStoreParameter;)V", param.object());
|
|
||||||
return handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Calendar Calendar::getInstance()
|
|
||||||
{
|
|
||||||
return handleExceptions(callStaticObjectMethod("java/util/Calendar", "getInstance",
|
|
||||||
"()Ljava/util/Calendar;"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Calendar::add(int field, int amount) const
|
|
||||||
{
|
|
||||||
callMethod<void>("add", "(II)V", field, amount);
|
|
||||||
return handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
Date Calendar::getTime() const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("getTime", "()Ljava/util/Date;"));
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPairGeneratorSpec::Builder::Builder(const Context &context)
|
|
||||||
: Object(QAndroidJniObject("android/security/KeyPairGeneratorSpec$Builder",
|
|
||||||
"(Landroid/content/Context;)V",
|
|
||||||
context.object()))
|
|
||||||
{
|
|
||||||
handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPairGeneratorSpec::Builder KeyPairGeneratorSpec::Builder::setAlias(const QString &alias) const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("setAlias",
|
|
||||||
"(Ljava/lang/String;)Landroid/security/KeyPairGeneratorSpec$Builder;",
|
|
||||||
fromString(alias).object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPairGeneratorSpec::Builder KeyPairGeneratorSpec::Builder::setSubject(const X500Principal &subject) const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("setSubject",
|
|
||||||
"(Ljavax/security/auth/x500/X500Principal;)Landroid/security/KeyPairGeneratorSpec$Builder;",
|
|
||||||
subject.object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPairGeneratorSpec::Builder KeyPairGeneratorSpec::Builder::setSerialNumber(const BigInteger &serial) const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("setSerialNumber",
|
|
||||||
"(Ljava/math/BigInteger;)Landroid/security/KeyPairGeneratorSpec$Builder;",
|
|
||||||
serial.object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPairGeneratorSpec::Builder KeyPairGeneratorSpec::Builder::setStartDate(const Date &date) const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("setStartDate",
|
|
||||||
"(Ljava/util/Date;)Landroid/security/KeyPairGeneratorSpec$Builder;",
|
|
||||||
date.object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPairGeneratorSpec::Builder KeyPairGeneratorSpec::Builder::setEndDate(const Date &date) const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("setEndDate",
|
|
||||||
"(Ljava/util/Date;)Landroid/security/KeyPairGeneratorSpec$Builder;",
|
|
||||||
date.object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyPairGeneratorSpec KeyPairGeneratorSpec::Builder::build() const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("build", "()Landroid/security/KeyPairGeneratorSpec;"));
|
|
||||||
}
|
|
||||||
|
|
||||||
X500Principal::X500Principal(const QString &name)
|
|
||||||
: Object(QAndroidJniObject("javax/security/auth/x500/X500Principal",
|
|
||||||
"(Ljava/lang/String;)V",
|
|
||||||
fromString(name).object()))
|
|
||||||
{
|
|
||||||
handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
Certificate KeyStore::PrivateKeyEntry::getCertificate() const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("getCertificate", "()Ljava/security/cert/Certificate;"));
|
|
||||||
}
|
|
||||||
|
|
||||||
PrivateKey KeyStore::PrivateKeyEntry::getPrivateKey() const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("getPrivateKey", "()Ljava/security/PrivateKey;"));
|
|
||||||
}
|
|
||||||
|
|
||||||
PublicKey Certificate::getPublicKey() const
|
|
||||||
{
|
|
||||||
return handleExceptions(callObjectMethod("getPublicKey", "()Ljava/security/PublicKey;"));
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayInputStream::ByteArrayInputStream(const QByteArray &bytes)
|
|
||||||
: InputStream(QAndroidJniObject("java/io/ByteArrayInputStream", "([B)V", toArray(bytes).object()))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayOutputStream::ByteArrayOutputStream()
|
|
||||||
: OutputStream(QAndroidJniObject("java/io/ByteArrayOutputStream"))
|
|
||||||
{
|
|
||||||
handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray ByteArrayOutputStream::toByteArray() const
|
|
||||||
{
|
|
||||||
const QAndroidJniObject wrapper = callObjectMethod<jbyteArray>("toByteArray");
|
|
||||||
|
|
||||||
if (!handleExceptions())
|
|
||||||
return QByteArray();
|
|
||||||
|
|
||||||
return fromArray(static_cast<jbyteArray>(wrapper.object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
int InputStream::read() const
|
|
||||||
{
|
|
||||||
return handleExceptions(callMethod<int>("read"), -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OutputStream::write(const QByteArray &bytes) const
|
|
||||||
{
|
|
||||||
callMethod<void>("write", "([B)V", toArray(bytes).object());
|
|
||||||
return handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OutputStream::close() const
|
|
||||||
{
|
|
||||||
callMethod<void>("close");
|
|
||||||
return handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OutputStream::flush() const
|
|
||||||
{
|
|
||||||
callMethod<void>("flush");
|
|
||||||
return handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
Cipher Cipher::getInstance(const QString &transformation)
|
|
||||||
{
|
|
||||||
return handleExceptions(callStaticObjectMethod("javax/crypto/Cipher", "getInstance",
|
|
||||||
"(Ljava/lang/String;)Ljavax/crypto/Cipher;",
|
|
||||||
fromString(transformation).object()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Cipher::init(int opMode, const Key &key) const
|
|
||||||
{
|
|
||||||
callMethod<void>("init", "(ILjava/security/Key;)V", opMode, key.object());
|
|
||||||
return handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CipherOutputStream::CipherOutputStream(const OutputStream &stream, const Cipher &cipher)
|
|
||||||
: FilterOutputStream(QAndroidJniObject("javax/crypto/CipherOutputStream",
|
|
||||||
"(Ljava/io/OutputStream;Ljavax/crypto/Cipher;)V",
|
|
||||||
stream.object(), cipher.object()))
|
|
||||||
{
|
|
||||||
handleExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
CipherInputStream::CipherInputStream(const InputStream &stream, const Cipher &cipher)
|
|
||||||
: FilterInputStream(QAndroidJniObject("javax/crypto/CipherInputStream",
|
|
||||||
"(Ljava/io/InputStream;Ljavax/crypto/Cipher;)V",
|
|
||||||
stream.object(), cipher.object()))
|
|
||||||
{
|
|
||||||
handleExceptions();
|
|
||||||
}
|
|
@ -1,371 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (C) 2016 Mathias Hasselmann <mathias.hasselmann@kdab.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 QTKEYCHAIN_ANDROIDKEYSTORE_P_H
|
|
||||||
#define QTKEYCHAIN_ANDROIDKEYSTORE_P_H
|
|
||||||
|
|
||||||
#include <QAndroidJniObject>
|
|
||||||
|
|
||||||
namespace QKeychain {
|
|
||||||
|
|
||||||
namespace javax {
|
|
||||||
namespace security {
|
|
||||||
|
|
||||||
namespace auth { namespace x500 { class X500Principal; } }
|
|
||||||
namespace cert { class Certificate; }
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace java {
|
|
||||||
namespace lang {
|
|
||||||
|
|
||||||
class Object : protected QAndroidJniObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inline Object(jobject object) : QAndroidJniObject(object) {}
|
|
||||||
inline Object(const QAndroidJniObject &object) : QAndroidJniObject(object) {}
|
|
||||||
inline operator bool() const { return isValid(); }
|
|
||||||
|
|
||||||
using QAndroidJniObject::object;
|
|
||||||
using QAndroidJniObject::toString;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static bool handleExceptions();
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static T handleExceptions(const T &result, const T &resultOnError = T());
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline T Object::handleExceptions(const T &result, const T &resultOnError)
|
|
||||||
{
|
|
||||||
if (!handleExceptions())
|
|
||||||
return resultOnError;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace lang
|
|
||||||
|
|
||||||
namespace io {
|
|
||||||
|
|
||||||
class InputStream : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
|
|
||||||
int read() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ByteArrayInputStream : public InputStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using InputStream::InputStream;
|
|
||||||
|
|
||||||
explicit ByteArrayInputStream(const QByteArray &bytes);
|
|
||||||
};
|
|
||||||
|
|
||||||
class FilterInputStream : public InputStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using InputStream::InputStream;
|
|
||||||
};
|
|
||||||
|
|
||||||
class OutputStream : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
|
|
||||||
bool write(const QByteArray &bytes) const;
|
|
||||||
bool flush() const;
|
|
||||||
bool close() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ByteArrayOutputStream : public OutputStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using OutputStream::OutputStream;
|
|
||||||
|
|
||||||
ByteArrayOutputStream();
|
|
||||||
|
|
||||||
QByteArray toByteArray() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FilterOutputStream : public OutputStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using OutputStream::OutputStream;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace io
|
|
||||||
|
|
||||||
namespace math {
|
|
||||||
|
|
||||||
class BigInteger : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
|
|
||||||
static const BigInteger ZERO;
|
|
||||||
static const BigInteger ONE;
|
|
||||||
static const BigInteger TEN;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace math
|
|
||||||
|
|
||||||
namespace util {
|
|
||||||
|
|
||||||
class Date : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Calendar : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
|
|
||||||
static const int YEAR;
|
|
||||||
static const int MONTH;
|
|
||||||
static const int DAY;
|
|
||||||
static const int HOUR;
|
|
||||||
static const int MINUTE;
|
|
||||||
static const int SECOND;
|
|
||||||
static const int MILLISECOND;
|
|
||||||
|
|
||||||
static Calendar getInstance();
|
|
||||||
|
|
||||||
bool add(int field, int amount) const;
|
|
||||||
Date getTime() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace util
|
|
||||||
|
|
||||||
namespace security {
|
|
||||||
namespace spec {
|
|
||||||
|
|
||||||
class AlgorithmParameterSpec : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace spec
|
|
||||||
|
|
||||||
class Key : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PrivateKey : public Key
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Key::Key;
|
|
||||||
|
|
||||||
PrivateKey(const Key &init): Key(init) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class PublicKey : public Key
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Key::Key;
|
|
||||||
|
|
||||||
PublicKey(const Key &init): Key(init) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class KeyPair : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
};
|
|
||||||
|
|
||||||
class KeyPairGenerator : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
|
|
||||||
static KeyPairGenerator getInstance(const QString &algorithm, const QString &provider);
|
|
||||||
KeyPair generateKeyPair() const;
|
|
||||||
bool initialize(const spec::AlgorithmParameterSpec &spec) const;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class KeyStore : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class Entry : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PrivateKeyEntry : public Entry
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Entry::Entry;
|
|
||||||
|
|
||||||
inline PrivateKeyEntry(const Entry &init): Entry(init) {}
|
|
||||||
|
|
||||||
javax::security::cert::Certificate getCertificate() const;
|
|
||||||
java::security::PrivateKey getPrivateKey() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class LoadStoreParameter : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ProtectionParameter : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
};
|
|
||||||
|
|
||||||
using Object::Object;
|
|
||||||
|
|
||||||
bool containsAlias(const QString &alias) const;
|
|
||||||
bool deleteEntry(const QString &alias) const;
|
|
||||||
static KeyStore getInstance(const QString &type);
|
|
||||||
Entry getEntry(const QString &alias, const ProtectionParameter ¶m = Q_NULLPTR) const;
|
|
||||||
bool load(const LoadStoreParameter ¶m = Q_NULLPTR) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace interfaces {
|
|
||||||
|
|
||||||
class RSAPrivateKey : public PrivateKey
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using PrivateKey::PrivateKey;
|
|
||||||
|
|
||||||
RSAPrivateKey(const PrivateKey &init): PrivateKey(init) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class RSAPublicKey : public PublicKey
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using PublicKey::PublicKey;
|
|
||||||
|
|
||||||
RSAPublicKey(const PublicKey &init): PublicKey(init) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace interfaces
|
|
||||||
|
|
||||||
} // namespace security
|
|
||||||
} // namespace java
|
|
||||||
|
|
||||||
namespace android {
|
|
||||||
namespace content {
|
|
||||||
|
|
||||||
class Context : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace content
|
|
||||||
|
|
||||||
namespace security {
|
|
||||||
|
|
||||||
class KeyPairGeneratorSpec : public java::security::spec::AlgorithmParameterSpec
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
class Builder : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
|
|
||||||
explicit Builder(const android::content::Context &context);
|
|
||||||
|
|
||||||
Builder setAlias(const QString &alias) const;
|
|
||||||
Builder setSubject(const javax::security::auth::x500::X500Principal &subject) const;
|
|
||||||
Builder setSerialNumber(const java::math::BigInteger &serial) const;
|
|
||||||
Builder setStartDate(const java::util::Date &date) const;
|
|
||||||
Builder setEndDate(const java::util::Date &date) const;
|
|
||||||
KeyPairGeneratorSpec build() const;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
using AlgorithmParameterSpec::AlgorithmParameterSpec;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace security
|
|
||||||
} // namespace android
|
|
||||||
|
|
||||||
namespace javax {
|
|
||||||
namespace crypto {
|
|
||||||
|
|
||||||
class Cipher : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static const int DECRYPT_MODE;
|
|
||||||
static const int ENCRYPT_MODE;
|
|
||||||
|
|
||||||
using Object::Object;
|
|
||||||
|
|
||||||
static Cipher getInstance(const QString &transformation);
|
|
||||||
bool init(int opMode, const java::security::Key &key) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CipherInputStream : public java::io::FilterInputStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using FilterInputStream::FilterInputStream;
|
|
||||||
|
|
||||||
explicit CipherInputStream(const InputStream &stream, const Cipher &cipher);
|
|
||||||
};
|
|
||||||
|
|
||||||
class CipherOutputStream : public java::io::FilterOutputStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using FilterOutputStream::FilterOutputStream;
|
|
||||||
|
|
||||||
explicit CipherOutputStream(const OutputStream &stream, const Cipher &cipher);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace security {
|
|
||||||
namespace auth {
|
|
||||||
namespace x500 {
|
|
||||||
|
|
||||||
class X500Principal;
|
|
||||||
|
|
||||||
class X500Principal : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
|
|
||||||
explicit X500Principal(const QString &name);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace x500
|
|
||||||
} // namespace auth
|
|
||||||
|
|
||||||
namespace cert {
|
|
||||||
|
|
||||||
class Certificate : public java::lang::Object
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using Object::Object;
|
|
||||||
|
|
||||||
java::security::PublicKey getPublicKey() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace cert
|
|
||||||
|
|
||||||
} // namespace security
|
|
||||||
} // namespace javax
|
|
||||||
|
|
||||||
} // namespace QKeychain
|
|
||||||
|
|
||||||
#endif // QTKEYCHAIN_ANDROIDKEYSTORE_P_H
|
|
@ -1,31 +0,0 @@
|
|||||||
version: '{build}'
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- ps: |
|
|
||||||
$ErrorActionPreference="Stop"
|
|
||||||
Import-Module $env:APPVEYOR_BUILD_FOLDER\appveyorHelp.psm1
|
|
||||||
|
|
||||||
Init @("ninja")
|
|
||||||
mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\build\$env:APPVEYOR_PROJECT_NAME
|
|
||||||
cd $env:APPVEYOR_BUILD_FOLDER\work\build\$env:APPVEYOR_PROJECT_NAME
|
|
||||||
LogExec cmake -G"Ninja" $env:APPVEYOR_BUILD_FOLDER -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$CMAKE_INSTALL_ROOT"
|
|
||||||
|
|
||||||
CmakeImageInstall
|
|
||||||
|
|
||||||
test: off
|
|
||||||
|
|
||||||
cache:
|
|
||||||
- work\install -> appveyor.yml
|
|
||||||
- C:\ProgramData\chocolatey\bin -> appveyor.yml
|
|
||||||
- C:\ProgramData\chocolatey\lib -> appveyor.yml
|
|
||||||
|
|
||||||
environment:
|
|
||||||
QT_VER: 5.7
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
- COMPILER: msvc2015
|
|
||||||
- COMPILER: msvc2015_64
|
|
||||||
- COMPILER: mingw53_32
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,362 +0,0 @@
|
|||||||
Write-Host "Appveyor Helper scrips https://github.com/TheOneRing/appVeyorHelp"
|
|
||||||
|
|
||||||
$ErrorActionPreference="Stop"
|
|
||||||
|
|
||||||
$script:INSTALL_DIR="$env:APPVEYOR_BUILD_FOLDER\work\install"
|
|
||||||
$CMAKE_INSTALL_ROOT="`"$INSTALL_DIR`"" -replace "\\", "/"
|
|
||||||
$env:PATH="$env:PATH;$script:INSTALL_DIR"
|
|
||||||
|
|
||||||
if(!$env:CI -eq "true")
|
|
||||||
{
|
|
||||||
function Push-AppveyorArtifact()
|
|
||||||
{
|
|
||||||
Write-Host "Push-AppveyorArtifact $ARGS"
|
|
||||||
}
|
|
||||||
function Start-FileDownload([string] $url, [string] $out)
|
|
||||||
{
|
|
||||||
if(!$out)
|
|
||||||
{
|
|
||||||
$out = $url.SubString($url.LastIndexOf("/"))
|
|
||||||
}
|
|
||||||
wget $url -Outfile $out
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function LogExec()
|
|
||||||
{
|
|
||||||
$OldErrorActionPreference=$ErrorActionPreference
|
|
||||||
$ErrorActionPreference="Continue"
|
|
||||||
$LastExitCode = 0
|
|
||||||
Write-Host $Args[0], $Args[1..(($Args.Count)-1)]
|
|
||||||
& $Args[0] $Args[1..(($Args.Count)-1)]
|
|
||||||
if(!$LastExitCode -eq 0)
|
|
||||||
{
|
|
||||||
exit $LastExitCode
|
|
||||||
}
|
|
||||||
$ErrorActionPreference=$OldErrorActionPreference
|
|
||||||
}
|
|
||||||
|
|
||||||
#Set environment variables for Visual Studio Command Prompt
|
|
||||||
#http://stackoverflow.com/questions/2124753/how-i-can-use-powershell-with-the-visual-studio-command-prompt
|
|
||||||
function BAT-CALL([string] $path, [string] $arg)
|
|
||||||
{
|
|
||||||
Write-Host "Calling `"$path`" `"$arg`""
|
|
||||||
cmd /c "$path" "$arg" `&`& set `|`| exit 1|
|
|
||||||
foreach {
|
|
||||||
if ($_ -match "=") {
|
|
||||||
$v = $_.split("=")
|
|
||||||
#Write-Host "ENV:\$($v[0])=$($v[1])"
|
|
||||||
set-item -force -path "ENV:\$($v[0])" -value "$($v[1])"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($LastExitCode -eq 1) {
|
|
||||||
Write-Error "$path not found."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-QtDir()
|
|
||||||
{
|
|
||||||
$ver = 5.5
|
|
||||||
if($env:QT_VER)
|
|
||||||
{
|
|
||||||
$ver = $env:QT_VER
|
|
||||||
}
|
|
||||||
return "C:\Qt\$ver\$env:COMPILER\"
|
|
||||||
}
|
|
||||||
|
|
||||||
function SETUP-QT()
|
|
||||||
{
|
|
||||||
[string] $compiler=$env:COMPILER
|
|
||||||
$qtDir = Get-QtDir
|
|
||||||
$script:QT_BINARY_DIRS = @($qtDir)
|
|
||||||
|
|
||||||
BAT-CALL "$qtDir\bin\qtenv2.bat"
|
|
||||||
if ($compiler.StartsWith("mingw49"))
|
|
||||||
{
|
|
||||||
#remove sh.exe from path
|
|
||||||
$env:PATH=$env:PATH -replace "C:\\Program Files \(x86\)\\Git\\bin", ""
|
|
||||||
$script:MAKE="mingw32-make"
|
|
||||||
$script:CMAKE_GENERATOR="MinGW Makefiles"
|
|
||||||
$script:STRIP=@("strip", "-s")
|
|
||||||
$script:QT_BINARY_DIRS += (Resolve-Path "$qtDir\..\..\Tools\mingw492_32\opt\")
|
|
||||||
}
|
|
||||||
elseif ($compiler.StartsWith("msvc"))
|
|
||||||
{
|
|
||||||
$arch = "x86"
|
|
||||||
if($compiler.EndsWith("64"))
|
|
||||||
{
|
|
||||||
$arch = "amd64"
|
|
||||||
}
|
|
||||||
$compilerDirs = @{
|
|
||||||
"msvc2010" = "VS100COMNTOOLS";
|
|
||||||
"msvc2012" = "VS110COMNTOOLS";
|
|
||||||
"msvc2013" = "VS120COMNTOOLS";
|
|
||||||
"msvc2015" = "VS140COMNTOOLS"
|
|
||||||
}
|
|
||||||
|
|
||||||
$compilerVar = $compilerDirs[$compiler.Split("_")[0]]
|
|
||||||
$compilerDir = (get-item -path "env:\$($compilerVar)").Value
|
|
||||||
BAT-CALL "$compilerDir\..\..\VC\vcvarsall.bat" $arch
|
|
||||||
$script:MAKE="nmake"
|
|
||||||
$script:CMAKE_GENERATOR="NMake Makefiles"
|
|
||||||
if($arch -eq "x86")
|
|
||||||
{
|
|
||||||
$script:QT_BINARY_DIRS += ("C:\OpenSSL-Win32")
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$script:QT_BINARY_DIRS += ("C:\OpenSSL-Win64")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Install-ChocolatelyModule([string] $module, [string[]] $myargs)
|
|
||||||
{
|
|
||||||
Write-Host "Install chocolately package $module"
|
|
||||||
LogExec cinst $module @myargs -y
|
|
||||||
}
|
|
||||||
|
|
||||||
function Install-CmakeGitModule([string] $url, [hashtable] $arguments)
|
|
||||||
{
|
|
||||||
$module = $url.SubString($url.LastIndexOf("/")+1)
|
|
||||||
$module = $module.Substring(0,$module.Length - 4)
|
|
||||||
if(!$arguments.Contains("branch"))
|
|
||||||
{
|
|
||||||
$arguments["branch"] = "master"
|
|
||||||
}
|
|
||||||
if(!$arguments.Contains("buildType"))
|
|
||||||
{
|
|
||||||
$arguments["buildType"] = "Release"
|
|
||||||
}
|
|
||||||
mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\build\$module
|
|
||||||
pushd $env:APPVEYOR_BUILD_FOLDER\work\git
|
|
||||||
LogExec git clone -q --depth 1 --branch ([string]$arguments["branch"]) $url $module
|
|
||||||
popd
|
|
||||||
pushd $env:APPVEYOR_BUILD_FOLDER\work\build\$module
|
|
||||||
LogExec cmake -G $script:CMAKE_GENERATOR ("-DCMAKE_BUILD_TYPE=`"{0}`"" -f [string]$arguments["buildType"]) $env:APPVEYOR_BUILD_FOLDER\work\git\$module -DCMAKE_INSTALL_PREFIX="$CMAKE_INSTALL_ROOT" $arguments["options"]
|
|
||||||
LogExec $script:MAKE install
|
|
||||||
popd
|
|
||||||
}
|
|
||||||
|
|
||||||
function Init([string[]] $chocoDeps, [System.Collections.Specialized.OrderedDictionary] $cmakeModules)
|
|
||||||
{
|
|
||||||
$script:MAKE=""
|
|
||||||
$script:CMAKE_GENERATOR=""
|
|
||||||
$script:STRIP=$null
|
|
||||||
|
|
||||||
mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\image | Out-Null
|
|
||||||
mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\build | Out-Null
|
|
||||||
|
|
||||||
SETUP-QT
|
|
||||||
|
|
||||||
if($chocoDeps -contains "ninja") {
|
|
||||||
$script:CMAKE_GENERATOR="Ninja"
|
|
||||||
$script:MAKE="ninja"
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !(Test-Path "$env:APPVEYOR_BUILD_FOLDER\work\install" ) )
|
|
||||||
{
|
|
||||||
mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\install | Out-Null
|
|
||||||
mkdir -Force $env:APPVEYOR_BUILD_FOLDER\work\git | Out-Null
|
|
||||||
|
|
||||||
foreach($module in $chocoDeps) {
|
|
||||||
if($module -eq "nsis")
|
|
||||||
{
|
|
||||||
Install-ChocolatelyModule "nsis.portable" @("-pre")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
Install-ChocolatelyModule $module
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($key in $cmakeModules.Keys) {
|
|
||||||
Install-CmakeGitModule $key $cmakeModules[$key]
|
|
||||||
}
|
|
||||||
|
|
||||||
[string] $compiler=$env:COMPILER
|
|
||||||
if($compiler.StartsWith("msvc"))
|
|
||||||
{
|
|
||||||
Write-Host "Downloading vcredist.exe"
|
|
||||||
if ($compiler.StartsWith("msvc2015"))
|
|
||||||
{
|
|
||||||
if($compiler.EndsWith("64"))
|
|
||||||
{
|
|
||||||
Start-FileDownload https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe $env:APPVEYOR_BUILD_FOLDER\work\install\vcredist.exe
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Start-FileDownload https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x86.exe $env:APPVEYOR_BUILD_FOLDER\work\install\vcredist.exe
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if($compiler.EndsWith("64"))
|
|
||||||
{
|
|
||||||
Start-FileDownload http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe $env:APPVEYOR_BUILD_FOLDER\work\install\vcredist.exe
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Start-FileDownload http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe $env:APPVEYOR_BUILD_FOLDER\work\install\vcredist.exe
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function relativePath([string] $root, [string] $path)
|
|
||||||
{
|
|
||||||
pushd $root
|
|
||||||
$out = Resolve-Path -Relative $path
|
|
||||||
popd
|
|
||||||
return $out
|
|
||||||
}
|
|
||||||
|
|
||||||
function StripFile([string] $name)
|
|
||||||
{
|
|
||||||
if($script:STRIP) {
|
|
||||||
if( $name.EndsWith(".dll") -or $name.EndsWith(".exe"))
|
|
||||||
{
|
|
||||||
Write-Host "strip file $name"
|
|
||||||
LogExec @script:STRIP $name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-DeployImageName()
|
|
||||||
{
|
|
||||||
$version = Get-Version
|
|
||||||
if($env:APPVEYOR_REPO_TAG -eq "true") {
|
|
||||||
return "$env:APPVEYOR_PROJECT_NAME`_$version`_Qt$env:QT_VER`_$env:COMPILER"
|
|
||||||
}else{
|
|
||||||
return "$env:APPVEYOR_PROJECT_NAME`_$env:APPVEYOR_REPO_BRANCH`_$version`_Qt$env:QT_VER`_$env:COMPILER"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Get-Version()
|
|
||||||
{
|
|
||||||
if($env:APPVEYOR_REPO_TAG -eq "true") {
|
|
||||||
return $env:APPVEYOR_REPO_TAG_NAME
|
|
||||||
}else{
|
|
||||||
$commit = ([string]$env:APPVEYOR_REPO_COMMIT).SubString(0,6)
|
|
||||||
return $commit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function CmakeImageInstall()
|
|
||||||
{
|
|
||||||
$imageName = Get-DeployImageName
|
|
||||||
$destDir = "$env:APPVEYOR_BUILD_FOLDER\work\cmakeDeployImage\$imageName"
|
|
||||||
$env:DESTDIR = $destDir
|
|
||||||
LogExec $script:MAKE install
|
|
||||||
$env:DESTDIR = $null
|
|
||||||
if(!$LastExitCode -eq 0)
|
|
||||||
{
|
|
||||||
Write-Error "Build Failed"
|
|
||||||
}
|
|
||||||
$env:DESTDIR=$null
|
|
||||||
$prefix=$script:INSTALL_DIR
|
|
||||||
if( $prefix.substring(1,1) -eq ":")
|
|
||||||
{
|
|
||||||
$prefix=$prefix.substring(3)
|
|
||||||
}
|
|
||||||
Write-Host "move $destDir\$prefix to $destDir"
|
|
||||||
mv -Force "$destDir\$prefix\*" "$destDir"
|
|
||||||
$rootLeftOver = $prefix.substring(0, $prefix.indexOf("\"))
|
|
||||||
rm -Recurse "$destDir\$rootLeftOver"
|
|
||||||
}
|
|
||||||
|
|
||||||
function CreateDeployImage([string[]] $whiteList, [string[]] $blackList)
|
|
||||||
{
|
|
||||||
$imageName = Get-DeployImageName
|
|
||||||
$deployPath = "$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName"
|
|
||||||
|
|
||||||
function copyWithWhitelist([string] $root)
|
|
||||||
{
|
|
||||||
$files = ls $root -Recurse
|
|
||||||
foreach($fileName in $files.FullName)
|
|
||||||
{
|
|
||||||
$relPath = (relativePath $root $fileName).SubString(2)
|
|
||||||
if($whiteList | Where {$relPath -match $_})
|
|
||||||
{
|
|
||||||
if($blackList | Where {$relPath -match $_})
|
|
||||||
{
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if(!(Test-Path $deployPath\$relPath))
|
|
||||||
{
|
|
||||||
Write-Host "copy $fileName to $deployPath\$relPath"
|
|
||||||
mkdir -Force (Split-Path -Parent $deployPath\$relPath) | Out-Null
|
|
||||||
cp -Force $fileName $deployPath\$relPath
|
|
||||||
StripFile $deployPath\$relPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Write-Host "CreateDeployImage $imageName"
|
|
||||||
mkdir $deployPath | Out-Null
|
|
||||||
|
|
||||||
copyWithWhitelist "$env:APPVEYOR_BUILD_FOLDER\work\cmakeDeployImage\$imageName"
|
|
||||||
copyWithWhitelist "$env:APPVEYOR_BUILD_FOLDER\work\install\"
|
|
||||||
foreach($folder in $script:QT_BINARY_DIRS)
|
|
||||||
{
|
|
||||||
copyWithWhitelist $folder
|
|
||||||
}
|
|
||||||
Write-Host "Deploy path $deployPath"
|
|
||||||
return $deployPath
|
|
||||||
}
|
|
||||||
|
|
||||||
function 7ZipDeployImage()
|
|
||||||
{
|
|
||||||
$imageName = Get-DeployImageName
|
|
||||||
LogExec 7za a "$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName.7z" "$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName"
|
|
||||||
Push-AppveyorArtifact "$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName.7z"
|
|
||||||
}
|
|
||||||
|
|
||||||
function NsisDeployImage([string] $scriptName)
|
|
||||||
{
|
|
||||||
$imageName = Get-DeployImageName
|
|
||||||
$installerName = "$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName.exe"
|
|
||||||
$version = Get-Version
|
|
||||||
if(([string]$env:COMPILER).StartsWith("msvc"))
|
|
||||||
{
|
|
||||||
$redist = "$env:APPVEYOR_BUILD_FOLDER\work\install\vcredist.exe"
|
|
||||||
}else{
|
|
||||||
$redist = "none"
|
|
||||||
}
|
|
||||||
if($env:COMPILER.EndsWith("64"))
|
|
||||||
{
|
|
||||||
$defaultinstdir = "`$PROGRAMFILES64"
|
|
||||||
}else{
|
|
||||||
$defaultinstdir = "`$PROGRAMFILES"
|
|
||||||
}
|
|
||||||
LogExec makensis.exe /DgitDir=$env:APPVEYOR_BUILD_FOLDER /Dsetupname=$installerName /Dcaption=$imageName /Dversion=$version /Dcompiler=$env:COMPILER /Dvcredist=$redist /Ddefaultinstdir=$defaultinstdir /Dsrcdir=$env:APPVEYOR_BUILD_FOLDER\work\deployImage\$imageName $scriptName
|
|
||||||
Push-AppveyorArtifact $installerName
|
|
||||||
}
|
|
||||||
|
|
||||||
# based on http://thesurlyadmin.com/2013/01/07/remove-empty-directories-recursively/
|
|
||||||
function DeleteEmptyFodlers([string] $root)
|
|
||||||
{
|
|
||||||
$Folders = @()
|
|
||||||
foreach($Folder in (Get-ChildItem -Path $root -Recurse -Directory))
|
|
||||||
{
|
|
||||||
$Folders += New-Object PSObject -Property @{
|
|
||||||
Object = $Folder
|
|
||||||
Depth = ($Folder.FullName.Split("\")).Count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$Folders = $Folders | Sort Depth -Descending
|
|
||||||
|
|
||||||
foreach($Folder in $Folders)
|
|
||||||
{
|
|
||||||
If ($Folder.Object.GetFileSystemInfos().Count -eq 0)
|
|
||||||
{
|
|
||||||
Write-Host "Delete empty dir:" $Folder.Object.FullName
|
|
||||||
Remove-Item -Path $Folder.Object.FullName -Force
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "CMAKE_INSTALL_ROOT: $CMAKE_INSTALL_ROOT"
|
|
||||||
Write-Host "Image-Name: ", (Get-DeployImageName)
|
|
||||||
|
|
||||||
Export-ModuleMember -Function @("Init","CmakeImageInstall", "CreateDeployImage", "LogExec", "7ZipDeployImage", "NsisDeployImage", "DeleteEmptyFodlers") -Variable @("CMAKE_INSTALL_ROOT")
|
|
@ -1,199 +0,0 @@
|
|||||||
#.rst:
|
|
||||||
# ECMGeneratePriFile
|
|
||||||
# ------------------
|
|
||||||
#
|
|
||||||
# Generate a ``.pri`` file for the benefit of qmake-based projects.
|
|
||||||
#
|
|
||||||
# As well as the function below, this module creates the cache variable
|
|
||||||
# ``ECM_MKSPECS_INSTALL_DIR`` and sets the default value to ``mkspecs/modules``.
|
|
||||||
# This assumes Qt and the current project are both installed to the same
|
|
||||||
# non-system prefix. Packagers who use ``-DCMAKE_INSTALL_PREFIX=/usr`` will
|
|
||||||
# certainly want to set ``ECM_MKSPECS_INSTALL_DIR`` to something like
|
|
||||||
# ``share/qt5/mkspecs/modules``.
|
|
||||||
#
|
|
||||||
# The main thing is that this should be the ``modules`` subdirectory of either
|
|
||||||
# the default qmake ``mkspecs`` directory or of a directory that will be in the
|
|
||||||
# ``$QMAKEPATH`` environment variable when qmake is run.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# ecm_generate_pri_file(BASE_NAME <baseName>
|
|
||||||
# LIB_NAME <libName>
|
|
||||||
# [DEPS "<dep> [<dep> [...]]"]
|
|
||||||
# [FILENAME_VAR <filename_variable>]
|
|
||||||
# [INCLUDE_INSTALL_DIR <dir>]
|
|
||||||
# [LIB_INSTALL_DIR <dir>])
|
|
||||||
#
|
|
||||||
# If your CMake project produces a Qt-based library, you may expect there to be
|
|
||||||
# applications that wish to use it that use a qmake-based build system, rather
|
|
||||||
# than a CMake-based one. Creating a ``.pri`` file will make use of your
|
|
||||||
# library convenient for them, in much the same way that CMake config files make
|
|
||||||
# things convenient for CMake-based applications.
|
|
||||||
#
|
|
||||||
# ecm_generate_pri_file() generates just such a file. It requires the
|
|
||||||
# ``PROJECT_VERSION_STRING`` variable to be set. This is typically set by
|
|
||||||
# :module:`ECMSetupVersion`, although the project() command in CMake 3.0.0 and
|
|
||||||
# later can also set this.
|
|
||||||
#
|
|
||||||
# BASE_NAME specifies the name qmake project (.pro) files should use to refer to
|
|
||||||
# the library (eg: KArchive). LIB_NAME is the name of the actual library to
|
|
||||||
# link to (ie: the first argument to add_library()). DEPS is a space-separated
|
|
||||||
# list of the base names of other libraries (for Qt libraries, use the same
|
|
||||||
# names you use with the ``QT`` variable in a qmake project file, such as "core"
|
|
||||||
# for QtCore). FILENAME_VAR specifies the name of a variable to store the path
|
|
||||||
# to the generated file in.
|
|
||||||
#
|
|
||||||
# INCLUDE_INSTALL_DIR is the path (relative to ``CMAKE_INSTALL_PREFIX``) that
|
|
||||||
# include files will be installed to. It defaults to
|
|
||||||
# ``${INCLUDE_INSTALL_DIR}/<baseName>`` if the ``INCLUDE_INSTALL_DIR`` variable
|
|
||||||
# is set. If that variable is not set, the ``CMAKE_INSTALL_INCLUDEDIR`` variable
|
|
||||||
# is used instead, and if neither are set ``include`` is used. LIB_INSTALL_DIR
|
|
||||||
# operates similarly for the installation location for libraries; it defaults to
|
|
||||||
# ``${LIB_INSTALL_DIR}``, ``${CMAKE_INSTALL_LIBDIR}`` or ``lib``, in that order.
|
|
||||||
#
|
|
||||||
# Example usage:
|
|
||||||
#
|
|
||||||
# .. code-block:: cmake
|
|
||||||
#
|
|
||||||
# ecm_generate_pri_file(
|
|
||||||
# BASE_NAME KArchive
|
|
||||||
# LIB_NAME KF5KArchive
|
|
||||||
# DEPS "core"
|
|
||||||
# FILENAME_VAR pri_filename
|
|
||||||
# )
|
|
||||||
# install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR})
|
|
||||||
#
|
|
||||||
# A qmake-based project that wished to use this would then do::
|
|
||||||
#
|
|
||||||
# QT += KArchive
|
|
||||||
#
|
|
||||||
# in their ``.pro`` file.
|
|
||||||
#
|
|
||||||
# Since pre-1.0.0.
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# SPDX-FileCopyrightText: 2014 David Faure <faure@kde.org>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
# Replicate the logic from KDEInstallDirs.cmake as we can't depend on it
|
|
||||||
# Ask qmake if we're using the same prefix as Qt
|
|
||||||
set(_askqmake OFF)
|
|
||||||
if(NOT DEFINED KDE_INSTALL_USE_QT_SYS_PATHS)
|
|
||||||
include(ECMQueryQmake)
|
|
||||||
query_qmake(qt_install_prefix_dir QT_INSTALL_PREFIX TRY)
|
|
||||||
if(qt_install_prefix_dir STREQUAL "${CMAKE_INSTALL_PREFIX}")
|
|
||||||
set(_askqmake ON)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(KDE_INSTALL_USE_QT_SYS_PATHS OR _askqmake)
|
|
||||||
include(ECMQueryQmake)
|
|
||||||
query_qmake(qt_host_data_dir QT_HOST_DATA)
|
|
||||||
set(ECM_MKSPECS_INSTALL_DIR ${qt_host_data_dir}/mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.")
|
|
||||||
else()
|
|
||||||
set(ECM_MKSPECS_INSTALL_DIR mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
function(ECM_GENERATE_PRI_FILE)
|
|
||||||
set(options )
|
|
||||||
set(oneValueArgs BASE_NAME LIB_NAME DEPS FILENAME_VAR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR)
|
|
||||||
set(multiValueArgs )
|
|
||||||
|
|
||||||
cmake_parse_arguments(EGPF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if(EGPF_UNPARSED_ARGUMENTS)
|
|
||||||
message(FATAL_ERROR "Unknown keywords given to ECM_GENERATE_PRI_FILE(): \"${EGPF_UNPARSED_ARGUMENTS}\"")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT EGPF_BASE_NAME)
|
|
||||||
message(FATAL_ERROR "Required argument BASE_NAME missing in ECM_GENERATE_PRI_FILE() call")
|
|
||||||
endif()
|
|
||||||
if(NOT EGPF_LIB_NAME)
|
|
||||||
message(FATAL_ERROR "Required argument LIB_NAME missing in ECM_GENERATE_PRI_FILE() call")
|
|
||||||
endif()
|
|
||||||
if(NOT PROJECT_VERSION_STRING)
|
|
||||||
message(FATAL_ERROR "Required variable PROJECT_VERSION_STRING not set before ECM_GENERATE_PRI_FILE() call. Did you call ecm_setup_version?")
|
|
||||||
endif()
|
|
||||||
if(NOT EGPF_INCLUDE_INSTALL_DIR)
|
|
||||||
if(INCLUDE_INSTALL_DIR)
|
|
||||||
set(EGPF_INCLUDE_INSTALL_DIR "${INCLUDE_INSTALL_DIR}/${EGPF_BASE_NAME}")
|
|
||||||
elseif(CMAKE_INSTALL_INCLUDEDIR)
|
|
||||||
set(EGPF_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${EGPF_BASE_NAME}")
|
|
||||||
else()
|
|
||||||
set(EGPF_INCLUDE_INSTALL_DIR "include/${EGPF_BASE_NAME}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
if(NOT EGPF_LIB_INSTALL_DIR)
|
|
||||||
if(LIB_INSTALL_DIR)
|
|
||||||
set(EGPF_LIB_INSTALL_DIR "${LIB_INSTALL_DIR}")
|
|
||||||
elseif(CMAKE_INSTALL_LIBDIR)
|
|
||||||
set(EGPF_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}")
|
|
||||||
else()
|
|
||||||
set(EGPF_LIB_INSTALL_DIR "lib")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" PROJECT_VERSION_MAJOR "${PROJECT_VERSION_STRING}")
|
|
||||||
string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" PROJECT_VERSION_MINOR "${PROJECT_VERSION_STRING}")
|
|
||||||
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" PROJECT_VERSION_PATCH "${PROJECT_VERSION_STRING}")
|
|
||||||
|
|
||||||
# Prepare the right number of "../.." to go from ECM_MKSPECS_INSTALL_DIR to the install prefix
|
|
||||||
# This allows to make the generated pri files relocatable (no absolute paths)
|
|
||||||
if (IS_ABSOLUTE ${ECM_MKSPECS_INSTALL_DIR})
|
|
||||||
set(BASEPATH ${CMAKE_INSTALL_PREFIX})
|
|
||||||
else()
|
|
||||||
string(REGEX REPLACE "[^/]+" ".." PRI_ROOT_RELATIVE_TO_MKSPECS ${ECM_MKSPECS_INSTALL_DIR})
|
|
||||||
set(BASEPATH "$$PWD/${PRI_ROOT_RELATIVE_TO_MKSPECS}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(PRI_TARGET_BASENAME ${EGPF_BASE_NAME})
|
|
||||||
set(PRI_TARGET_LIBNAME ${EGPF_LIB_NAME})
|
|
||||||
set(PRI_TARGET_QTDEPS ${EGPF_DEPS})
|
|
||||||
if(IS_ABSOLUTE "${EGPF_INCLUDE_INSTALL_DIR}")
|
|
||||||
set(PRI_TARGET_INCLUDES "${EGPF_INCLUDE_INSTALL_DIR}")
|
|
||||||
else()
|
|
||||||
set(PRI_TARGET_INCLUDES "${BASEPATH}/${EGPF_INCLUDE_INSTALL_DIR}")
|
|
||||||
endif()
|
|
||||||
if(IS_ABSOLUTE "${EGPF_LIB_INSTALL_DIR}")
|
|
||||||
set(PRI_TARGET_LIBS "${EGPF_LIB_INSTALL_DIR}")
|
|
||||||
else()
|
|
||||||
set(PRI_TARGET_LIBS "${BASEPATH}/${EGPF_LIB_INSTALL_DIR}")
|
|
||||||
endif()
|
|
||||||
set(PRI_TARGET_DEFINES "")
|
|
||||||
|
|
||||||
set(PRI_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/qt_${PRI_TARGET_BASENAME}.pri)
|
|
||||||
if (EGPF_FILENAME_VAR)
|
|
||||||
set(${EGPF_FILENAME_VAR} ${PRI_FILENAME} PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(PRI_TARGET_MODULE_CONFIG "")
|
|
||||||
# backward compat: it was not obvious LIB_NAME needs to be a target name,
|
|
||||||
# and some projects where the target name was not the actual library output name
|
|
||||||
# passed the output name for LIB_NAME, so .name & .module prperties are correctly set.
|
|
||||||
# TODO: improve API dox, allow control over module name if target name != output name
|
|
||||||
if(TARGET ${EGPF_LIB_NAME})
|
|
||||||
get_target_property(target_type ${EGPF_LIB_NAME} TYPE)
|
|
||||||
if (target_type STREQUAL "STATIC_LIBRARY")
|
|
||||||
set(PRI_TARGET_MODULE_CONFIG "staticlib")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
file(GENERATE
|
|
||||||
OUTPUT ${PRI_FILENAME}
|
|
||||||
CONTENT
|
|
||||||
"QT.${PRI_TARGET_BASENAME}.VERSION = ${PROJECT_VERSION_STRING}
|
|
||||||
QT.${PRI_TARGET_BASENAME}.MAJOR_VERSION = ${PROJECT_VERSION_MAJOR}
|
|
||||||
QT.${PRI_TARGET_BASENAME}.MINOR_VERSION = ${PROJECT_VERSION_MINOR}
|
|
||||||
QT.${PRI_TARGET_BASENAME}.PATCH_VERSION = ${PROJECT_VERSION_PATCH}
|
|
||||||
QT.${PRI_TARGET_BASENAME}.name = ${PRI_TARGET_LIBNAME}
|
|
||||||
QT.${PRI_TARGET_BASENAME}.module = ${PRI_TARGET_LIBNAME}
|
|
||||||
QT.${PRI_TARGET_BASENAME}.defines = ${PRI_TARGET_DEFINES}
|
|
||||||
QT.${PRI_TARGET_BASENAME}.includes = ${PRI_TARGET_INCLUDES}
|
|
||||||
QT.${PRI_TARGET_BASENAME}.private_includes =
|
|
||||||
QT.${PRI_TARGET_BASENAME}.libs = ${PRI_TARGET_LIBS}
|
|
||||||
QT.${PRI_TARGET_BASENAME}.depends = ${PRI_TARGET_QTDEPS}
|
|
||||||
QT.${PRI_TARGET_BASENAME}.module_config = ${PRI_TARGET_MODULE_CONFIG}
|
|
||||||
"
|
|
||||||
)
|
|
||||||
endfunction()
|
|
@ -1,202 +0,0 @@
|
|||||||
#.rst:
|
|
||||||
# ECMPackageConfigHelpers
|
|
||||||
# -----------------------
|
|
||||||
#
|
|
||||||
# Helper macros for generating CMake package config files.
|
|
||||||
#
|
|
||||||
# ``write_basic_package_version_file()`` is the same as the one provided by the
|
|
||||||
# `CMakePackageConfigHelpers
|
|
||||||
# <https://www.cmake.org/cmake/help/v2.8.12/cmake.html#module:CMakePackageConfigHelpers>`_
|
|
||||||
# module in CMake; see that module's documentation for
|
|
||||||
# more information.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# ecm_configure_package_config_file(<input> <output>
|
|
||||||
# INSTALL_DESTINATION <path>
|
|
||||||
# [PATH_VARS <var1> [<var2> [...]]
|
|
||||||
# [NO_SET_AND_CHECK_MACRO]
|
|
||||||
# [NO_CHECK_REQUIRED_COMPONENTS_MACRO])
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# This behaves in the same way as configure_package_config_file() from CMake
|
|
||||||
# 2.8.12, except that it adds an extra helper macro: find_dependency(). It is
|
|
||||||
# highly recommended that you read the `documentation for
|
|
||||||
# CMakePackageConfigHelpers
|
|
||||||
# <https://www.cmake.org/cmake/help/v2.8.12/cmake.html#module:CMakePackageConfigHelpers>`_
|
|
||||||
# for more information, particularly with regard to the PATH_VARS argument.
|
|
||||||
#
|
|
||||||
# Note that there is no argument that will disable the find_dependency() macro;
|
|
||||||
# if you do not require this macro, you should use
|
|
||||||
# ``configure_package_config_file`` from the CMakePackageConfigHelpers module.
|
|
||||||
#
|
|
||||||
# CMake 3.0 includes a CMakeFindDependencyMacro module that provides the
|
|
||||||
# find_dependency() macro (which you can ``include()`` in your package config
|
|
||||||
# file), so this file is only useful for projects wishing to provide config
|
|
||||||
# files that will work with CMake 2.8.12.
|
|
||||||
#
|
|
||||||
# Additional Config File Macros
|
|
||||||
# =============================
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# find_dependency(<dep> [<version> [EXACT]])
|
|
||||||
#
|
|
||||||
# find_dependency() should be used instead of find_package() to find package
|
|
||||||
# dependencies. It forwards the correct parameters for EXACT, QUIET and
|
|
||||||
# REQUIRED which were passed to the original find_package() call. It also sets
|
|
||||||
# an informative diagnostic message if the dependency could not be found.
|
|
||||||
#
|
|
||||||
# Since pre-1.0.0.
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kdemail.net>
|
|
||||||
# SPDX-FileCopyrightText: 2013 Stephen Kelly <steveire@gmail.com>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
include(${CMAKE_ROOT}/Modules/CMakePackageConfigHelpers.cmake)
|
|
||||||
|
|
||||||
set(_ecm_package_config_helpers_included TRUE)
|
|
||||||
|
|
||||||
if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.13)
|
|
||||||
message(AUTHOR_WARNING "Your project already requires a version of CMake that includes the find_dependency macro via the CMakeFindDependencyMacro module. You should use CMakePackageConfigHelpers instead of ECMPackageConfigHelpers.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
function(ECM_CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile)
|
|
||||||
set(options NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO)
|
|
||||||
set(oneValueArgs INSTALL_DESTINATION )
|
|
||||||
set(multiValueArgs PATH_VARS )
|
|
||||||
|
|
||||||
cmake_parse_arguments(CCF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if(CCF_UNPARSED_ARGUMENTS)
|
|
||||||
message(FATAL_ERROR "Unknown keywords given to CONFIGURE_PACKAGE_CONFIG_FILE(): \"${CCF_UNPARSED_ARGUMENTS}\"")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CCF_INSTALL_DESTINATION)
|
|
||||||
message(FATAL_ERROR "No INSTALL_DESTINATION given to CONFIGURE_PACKAGE_CONFIG_FILE()")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(IS_ABSOLUTE "${CCF_INSTALL_DESTINATION}")
|
|
||||||
set(absInstallDir "${CCF_INSTALL_DESTINATION}")
|
|
||||||
else()
|
|
||||||
set(absInstallDir "${CMAKE_INSTALL_PREFIX}/${CCF_INSTALL_DESTINATION}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
file(RELATIVE_PATH PACKAGE_RELATIVE_PATH "${absInstallDir}" "${CMAKE_INSTALL_PREFIX}" )
|
|
||||||
|
|
||||||
foreach(var ${CCF_PATH_VARS})
|
|
||||||
if(NOT DEFINED ${var})
|
|
||||||
message(FATAL_ERROR "Variable ${var} does not exist")
|
|
||||||
else()
|
|
||||||
if(IS_ABSOLUTE "${${var}}")
|
|
||||||
string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${PACKAGE_PREFIX_DIR}"
|
|
||||||
PACKAGE_${var} "${${var}}")
|
|
||||||
else()
|
|
||||||
set(PACKAGE_${var} "\${PACKAGE_PREFIX_DIR}/${${var}}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
get_filename_component(inputFileName "${_inputFile}" NAME)
|
|
||||||
|
|
||||||
set(PACKAGE_INIT "
|
|
||||||
####### Expanded from @PACKAGE_INIT@ by configure_package_config_file() (ECM variant) #######
|
|
||||||
####### Any changes to this file will be overwritten by the next CMake run #######
|
|
||||||
####### The input file was ${inputFileName} #######
|
|
||||||
|
|
||||||
get_filename_component(PACKAGE_PREFIX_DIR \"\${CMAKE_CURRENT_LIST_DIR}/${PACKAGE_RELATIVE_PATH}\" ABSOLUTE)
|
|
||||||
")
|
|
||||||
|
|
||||||
if("${absInstallDir}" MATCHES "^(/usr)?/lib(64)?/.+")
|
|
||||||
# Handle "/usr move" symlinks created by some Linux distros.
|
|
||||||
set(PACKAGE_INIT "${PACKAGE_INIT}
|
|
||||||
# Use original install prefix when loaded through a \"/usr move\"
|
|
||||||
# cross-prefix symbolic link such as /lib -> /usr/lib.
|
|
||||||
get_filename_component(_realCurr \"\${CMAKE_CURRENT_LIST_DIR}\" REALPATH)
|
|
||||||
get_filename_component(_realOrig \"${absInstallDir}\" REALPATH)
|
|
||||||
if(_realCurr STREQUAL _realOrig)
|
|
||||||
set(PACKAGE_PREFIX_DIR \"${CMAKE_INSTALL_PREFIX}\")
|
|
||||||
endif()
|
|
||||||
unset(_realOrig)
|
|
||||||
unset(_realCurr)
|
|
||||||
")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CCF_NO_SET_AND_CHECK_MACRO)
|
|
||||||
set(PACKAGE_INIT "${PACKAGE_INIT}
|
|
||||||
macro(set_and_check _var _file)
|
|
||||||
set(\${_var} \"\${_file}\")
|
|
||||||
if(NOT EXISTS \"\${_file}\")
|
|
||||||
message(FATAL_ERROR \"File or directory \${_file} referenced by variable \${_var} does not exist !\")
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
include(CMakeFindDependencyMacro OPTIONAL RESULT_VARIABLE _CMakeFindDependencyMacro_FOUND)
|
|
||||||
|
|
||||||
if (NOT _CMakeFindDependencyMacro_FOUND)
|
|
||||||
macro(find_dependency dep)
|
|
||||||
if (NOT \${dep}_FOUND)
|
|
||||||
|
|
||||||
set(ecm_fd_version)
|
|
||||||
if (\${ARGC} GREATER 1)
|
|
||||||
set(ecm_fd_version \${ARGV1})
|
|
||||||
endif()
|
|
||||||
set(ecm_fd_exact_arg)
|
|
||||||
if(\${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION_EXACT)
|
|
||||||
set(ecm_fd_exact_arg EXACT)
|
|
||||||
endif()
|
|
||||||
set(ecm_fd_quiet_arg)
|
|
||||||
if(\${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
|
|
||||||
set(ecm_fd_quiet_arg QUIET)
|
|
||||||
endif()
|
|
||||||
set(ecm_fd_required_arg)
|
|
||||||
if(\${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED)
|
|
||||||
set(ecm_fd_required_arg REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(\${dep} \${ecm_fd_version}
|
|
||||||
\${ecm_fd_exact_arg}
|
|
||||||
\${ecm_fd_quiet_arg}
|
|
||||||
\${ecm_fd_required_arg}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (NOT \${dep}_FOUND)
|
|
||||||
set(\${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE \"\${CMAKE_FIND_PACKAGE_NAME} could not be found because dependency \${dep} could not be found.\")
|
|
||||||
set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND False)
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(ecm_fd_version)
|
|
||||||
set(ecm_fd_required_arg)
|
|
||||||
set(ecm_fd_quiet_arg)
|
|
||||||
set(ecm_fd_exact_arg)
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
if(NOT CCF_NO_CHECK_REQUIRED_COMPONENTS_MACRO)
|
|
||||||
set(PACKAGE_INIT "${PACKAGE_INIT}
|
|
||||||
macro(check_required_components _NAME)
|
|
||||||
foreach(comp \${\${_NAME}_FIND_COMPONENTS})
|
|
||||||
if(NOT \${_NAME}_\${comp}_FOUND)
|
|
||||||
if(\${_NAME}_FIND_REQUIRED_\${comp})
|
|
||||||
set(\${_NAME}_FOUND FALSE)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endmacro()
|
|
||||||
")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(PACKAGE_INIT "${PACKAGE_INIT}
|
|
||||||
####################################################################################")
|
|
||||||
|
|
||||||
configure_file("${_inputFile}" "${_outputFile}" @ONLY)
|
|
||||||
|
|
||||||
endfunction()
|
|
@ -1,46 +0,0 @@
|
|||||||
find_package(Qt5Core QUIET)
|
|
||||||
|
|
||||||
if (Qt5Core_FOUND)
|
|
||||||
set(_qmake_executable_default "qmake-qt5")
|
|
||||||
endif ()
|
|
||||||
if (TARGET Qt5::qmake)
|
|
||||||
get_target_property(_qmake_executable_default Qt5::qmake LOCATION)
|
|
||||||
endif()
|
|
||||||
set(QMAKE_EXECUTABLE ${_qmake_executable_default}
|
|
||||||
CACHE FILEPATH "Location of the Qt5 qmake executable")
|
|
||||||
|
|
||||||
# Helper method
|
|
||||||
# This is not public API (yet)!
|
|
||||||
# Usage: query_qmake(<result_variable> <qt_variable> [TRY])
|
|
||||||
# Passing TRY will result in the method not failing fatal if no qmake executable
|
|
||||||
# has been found, but instead simply returning an empty string
|
|
||||||
function(query_qmake result_variable qt_variable)
|
|
||||||
set(options TRY)
|
|
||||||
set(oneValueArgs )
|
|
||||||
set(multiValueArgs )
|
|
||||||
|
|
||||||
cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if(NOT QMAKE_EXECUTABLE)
|
|
||||||
if(ARGS_TRY)
|
|
||||||
set(${result_variable} "" PARENT_SCOPE)
|
|
||||||
message(STATUS "No qmake Qt5 binary found. Can't check ${qt_variable}")
|
|
||||||
return()
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "No qmake Qt5 binary found. Can't check ${qt_variable} as required")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${QMAKE_EXECUTABLE} -query "${qt_variable}"
|
|
||||||
RESULT_VARIABLE return_code
|
|
||||||
OUTPUT_VARIABLE output
|
|
||||||
)
|
|
||||||
if(return_code EQUAL 0)
|
|
||||||
string(STRIP "${output}" output)
|
|
||||||
file(TO_CMAKE_PATH "${output}" output_path)
|
|
||||||
set(${result_variable} "${output_path}" PARENT_SCOPE)
|
|
||||||
else()
|
|
||||||
message(WARNING "Failed call: ${QMAKE_EXECUTABLE} -query \"${qt_variable}\"")
|
|
||||||
message(FATAL_ERROR "QMake call failed: ${return_code}")
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
@ -1,202 +0,0 @@
|
|||||||
#.rst:
|
|
||||||
# ECMSetupVersion
|
|
||||||
# ---------------
|
|
||||||
#
|
|
||||||
# Handle library version information.
|
|
||||||
#
|
|
||||||
# ::
|
|
||||||
#
|
|
||||||
# ecm_setup_version(<version>
|
|
||||||
# VARIABLE_PREFIX <prefix>
|
|
||||||
# [SOVERSION <soversion>]
|
|
||||||
# [VERSION_HEADER <filename>]
|
|
||||||
# [PACKAGE_VERSION_FILE <filename> [COMPATIBILITY <compat>]] )
|
|
||||||
#
|
|
||||||
# This parses a version string and sets up a standard set of version variables.
|
|
||||||
# It can optionally also create a C version header file and a CMake package
|
|
||||||
# version file to install along with the library.
|
|
||||||
#
|
|
||||||
# If the ``<version>`` argument is of the form ``<major>.<minor>.<patch>``
|
|
||||||
# (or ``<major>.<minor>.<patch>.<tweak>``), The following CMake variables are
|
|
||||||
# set::
|
|
||||||
#
|
|
||||||
# <prefix>_VERSION_MAJOR - <major>
|
|
||||||
# <prefix>_VERSION_MINOR - <minor>
|
|
||||||
# <prefix>_VERSION_PATCH - <patch>
|
|
||||||
# <prefix>_VERSION - <version>
|
|
||||||
# <prefix>_VERSION_STRING - <version> (for compatibility: use <prefix>_VERSION instead)
|
|
||||||
# <prefix>_SOVERSION - <soversion>, or <major> if SOVERSION was not given
|
|
||||||
#
|
|
||||||
# If CMake policy CMP0048 is not NEW, the following CMake variables will also
|
|
||||||
# be set::
|
|
||||||
#
|
|
||||||
# PROJECT_VERSION_MAJOR - <major>
|
|
||||||
# PROJECT_VERSION_MINOR - <minor>
|
|
||||||
# PROJECT_VERSION_PATCH - <patch>
|
|
||||||
# PROJECT_VERSION - <version>
|
|
||||||
# PROJECT_VERSION_STRING - <version> (for compatibility: use PROJECT_VERSION instead)
|
|
||||||
#
|
|
||||||
# If the VERSION_HEADER option is used, a simple C header is generated with the
|
|
||||||
# given filename. If filename is a relative path, it is interpreted as relative
|
|
||||||
# to CMAKE_CURRENT_BINARY_DIR. The generated header contains the following
|
|
||||||
# macros::
|
|
||||||
#
|
|
||||||
# <prefix>_VERSION_MAJOR - <major> as an integer
|
|
||||||
# <prefix>_VERSION_MINOR - <minor> as an integer
|
|
||||||
# <prefix>_VERSION_PATCH - <patch> as an integer
|
|
||||||
# <prefix>_VERSION_STRING - <version> as a C string
|
|
||||||
# <prefix>_VERSION - the version as an integer
|
|
||||||
#
|
|
||||||
# ``<prefix>_VERSION`` has ``<patch>`` in the bottom 8 bits, ``<minor>`` in the
|
|
||||||
# next 8 bits and ``<major>`` in the remaining bits. Note that ``<patch>`` and
|
|
||||||
# ``<minor>`` must be less than 256.
|
|
||||||
#
|
|
||||||
# If the PACKAGE_VERSION_FILE option is used, a simple CMake package version
|
|
||||||
# file is created using the write_basic_package_version_file() macro provided by
|
|
||||||
# CMake. It should be installed in the same location as the Config.cmake file of
|
|
||||||
# the library so that it can be found by find_package(). If the filename is a
|
|
||||||
# relative path, it is interpreted as relative to CMAKE_CURRENT_BINARY_DIR. The
|
|
||||||
# optional COMPATIBILITY option is forwarded to
|
|
||||||
# write_basic_package_version_file(), and defaults to AnyNewerVersion.
|
|
||||||
#
|
|
||||||
# If CMake policy CMP0048 is NEW, an alternative form of the command is
|
|
||||||
# available::
|
|
||||||
#
|
|
||||||
# ecm_setup_version(PROJECT
|
|
||||||
# [VARIABLE_PREFIX <prefix>]
|
|
||||||
# [SOVERSION <soversion>]
|
|
||||||
# [VERSION_HEADER <filename>]
|
|
||||||
# [PACKAGE_VERSION_FILE <filename>] )
|
|
||||||
#
|
|
||||||
# This will use the version information set by the project() command.
|
|
||||||
# VARIABLE_PREFIX defaults to the project name. Note that PROJECT must be the
|
|
||||||
# first argument. In all other respects, it behaves like the other form of the
|
|
||||||
# command.
|
|
||||||
#
|
|
||||||
# Since pre-1.0.0.
|
|
||||||
#
|
|
||||||
# COMPATIBILITY option available since 1.6.0.
|
|
||||||
|
|
||||||
#=============================================================================
|
|
||||||
# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org>
|
|
||||||
# SPDX-FileCopyrightText: 2012 Alexander Neundorf <neundorf@kde.org>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
|
|
||||||
# save the location of the header template while CMAKE_CURRENT_LIST_DIR
|
|
||||||
# has the value we want
|
|
||||||
set(_ECM_SETUP_VERSION_HEADER_TEMPLATE "${CMAKE_CURRENT_LIST_DIR}/ECMVersionHeader.h.in")
|
|
||||||
|
|
||||||
function(ecm_setup_version _version)
|
|
||||||
set(options )
|
|
||||||
set(oneValueArgs VARIABLE_PREFIX SOVERSION VERSION_HEADER PACKAGE_VERSION_FILE COMPATIBILITY)
|
|
||||||
set(multiValueArgs )
|
|
||||||
|
|
||||||
cmake_parse_arguments(ESV "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
if(ESV_UNPARSED_ARGUMENTS)
|
|
||||||
message(FATAL_ERROR "Unknown keywords given to ECM_SETUP_VERSION(): \"${ESV_UNPARSED_ARGUMENTS}\"")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(project_manages_version FALSE)
|
|
||||||
set(use_project_version FALSE)
|
|
||||||
# CMP0048 only exists in CMake 3.0.0 and later
|
|
||||||
if(CMAKE_VERSION VERSION_LESS 3.0.0)
|
|
||||||
set(project_version_policy "OLD")
|
|
||||||
else()
|
|
||||||
cmake_policy(GET CMP0048 project_version_policy)
|
|
||||||
endif()
|
|
||||||
if(project_version_policy STREQUAL "NEW")
|
|
||||||
set(project_manages_version TRUE)
|
|
||||||
if(_version STREQUAL "PROJECT")
|
|
||||||
set(use_project_version TRUE)
|
|
||||||
endif()
|
|
||||||
elseif(_version STREQUAL "PROJECT")
|
|
||||||
message(FATAL_ERROR "ecm_setup_version given PROJECT argument, but CMP0048 is not NEW")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(should_set_prefixed_vars TRUE)
|
|
||||||
if(NOT ESV_VARIABLE_PREFIX)
|
|
||||||
if(use_project_version)
|
|
||||||
set(ESV_VARIABLE_PREFIX "${PROJECT_NAME}")
|
|
||||||
set(should_set_prefixed_vars FALSE)
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Required argument PREFIX missing in ECM_SETUP_VERSION() call")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(use_project_version)
|
|
||||||
set(_version "${PROJECT_VERSION}")
|
|
||||||
set(_major "${PROJECT_VERSION_MAJOR}")
|
|
||||||
set(_minor "${PROJECT_VERSION_MINOR}")
|
|
||||||
set(_patch "${PROJECT_VERSION_PATCH}")
|
|
||||||
else()
|
|
||||||
string(REGEX REPLACE "^0*([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _major "${_version}")
|
|
||||||
string(REGEX REPLACE "^[0-9]+\\.0*([0-9]+)\\.[0-9]+.*" "\\1" _minor "${_version}")
|
|
||||||
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.0*([0-9]+).*" "\\1" _patch "${_version}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT ESV_SOVERSION)
|
|
||||||
set(ESV_SOVERSION ${_major})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(should_set_prefixed_vars)
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_VERSION "${_version}")
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_VERSION_MAJOR ${_major})
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_VERSION_MINOR ${_minor})
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_VERSION_PATCH ${_patch})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_SOVERSION ${ESV_SOVERSION})
|
|
||||||
|
|
||||||
if(NOT project_manages_version)
|
|
||||||
set(PROJECT_VERSION "${_version}")
|
|
||||||
set(PROJECT_VERSION_MAJOR "${_major}")
|
|
||||||
set(PROJECT_VERSION_MINOR "${_minor}")
|
|
||||||
set(PROJECT_VERSION_PATCH "${_patch}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# compat
|
|
||||||
set(PROJECT_VERSION_STRING "${PROJECT_VERSION}")
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_VERSION_STRING "${${ESV_VARIABLE_PREFIX}_VERSION}")
|
|
||||||
|
|
||||||
if(ESV_VERSION_HEADER)
|
|
||||||
set(HEADER_PREFIX "${ESV_VARIABLE_PREFIX}")
|
|
||||||
set(HEADER_VERSION "${_version}")
|
|
||||||
set(HEADER_VERSION_MAJOR "${_major}")
|
|
||||||
set(HEADER_VERSION_MINOR "${_minor}")
|
|
||||||
set(HEADER_VERSION_PATCH "${_patch}")
|
|
||||||
configure_file("${_ECM_SETUP_VERSION_HEADER_TEMPLATE}" "${ESV_VERSION_HEADER}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(ESV_PACKAGE_VERSION_FILE)
|
|
||||||
if(NOT ESV_COMPATIBILITY)
|
|
||||||
set(ESV_COMPATIBILITY AnyNewerVersion)
|
|
||||||
endif()
|
|
||||||
write_basic_package_version_file("${ESV_PACKAGE_VERSION_FILE}" VERSION ${_version} COMPATIBILITY ${ESV_COMPATIBILITY})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(should_set_prefixed_vars)
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_VERSION_MAJOR "${${ESV_VARIABLE_PREFIX}_VERSION_MAJOR}" PARENT_SCOPE)
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_VERSION_MINOR "${${ESV_VARIABLE_PREFIX}_VERSION_MINOR}" PARENT_SCOPE)
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_VERSION_PATCH "${${ESV_VARIABLE_PREFIX}_VERSION_PATCH}" PARENT_SCOPE)
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_VERSION "${${ESV_VARIABLE_PREFIX}_VERSION}" PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# always set the soversion
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_SOVERSION "${${ESV_VARIABLE_PREFIX}_SOVERSION}" PARENT_SCOPE)
|
|
||||||
|
|
||||||
if(NOT project_manages_version)
|
|
||||||
set(PROJECT_VERSION "${PROJECT_VERSION}" PARENT_SCOPE)
|
|
||||||
set(PROJECT_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}" PARENT_SCOPE)
|
|
||||||
set(PROJECT_VERSION_MINOR "${PROJECT_VERSION_MINOR}" PARENT_SCOPE)
|
|
||||||
set(PROJECT_VERSION_PATCH "${PROJECT_VERSION_PATCH}" PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# always set the compatibility variables
|
|
||||||
set(PROJECT_VERSION_STRING "${PROJECT_VERSION_STRING}" PARENT_SCOPE)
|
|
||||||
set(${ESV_VARIABLE_PREFIX}_VERSION_STRING "${${ESV_VARIABLE_PREFIX}_VERSION}" PARENT_SCOPE)
|
|
||||||
|
|
||||||
endfunction()
|
|
@ -1,188 +0,0 @@
|
|||||||
# - 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()
|
|
@ -1,86 +0,0 @@
|
|||||||
#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* type,
|
|
||||||
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,
|
|
||||||
"type", type,
|
|
||||||
static_cast<char*>(0) );
|
|
||||||
}
|
|
||||||
|
|
||||||
GnomeKeyring::gpointer GnomeKeyring::find_network_password(
|
|
||||||
const gchar* user, const gchar* server, const gchar* type,
|
|
||||||
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, "type", type,
|
|
||||||
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(QLatin1String("gnome-keyring"), 0)
|
|
||||||
{
|
|
||||||
static const PasswordSchema schema = {
|
|
||||||
ITEM_NETWORK_PASSWORD,
|
|
||||||
{{ "user", ATTRIBUTE_TYPE_STRING },
|
|
||||||
{ "server", ATTRIBUTE_TYPE_STRING },
|
|
||||||
{ "type", 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;
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
#ifndef QTKEYCHAIN_GNOME_P_H
|
|
||||||
#define QTKEYCHAIN_GNOME_P_H
|
|
||||||
|
|
||||||
#include <QLibrary>
|
|
||||||
|
|
||||||
class GnomeKeyring : private QLibrary {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
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, bool binary,
|
|
||||||
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* type, const gchar* password,
|
|
||||||
OperationDoneCallback callback, gpointer data, GDestroyNotify destroy_data );
|
|
||||||
|
|
||||||
static gpointer find_network_password( const gchar* user, const gchar* server,
|
|
||||||
const gchar* type,
|
|
||||||
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
|
|
@ -1,235 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* 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( JobPrivate *q, QObject *parent )
|
|
||||||
: QObject( parent )
|
|
||||||
, d ( q ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
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::doStart() {
|
|
||||||
JobExecutor::instance()->enqueue( this );
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Job::scheduledStart() {
|
|
||||||
d->scheduledStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
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( new ReadPasswordJobPrivate( service, this ), parent ) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadPasswordJob::~ReadPasswordJob() {
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ReadPasswordJob::textData() const {
|
|
||||||
return QString::fromUtf8( d->data );
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray ReadPasswordJob::binaryData() const {
|
|
||||||
return d->data;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Job::key() const {
|
|
||||||
return d->key;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Job::setKey( const QString& key_ ) {
|
|
||||||
d->key = key_;
|
|
||||||
}
|
|
||||||
|
|
||||||
WritePasswordJob::WritePasswordJob( const QString& service, QObject* parent )
|
|
||||||
: Job( new WritePasswordJobPrivate( service, this ), parent ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
WritePasswordJob::~WritePasswordJob() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void WritePasswordJob::setBinaryData( const QByteArray& data ) {
|
|
||||||
d->data = data;
|
|
||||||
d->mode = JobPrivate::Binary;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WritePasswordJob::setTextData( const QString& data ) {
|
|
||||||
d->data = data.toUtf8();
|
|
||||||
d->mode = JobPrivate::Text;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeletePasswordJob::DeletePasswordJob( const QString& service, QObject* parent )
|
|
||||||
: Job( new DeletePasswordJobPrivate( service, this ), parent ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
DeletePasswordJob::~DeletePasswordJob() {
|
|
||||||
}
|
|
||||||
|
|
||||||
DeletePasswordJobPrivate::DeletePasswordJobPrivate(const QString &service_, DeletePasswordJob *qq) :
|
|
||||||
JobPrivate(service_, qq) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JobExecutor::JobExecutor()
|
|
||||||
: QObject( 0 )
|
|
||||||
, m_jobRunning( false ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void JobExecutor::enqueue( Job* job ) {
|
|
||||||
m_queue.enqueue( job );
|
|
||||||
startNextIfNoneRunning();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JobExecutor::startNextIfNoneRunning() {
|
|
||||||
if ( m_queue.isEmpty() || m_jobRunning )
|
|
||||||
return;
|
|
||||||
QPointer<Job> next;
|
|
||||||
while ( !next && !m_queue.isEmpty() ) {
|
|
||||||
next = m_queue.dequeue();
|
|
||||||
}
|
|
||||||
if ( next ) {
|
|
||||||
connect( next, SIGNAL(finished(QKeychain::Job*)), this, SLOT(jobFinished(QKeychain::Job*)) );
|
|
||||||
connect( next, SIGNAL(destroyed(QObject*)), this, SLOT(jobDestroyed(QObject*)) );
|
|
||||||
m_jobRunning = true;
|
|
||||||
next->scheduledStart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void JobExecutor::jobDestroyed( QObject* object ) {
|
|
||||||
Job* job = static_cast<Job*>(object);
|
|
||||||
Q_UNUSED( object ) // for release mode
|
|
||||||
job->disconnect( this );
|
|
||||||
m_jobRunning = false;
|
|
||||||
startNextIfNoneRunning();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JobExecutor::jobFinished( Job* job ) {
|
|
||||||
Q_UNUSED( job ) // for release mode
|
|
||||||
job->disconnect( this );
|
|
||||||
m_jobRunning = false;
|
|
||||||
startNextIfNoneRunning();
|
|
||||||
}
|
|
||||||
|
|
||||||
JobExecutor* JobExecutor::s_instance = 0;
|
|
||||||
|
|
||||||
JobExecutor* JobExecutor::instance() {
|
|
||||||
if ( !s_instance )
|
|
||||||
s_instance = new JobExecutor;
|
|
||||||
return s_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadPasswordJobPrivate::ReadPasswordJobPrivate(const QString &service_, ReadPasswordJob *qq) :
|
|
||||||
JobPrivate(service_, qq) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JobPrivate::JobPrivate(const QString &service_, Job *qq)
|
|
||||||
: q(qq)
|
|
||||||
, mode( Text )
|
|
||||||
, error( NoError )
|
|
||||||
, service( service_ )
|
|
||||||
, autoDelete( true )
|
|
||||||
, insecureFallback( false )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QString JobPrivate::modeToString(Mode m)
|
|
||||||
{
|
|
||||||
switch (m) {
|
|
||||||
case Text:
|
|
||||||
return QLatin1String("Text");
|
|
||||||
case Binary:
|
|
||||||
return QLatin1String("Binary");
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Unhandled Mode value");
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
JobPrivate::Mode JobPrivate::stringToMode(const QString& s)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
WritePasswordJobPrivate::WritePasswordJobPrivate(const QString &service_, WritePasswordJob *qq) :
|
|
||||||
JobPrivate(service_, qq) {
|
|
||||||
|
|
||||||
}
|
|
@ -1,271 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* 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
|
|
||||||
|
|
||||||
#if !defined(QTKEYCHAIN_NO_EXPORT)
|
|
||||||
#include "qkeychain_export.h"
|
|
||||||
#else
|
|
||||||
#define QKEYCHAIN_EXPORT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Abstract base class for all QKeychain jobs.
|
|
||||||
*/
|
|
||||||
class QKEYCHAIN_EXPORT Job : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
~Job() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The QSettings instance used as plaintext storage if insecureFallback() is true.
|
|
||||||
* @see setSettings()
|
|
||||||
* @see insecureFallback()
|
|
||||||
*/
|
|
||||||
QSettings* settings() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Set the QSettings instance that will be used as plaintext storage if insecureFallback() is true.
|
|
||||||
* @see settings()
|
|
||||||
* @see insecureFallback()
|
|
||||||
*/
|
|
||||||
void setSettings( QSettings* settings );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this method to start the job.
|
|
||||||
* Typically you want to connect some slot to the finished() signal first:
|
|
||||||
*
|
|
||||||
* \code
|
|
||||||
* SomeClass::startJob()
|
|
||||||
* {
|
|
||||||
* connect(job, &Job::finished, this, &SomeClass::slotJobFinished);
|
|
||||||
* job->start();
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* SomeClass::slotJobFinished(Job *job)
|
|
||||||
* {
|
|
||||||
* if (job->error()) {
|
|
||||||
* // handle error
|
|
||||||
* } else {
|
|
||||||
* // do job-specific stuff
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* \endcode
|
|
||||||
*
|
|
||||||
* @see finished()
|
|
||||||
*/
|
|
||||||
void start();
|
|
||||||
|
|
||||||
QString service() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @note Call this method only after finished() has been emitted.
|
|
||||||
* @return The error code of the job (0 if no error).
|
|
||||||
*/
|
|
||||||
Error error() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return An error message that might provide details if error() returns OtherError.
|
|
||||||
*/
|
|
||||||
QString errorString() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Whether this job autodeletes itself once finished() has been emitted. Default is true.
|
|
||||||
* @see setAutoDelete()
|
|
||||||
*/
|
|
||||||
bool autoDelete() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set whether this job should autodelete itself once finished() has been emitted.
|
|
||||||
* @see autoDelete()
|
|
||||||
*/
|
|
||||||
void setAutoDelete( bool autoDelete );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Whether this job will use plaintext storage on unsupported platforms. Default is false.
|
|
||||||
* @see setInsecureFallback()
|
|
||||||
*/
|
|
||||||
bool insecureFallback() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set whether this job should use plaintext storage on unsupported platforms.
|
|
||||||
* @see insecureFallback()
|
|
||||||
*/
|
|
||||||
void setInsecureFallback( bool insecureFallback );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The string used as key by this job.
|
|
||||||
* @see setKey()
|
|
||||||
*/
|
|
||||||
QString key() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the @p key that this job will use to read or write data from/to the keychain.
|
|
||||||
* The key can be an empty string.
|
|
||||||
* @see key()
|
|
||||||
*/
|
|
||||||
void setKey( const QString& key );
|
|
||||||
|
|
||||||
void emitFinished();
|
|
||||||
void emitFinishedWithError(Error, const QString& errorString);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
/**
|
|
||||||
* Emitted when this job is finished.
|
|
||||||
* You can connect to this signal to be notified about the job's completion.
|
|
||||||
* @see start()
|
|
||||||
*/
|
|
||||||
void finished( QKeychain::Job* );
|
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit Job( JobPrivate *q, QObject* parent=nullptr );
|
|
||||||
Q_INVOKABLE void doStart();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setError( Error error );
|
|
||||||
void setErrorString( const QString& errorString );
|
|
||||||
|
|
||||||
void scheduledStart();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
JobPrivate* const d;
|
|
||||||
|
|
||||||
friend class JobExecutor;
|
|
||||||
friend class JobPrivate;
|
|
||||||
friend class ReadPasswordJobPrivate;
|
|
||||||
friend class WritePasswordJobPrivate;
|
|
||||||
friend class DeletePasswordJobPrivate;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ReadPasswordJobPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Job for reading secrets from the keychain.
|
|
||||||
* You can use a ReadPasswordJob to read passwords or binary data from the keychain.
|
|
||||||
* This job requires a "service" string, which is basically a namespace of keys within the keychain.
|
|
||||||
* This means that you can read all the pairs <key, secret> stored in the same service string.
|
|
||||||
*/
|
|
||||||
class QKEYCHAIN_EXPORT ReadPasswordJob : public Job {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a new ReadPasswordJob.
|
|
||||||
* @param service The service string used by this job (can be empty).
|
|
||||||
* @param parent The parent of this job.
|
|
||||||
*/
|
|
||||||
explicit ReadPasswordJob( const QString& service, QObject* parent=nullptr );
|
|
||||||
~ReadPasswordJob() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The binary data stored as value of this job's key().
|
|
||||||
* @see Job::key()
|
|
||||||
*/
|
|
||||||
QByteArray binaryData() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The string stored as value of this job's key().
|
|
||||||
* @see Job::key()
|
|
||||||
* @warning Returns meaningless data if the data was stored as binary data.
|
|
||||||
* @see WritePasswordJob::setTextData()
|
|
||||||
*/
|
|
||||||
QString textData() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class QKeychain::ReadPasswordJobPrivate;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WritePasswordJobPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Job for writing secrets to the keychain.
|
|
||||||
* You can use a WritePasswordJob to store passwords or binary data in the keychain.
|
|
||||||
* This job requires a "service" string, which is basically a namespace of keys within the keychain.
|
|
||||||
* This means that you can store different pairs <key, secret> under the same service string.
|
|
||||||
*/
|
|
||||||
class QKEYCHAIN_EXPORT WritePasswordJob : public Job {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a new WritePasswordJob.
|
|
||||||
* @param service The service string used by this job (can be empty).
|
|
||||||
* @param parent The parent of this job.
|
|
||||||
*/
|
|
||||||
explicit WritePasswordJob( const QString& service, QObject* parent=nullptr );
|
|
||||||
~WritePasswordJob() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the @p data that the job will store in the keychain as binary data.
|
|
||||||
* @warning setBinaryData() and setTextData() are mutually exclusive.
|
|
||||||
*/
|
|
||||||
void setBinaryData( const QByteArray& data );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the @p data that the job will store in the keychain as string.
|
|
||||||
* Typically @p data is a password.
|
|
||||||
* @warning setBinaryData() and setTextData() are mutually exclusive.
|
|
||||||
*/
|
|
||||||
void setTextData( const QString& data );
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
friend class QKeychain::WritePasswordJobPrivate;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DeletePasswordJobPrivate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Job for deleting secrets from the keychain.
|
|
||||||
* You can use a DeletePasswordJob to delete passwords or binary data from the keychain.
|
|
||||||
* This job requires a "service" string, which is basically a namespace of keys within the keychain.
|
|
||||||
* This means that you can delete all the pairs <key, secret> stored in the same service string.
|
|
||||||
*/
|
|
||||||
class QKEYCHAIN_EXPORT DeletePasswordJob : public Job {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Create a new DeletePasswordJob.
|
|
||||||
* @param service The service string used by this job (can be empty).
|
|
||||||
* @param parent The parent of this job.
|
|
||||||
*/
|
|
||||||
explicit DeletePasswordJob( const QString& service, QObject* parent=nullptr );
|
|
||||||
~DeletePasswordJob() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class QKeychain::DeletePasswordJobPrivate;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace QtKeychain
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,182 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (C) 2016 Mathias Hasselmann <mathias.hasselmann@kdab.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 "androidkeystore_p.h"
|
|
||||||
#include "plaintextstore_p.h"
|
|
||||||
|
|
||||||
#include <QtAndroid>
|
|
||||||
|
|
||||||
using namespace QKeychain;
|
|
||||||
|
|
||||||
using android::content::Context;
|
|
||||||
using android::security::KeyPairGeneratorSpec;
|
|
||||||
|
|
||||||
using java::io::ByteArrayInputStream;
|
|
||||||
using java::io::ByteArrayOutputStream;
|
|
||||||
using java::security::interfaces::RSAPrivateKey;
|
|
||||||
using java::security::interfaces::RSAPublicKey;
|
|
||||||
using java::security::KeyPair;
|
|
||||||
using java::security::KeyPairGenerator;
|
|
||||||
using java::security::KeyStore;
|
|
||||||
using java::util::Calendar;
|
|
||||||
|
|
||||||
using javax::crypto::Cipher;
|
|
||||||
using javax::crypto::CipherInputStream;
|
|
||||||
using javax::crypto::CipherOutputStream;
|
|
||||||
using javax::security::auth::x500::X500Principal;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
inline QString makeAlias(const QString &service, const QString &key)
|
|
||||||
{
|
|
||||||
return service + QLatin1Char('/') + key;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadPasswordJobPrivate::scheduledStart()
|
|
||||||
{
|
|
||||||
PlainTextStore plainTextStore(q->service(), q->settings());
|
|
||||||
|
|
||||||
if (!plainTextStore.contains(q->key())) {
|
|
||||||
q->emitFinishedWithError(Error::EntryNotFound, tr("Entry not found"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QByteArray &encryptedData = plainTextStore.readData(q->key());
|
|
||||||
const KeyStore keyStore = KeyStore::getInstance(QStringLiteral("AndroidKeyStore"));
|
|
||||||
|
|
||||||
if (!keyStore || !keyStore.load()) {
|
|
||||||
q->emitFinishedWithError(Error::AccessDenied, tr("Could not open keystore"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &alias = makeAlias(q->service(), q->key());
|
|
||||||
const KeyStore::PrivateKeyEntry entry = keyStore.getEntry(alias);
|
|
||||||
|
|
||||||
if (!entry) {
|
|
||||||
q->emitFinishedWithError(Error::AccessDenied, tr("Could not retrieve private key from keystore"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Cipher cipher = Cipher::getInstance(QStringLiteral("RSA/ECB/PKCS1Padding"));
|
|
||||||
|
|
||||||
if (!cipher || !cipher.init(Cipher::DECRYPT_MODE, entry.getPrivateKey())) {
|
|
||||||
q->emitFinishedWithError(Error::OtherError, tr("Could not create decryption cipher"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray plainData;
|
|
||||||
const CipherInputStream inputStream(ByteArrayInputStream(encryptedData), cipher);
|
|
||||||
|
|
||||||
for (int nextByte; (nextByte = inputStream.read()) != -1; )
|
|
||||||
plainData.append(nextByte);
|
|
||||||
|
|
||||||
mode = plainTextStore.readMode(q->key());
|
|
||||||
data = plainData;
|
|
||||||
q->emitFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WritePasswordJobPrivate::scheduledStart()
|
|
||||||
{
|
|
||||||
const KeyStore keyStore = KeyStore::getInstance(QStringLiteral("AndroidKeyStore"));
|
|
||||||
|
|
||||||
if (!keyStore || !keyStore.load()) {
|
|
||||||
q->emitFinishedWithError(Error::AccessDenied, tr("Could not open keystore"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &alias = makeAlias(q->service(), q->key());
|
|
||||||
if (!keyStore.containsAlias(alias)) {
|
|
||||||
const Calendar start = Calendar::getInstance();
|
|
||||||
const Calendar end = Calendar::getInstance();
|
|
||||||
end.add(Calendar::YEAR, 99);
|
|
||||||
|
|
||||||
const KeyPairGeneratorSpec spec =
|
|
||||||
KeyPairGeneratorSpec::Builder(Context(QtAndroid::androidActivity())).
|
|
||||||
setAlias(alias).
|
|
||||||
setSubject(X500Principal(QStringLiteral("CN=QtKeychain, O=Android Authority"))).
|
|
||||||
setSerialNumber(java::math::BigInteger::ONE).
|
|
||||||
setStartDate(start.getTime()).
|
|
||||||
setEndDate(end.getTime()).
|
|
||||||
build();
|
|
||||||
|
|
||||||
const KeyPairGenerator generator = KeyPairGenerator::getInstance(QStringLiteral("RSA"),
|
|
||||||
QStringLiteral("AndroidKeyStore"));
|
|
||||||
|
|
||||||
if (!generator) {
|
|
||||||
q->emitFinishedWithError(Error::OtherError, tr("Could not create private key generator"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
generator.initialize(spec);
|
|
||||||
|
|
||||||
if (!generator.generateKeyPair()) {
|
|
||||||
q->emitFinishedWithError(Error::OtherError, tr("Could not generate new private key"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const KeyStore::PrivateKeyEntry entry = keyStore.getEntry(alias);
|
|
||||||
|
|
||||||
if (!entry) {
|
|
||||||
q->emitFinishedWithError(Error::AccessDenied, tr("Could not retrieve private key from keystore"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const RSAPublicKey publicKey = entry.getCertificate().getPublicKey();
|
|
||||||
const Cipher cipher = Cipher::getInstance(QStringLiteral("RSA/ECB/PKCS1Padding"));
|
|
||||||
|
|
||||||
if (!cipher || !cipher.init(Cipher::ENCRYPT_MODE, publicKey)) {
|
|
||||||
q->emitFinishedWithError(Error::OtherError, tr("Could not create encryption cipher"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayOutputStream outputStream;
|
|
||||||
CipherOutputStream cipherOutputStream(outputStream, cipher);
|
|
||||||
|
|
||||||
if (!cipherOutputStream.write(data) || !cipherOutputStream.close()) {
|
|
||||||
q->emitFinishedWithError(Error::OtherError, tr("Could not encrypt data"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlainTextStore plainTextStore(q->service(), q->settings());
|
|
||||||
plainTextStore.write(q->key(), outputStream.toByteArray(), mode);
|
|
||||||
|
|
||||||
if (plainTextStore.error() != NoError)
|
|
||||||
q->emitFinishedWithError(plainTextStore.error(), plainTextStore.errorString());
|
|
||||||
else
|
|
||||||
q->emitFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeletePasswordJobPrivate::scheduledStart()
|
|
||||||
{
|
|
||||||
const KeyStore keyStore = KeyStore::getInstance(QStringLiteral("AndroidKeyStore"));
|
|
||||||
|
|
||||||
if (!keyStore || !keyStore.load()) {
|
|
||||||
q->emitFinishedWithError(Error::AccessDenied, tr("Could not open keystore"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &alias = makeAlias(q->service(), q->key());
|
|
||||||
if (!keyStore.deleteEntry(alias)) {
|
|
||||||
q->emitFinishedWithError(Error::OtherError, tr("Could not remove private key from keystore"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlainTextStore plainTextStore(q->service(), q->settings());
|
|
||||||
plainTextStore.remove(q->key());
|
|
||||||
|
|
||||||
if (plainTextStore.error() != NoError)
|
|
||||||
q->emitFinishedWithError(plainTextStore.error(), plainTextStore.errorString());
|
|
||||||
else
|
|
||||||
q->emitFinished();
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (C) 2016 Mathias Hasselmann <mathias.hasselmann@kdab.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"
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import <Security/Security.h>
|
|
||||||
|
|
||||||
using namespace QKeychain;
|
|
||||||
|
|
||||||
struct ErrorDescription
|
|
||||||
{
|
|
||||||
QKeychain::Error code;
|
|
||||||
QString message;
|
|
||||||
|
|
||||||
ErrorDescription(QKeychain::Error code, const QString &message)
|
|
||||||
: code(code), message(message) {}
|
|
||||||
|
|
||||||
static ErrorDescription fromStatus(OSStatus status)
|
|
||||||
{
|
|
||||||
switch(status) {
|
|
||||||
case errSecSuccess:
|
|
||||||
return ErrorDescription(QKeychain::NoError, Job::tr("No error"));
|
|
||||||
case errSecItemNotFound:
|
|
||||||
return ErrorDescription(QKeychain::EntryNotFound, Job::tr("The specified item could not be found in the keychain"));
|
|
||||||
case errSecUserCanceled:
|
|
||||||
return ErrorDescription(QKeychain::AccessDeniedByUser, Job::tr("User canceled the operation"));
|
|
||||||
case errSecInteractionNotAllowed:
|
|
||||||
return ErrorDescription(QKeychain::AccessDenied, Job::tr("User interaction is not allowed"));
|
|
||||||
case errSecNotAvailable:
|
|
||||||
return ErrorDescription(QKeychain::AccessDenied, Job::tr("No keychain is available. You may need to restart your computer"));
|
|
||||||
case errSecAuthFailed:
|
|
||||||
return ErrorDescription(QKeychain::AccessDenied, Job::tr("The user name or passphrase you entered is not correct"));
|
|
||||||
case errSecVerifyFailed:
|
|
||||||
return ErrorDescription(QKeychain::AccessDenied, Job::tr("A cryptographic verification failure has occurred"));
|
|
||||||
case errSecUnimplemented:
|
|
||||||
return ErrorDescription(QKeychain::NotImplemented, Job::tr("Function or operation not implemented"));
|
|
||||||
case errSecIO:
|
|
||||||
return ErrorDescription(QKeychain::OtherError, Job::tr("I/O error"));
|
|
||||||
case errSecOpWr:
|
|
||||||
return ErrorDescription(QKeychain::OtherError, Job::tr("Already open with with write permission"));
|
|
||||||
case errSecParam:
|
|
||||||
return ErrorDescription(QKeychain::OtherError, Job::tr("Invalid parameters passed to a function"));
|
|
||||||
case errSecAllocate:
|
|
||||||
return ErrorDescription(QKeychain::OtherError, Job::tr("Failed to allocate memory"));
|
|
||||||
case errSecBadReq:
|
|
||||||
return ErrorDescription(QKeychain::OtherError, Job::tr("Bad parameter or invalid state for operation"));
|
|
||||||
case errSecInternalComponent:
|
|
||||||
return ErrorDescription(QKeychain::OtherError, Job::tr("An internal component failed"));
|
|
||||||
case errSecDuplicateItem:
|
|
||||||
return ErrorDescription(QKeychain::OtherError, Job::tr("The specified item already exists in the keychain"));
|
|
||||||
case errSecDecode:
|
|
||||||
return ErrorDescription(QKeychain::OtherError, Job::tr("Unable to decode the provided data"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ErrorDescription(QKeychain::OtherError, Job::tr("Unknown error"));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void ReadPasswordJobPrivate::scheduledStart()
|
|
||||||
{
|
|
||||||
NSDictionary *const query = @{
|
|
||||||
(__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
|
|
||||||
(__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
|
|
||||||
(__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
|
|
||||||
(__bridge id) kSecReturnData: @YES,
|
|
||||||
};
|
|
||||||
|
|
||||||
CFTypeRef dataRef = nil;
|
|
||||||
const OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, &dataRef);
|
|
||||||
|
|
||||||
data.clear();
|
|
||||||
mode = Binary;
|
|
||||||
|
|
||||||
if (status == errSecSuccess) {
|
|
||||||
if (dataRef)
|
|
||||||
data = QByteArray::fromCFData((CFDataRef) dataRef);
|
|
||||||
|
|
||||||
q->emitFinished();
|
|
||||||
} else {
|
|
||||||
const ErrorDescription error = ErrorDescription::fromStatus(status);
|
|
||||||
q->emitFinishedWithError(error.code, Job::tr("Could not retrieve private key from keystore: %1").arg(error.message));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataRef)
|
|
||||||
[dataRef release];
|
|
||||||
}
|
|
||||||
|
|
||||||
void WritePasswordJobPrivate::scheduledStart()
|
|
||||||
{
|
|
||||||
NSDictionary *const query = @{
|
|
||||||
(__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
|
|
||||||
(__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
|
|
||||||
(__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
|
|
||||||
};
|
|
||||||
|
|
||||||
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef) query, nil);
|
|
||||||
|
|
||||||
if (status == errSecSuccess) {
|
|
||||||
NSDictionary *const update = @{
|
|
||||||
(__bridge id) kSecValueData: (__bridge NSData *) data.toCFData(),
|
|
||||||
};
|
|
||||||
|
|
||||||
status = SecItemUpdate((__bridge CFDictionaryRef) query, (__bridge CFDictionaryRef) update);
|
|
||||||
} else {
|
|
||||||
NSDictionary *const insert = @{
|
|
||||||
(__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
|
|
||||||
(__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
|
|
||||||
(__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
|
|
||||||
(__bridge id) kSecValueData: (__bridge NSData *) data.toCFData(),
|
|
||||||
};
|
|
||||||
|
|
||||||
status = SecItemAdd((__bridge CFDictionaryRef) insert, nil);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status == errSecSuccess) {
|
|
||||||
q->emitFinished();
|
|
||||||
} else {
|
|
||||||
const ErrorDescription error = ErrorDescription::fromStatus(status);
|
|
||||||
q->emitFinishedWithError(error.code, tr("Could not store data in settings: %1").arg(error.message));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeletePasswordJobPrivate::scheduledStart()
|
|
||||||
{
|
|
||||||
const NSDictionary *const query = @{
|
|
||||||
(__bridge id) kSecClass: (__bridge id) kSecClassGenericPassword,
|
|
||||||
(__bridge id) kSecAttrService: (__bridge NSString *) service.toCFString(),
|
|
||||||
(__bridge id) kSecAttrAccount: (__bridge NSString *) key.toCFString(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const OSStatus status = SecItemDelete((__bridge CFDictionaryRef) query);
|
|
||||||
|
|
||||||
if (status == errSecSuccess) {
|
|
||||||
q->emitFinished();
|
|
||||||
} else {
|
|
||||||
const ErrorDescription error = ErrorDescription::fromStatus(status);
|
|
||||||
q->emitFinishedWithError(error.code, Job::tr("Could not remove private key from keystore: %1").arg(error.message));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,187 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (C) 2018 François Revol <revol@free.fr> *
|
|
||||||
* *
|
|
||||||
* 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 <KeyStore.h>
|
|
||||||
|
|
||||||
#include <Application.h>
|
|
||||||
#include <AppFileInfo.h>
|
|
||||||
#include <File.h>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
using namespace QKeychain;
|
|
||||||
|
|
||||||
class AutoApp {
|
|
||||||
public:
|
|
||||||
AutoApp();
|
|
||||||
~AutoApp();
|
|
||||||
BApplication *app;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
AutoApp::AutoApp()
|
|
||||||
: app(NULL)
|
|
||||||
{
|
|
||||||
if (be_app != NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// no BApplication object, probably using QCoreApplication
|
|
||||||
// but we need one around
|
|
||||||
|
|
||||||
QString appSignature;
|
|
||||||
|
|
||||||
char signature[B_MIME_TYPE_LENGTH];
|
|
||||||
signature[0] = '\0';
|
|
||||||
|
|
||||||
QString appPath = QCoreApplication::applicationFilePath();
|
|
||||||
|
|
||||||
BFile appFile(appPath.toUtf8(), B_READ_ONLY);
|
|
||||||
if (appFile.InitCheck() == B_OK) {
|
|
||||||
BAppFileInfo info(&appFile);
|
|
||||||
if (info.InitCheck() == B_OK) {
|
|
||||||
if (info.GetSignature(signature) != B_OK)
|
|
||||||
signature[0] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signature[0] != '\0')
|
|
||||||
appSignature = QLatin1String(signature);
|
|
||||||
else
|
|
||||||
appSignature = QLatin1String("application/x-vnd.qtkeychain-") +
|
|
||||||
QCoreApplication::applicationName().remove("_x86");
|
|
||||||
|
|
||||||
app = new BApplication(appSignature.toUtf8().constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoApp::~AutoApp()
|
|
||||||
{
|
|
||||||
delete app;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString strForStatus( status_t os ) {
|
|
||||||
const char * const buf = strerror(os) ;
|
|
||||||
return QObject::tr( "error 0x%1: %2" )
|
|
||||||
.arg( os, 8, 16 ).arg( QString::fromUtf8( buf, strlen( buf ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadPasswordJobPrivate::scheduledStart()
|
|
||||||
{
|
|
||||||
AutoApp aa;
|
|
||||||
QString errorString;
|
|
||||||
Error error = NoError;
|
|
||||||
BKeyStore keyStore;
|
|
||||||
BPasswordKey password;
|
|
||||||
|
|
||||||
status_t result = keyStore.GetKey(B_KEY_TYPE_PASSWORD,
|
|
||||||
q->service().toUtf8().constData(),
|
|
||||||
q->key().toUtf8().constData(),
|
|
||||||
false, password);
|
|
||||||
|
|
||||||
data = QByteArray(reinterpret_cast<const char*>(password.Data()), password.DataLength());
|
|
||||||
|
|
||||||
switch ( result ) {
|
|
||||||
case B_OK:
|
|
||||||
q->emitFinished();
|
|
||||||
return;
|
|
||||||
case B_ENTRY_NOT_FOUND:
|
|
||||||
errorString = tr("Password not found");
|
|
||||||
error = EntryNotFound;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errorString = strForStatus( result );
|
|
||||||
error = OtherError;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
q->emitFinishedWithError( error, errorString );
|
|
||||||
}
|
|
||||||
|
|
||||||
void WritePasswordJobPrivate::scheduledStart()
|
|
||||||
{
|
|
||||||
AutoApp aa;
|
|
||||||
QString errorString;
|
|
||||||
Error error = NoError;
|
|
||||||
BKeyStore keyStore;
|
|
||||||
BPasswordKey password(data.constData(),
|
|
||||||
B_KEY_PURPOSE_GENERIC,
|
|
||||||
q->service().toUtf8().constData(),
|
|
||||||
q->key().toUtf8().constData());
|
|
||||||
status_t result = B_OK;
|
|
||||||
|
|
||||||
// re-add as binary if it's not text
|
|
||||||
if (mode == Binary)
|
|
||||||
result = password.SetData(reinterpret_cast<const uint8*>(data.constData()), data.size());
|
|
||||||
|
|
||||||
if (result == B_OK)
|
|
||||||
result = keyStore.AddKey(password);
|
|
||||||
|
|
||||||
if (result == B_NAME_IN_USE) {
|
|
||||||
BPasswordKey old_password;
|
|
||||||
result = keyStore.GetKey(B_KEY_TYPE_PASSWORD,
|
|
||||||
q->service().toUtf8().constData(),
|
|
||||||
q->key().toUtf8().constData(),
|
|
||||||
false, old_password);
|
|
||||||
if (result == B_OK)
|
|
||||||
result = keyStore.RemoveKey(old_password);
|
|
||||||
if (result == B_OK)
|
|
||||||
result = keyStore.AddKey(password);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ( result ) {
|
|
||||||
case B_OK:
|
|
||||||
q->emitFinished();
|
|
||||||
return;
|
|
||||||
case B_ENTRY_NOT_FOUND:
|
|
||||||
errorString = tr("Password not found");
|
|
||||||
error = EntryNotFound;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errorString = strForStatus( result );
|
|
||||||
error = OtherError;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
q->emitFinishedWithError( error, errorString );
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeletePasswordJobPrivate::scheduledStart()
|
|
||||||
{
|
|
||||||
AutoApp aa;
|
|
||||||
QString errorString;
|
|
||||||
Error error = NoError;
|
|
||||||
BKeyStore keyStore;
|
|
||||||
BPasswordKey password;
|
|
||||||
|
|
||||||
status_t result = keyStore.GetKey(B_KEY_TYPE_PASSWORD,
|
|
||||||
q->service().toUtf8().constData(),
|
|
||||||
q->key().toUtf8().constData(),
|
|
||||||
false, password);
|
|
||||||
|
|
||||||
if (result == B_OK)
|
|
||||||
result = keyStore.RemoveKey(password);
|
|
||||||
|
|
||||||
switch ( result ) {
|
|
||||||
case B_OK:
|
|
||||||
q->emitFinished();
|
|
||||||
return;
|
|
||||||
case B_ENTRY_NOT_FOUND:
|
|
||||||
errorString = tr("Password not found");
|
|
||||||
error = EntryNotFound;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errorString = strForStatus( result );
|
|
||||||
error = CouldNotDeleteEntry;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
q->emitFinishedWithError( error, errorString );
|
|
||||||
}
|
|
@ -1,167 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* 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 <QQueue>
|
|
||||||
|
|
||||||
#if defined(KEYCHAIN_DBUS)
|
|
||||||
|
|
||||||
#include <QDBusPendingCallWatcher>
|
|
||||||
|
|
||||||
#include "kwallet_interface.h"
|
|
||||||
#else
|
|
||||||
|
|
||||||
class QDBusPendingCallWatcher;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "keychain.h"
|
|
||||||
|
|
||||||
namespace QKeychain {
|
|
||||||
|
|
||||||
class JobExecutor;
|
|
||||||
|
|
||||||
class JobPrivate : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
enum Mode {
|
|
||||||
Text,
|
|
||||||
Binary
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual void scheduledStart() = 0;
|
|
||||||
|
|
||||||
static QString modeToString(Mode m);
|
|
||||||
static Mode stringToMode(const QString& s);
|
|
||||||
|
|
||||||
Job* const q;
|
|
||||||
Mode mode;
|
|
||||||
QByteArray data;
|
|
||||||
|
|
||||||
#if defined(KEYCHAIN_DBUS)
|
|
||||||
org::kde::KWallet* iface;
|
|
||||||
int walletHandle;
|
|
||||||
|
|
||||||
static void gnomeKeyring_readCb( int result, const char* string, JobPrivate* data );
|
|
||||||
static void gnomeKeyring_writeCb( int result, JobPrivate* self );
|
|
||||||
|
|
||||||
virtual void fallbackOnError(const QDBusError& err) = 0;
|
|
||||||
|
|
||||||
protected Q_SLOTS:
|
|
||||||
void kwalletWalletFound( QDBusPendingCallWatcher* watcher );
|
|
||||||
virtual void kwalletFinished( QDBusPendingCallWatcher* watcher );
|
|
||||||
virtual void kwalletOpenFinished( QDBusPendingCallWatcher* watcher );
|
|
||||||
#else
|
|
||||||
void kwalletWalletFound( QDBusPendingCallWatcher* ) {}
|
|
||||||
virtual void kwalletFinished( QDBusPendingCallWatcher* ) {}
|
|
||||||
virtual void kwalletOpenFinished( QDBusPendingCallWatcher* ) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
|
||||||
JobPrivate( const QString& service_, Job *q );
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QKeychain::Error error;
|
|
||||||
QString errorString;
|
|
||||||
QString service;
|
|
||||||
bool autoDelete;
|
|
||||||
bool insecureFallback;
|
|
||||||
QPointer<QSettings> settings;
|
|
||||||
QString key;
|
|
||||||
|
|
||||||
friend class Job;
|
|
||||||
friend class JobExecutor;
|
|
||||||
friend class ReadPasswordJob;
|
|
||||||
friend class WritePasswordJob;
|
|
||||||
friend class PlainTextStore;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ReadPasswordJobPrivate : public JobPrivate {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit ReadPasswordJobPrivate( const QString &service_, ReadPasswordJob* qq );
|
|
||||||
void scheduledStart() override;
|
|
||||||
|
|
||||||
#if defined(KEYCHAIN_DBUS)
|
|
||||||
void fallbackOnError(const QDBusError& err) override;
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) override;
|
|
||||||
void kwalletEntryTypeFinished( QDBusPendingCallWatcher* watcher );
|
|
||||||
void kwalletFinished( QDBusPendingCallWatcher* watcher ) override;
|
|
||||||
#else //moc's too dumb to respect above macros, so just define empty slot implementations
|
|
||||||
private Q_SLOTS:
|
|
||||||
void kwalletOpenFinished( QDBusPendingCallWatcher* ) {}
|
|
||||||
void kwalletEntryTypeFinished( QDBusPendingCallWatcher* ) {}
|
|
||||||
void kwalletFinished( QDBusPendingCallWatcher* ) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
friend class ReadPasswordJob;
|
|
||||||
};
|
|
||||||
|
|
||||||
class WritePasswordJobPrivate : public JobPrivate {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit WritePasswordJobPrivate( const QString &service_, WritePasswordJob* qq );
|
|
||||||
void scheduledStart() override;
|
|
||||||
|
|
||||||
#if defined(KEYCHAIN_DBUS)
|
|
||||||
void fallbackOnError(const QDBusError& err) override;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
friend class WritePasswordJob;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DeletePasswordJobPrivate : public JobPrivate {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit DeletePasswordJobPrivate( const QString &service_, DeletePasswordJob* qq );
|
|
||||||
|
|
||||||
void scheduledStart() override;
|
|
||||||
|
|
||||||
#if defined(KEYCHAIN_DBUS)
|
|
||||||
void fallbackOnError(const QDBusError& err) override;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void doStart();
|
|
||||||
|
|
||||||
friend class DeletePasswordJob;
|
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
QQueue<QPointer<Job> > m_queue;
|
|
||||||
bool m_jobRunning;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // KEYCHAIN_P_H
|
|
@ -1,586 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* 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 "libsecret_p.h"
|
|
||||||
#include "plaintextstore_p.h"
|
|
||||||
|
|
||||||
#include <QScopedPointer>
|
|
||||||
|
|
||||||
using namespace QKeychain;
|
|
||||||
|
|
||||||
enum KeyringBackend {
|
|
||||||
Backend_LibSecretKeyring,
|
|
||||||
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() {
|
|
||||||
QByteArray 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();
|
|
||||||
} else if ( xdgCurrentDesktop == "XFCE" ) {
|
|
||||||
return DesktopEnv_Xfce;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 bool isKwallet5Available()
|
|
||||||
{
|
|
||||||
if (!QDBusConnection::sessionBus().isConnected())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
org::kde::KWallet iface(
|
|
||||||
QLatin1String("org.kde.kwalletd5"),
|
|
||||||
QLatin1String("/modules/kwalletd5"),
|
|
||||||
QDBusConnection::sessionBus());
|
|
||||||
|
|
||||||
// At this point iface.isValid() can return false even though the
|
|
||||||
// interface is activatable by making a call. Hence we check whether
|
|
||||||
// a wallet can be opened.
|
|
||||||
|
|
||||||
iface.setTimeout(500);
|
|
||||||
QDBusMessage reply = iface.call(QLatin1String("networkWallet"));
|
|
||||||
return reply.type() == QDBusMessage::ReplyMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
static KeyringBackend detectKeyringBackend()
|
|
||||||
{
|
|
||||||
/* The secret service dbus api, accessible through libsecret, is supposed
|
|
||||||
* to unify password services.
|
|
||||||
*
|
|
||||||
* Unfortunately at the time of Kubuntu 18.04 the secret service backend
|
|
||||||
* in KDE is gnome-keyring-daemon - using it has several complications:
|
|
||||||
* - the default collection isn't opened on session start, so users need
|
|
||||||
* to manually unlock it when the first application uses it
|
|
||||||
* - it's separate from the kwallet5 keyring, so switching to it means the
|
|
||||||
* existing keyring data can't be accessed anymore
|
|
||||||
*
|
|
||||||
* Thus we still prefer kwallet backends on KDE even if libsecret is
|
|
||||||
* available.
|
|
||||||
*/
|
|
||||||
|
|
||||||
switch (detectDesktopEnvironment()) {
|
|
||||||
case DesktopEnv_Kde4:
|
|
||||||
return Backend_Kwallet4;
|
|
||||||
|
|
||||||
case DesktopEnv_Plasma5:
|
|
||||||
if (isKwallet5Available()) {
|
|
||||||
return Backend_Kwallet5;
|
|
||||||
}
|
|
||||||
if (LibSecretKeyring::isAvailable()) {
|
|
||||||
return Backend_LibSecretKeyring;
|
|
||||||
}
|
|
||||||
if (GnomeKeyring::isAvailable()) {
|
|
||||||
return Backend_GnomeKeyring;
|
|
||||||
}
|
|
||||||
// During startup the keychain backend might just not have started yet
|
|
||||||
return Backend_Kwallet5;
|
|
||||||
|
|
||||||
case DesktopEnv_Gnome:
|
|
||||||
case DesktopEnv_Unity:
|
|
||||||
case DesktopEnv_Xfce:
|
|
||||||
case DesktopEnv_Other:
|
|
||||||
default:
|
|
||||||
if (LibSecretKeyring::isAvailable()) {
|
|
||||||
return Backend_LibSecretKeyring;
|
|
||||||
}
|
|
||||||
if (GnomeKeyring::isAvailable()) {
|
|
||||||
return Backend_GnomeKeyring;
|
|
||||||
}
|
|
||||||
if (isKwallet5Available()) {
|
|
||||||
return Backend_Kwallet5;
|
|
||||||
}
|
|
||||||
// During startup the keychain backend might just not have started yet
|
|
||||||
//
|
|
||||||
// This doesn't need to be libsecret because LibSecretKeyring::isAvailable()
|
|
||||||
// only fails if the libsecret shared library couldn't be loaded. In contrast
|
|
||||||
// to that GnomeKeyring::isAvailable() can return false if the shared library
|
|
||||||
// *was* loaded but its libgnome_keyring::is_available() returned false.
|
|
||||||
//
|
|
||||||
// In the future there should be a difference between "API available" and
|
|
||||||
// "keychain available".
|
|
||||||
return Backend_GnomeKeyring;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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_LibSecretKeyring: {
|
|
||||||
if ( !LibSecretKeyring::findPassword(key, q->service(), this) ) {
|
|
||||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case Backend_GnomeKeyring:
|
|
||||||
this->mode = JobPrivate::Text;
|
|
||||||
if ( !GnomeKeyring::find_network_password( key.toUtf8().constData(),
|
|
||||||
q->service().toUtf8().constData(),
|
|
||||||
"plaintext",
|
|
||||||
reinterpret_cast<GnomeKeyring::OperationGetStringCallback>( &JobPrivate::gnomeKeyring_readCb ),
|
|
||||||
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 JobPrivate::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 JobPrivate::gnomeKeyring_readCb( int result, const char* string, JobPrivate* self )
|
|
||||||
{
|
|
||||||
if ( result == GnomeKeyring::RESULT_OK ) {
|
|
||||||
if (self->mode == JobPrivate::Text)
|
|
||||||
self->data = QByteArray(string);
|
|
||||||
else
|
|
||||||
self->data = QByteArray::fromBase64(string);
|
|
||||||
|
|
||||||
self->q->emitFinished();
|
|
||||||
} else if (self->mode == JobPrivate::Text) {
|
|
||||||
self->mode = JobPrivate::Binary;
|
|
||||||
if ( !GnomeKeyring::find_network_password( self->key.toUtf8().constData(),
|
|
||||||
self->q->service().toUtf8().constData(),
|
|
||||||
"base64",
|
|
||||||
reinterpret_cast<GnomeKeyring::OperationGetStringCallback>( &JobPrivate::gnomeKeyring_readCb ),
|
|
||||||
self, 0 ) )
|
|
||||||
self->q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
|
||||||
} else {
|
|
||||||
const QPair<Error, QString> errorResult = mapGnomeKeyringError( result );
|
|
||||||
self->q->emitFinishedWithError( errorResult.first, errorResult.second );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadPasswordJobPrivate::fallbackOnError(const QDBusError& err )
|
|
||||||
{
|
|
||||||
PlainTextStore plainTextStore( q->service(), q->settings() );
|
|
||||||
|
|
||||||
if ( q->insecureFallback() && plainTextStore.contains( key ) ) {
|
|
||||||
mode = plainTextStore.readMode( key );
|
|
||||||
data = plainTextStore.readData( key );
|
|
||||||
|
|
||||||
if ( plainTextStore.error() != NoError )
|
|
||||||
q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() );
|
|
||||||
else
|
|
||||||
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;
|
|
||||||
|
|
||||||
if ( reply.isError() ) {
|
|
||||||
fallbackOnError( reply.error() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlainTextStore plainTextStore( q->service(), q->settings() );
|
|
||||||
|
|
||||||
if ( plainTextStore.contains( key ) ) {
|
|
||||||
// We previously stored data in the insecure QSettings, but now have KWallet available.
|
|
||||||
// Do the migration
|
|
||||||
|
|
||||||
data = plainTextStore.readData( key );
|
|
||||||
const WritePasswordJobPrivate::Mode mode = plainTextStore.readMode( key );
|
|
||||||
plainTextStore.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:
|
|
||||||
mode = Text;
|
|
||||||
break;
|
|
||||||
case Stream:
|
|
||||||
mode = 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 = (mode == 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(kwalletFinished(QDBusPendingCallWatcher*)) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadPasswordJobPrivate::kwalletFinished( QDBusPendingCallWatcher* watcher ) {
|
|
||||||
if ( !watcher->isError() ) {
|
|
||||||
if ( mode == Binary ) {
|
|
||||||
QDBusPendingReply<QByteArray> reply = *watcher;
|
|
||||||
if (reply.isValid()) {
|
|
||||||
data = reply.value();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QDBusPendingReply<QString> reply = *watcher;
|
|
||||||
if (reply.isValid()) {
|
|
||||||
data = reply.value().toUtf8();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JobPrivate::kwalletFinished(watcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void kwalletWritePasswordScheduledStart( const char * service, const char * path, JobPrivate * 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_LibSecretKeyring: {
|
|
||||||
if ( !LibSecretKeyring::writePassword(service, key, service, mode,
|
|
||||||
data, this) ) {
|
|
||||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case Backend_GnomeKeyring: {
|
|
||||||
QString type;
|
|
||||||
QByteArray password;
|
|
||||||
|
|
||||||
switch(mode) {
|
|
||||||
case JobPrivate::Text:
|
|
||||||
type = QLatin1String("plaintext");
|
|
||||||
password = data;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
type = QLatin1String("base64");
|
|
||||||
password = data.toBase64();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray service = q->service().toUtf8();
|
|
||||||
if ( !GnomeKeyring::store_network_password( GnomeKeyring::GNOME_KEYRING_DEFAULT,
|
|
||||||
service.constData(),
|
|
||||||
key.toUtf8().constData(),
|
|
||||||
service.constData(),
|
|
||||||
type.toUtf8().constData(),
|
|
||||||
password.constData(),
|
|
||||||
reinterpret_cast<GnomeKeyring::OperationDoneCallback>( &JobPrivate::gnomeKeyring_writeCb ),
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WritePasswordJobPrivate::fallbackOnError(const QDBusError &err)
|
|
||||||
{
|
|
||||||
if ( !q->insecureFallback() ) {
|
|
||||||
q->emitFinishedWithError( OtherError, tr("Could not open wallet: %1; %2").arg( QDBusError::errorString( err.type() ), err.message() ) );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlainTextStore plainTextStore( q->service(), q->settings() );
|
|
||||||
plainTextStore.write( key, data, mode );
|
|
||||||
|
|
||||||
if ( plainTextStore.error() != NoError )
|
|
||||||
q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() );
|
|
||||||
else
|
|
||||||
q->emitFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void JobPrivate::gnomeKeyring_writeCb(int result, JobPrivate* 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 JobPrivate::kwalletOpenFinished( QDBusPendingCallWatcher* watcher ) {
|
|
||||||
watcher->deleteLater();
|
|
||||||
QDBusPendingReply<int> reply = *watcher;
|
|
||||||
|
|
||||||
if ( reply.isError() ) {
|
|
||||||
fallbackOnError( reply.error() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlainTextStore plainTextStore( q->service(), q->settings() );
|
|
||||||
if ( plainTextStore.contains( key ) ) {
|
|
||||||
// If we had previously written to QSettings, but we now have a kwallet available, migrate and delete old insecure data
|
|
||||||
plainTextStore.remove( key );
|
|
||||||
}
|
|
||||||
|
|
||||||
const int handle = reply.value();
|
|
||||||
|
|
||||||
if ( handle < 0 ) {
|
|
||||||
q->emitFinishedWithError( AccessDenied, tr("Access to keychain denied") );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDBusPendingReply<int> nextReply;
|
|
||||||
|
|
||||||
if ( mode == Text )
|
|
||||||
nextReply = iface->writePassword( handle, q->service(), key, QString::fromUtf8(data), q->service() );
|
|
||||||
else if ( mode == Binary )
|
|
||||||
nextReply = iface->writeEntry( handle, q->service(), key, data, 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(kwalletFinished(QDBusPendingCallWatcher*)) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void JobPrivate::kwalletFinished( QDBusPendingCallWatcher* watcher ) {
|
|
||||||
if ( !watcher->isError() ) {
|
|
||||||
if ( mode == Binary ) {
|
|
||||||
QDBusPendingReply<QByteArray> reply = *watcher;
|
|
||||||
if (reply.isValid()) {
|
|
||||||
data = reply.value();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QDBusPendingReply<QString> reply = *watcher;
|
|
||||||
if (reply.isValid()) {
|
|
||||||
data = reply.value().toUtf8();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
q->emitFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeletePasswordJobPrivate::scheduledStart() {
|
|
||||||
switch ( getKeyringBackend() ) {
|
|
||||||
case Backend_LibSecretKeyring: {
|
|
||||||
if ( !LibSecretKeyring::deletePassword(key, q->service(), this) ) {
|
|
||||||
q->emitFinishedWithError( OtherError, tr("Unknown error") );
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case Backend_GnomeKeyring: {
|
|
||||||
if ( !GnomeKeyring::delete_network_password(
|
|
||||||
key.toUtf8().constData(), q->service().toUtf8().constData(),
|
|
||||||
reinterpret_cast<GnomeKeyring::OperationDoneCallback>( &JobPrivate::gnomeKeyring_writeCb ),
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeletePasswordJobPrivate::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
actual->remove( key );
|
|
||||||
actual->sync();
|
|
||||||
|
|
||||||
q->emitFinished();
|
|
||||||
|
|
||||||
|
|
||||||
q->emitFinished();
|
|
||||||
}
|
|
@ -1,188 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* 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 "plaintextstore_p.h"
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <wincrypt.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
using namespace QKeychain;
|
|
||||||
|
|
||||||
#if defined(USE_CREDENTIAL_STORE)
|
|
||||||
#include <wincred.h>
|
|
||||||
|
|
||||||
void ReadPasswordJobPrivate::scheduledStart() {
|
|
||||||
LPCWSTR name = (LPCWSTR)key.utf16();
|
|
||||||
PCREDENTIALW cred;
|
|
||||||
|
|
||||||
if (!CredReadW(name, CRED_TYPE_GENERIC, 0, &cred)) {
|
|
||||||
Error err;
|
|
||||||
QString msg;
|
|
||||||
switch(GetLastError()) {
|
|
||||||
case ERROR_NOT_FOUND:
|
|
||||||
err = EntryNotFound;
|
|
||||||
msg = tr("Password entry not found");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
err = OtherError;
|
|
||||||
msg = tr("Could not decrypt data");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
q->emitFinishedWithError( err, msg );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = QByteArray((char*)cred->CredentialBlob, cred->CredentialBlobSize);
|
|
||||||
CredFree(cred);
|
|
||||||
|
|
||||||
q->emitFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WritePasswordJobPrivate::scheduledStart() {
|
|
||||||
CREDENTIALW cred;
|
|
||||||
char *pwd = data.data();
|
|
||||||
LPWSTR name = (LPWSTR)key.utf16();
|
|
||||||
|
|
||||||
memset(&cred, 0, sizeof(cred));
|
|
||||||
cred.Comment = const_cast<wchar_t*>(L"QtKeychain");
|
|
||||||
cred.Type = CRED_TYPE_GENERIC;
|
|
||||||
cred.TargetName = name;
|
|
||||||
cred.CredentialBlobSize = data.size();
|
|
||||||
cred.CredentialBlob = (LPBYTE)pwd;
|
|
||||||
cred.Persist = CRED_PERSIST_ENTERPRISE;
|
|
||||||
|
|
||||||
if (CredWriteW(&cred, 0)) {
|
|
||||||
q->emitFinished();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD err = GetLastError();
|
|
||||||
|
|
||||||
// Detect size-exceeded errors and provide nicer messages.
|
|
||||||
// Unfortunately these error codes aren't documented.
|
|
||||||
// Found empirically on Win10 1803 build 17134.523.
|
|
||||||
if (err == RPC_X_BAD_STUB_DATA) {
|
|
||||||
const size_t maxBlob = CRED_MAX_CREDENTIAL_BLOB_SIZE;
|
|
||||||
if (cred.CredentialBlobSize > maxBlob) {
|
|
||||||
q->emitFinishedWithError(
|
|
||||||
OtherError,
|
|
||||||
tr("Credential size exceeds maximum size of %1").arg(maxBlob));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (err == RPC_S_INVALID_BOUND) {
|
|
||||||
const size_t maxTargetName = CRED_MAX_GENERIC_TARGET_NAME_LENGTH;
|
|
||||||
if (key.size() > maxTargetName) {
|
|
||||||
q->emitFinishedWithError(
|
|
||||||
OtherError,
|
|
||||||
tr("Credential key exceeds maximum size of %1").arg(maxTargetName));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
q->emitFinishedWithError( OtherError, tr("Writing credentials failed: Win32 error code %1").arg(err) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeletePasswordJobPrivate::scheduledStart() {
|
|
||||||
LPCWSTR name = (LPCWSTR)key.utf16();
|
|
||||||
|
|
||||||
if (!CredDeleteW(name, CRED_TYPE_GENERIC, 0)) {
|
|
||||||
Error err;
|
|
||||||
QString msg;
|
|
||||||
switch(GetLastError()) {
|
|
||||||
case ERROR_NOT_FOUND:
|
|
||||||
err = EntryNotFound;
|
|
||||||
msg = tr("Password entry not found");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
err = OtherError;
|
|
||||||
msg = tr("Could not decrypt data");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
q->emitFinishedWithError( err, msg );
|
|
||||||
} else {
|
|
||||||
q->emitFinished();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void ReadPasswordJobPrivate::scheduledStart() {
|
|
||||||
PlainTextStore plainTextStore( q->service(), q->settings() );
|
|
||||||
QByteArray encrypted = plainTextStore.readData( key );
|
|
||||||
if ( plainTextStore.error() != NoError ) {
|
|
||||||
q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() );
|
|
||||||
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() {
|
|
||||||
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 );
|
|
||||||
|
|
||||||
PlainTextStore plainTextStore( q->service(), q->settings() );
|
|
||||||
plainTextStore.write( key, encrypted, Binary );
|
|
||||||
if ( plainTextStore.error() != NoError ) {
|
|
||||||
q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
q->emitFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeletePasswordJobPrivate::scheduledStart() {
|
|
||||||
PlainTextStore plainTextStore( q->service(), q->settings() );
|
|
||||||
plainTextStore.remove( key );
|
|
||||||
if ( plainTextStore.error() != NoError ) {
|
|
||||||
q->emitFinishedWithError( plainTextStore.error(), plainTextStore.errorString() );
|
|
||||||
} else {
|
|
||||||
q->emitFinished();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,350 +0,0 @@
|
|||||||
#undef signals
|
|
||||||
|
|
||||||
#if defined(HAVE_LIBSECRET)
|
|
||||||
#include <libsecret/secret.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "libsecret_p.h"
|
|
||||||
|
|
||||||
#include <QLibrary>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
#if defined(HAVE_LIBSECRET)
|
|
||||||
const SecretSchema* qtkeychainSchema(void) {
|
|
||||||
static const SecretSchema schema = {
|
|
||||||
"org.qt.keychain", SECRET_SCHEMA_DONT_MATCH_NAME,
|
|
||||||
{
|
|
||||||
{ "user", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
|
||||||
{ "server", SECRET_SCHEMA_ATTRIBUTE_STRING },
|
|
||||||
{ "type", SECRET_SCHEMA_ATTRIBUTE_STRING }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return &schema;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
QKeychain::JobPrivate *self;
|
|
||||||
QString user;
|
|
||||||
QString server;
|
|
||||||
} callbackArg;
|
|
||||||
|
|
||||||
typedef void (*secret_password_lookup_t) (const SecretSchema *schema,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data,
|
|
||||||
...) G_GNUC_NULL_TERMINATED;
|
|
||||||
typedef gchar *(*secret_password_lookup_finish_t) (GAsyncResult *result,
|
|
||||||
GError **error);
|
|
||||||
typedef void (*secret_password_store_t) (const SecretSchema *schema,
|
|
||||||
const gchar *collection,
|
|
||||||
const gchar *label,
|
|
||||||
const gchar *password,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data,
|
|
||||||
...) G_GNUC_NULL_TERMINATED;
|
|
||||||
typedef gboolean (*secret_password_store_finish_t) (GAsyncResult *result,
|
|
||||||
GError **error);
|
|
||||||
typedef void (*secret_password_clear_t) (const SecretSchema *schema,
|
|
||||||
GCancellable *cancellable,
|
|
||||||
GAsyncReadyCallback callback,
|
|
||||||
gpointer user_data,
|
|
||||||
...) G_GNUC_NULL_TERMINATED;
|
|
||||||
typedef gboolean (*secret_password_clear_finish_t) (GAsyncResult *result,
|
|
||||||
GError **error);
|
|
||||||
typedef void (*secret_password_free_t) (gchar *password);
|
|
||||||
typedef GQuark (*secret_error_get_quark_t) (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
static secret_password_lookup_t secret_password_lookup_fn = NULL;
|
|
||||||
static secret_password_lookup_finish_t secret_password_lookup_finish_fn = NULL;
|
|
||||||
static secret_password_store_t secret_password_store_fn = NULL;
|
|
||||||
static secret_password_store_finish_t secret_password_store_finish_fn = NULL;
|
|
||||||
static secret_password_clear_t secret_password_clear_fn = NULL;
|
|
||||||
static secret_password_clear_finish_t secret_password_clear_finish_fn = NULL;
|
|
||||||
static secret_password_free_t secret_password_free_fn = NULL;
|
|
||||||
static secret_error_get_quark_t secret_error_get_quark_fn = NULL;
|
|
||||||
|
|
||||||
static QKeychain::Error gerrorToCode(const GError *error) {
|
|
||||||
if (error->domain != secret_error_get_quark_fn()) {
|
|
||||||
return QKeychain::OtherError;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(error->code) {
|
|
||||||
case SECRET_ERROR_NO_SUCH_OBJECT:
|
|
||||||
return QKeychain::EntryNotFound;
|
|
||||||
case SECRET_ERROR_IS_LOCKED:
|
|
||||||
return QKeychain::AccessDenied;
|
|
||||||
default:
|
|
||||||
return QKeychain::OtherError;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_password_lookup (GObject *source,
|
|
||||||
GAsyncResult *result,
|
|
||||||
gpointer inst)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
callbackArg *arg = (callbackArg*)inst;
|
|
||||||
gchar *password = secret_password_lookup_finish_fn (result, &error);
|
|
||||||
|
|
||||||
Q_UNUSED(source);
|
|
||||||
|
|
||||||
if (arg) {
|
|
||||||
if (error) {
|
|
||||||
QKeychain::Error code = gerrorToCode(error);
|
|
||||||
|
|
||||||
arg->self->q->emitFinishedWithError( code, QString::fromUtf8(error->message) );
|
|
||||||
} else {
|
|
||||||
if (password != NULL) {
|
|
||||||
QByteArray raw = QByteArray(password);
|
|
||||||
switch(arg->self->mode) {
|
|
||||||
case QKeychain::JobPrivate::Binary:
|
|
||||||
arg->self->data = QByteArray::fromBase64(raw);
|
|
||||||
break;
|
|
||||||
case QKeychain::JobPrivate::Text:
|
|
||||||
default:
|
|
||||||
arg->self->data = raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
arg->self->q->emitFinished();
|
|
||||||
} else if (arg->self->mode == QKeychain::JobPrivate::Text) {
|
|
||||||
arg->self->mode = QKeychain::JobPrivate::Binary;
|
|
||||||
secret_password_lookup_fn (qtkeychainSchema(), NULL,
|
|
||||||
on_password_lookup, arg,
|
|
||||||
"user", arg->user.toUtf8().constData(),
|
|
||||||
"server", arg->server.toUtf8().constData(),
|
|
||||||
"type", "base64",
|
|
||||||
NULL);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
arg->self->q->emitFinishedWithError( QKeychain::EntryNotFound, QObject::tr("Entry not found") );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (error) {
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (password) {
|
|
||||||
secret_password_free_fn (password);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg) {
|
|
||||||
delete arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_password_stored (GObject *source,
|
|
||||||
GAsyncResult *result,
|
|
||||||
gpointer inst)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
QKeychain::JobPrivate *self = (QKeychain::JobPrivate*)inst;
|
|
||||||
|
|
||||||
Q_UNUSED(source);
|
|
||||||
|
|
||||||
secret_password_store_finish_fn (result, &error);
|
|
||||||
|
|
||||||
if (self) {
|
|
||||||
if (error != NULL) {
|
|
||||||
self->q->emitFinishedWithError( gerrorToCode(error),
|
|
||||||
QString::fromUtf8(error->message) );
|
|
||||||
} else {
|
|
||||||
self->q->emitFinished();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (error != NULL) {
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_password_cleared (GObject *source,
|
|
||||||
GAsyncResult *result,
|
|
||||||
gpointer inst)
|
|
||||||
{
|
|
||||||
GError *error = NULL;
|
|
||||||
QKeychain::JobPrivate *self = (QKeychain::JobPrivate*)inst;
|
|
||||||
gboolean removed = secret_password_clear_finish_fn (result, &error);
|
|
||||||
|
|
||||||
Q_UNUSED(source);
|
|
||||||
if (self) {
|
|
||||||
if ( error ) {
|
|
||||||
self->q->emitFinishedWithError( gerrorToCode(error),
|
|
||||||
QString::fromUtf8(error->message) );
|
|
||||||
} else {
|
|
||||||
Q_UNUSED(removed);
|
|
||||||
self->q->emitFinished();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (error != NULL) {
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString modeToString(QKeychain::JobPrivate::Mode mode) {
|
|
||||||
switch(mode) {
|
|
||||||
case QKeychain::JobPrivate::Binary:
|
|
||||||
return "base64";
|
|
||||||
default:
|
|
||||||
return "plaintext";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool LibSecretKeyring::isAvailable() {
|
|
||||||
#if defined(HAVE_LIBSECRET)
|
|
||||||
const LibSecretKeyring& keyring = instance();
|
|
||||||
if (!keyring.isLoaded())
|
|
||||||
return false;
|
|
||||||
if (secret_password_lookup_fn == NULL)
|
|
||||||
return false;
|
|
||||||
if (secret_password_lookup_finish_fn == NULL)
|
|
||||||
return false;
|
|
||||||
if (secret_password_store_fn == NULL)
|
|
||||||
return false;
|
|
||||||
if (secret_password_store_finish_fn == NULL)
|
|
||||||
return false;
|
|
||||||
if (secret_password_clear_fn == NULL)
|
|
||||||
return false;
|
|
||||||
if (secret_password_clear_finish_fn == NULL)
|
|
||||||
return false;
|
|
||||||
if (secret_password_free_fn == NULL)
|
|
||||||
return false;
|
|
||||||
if (secret_error_get_quark_fn == NULL)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LibSecretKeyring::findPassword(const QString &user, const QString &server,
|
|
||||||
QKeychain::JobPrivate *self)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_LIBSECRET)
|
|
||||||
if (!isAvailable()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->mode = QKeychain::JobPrivate::Text;
|
|
||||||
self->data = QByteArray();
|
|
||||||
|
|
||||||
callbackArg *arg = new callbackArg;
|
|
||||||
arg->self = self;
|
|
||||||
arg->user = user;
|
|
||||||
arg->server = server;
|
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO;
|
|
||||||
secret_password_lookup_fn (qtkeychainSchema(), NULL, on_password_lookup, arg,
|
|
||||||
"user", user.toUtf8().constData(),
|
|
||||||
"server", server.toUtf8().constData(),
|
|
||||||
"type", "plaintext",
|
|
||||||
NULL);
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
Q_UNUSED(user)
|
|
||||||
Q_UNUSED(server)
|
|
||||||
Q_UNUSED(self)
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LibSecretKeyring::writePassword(const QString &display_name,
|
|
||||||
const QString &user,
|
|
||||||
const QString &server,
|
|
||||||
const QKeychain::JobPrivate::Mode mode,
|
|
||||||
const QByteArray &password,
|
|
||||||
QKeychain::JobPrivate *self)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_LIBSECRET)
|
|
||||||
if (!isAvailable()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString type = modeToString(mode);
|
|
||||||
QByteArray pwd;
|
|
||||||
switch(mode) {
|
|
||||||
case QKeychain::JobPrivate::Binary:
|
|
||||||
pwd = password.toBase64();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pwd = password;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO;
|
|
||||||
secret_password_store_fn (qtkeychainSchema(), SECRET_COLLECTION_DEFAULT,
|
|
||||||
display_name.toUtf8().constData(),
|
|
||||||
pwd.constData(), NULL, on_password_stored, self,
|
|
||||||
"user", user.toUtf8().constData(),
|
|
||||||
"server", server.toUtf8().constData(),
|
|
||||||
"type", type.toUtf8().constData(),
|
|
||||||
NULL);
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
Q_UNUSED(display_name)
|
|
||||||
Q_UNUSED(user)
|
|
||||||
Q_UNUSED(server)
|
|
||||||
Q_UNUSED(mode)
|
|
||||||
Q_UNUSED(password)
|
|
||||||
Q_UNUSED(self)
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LibSecretKeyring::deletePassword(const QString &key, const QString &service,
|
|
||||||
QKeychain::JobPrivate* self)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_LIBSECRET)
|
|
||||||
if (!isAvailable()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO;
|
|
||||||
secret_password_clear_fn (qtkeychainSchema(), NULL, on_password_cleared, self,
|
|
||||||
"user", key.toUtf8().constData(),
|
|
||||||
"server", service.toUtf8().constData(),
|
|
||||||
NULL);
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
Q_UNUSED(key)
|
|
||||||
Q_UNUSED(service)
|
|
||||||
Q_UNUSED(self)
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
LibSecretKeyring::LibSecretKeyring()
|
|
||||||
: QLibrary(QLatin1String("secret-1"), 0)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_LIBSECRET
|
|
||||||
if (load()) {
|
|
||||||
secret_password_lookup_fn =
|
|
||||||
(secret_password_lookup_t)resolve("secret_password_lookup");
|
|
||||||
secret_password_lookup_finish_fn =
|
|
||||||
(secret_password_lookup_finish_t)resolve("secret_password_lookup_finish");
|
|
||||||
secret_password_store_fn =
|
|
||||||
(secret_password_store_t)resolve("secret_password_store");
|
|
||||||
secret_password_store_finish_fn =
|
|
||||||
(secret_password_store_finish_t)resolve("secret_password_store_finish");
|
|
||||||
secret_password_clear_fn =
|
|
||||||
(secret_password_clear_t)resolve("secret_password_clear");
|
|
||||||
secret_password_clear_finish_fn =
|
|
||||||
(secret_password_clear_finish_t)resolve("secret_password_clear_finish");
|
|
||||||
secret_password_free_fn =
|
|
||||||
(secret_password_free_t)resolve("secret_password_free");
|
|
||||||
secret_error_get_quark_fn =
|
|
||||||
(secret_error_get_quark_t)resolve("secret_error_get_quark");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
LibSecretKeyring &LibSecretKeyring::instance() {
|
|
||||||
static LibSecretKeyring instance;
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
#ifndef QTKEYCHAIN_LIBSECRET_P_H
|
|
||||||
#define QTKEYCHAIN_LIBSECRET_P_H
|
|
||||||
|
|
||||||
#include <QLibrary>
|
|
||||||
|
|
||||||
#include "keychain_p.h"
|
|
||||||
|
|
||||||
class LibSecretKeyring : public QLibrary {
|
|
||||||
public:
|
|
||||||
static bool isAvailable();
|
|
||||||
|
|
||||||
static bool findPassword(const QString& user,
|
|
||||||
const QString& server,
|
|
||||||
QKeychain::JobPrivate* self);
|
|
||||||
|
|
||||||
static bool writePassword(const QString& display_name,
|
|
||||||
const QString& user,
|
|
||||||
const QString& server,
|
|
||||||
const QKeychain::JobPrivate::Mode type,
|
|
||||||
const QByteArray& password,
|
|
||||||
QKeychain::JobPrivate* self);
|
|
||||||
|
|
||||||
static bool deletePassword(const QString &key, const QString &service,
|
|
||||||
QKeychain::JobPrivate* self);
|
|
||||||
|
|
||||||
private:
|
|
||||||
LibSecretKeyring();
|
|
||||||
|
|
||||||
static LibSecretKeyring &instance();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,276 +0,0 @@
|
|||||||
<!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>
|
|
@ -1,110 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> *
|
|
||||||
* Copyright (C) 2016 Mathias Hasselmann <mathias.hasselmann@kdab.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 "plaintextstore_p.h"
|
|
||||||
|
|
||||||
using namespace QKeychain;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
inline QString dataKey(const QString &key) { return key; }
|
|
||||||
#else // Q_OS_WIN
|
|
||||||
inline QString dataKey(const QString &key) { return key + QLatin1String("/data"); }
|
|
||||||
inline QString typeKey(const QString &key) { return key + QLatin1String("/type"); }
|
|
||||||
#endif // Q_OS_WIN
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PlainTextStore::PlainTextStore(const QString &service, QSettings *settings)
|
|
||||||
: m_localSettings(settings ? 0 : new QSettings(service))
|
|
||||||
, m_actualSettings(settings ? settings : m_localSettings.data())
|
|
||||||
, m_error(NoError)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PlainTextStore::contains(const QString &key) const
|
|
||||||
{
|
|
||||||
return m_actualSettings->contains(dataKey(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray PlainTextStore::readData(const QString &key)
|
|
||||||
{
|
|
||||||
return read(dataKey(key)).toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
|
|
||||||
JobPrivate::Mode PlainTextStore::readMode(const QString &key)
|
|
||||||
{
|
|
||||||
return JobPrivate::stringToMode(read(typeKey(key)).toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // Q_OS_WIN
|
|
||||||
|
|
||||||
void PlainTextStore::write(const QString &key, const QByteArray &data, JobPrivate::Mode mode)
|
|
||||||
{
|
|
||||||
if (m_actualSettings->status() != QSettings::NoError)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
m_actualSettings->setValue(typeKey(key), JobPrivate::modeToString(mode));
|
|
||||||
#else // Q_OS_WIN
|
|
||||||
Q_UNUSED(mode);
|
|
||||||
#endif // Q_OS_WIN
|
|
||||||
m_actualSettings->setValue(dataKey(key), data);
|
|
||||||
m_actualSettings->sync();
|
|
||||||
|
|
||||||
if (m_actualSettings->status() == QSettings::AccessError) {
|
|
||||||
setError(AccessDenied, tr("Could not store data in settings: access error"));
|
|
||||||
} else if (m_actualSettings->status() != QSettings::NoError) {
|
|
||||||
setError(OtherError, tr("Could not store data in settings: format error"));
|
|
||||||
} else {
|
|
||||||
setError(NoError, QString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlainTextStore::remove(const QString &key)
|
|
||||||
{
|
|
||||||
if (m_actualSettings->status() != QSettings::NoError)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
|
||||||
m_actualSettings->remove(typeKey(key));
|
|
||||||
#endif // Q_OS_WIN
|
|
||||||
m_actualSettings->remove(dataKey(key));
|
|
||||||
m_actualSettings->sync();
|
|
||||||
|
|
||||||
if (m_actualSettings->status() == QSettings::AccessError) {
|
|
||||||
setError(AccessDenied, tr("Could not delete data from settings: access error"));
|
|
||||||
} else if (m_actualSettings->status() != QSettings::NoError) {
|
|
||||||
setError(OtherError, tr("Could not delete data from settings: format error"));
|
|
||||||
} else {
|
|
||||||
setError(NoError, QString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlainTextStore::setError(Error error, const QString &errorString)
|
|
||||||
{
|
|
||||||
m_error = error;
|
|
||||||
m_errorString = errorString;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant PlainTextStore::read(const QString &key)
|
|
||||||
{
|
|
||||||
const QVariant value = m_actualSettings->value(key);
|
|
||||||
|
|
||||||
if (value.isNull()) {
|
|
||||||
setError(EntryNotFound, tr("Entry not found"));
|
|
||||||
} else {
|
|
||||||
setError(NoError, QString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Copyright (C) 2011-2015 Frank Osterfeld <frank.osterfeld@gmail.com> *
|
|
||||||
* Copyright (C) 2016 Mathias Hasselmann <mathias.hasselmann@kdab.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 QTKEYCHAIN_PLAINTEXTSTORE_P_H
|
|
||||||
#define QTKEYCHAIN_PLAINTEXTSTORE_P_H
|
|
||||||
|
|
||||||
#include "keychain_p.h"
|
|
||||||
|
|
||||||
namespace QKeychain {
|
|
||||||
|
|
||||||
class PlainTextStore {
|
|
||||||
Q_DECLARE_TR_FUNCTIONS(QKeychain::PlainTextStore)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit PlainTextStore(const QString &service, QSettings *settings);
|
|
||||||
|
|
||||||
Error error() const { return m_error; }
|
|
||||||
QString errorString() const { return m_errorString; }
|
|
||||||
|
|
||||||
bool contains(const QString &key) const;
|
|
||||||
|
|
||||||
QByteArray readData(const QString &key);
|
|
||||||
JobPrivate::Mode readMode(const QString &key);
|
|
||||||
|
|
||||||
void write(const QString &key, const QByteArray &data, JobPrivate::Mode mode);
|
|
||||||
void remove(const QString &key);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void setError(Error error, const QString &errorString);
|
|
||||||
QVariant read(const QString &key);
|
|
||||||
|
|
||||||
const QScopedPointer<QSettings> m_localSettings;
|
|
||||||
QSettings *const m_actualSettings;
|
|
||||||
QString m_errorString;
|
|
||||||
Error m_error;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // QTKEYCHAIN_PLAINTEXTSTORE_P_H
|
|
@ -1,100 +0,0 @@
|
|||||||
# Minimal qmake support.
|
|
||||||
# This file is provided as is without any warranty.
|
|
||||||
# It can break at anytime or be removed without notice.
|
|
||||||
|
|
||||||
lessThan(QT_MAJOR_VERSION, 5) {
|
|
||||||
error("qtkeychain requires Qt 5 or later")
|
|
||||||
}
|
|
||||||
|
|
||||||
QTKEYCHAIN_PWD = $$PWD
|
|
||||||
|
|
||||||
CONFIG += depend_includepath
|
|
||||||
DEFINES += QTKEYCHAIN_NO_EXPORT
|
|
||||||
|
|
||||||
INCLUDEPATH += \
|
|
||||||
$$PWD/.. \
|
|
||||||
$$QTKEYCHAIN_PWD
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
$$QTKEYCHAIN_PWD/keychain_p.h \
|
|
||||||
$$QTKEYCHAIN_PWD/keychain.h
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
$$QTKEYCHAIN_PWD/keychain.cpp
|
|
||||||
|
|
||||||
unix:!android:!macx:!ios {
|
|
||||||
# Remove the following LIBSECRET_SUPPORT line
|
|
||||||
# to build without libsecret support.
|
|
||||||
DEFINES += LIBSECRET_SUPPORT
|
|
||||||
contains(DEFINES, LIBSECRET_SUPPORT) {
|
|
||||||
packagesExist(libsecret-1) {
|
|
||||||
!build_pass:message("Libsecret support: on")
|
|
||||||
CONFIG += link_pkgconfig
|
|
||||||
PKGCONFIG += libsecret-1
|
|
||||||
DEFINES += HAVE_LIBSECRET
|
|
||||||
} else {
|
|
||||||
!build_pass:warning("Libsecret not found.")
|
|
||||||
!build_pass:message("Libsecret support: off")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
!build_pass:message("Libsecret support: off")
|
|
||||||
}
|
|
||||||
|
|
||||||
# Generate D-Bus interface:
|
|
||||||
DEFINES += KEYCHAIN_DBUS
|
|
||||||
QT += dbus
|
|
||||||
kwallet_interface.files = $$PWD/org.kde.KWallet.xml
|
|
||||||
DBUS_INTERFACES += kwallet_interface
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
$$QTKEYCHAIN_PWD/gnomekeyring_p.h \
|
|
||||||
$$QTKEYCHAIN_PWD/plaintextstore_p.h \
|
|
||||||
$$QTKEYCHAIN_PWD/libsecret_p.h
|
|
||||||
SOURCES += \
|
|
||||||
$$QTKEYCHAIN_PWD/keychain_unix.cpp \
|
|
||||||
$$QTKEYCHAIN_PWD/plaintextstore.cpp \
|
|
||||||
$$QTKEYCHAIN_PWD/gnomekeyring.cpp \
|
|
||||||
$$QTKEYCHAIN_PWD/libsecret.cpp
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
QT += androidextras
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
$$QTKEYCHAIN_PWD/androidkeystore_p.h \
|
|
||||||
$$QTKEYCHAIN_PWD/plaintextstore_p.h
|
|
||||||
SOURCES += \
|
|
||||||
$$QTKEYCHAIN_PWD/androidkeystore.cpp \
|
|
||||||
$$QTKEYCHAIN_PWD/keychain_android.cpp \
|
|
||||||
$$QTKEYCHAIN_PWD/plaintextstore.cpp
|
|
||||||
}
|
|
||||||
|
|
||||||
win32 {
|
|
||||||
# Remove the following USE_CREDENTIAL_STORE line
|
|
||||||
# to use the CryptProtectData Windows API function
|
|
||||||
# instead of the Windows Credential Store.
|
|
||||||
DEFINES += USE_CREDENTIAL_STORE
|
|
||||||
contains(DEFINES, USE_CREDENTIAL_STORE) {
|
|
||||||
!build_pass:message("Windows Credential Store support: on")
|
|
||||||
LIBS += -ladvapi32
|
|
||||||
} else {
|
|
||||||
!build_pass:message("Windows Credential Store support: off")
|
|
||||||
LIBS += -lcrypt32
|
|
||||||
HEADERS += $$QTKEYCHAIN_PWD/plaintextstore_p.h
|
|
||||||
SOURCES += $$QTKEYCHAIN_PWD/plaintextstore.cpp
|
|
||||||
}
|
|
||||||
HEADERS += $$QTKEYCHAIN_PWD/libsecret_p.h
|
|
||||||
SOURCES += \
|
|
||||||
$$QTKEYCHAIN_PWD/keychain_win.cpp \
|
|
||||||
$$QTKEYCHAIN_PWD/libsecret.cpp
|
|
||||||
}
|
|
||||||
|
|
||||||
macx:!ios {
|
|
||||||
LIBS += -framework Security -framework Foundation
|
|
||||||
SOURCES += $$QTKEYCHAIN_PWD/keychain_apple.mm
|
|
||||||
}
|
|
||||||
|
|
||||||
ios {
|
|
||||||
LIBS += -framework Security -framework Foundation
|
|
||||||
OBJECTIVE_SOURCES += $$QTKEYCHAIN_PWD/keychain_ios.mm
|
|
||||||
}
|
|
@ -1,121 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* 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("bstore") ) {
|
|
||||||
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.setBinaryData( pass.toUtf8() );
|
|
||||||
QEventLoop loop;
|
|
||||||
job.connect( &job, SIGNAL(finished(QKeychain::Job*)), &loop, SLOT(quit()) );
|
|
||||||
job.start();
|
|
||||||
loop.exec();
|
|
||||||
if ( job.error() ) {
|
|
||||||
std::cerr << "Storing binary 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,326 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!DOCTYPE TS>
|
|
||||||
<TS version="2.1" language="de_DE">
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::DeletePasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="104"/>
|
|
||||||
<source>Password entry not found</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="108"/>
|
|
||||||
<source>Could not decrypt data</source>
|
|
||||||
<translation type="unfinished">Kann Daten nicht entschlüsseln</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="548"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="556"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation type="unfinished">Unbekannter Fehler</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="574"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation type="unfinished">Konnte Brieftasche nicht öffnen: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="177"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation type="unfinished">Passwort nicht gefunden</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="165"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="171"/>
|
|
||||||
<source>Could not remove private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::JobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="265"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation type="unfinished">Unbekannter Fehler</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="509"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation type="unfinished">Zugriff auf Schlüsselbund verweigert</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::PlainTextStore</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="65"/>
|
|
||||||
<source>Could not store data in settings: access error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="67"/>
|
|
||||||
<source>Could not store data in settings: format error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="85"/>
|
|
||||||
<source>Could not delete data from settings: access error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="87"/>
|
|
||||||
<source>Could not delete data from settings: format error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="104"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation type="unfinished">Eintrag nicht gefunden</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::ReadPasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="187"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="197"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Unbekannter Fehler</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="178"/>
|
|
||||||
<source>D-Bus is not running</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="286"/>
|
|
||||||
<source>No keychain service available</source>
|
|
||||||
<translation>Kein Schlüsselbund-Dienst verfügbar</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="288"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>Konnte Brieftasche nicht öffnen: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="333"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>Zugriff auf Schlüsselbund verweigert</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="354"/>
|
|
||||||
<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="372"/>
|
|
||||||
<source>Unsupported entry type 'Map'</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="375"/>
|
|
||||||
<source>Unknown kwallet entry type '%1'</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not read password: %1; %2</source>
|
|
||||||
<translation type="vanished">Passwort konnte nicht ausgelesen werden: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="96"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation>Passwort nicht gefunden</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="363"/>
|
|
||||||
<location filename="../keychain_android.cpp" line="50"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation>Eintrag nicht gefunden</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="32"/>
|
|
||||||
<source>Password entry not found</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="36"/>
|
|
||||||
<location filename="../keychain_win.cpp" line="139"/>
|
|
||||||
<source>Could not decrypt data</source>
|
|
||||||
<translation>Kann Daten nicht entschlüsseln</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="58"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="66"/>
|
|
||||||
<source>Could not retrieve private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="73"/>
|
|
||||||
<source>Could not create decryption cipher</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::WritePasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="425"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="452"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Unbekannter Fehler</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="415"/>
|
|
||||||
<source>D-Bus is not running</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="468"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>Konnte Brieftasche nicht öffnen: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation type="vanished">Zugriff auf Schlüsselbund verweigert</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not delete encrypted data from settings: access error</source>
|
|
||||||
<translation type="vanished">Kann verschlüsselte Daten nicht aus den Einstellungen entfernen: Zugriffsfehler</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not delete encrypted data from settings: format error</source>
|
|
||||||
<translation type="vanished">Kann verschlüsselte Daten nicht aus den Einstellungen entfernen: Formatfehler</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="78"/>
|
|
||||||
<source>Credential size exceeds maximum size of %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="87"/>
|
|
||||||
<source>Credential key exceeds maximum size of %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="92"/>
|
|
||||||
<source>Writing credentials failed: Win32 error code %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="162"/>
|
|
||||||
<source>Encryption failed</source>
|
|
||||||
<translation>Verschlüsselung fehlgeschlagen</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not store encrypted data in settings: access error</source>
|
|
||||||
<translation type="vanished">Kann verschlüsselte Daten nicht in den Einstellungen speichern: Zugriffsfehler</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not store encrypted data in settings: format error</source>
|
|
||||||
<translation type="vanished">Kann verschlüsselte Daten nicht in den Einstellungen speichern: Formatfehler</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="144"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation type="unfinished">Passwort nicht gefunden</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="93"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="116"/>
|
|
||||||
<source>Could not create private key generator</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="123"/>
|
|
||||||
<source>Could not generate new private key</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="131"/>
|
|
||||||
<source>Could not retrieve private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="139"/>
|
|
||||||
<source>Could not create encryption cipher</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="147"/>
|
|
||||||
<source>Could not encrypt data</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QObject</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="225"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>Zugriff auf Schlüsselbund verweigert</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="227"/>
|
|
||||||
<source>No keyring daemon</source>
|
|
||||||
<translation>Kein Schlüsselbund-Dienst </translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="229"/>
|
|
||||||
<source>Already unlocked</source>
|
|
||||||
<translation>Bereits entsperrt</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="231"/>
|
|
||||||
<source>No such keyring</source>
|
|
||||||
<translation>Kein solcher Schlüsselbund</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="233"/>
|
|
||||||
<source>Bad arguments</source>
|
|
||||||
<translation>Ungültige Argumente</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="235"/>
|
|
||||||
<source>I/O error</source>
|
|
||||||
<translation>Ein-/Ausgabe-Fehler</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="237"/>
|
|
||||||
<source>Cancelled</source>
|
|
||||||
<translation>Abgebrochen</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="239"/>
|
|
||||||
<source>Keyring already exists</source>
|
|
||||||
<translation>Schlüsselbund existiert bereits</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="241"/>
|
|
||||||
<source>No match</source>
|
|
||||||
<translation>Kein Treffer</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="246"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Unbekannter Fehler</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../libsecret.cpp" line="122"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation type="unfinished">Eintrag nicht gefunden</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="72"/>
|
|
||||||
<source>error 0x%1: %2</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
</TS>
|
|
@ -1,334 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!DOCTYPE TS>
|
|
||||||
<TS version="2.1" language="fr_FR">
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::DeletePasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="104"/>
|
|
||||||
<source>Password entry not found</source>
|
|
||||||
<translation>Mot de passe introuvable</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="108"/>
|
|
||||||
<source>Could not decrypt data</source>
|
|
||||||
<translation>Impossible de déchiffrer les données</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="548"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="556"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Erreur inconnue</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="574"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>Impossible d'ouvrir le portefeuille : %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="177"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation>Mot de passe introuvable</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="165"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="171"/>
|
|
||||||
<source>Could not remove private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::JobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="265"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Erreur inconnue</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="509"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>Accès au trousseau refusé</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::PlainTextStore</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="65"/>
|
|
||||||
<source>Could not store data in settings: access error</source>
|
|
||||||
<translation>Impossible de stocker les données dans les paramètres : Erreur d'accès</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="67"/>
|
|
||||||
<source>Could not store data in settings: format error</source>
|
|
||||||
<translation>Impossible de stocker les données dans les paramètres : Erreur de format</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="85"/>
|
|
||||||
<source>Could not delete data from settings: access error</source>
|
|
||||||
<translation>Impossible de supprimer les données depuis les paramètres : Erreur d'accès</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="87"/>
|
|
||||||
<source>Could not delete data from settings: format error</source>
|
|
||||||
<translation>Impossible de supprimer les données depuis les paramètres : Erreur de format</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="104"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation>Entrée introuvable</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::ReadPasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="187"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="197"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Erreur inconnue</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="178"/>
|
|
||||||
<source>D-Bus is not running</source>
|
|
||||||
<translation>D-Bus n'est pas en cours d'exécution</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="286"/>
|
|
||||||
<source>No keychain service available</source>
|
|
||||||
<translation>Aucun service de trousseau disponible</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="288"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>Impossible d'ouvrir le trousseau : %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="333"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>Accès au trousseau refusé</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="354"/>
|
|
||||||
<source>Could not determine data type: %1; %2</source>
|
|
||||||
<translation>Impossible de déterminer le type de données : %1: %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="372"/>
|
|
||||||
<source>Unsupported entry type 'Map'</source>
|
|
||||||
<translation>Type d'entrée non supporté 'Map'</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="375"/>
|
|
||||||
<source>Unknown kwallet entry type '%1'</source>
|
|
||||||
<translation>Type de trousseau inconnu '%1'</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not read password: %1; %2</source>
|
|
||||||
<translation type="vanished">Impossible de lire le mot de passe : %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="96"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation>Mot de passe introuvable</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="363"/>
|
|
||||||
<location filename="../keychain_android.cpp" line="50"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation>Entrée introuvable</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="32"/>
|
|
||||||
<source>Password entry not found</source>
|
|
||||||
<translation>Entrée de mot de passe introuvable</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="36"/>
|
|
||||||
<location filename="../keychain_win.cpp" line="139"/>
|
|
||||||
<source>Could not decrypt data</source>
|
|
||||||
<translation>Impossible de déchiffrer les données</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="58"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="66"/>
|
|
||||||
<source>Could not retrieve private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="73"/>
|
|
||||||
<source>Could not create decryption cipher</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::WritePasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="425"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="452"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Erreur inconnue</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="415"/>
|
|
||||||
<source>D-Bus is not running</source>
|
|
||||||
<translation>D-Bus n'est pas en cours d'exécution</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="468"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>Impossible d'ouvrir le trousseau : %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation type="vanished">Accès au trousseau refusé</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not delete encrypted data from settings: access error</source>
|
|
||||||
<translation type="vanished">Impossible de supprimer des données chiffrées dans les paramètres : Erreur d'accès</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not delete encrypted data from settings: format error</source>
|
|
||||||
<translation type="vanished">Impossible de supprimer des données chiffrées dans les paramètres : Erreur de format</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="78"/>
|
|
||||||
<source>Credential size exceeds maximum size of %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="87"/>
|
|
||||||
<source>Credential key exceeds maximum size of %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="92"/>
|
|
||||||
<source>Writing credentials failed: Win32 error code %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="162"/>
|
|
||||||
<source>Encryption failed</source>
|
|
||||||
<translation>Le chiffrement a échoué</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not store encrypted data in settings: access error</source>
|
|
||||||
<translation type="vanished">Impossible de stocker des données chiffrées dans les paramètres : Erreur d'accès</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not store encrypted data in settings: format error</source>
|
|
||||||
<translation type="vanished">Impossible de stocker des données chiffrées dans les paramètres : Erreur de format</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="144"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation>Mot de passe introuvable</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="93"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="116"/>
|
|
||||||
<source>Could not create private key generator</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="123"/>
|
|
||||||
<source>Could not generate new private key</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="131"/>
|
|
||||||
<source>Could not retrieve private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="139"/>
|
|
||||||
<source>Could not create encryption cipher</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="147"/>
|
|
||||||
<source>Could not encrypt data</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QObject</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="225"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>Accès au trousseau refusé</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="227"/>
|
|
||||||
<source>No keyring daemon</source>
|
|
||||||
<translation>Aucun démon de trousseau</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="229"/>
|
|
||||||
<source>Already unlocked</source>
|
|
||||||
<translation>Déjà déverrouillé</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="231"/>
|
|
||||||
<source>No such keyring</source>
|
|
||||||
<translation>Aucun trousseau</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="233"/>
|
|
||||||
<source>Bad arguments</source>
|
|
||||||
<translation>Mauvais arguments</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="235"/>
|
|
||||||
<source>I/O error</source>
|
|
||||||
<translation>Erreur d'E/S</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="237"/>
|
|
||||||
<source>Cancelled</source>
|
|
||||||
<translation>Annulé</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="239"/>
|
|
||||||
<source>Keyring already exists</source>
|
|
||||||
<translation>Trousseau déjà existant</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="241"/>
|
|
||||||
<source>No match</source>
|
|
||||||
<translation>Aucune correspondance</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="246"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Erreur inconnue</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>OS X Keychain error (OSStatus %1)</source>
|
|
||||||
<translation type="vanished">OS X Keychain error (OSStatus %1)</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>%1 (OSStatus %2)</source>
|
|
||||||
<translation type="vanished">%1 (OSStatus %2)</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../libsecret.cpp" line="122"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation>Entrée introuvable</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="72"/>
|
|
||||||
<source>error 0x%1: %2</source>
|
|
||||||
<translation>Erreur 0x%1 : %2</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
</TS>
|
|
@ -1,331 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!DOCTYPE TS>
|
|
||||||
<TS version="2.1" language="ro_RO">
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::DeletePasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="104"/>
|
|
||||||
<source>Password entry not found</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="108"/>
|
|
||||||
<source>Could not decrypt data</source>
|
|
||||||
<translation type="unfinished">Nu se poate decripta data</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="548"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="556"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation type="unfinished">Eroare necunoscută</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="574"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation type="unfinished">Nu se poate deschide portofelul: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="177"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation type="unfinished">Parola nu a fost găsită</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="165"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="171"/>
|
|
||||||
<source>Could not remove private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::JobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="265"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation type="unfinished">Eroare necunoscută</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="509"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation type="unfinished">Acces interzis la serviciul de chei</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::PlainTextStore</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="65"/>
|
|
||||||
<source>Could not store data in settings: access error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="67"/>
|
|
||||||
<source>Could not store data in settings: format error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="85"/>
|
|
||||||
<source>Could not delete data from settings: access error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="87"/>
|
|
||||||
<source>Could not delete data from settings: format error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="104"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation type="unfinished">Înregistrarea nu a fost găsită</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::ReadPasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="187"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="197"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Eroare necunoscută</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="178"/>
|
|
||||||
<source>D-Bus is not running</source>
|
|
||||||
<translation>D-Bus nu rulează</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="286"/>
|
|
||||||
<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="288"/>
|
|
||||||
<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="333"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>Acces interzis la serviciul de chei</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="354"/>
|
|
||||||
<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="372"/>
|
|
||||||
<source>Unsupported entry type 'Map'</source>
|
|
||||||
<translation>Tip de înregistrare nesuportat 'Map'</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="375"/>
|
|
||||||
<source>Unknown kwallet entry type '%1'</source>
|
|
||||||
<translation>Tip de înregistrare kwallet necunoscut '%1'</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not read password: %1; %2</source>
|
|
||||||
<translation type="vanished">Nu se poate citi parola: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="96"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation>Parola nu a fost găsită</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="363"/>
|
|
||||||
<location filename="../keychain_android.cpp" line="50"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation>Înregistrarea nu a fost găsită</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="32"/>
|
|
||||||
<source>Password entry not found</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="36"/>
|
|
||||||
<location filename="../keychain_win.cpp" line="139"/>
|
|
||||||
<source>Could not decrypt data</source>
|
|
||||||
<translation>Nu se poate decripta data</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="58"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="66"/>
|
|
||||||
<source>Could not retrieve private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="73"/>
|
|
||||||
<source>Could not create decryption cipher</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::WritePasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="425"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="452"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Eroare necunoscută</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="415"/>
|
|
||||||
<source>D-Bus is not running</source>
|
|
||||||
<translation>D-Bus nu rulează</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="468"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>Nu se poate deschide portofelul: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation type="vanished">Acces interzis la serviciul de chei</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not delete encrypted data from settings: access error</source>
|
|
||||||
<translation type="vanished">Nu se pot șterge datele criptate din setări: eroare de acces</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not delete encrypted data from settings: format error</source>
|
|
||||||
<translation type="vanished">Nu se pot șterge datele criptate din setări: eroare de format</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="78"/>
|
|
||||||
<source>Credential size exceeds maximum size of %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="87"/>
|
|
||||||
<source>Credential key exceeds maximum size of %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="92"/>
|
|
||||||
<source>Writing credentials failed: Win32 error code %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="162"/>
|
|
||||||
<source>Encryption failed</source>
|
|
||||||
<translation>Criptarea a eșuat</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not store encrypted data in settings: access error</source>
|
|
||||||
<translation type="vanished">Nu se pot stoca datele criptate în setări: eroare de acces</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not store encrypted data in settings: format error</source>
|
|
||||||
<translation type="vanished">Nu se pot stoca datele criptate în setări: eroare de format</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="144"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation type="unfinished">Parola nu a fost găsită</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="93"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="116"/>
|
|
||||||
<source>Could not create private key generator</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="123"/>
|
|
||||||
<source>Could not generate new private key</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="131"/>
|
|
||||||
<source>Could not retrieve private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="139"/>
|
|
||||||
<source>Could not create encryption cipher</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="147"/>
|
|
||||||
<source>Could not encrypt data</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QObject</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="225"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>Acces interzis la serviciul de chei</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="227"/>
|
|
||||||
<source>No keyring daemon</source>
|
|
||||||
<translation>Niciun demon pentru inelul de chei</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="229"/>
|
|
||||||
<source>Already unlocked</source>
|
|
||||||
<translation>Deja deblocat</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="231"/>
|
|
||||||
<source>No such keyring</source>
|
|
||||||
<translation>Nu există astfel de inel de chei</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="233"/>
|
|
||||||
<source>Bad arguments</source>
|
|
||||||
<translation>Argumente greșite</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="235"/>
|
|
||||||
<source>I/O error</source>
|
|
||||||
<translation>Eroare de I/E</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="237"/>
|
|
||||||
<source>Cancelled</source>
|
|
||||||
<translation>Anulat</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="239"/>
|
|
||||||
<source>Keyring already exists</source>
|
|
||||||
<translation>Inelul de chei deja există</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="241"/>
|
|
||||||
<source>No match</source>
|
|
||||||
<translation>Nicio potrivire</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="246"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Eroare necunoscută</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>%1 (OSStatus %2)</source>
|
|
||||||
<translation type="vanished">%1 (OSStatus %2)</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../libsecret.cpp" line="122"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation type="unfinished">Înregistrarea nu a fost găsită</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="72"/>
|
|
||||||
<source>error 0x%1: %2</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
</TS>
|
|
@ -1,310 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!DOCTYPE TS>
|
|
||||||
<TS version="2.1" language="ru_RU">
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::DeletePasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="548"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="556"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Неизвестная ошибка</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="574"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>Не удалось открыть бумажник: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="104"/>
|
|
||||||
<source>Password entry not found</source>
|
|
||||||
<translation>Пароль не найден</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="108"/>
|
|
||||||
<source>Could not decrypt data</source>
|
|
||||||
<translation>Не удалось расшифровать данные</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="177"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation type="unfinished">Пароль не найден</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="165"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="171"/>
|
|
||||||
<source>Could not remove private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::JobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="265"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Неизвестная ошибка</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="509"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>Доступ к связке ключей запрещён</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::PlainTextStore</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="65"/>
|
|
||||||
<source>Could not store data in settings: access error</source>
|
|
||||||
<translation>Не удалось сохранить данные в настройках: ошибка доступа</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="67"/>
|
|
||||||
<source>Could not store data in settings: format error</source>
|
|
||||||
<translation>Не удалось сохранить данные в настройках: ошибка формата</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="85"/>
|
|
||||||
<source>Could not delete data from settings: access error</source>
|
|
||||||
<translation>Не удалось удалить данные из настроек: ошибка доступа</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="87"/>
|
|
||||||
<source>Could not delete data from settings: format error</source>
|
|
||||||
<translation>Не удалось удалить данные из настроек: ошибка формата</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="104"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation>Запись не найдена</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::ReadPasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="96"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation>Пароль не найден</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="178"/>
|
|
||||||
<source>D-Bus is not running</source>
|
|
||||||
<translation>D-Bus не запущен</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="187"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="197"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Неизвестная ошибка</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="286"/>
|
|
||||||
<source>No keychain service available</source>
|
|
||||||
<translation>Служба связки ключей недоступна</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="288"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>Не удалось открыть кошелёк: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="333"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>Доступ к связке ключей запрещён</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="354"/>
|
|
||||||
<source>Could not determine data type: %1; %2</source>
|
|
||||||
<translation>Не удалось определить тип данных: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="363"/>
|
|
||||||
<location filename="../keychain_android.cpp" line="50"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation>Запись не найдена</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="372"/>
|
|
||||||
<source>Unsupported entry type 'Map'</source>
|
|
||||||
<translation>Неподдерживаемый тип записи 'Map'</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="375"/>
|
|
||||||
<source>Unknown kwallet entry type '%1'</source>
|
|
||||||
<translation>Неизвестный тип записи kwallet '%1'</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="32"/>
|
|
||||||
<source>Password entry not found</source>
|
|
||||||
<translation>Пароль не найден</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="36"/>
|
|
||||||
<location filename="../keychain_win.cpp" line="139"/>
|
|
||||||
<source>Could not decrypt data</source>
|
|
||||||
<translation>Не удалось расшифровать данные</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="58"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="66"/>
|
|
||||||
<source>Could not retrieve private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="73"/>
|
|
||||||
<source>Could not create decryption cipher</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::WritePasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="415"/>
|
|
||||||
<source>D-Bus is not running</source>
|
|
||||||
<translation>D-Bus не запущен</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="425"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="452"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Неизвестная ошибка</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="468"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>Не удалось открыть кошелёк: %1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="78"/>
|
|
||||||
<source>Credential size exceeds maximum size of %1</source>
|
|
||||||
<translation>Учётные данные превышают максимальный размер %1</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="87"/>
|
|
||||||
<source>Credential key exceeds maximum size of %1</source>
|
|
||||||
<translation>Ключ учётных данных превышает максимальный размер %1</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="92"/>
|
|
||||||
<source>Writing credentials failed: Win32 error code %1</source>
|
|
||||||
<translation>Не удалось сохранить учётные данные: код ошибки win32 %1</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="162"/>
|
|
||||||
<source>Encryption failed</source>
|
|
||||||
<translation>Шифрование не удалось</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="144"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation type="unfinished">Пароль не найден</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="93"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="116"/>
|
|
||||||
<source>Could not create private key generator</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="123"/>
|
|
||||||
<source>Could not generate new private key</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="131"/>
|
|
||||||
<source>Could not retrieve private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="139"/>
|
|
||||||
<source>Could not create encryption cipher</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="147"/>
|
|
||||||
<source>Could not encrypt data</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QObject</name>
|
|
||||||
<message>
|
|
||||||
<source>OS X Keychain error (OSStatus %1)</source>
|
|
||||||
<translation type="vanished">Ошибка связки ключей OS X (OSStatus %1)</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>%1 (OSStatus %2)</source>
|
|
||||||
<translation type="vanished">%1 (OSStatus %2)</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="225"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>Доступ к связке ключей запрещён</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="227"/>
|
|
||||||
<source>No keyring daemon</source>
|
|
||||||
<translation>Нет демона связки ключей</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="229"/>
|
|
||||||
<source>Already unlocked</source>
|
|
||||||
<translation>Уже разблокировано</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="231"/>
|
|
||||||
<source>No such keyring</source>
|
|
||||||
<translation>Связка ключей не найдена</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="233"/>
|
|
||||||
<source>Bad arguments</source>
|
|
||||||
<translation>Неверные аргументы</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="235"/>
|
|
||||||
<source>I/O error</source>
|
|
||||||
<translation>Ошибка ввода/вывода</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="237"/>
|
|
||||||
<source>Cancelled</source>
|
|
||||||
<translation>Отменено</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="239"/>
|
|
||||||
<source>Keyring already exists</source>
|
|
||||||
<translation>Связка ключей уже существует</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="241"/>
|
|
||||||
<source>No match</source>
|
|
||||||
<translation>Нет совпадений</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="246"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>Неизвестная ошибка</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../libsecret.cpp" line="122"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation>Запись не найдена</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="72"/>
|
|
||||||
<source>error 0x%1: %2</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
</TS>
|
|
@ -1,330 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!DOCTYPE TS>
|
|
||||||
<TS version="2.1" language="zh_TW">
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::DeletePasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="104"/>
|
|
||||||
<source>Password entry not found</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="108"/>
|
|
||||||
<source>Could not decrypt data</source>
|
|
||||||
<translation type="unfinished">無法解密資料</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="548"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="556"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation type="unfinished">未知的錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="574"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation type="unfinished">無法開啟錢包:%1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="177"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation type="unfinished">找不到密碼</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="165"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="171"/>
|
|
||||||
<source>Could not remove private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::JobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="265"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation type="unfinished">未知的錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="509"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation type="unfinished">鑰匙圈存取被拒絕</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::PlainTextStore</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="65"/>
|
|
||||||
<source>Could not store data in settings: access error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="67"/>
|
|
||||||
<source>Could not store data in settings: format error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="85"/>
|
|
||||||
<source>Could not delete data from settings: access error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="87"/>
|
|
||||||
<source>Could not delete data from settings: format error</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../plaintextstore.cpp" line="104"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation type="unfinished">找不到項目</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::ReadPasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="187"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="197"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>未知的錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="178"/>
|
|
||||||
<source>D-Bus is not running</source>
|
|
||||||
<translation>D-Bus 不在執行中</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="286"/>
|
|
||||||
<source>No keychain service available</source>
|
|
||||||
<translation>沒有可用的鑰匙圈服務</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="288"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>無法開啟錢包:%1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="333"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>鑰匙圈存取被拒絕</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="354"/>
|
|
||||||
<source>Could not determine data type: %1; %2</source>
|
|
||||||
<translation>無法判斷資料型別:%1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="372"/>
|
|
||||||
<source>Unsupported entry type 'Map'</source>
|
|
||||||
<translation>不支援的項目類型 'Map'</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="375"/>
|
|
||||||
<source>Unknown kwallet entry type '%1'</source>
|
|
||||||
<translation>未知的 kwallet 項目類型 '%1'</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not read password: %1; %2</source>
|
|
||||||
<translation type="vanished">無法讀取密碼:%1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="96"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation>找不到密碼</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="363"/>
|
|
||||||
<location filename="../keychain_android.cpp" line="50"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation>找不到項目</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="32"/>
|
|
||||||
<source>Password entry not found</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="36"/>
|
|
||||||
<location filename="../keychain_win.cpp" line="139"/>
|
|
||||||
<source>Could not decrypt data</source>
|
|
||||||
<translation>無法解密資料</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="58"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="66"/>
|
|
||||||
<source>Could not retrieve private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="73"/>
|
|
||||||
<source>Could not create decryption cipher</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QKeychain::WritePasswordJobPrivate</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="425"/>
|
|
||||||
<location filename="../keychain_unix.cpp" line="452"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>未知的錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="415"/>
|
|
||||||
<source>D-Bus is not running</source>
|
|
||||||
<translation>D-Bus 不在執行中</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="468"/>
|
|
||||||
<source>Could not open wallet: %1; %2</source>
|
|
||||||
<translation>無法開啟錢包:%1; %2</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation type="vanished">鑰匙圈存取被拒絕</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not delete encrypted data from settings: access error</source>
|
|
||||||
<translation type="vanished">無法從設定刪除加密資料:存取錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not delete encrypted data from settings: format error</source>
|
|
||||||
<translation type="vanished">無法從設定刪除加密資料:格式錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="78"/>
|
|
||||||
<source>Credential size exceeds maximum size of %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="87"/>
|
|
||||||
<source>Credential key exceeds maximum size of %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="92"/>
|
|
||||||
<source>Writing credentials failed: Win32 error code %1</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_win.cpp" line="162"/>
|
|
||||||
<source>Encryption failed</source>
|
|
||||||
<translation>加密失敗</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not store encrypted data in settings: access error</source>
|
|
||||||
<translation type="vanished">無法將加密資料儲存至設定:存取錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Could not store encrypted data in settings: format error</source>
|
|
||||||
<translation type="vanished">無法將加密資料儲存至設定:格式錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="144"/>
|
|
||||||
<source>Password not found</source>
|
|
||||||
<translation type="unfinished">找不到密碼</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="93"/>
|
|
||||||
<source>Could not open keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="116"/>
|
|
||||||
<source>Could not create private key generator</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="123"/>
|
|
||||||
<source>Could not generate new private key</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="131"/>
|
|
||||||
<source>Could not retrieve private key from keystore</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="139"/>
|
|
||||||
<source>Could not create encryption cipher</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_android.cpp" line="147"/>
|
|
||||||
<source>Could not encrypt data</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>QObject</name>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="225"/>
|
|
||||||
<source>Access to keychain denied</source>
|
|
||||||
<translation>鑰匙圈存取被拒絕</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="227"/>
|
|
||||||
<source>No keyring daemon</source>
|
|
||||||
<translation>沒有可用的鑰匙圈背景程式</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="229"/>
|
|
||||||
<source>Already unlocked</source>
|
|
||||||
<translation>已解鎖</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="231"/>
|
|
||||||
<source>No such keyring</source>
|
|
||||||
<translation>鑰匙圈不存在</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="233"/>
|
|
||||||
<source>Bad arguments</source>
|
|
||||||
<translation>引數錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="235"/>
|
|
||||||
<source>I/O error</source>
|
|
||||||
<translation>I/O 錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="237"/>
|
|
||||||
<source>Cancelled</source>
|
|
||||||
<translation>已取消</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="239"/>
|
|
||||||
<source>Keyring already exists</source>
|
|
||||||
<translation>鑰匙圈已存在</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="241"/>
|
|
||||||
<source>No match</source>
|
|
||||||
<translation>無相符項目</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_unix.cpp" line="246"/>
|
|
||||||
<source>Unknown error</source>
|
|
||||||
<translation>未知的錯誤</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>%1 (OSStatus %2)</source>
|
|
||||||
<translation type="vanished">%1 (OSStatus %2)</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../libsecret.cpp" line="122"/>
|
|
||||||
<source>Entry not found</source>
|
|
||||||
<translation type="unfinished">找不到項目</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../keychain_haiku.cpp" line="72"/>
|
|
||||||
<source>error 0x%1: %2</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
</TS>
|
|
9
fuel.pro
9
fuel.pro
@ -19,6 +19,7 @@ QT-= quick multimediawidgets opengl printsupport qml multimedia positioning sens
|
|||||||
|
|
||||||
TARGET = Fuel
|
TARGET = Fuel
|
||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
|
DEFINES += FUEL_VERSION=\\\"2.0.1\\\"
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
RC_FILE = rsrc/fuel.rc
|
RC_FILE = rsrc/fuel.rc
|
||||||
@ -52,6 +53,11 @@ unix:!macx {
|
|||||||
INSTALLS += target desktop icon
|
INSTALLS += target desktop icon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exists( $$OUT_PWD/conanbuildinfo.pri ) {
|
||||||
|
message("Using conan packages")
|
||||||
|
CONFIG += conan_basic_setup
|
||||||
|
include($$OUT_PWD/conanbuildinfo.pri)
|
||||||
|
}
|
||||||
|
|
||||||
INCLUDEPATH += src
|
INCLUDEPATH += src
|
||||||
|
|
||||||
@ -109,9 +115,6 @@ FORMS += ui/MainWindow.ui \
|
|||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
rsrc/resources.qrc
|
rsrc/resources.qrc
|
||||||
|
|
||||||
# QtKeychain
|
|
||||||
include(ext/qtkeychain.pri)
|
|
||||||
|
|
||||||
CODECFORTR = UTF-8
|
CODECFORTR = UTF-8
|
||||||
|
|
||||||
TRANSLATIONS += \
|
TRANSLATIONS += \
|
||||||
|
34
recipes/qtkeychain/conanfile.py
Normal file
34
recipes/qtkeychain/conanfile.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
from conans import ConanFile, CMake, tools
|
||||||
|
|
||||||
|
|
||||||
|
class QtkeychainConan(ConanFile):
|
||||||
|
name = "qtkeychain"
|
||||||
|
version = "0.12.0"
|
||||||
|
license = "BSD-3"
|
||||||
|
author = "Edgar"
|
||||||
|
url = "https://github.com/AnotherFoxGuy/fuel-scm"
|
||||||
|
description = "Platform-independent Qt API for storing passwords securely"
|
||||||
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
|
options = {"static": [True, False]}
|
||||||
|
default_options = {"static": False}
|
||||||
|
scm = {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/frankosterfeld/qtkeychain.git",
|
||||||
|
"revision": "v0.12.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
cmake = CMake(self)
|
||||||
|
cmake.definitions["QTKEYCHAIN_STATIC"] = self.options.static
|
||||||
|
cmake.definitions["BUILD_TEST_APPLICATION"] = "OFF"
|
||||||
|
cmake.configure()
|
||||||
|
cmake.build()
|
||||||
|
|
||||||
|
def package(self):
|
||||||
|
cmake = CMake(self)
|
||||||
|
cmake.install()
|
||||||
|
|
||||||
|
def package_info(self):
|
||||||
|
self.cpp_info.names["cmake_find_package"] = "Qt5Keychain"
|
||||||
|
self.cpp_info.names["cmake_find_package_multi"] = "Qt5Keychain"
|
||||||
|
self.cpp_info.libs = tools.collect_libs(self)
|
@ -6,7 +6,7 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include "ext/qtkeychain/keychain.h"
|
#include <qt5keychain/keychain.h>
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
QMessageBox::StandardButton DialogQuery(QWidget *parent, const QString &title, const QString &query, QMessageBox::StandardButtons buttons)
|
QMessageBox::StandardButton DialogQuery(QWidget *parent, const QString &title, const QString &query, QMessageBox::StandardButtons buttons)
|
||||||
|
@ -5,7 +5,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
app.setApplicationName("Fuel");
|
app.setApplicationName("Fuel");
|
||||||
app.setApplicationVersion("2.0.1");
|
app.setApplicationVersion(FUEL_VERSION);
|
||||||
app.setOrganizationDomain("fuel-scm.org");
|
app.setOrganizationDomain("fuel-scm.org");
|
||||||
app.setOrganizationName("Fuel-SCM");
|
app.setOrganizationName("Fuel-SCM");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user