Page MenuHome GnuPG

No OneTemporary

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7a32ef3ae..ae5764160 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,655 +1,657 @@
# SPDX-FileCopyrightText: none
# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(icons)
add_subdirectory(mimetypes)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
if (NOT DISABLE_KWATCHGNUPG)
add_subdirectory(kwatchgnupg)
endif()
add_subdirectory(libkleopatraclient)
add_subdirectory(conf)
add_subdirectory(kconf_update)
if(WIN32)
set(_kleopatra_extra_uiserver_SRCS uiserver/uiserver_win.cpp)
set(_kleopatra_extra_SRCS
selftest/registrycheck.cpp selftest/registrycheck.h
utils/gnupg-registry.c
utils/userinfo_win.cpp
utils/winapi-helpers.cpp utils/winapi-helpers.h
utils/windowsprocessdevice.cpp utils/windowsprocessdevice.h
versioninfo.rc kleopatra.w32-manifest
)
else()
set(_kleopatra_extra_uiserver_SRCS uiserver/uiserver_unix.cpp)
set(_kleopatra_extra_SRCS)
endif()
set(_kleopatra_uiserver_SRCS
${_kleopatra_extra_uiserver_SRCS}
selftest/uiservercheck.cpp selftest/uiservercheck.h
uiserver/assuanserverconnection.cpp uiserver/assuanserverconnection.h
uiserver/createchecksumscommand.cpp uiserver/createchecksumscommand.h
uiserver/decryptverifycommandemailbase.cpp uiserver/decryptverifycommandemailbase.h
uiserver/decryptverifycommandfilesbase.cpp uiserver/decryptverifycommandfilesbase.h
uiserver/echocommand.cpp uiserver/echocommand.h
uiserver/encryptcommand.cpp uiserver/encryptcommand.h
uiserver/importfilescommand.cpp uiserver/importfilescommand.h
uiserver/prepencryptcommand.cpp uiserver/prepencryptcommand.h
uiserver/prepsigncommand.cpp uiserver/prepsigncommand.h
uiserver/selectcertificatecommand.cpp
uiserver/sessiondata.cpp uiserver/sessiondata.h
uiserver/signcommand.cpp uiserver/signcommand.h
uiserver/signencryptfilescommand.cpp
uiserver/uiserver.cpp
uiserver/verifychecksumscommand.cpp uiserver/verifychecksumscommand.h
)
set(_kleopatra_uiserver_extra_libs LibAssuan::LibAssuan LibGpgError::LibGpgError)
if(HAVE_GPG_ERR_SOURCE_KLEO)
add_definitions(-DGPG_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_KLEO)
add_definitions(-DGPGMEPP_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_KLEO)
else()
add_definitions(-DGPG_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_USER_1)
add_definitions(-DGPGMEPP_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_USER_1)
endif()
if(KPim${KF_MAJOR_VERSION}IdentityManagement_FOUND AND KPim${KF_MAJOR_VERSION}MailTransport_FOUND AND KPim${KF_MAJOR_VERSION}AkonadiMime_FOUND)
set(_kleopatra_mail_libs
KPim${KF_MAJOR_VERSION}::IdentityManagement # Export OpenPGP keys using WKS
KPim${KF_MAJOR_VERSION}::MailTransport
KPim${KF_MAJOR_VERSION}::AkonadiMime
)
add_definitions(-DMAILAKONADI_ENABLED)
endif()
ki18n_wrap_ui(_kleopatra_uiserver_SRCS crypto/gui/signingcertificateselectionwidget.ui)
set(_kleopatra_SRCS
${_kleopatra_extra_SRCS}
accessibility/accessiblelink.cpp
accessibility/accessiblelink_p.h
accessibility/accessiblerichtextlabel.cpp
accessibility/accessiblerichtextlabel_p.h
accessibility/accessiblevaluelabel.cpp
accessibility/accessiblevaluelabel_p.h
accessibility/accessiblewidgetfactory.cpp
accessibility/accessiblewidgetfactory.h
commands/addadskcommand.cpp
commands/addadskcommand.h
commands/addsubkeycommand.cpp
commands/addsubkeycommand.h
commands/adduseridcommand.cpp
commands/adduseridcommand.h
commands/authenticatepivcardapplicationcommand.cpp
commands/authenticatepivcardapplicationcommand.h
commands/cardcommand.cpp
commands/cardcommand.h
commands/certificatetopivcardcommand.cpp
commands/certificatetopivcardcommand.h
commands/certifycertificatecommand.cpp
commands/certifycertificatecommand.h
commands/certifygroupcommand.cpp
commands/certifygroupcommand.h
commands/changeexpirycommand.cpp
commands/changeexpirycommand.h
commands/changeownertrustcommand.cpp
commands/changeownertrustcommand.h
commands/changepassphrasecommand.cpp
commands/changepassphrasecommand.h
commands/changepincommand.cpp
commands/changepincommand.h
commands/changeroottrustcommand.cpp
commands/changeroottrustcommand.h
commands/checksumcreatefilescommand.cpp
commands/checksumcreatefilescommand.h
commands/checksumverifyfilescommand.cpp
commands/checksumverifyfilescommand.h
commands/clearcrlcachecommand.cpp
commands/clearcrlcachecommand.h
commands/command.cpp
commands/command.h
commands/createcsrforcardkeycommand.cpp
commands/createcsrforcardkeycommand.h
commands/creategroupcommand.cpp
commands/creategroupcommand.h
commands/createopenpgpkeyfromcardkeyscommand.cpp
commands/createopenpgpkeyfromcardkeyscommand.h
commands/decryptverifyclipboardcommand.cpp
commands/decryptverifyclipboardcommand.h
commands/decryptverifyfilescommand.cpp
commands/decryptverifyfilescommand.h
commands/deletecertificatescommand.cpp
commands/deletecertificatescommand.h
commands/detailscommand.cpp
commands/detailscommand.h
commands/dumpcertificatecommand.cpp
commands/dumpcertificatecommand.h
commands/dumpcrlcachecommand.cpp
commands/dumpcrlcachecommand.h
commands/encryptclipboardcommand.cpp
commands/encryptclipboardcommand.h
commands/exportcertificatecommand.cpp
commands/exportcertificatecommand.h
commands/exportgroupscommand.cpp
commands/exportgroupscommand.h
commands/exportopenpgpcertstoservercommand.cpp
commands/exportopenpgpcertstoservercommand.h
commands/exportopenpgpcerttoprovidercommand.cpp
commands/exportopenpgpcerttoprovidercommand.h
commands/exportpaperkeycommand.cpp
commands/exportpaperkeycommand.h
commands/exportsecretkeycommand.cpp
commands/exportsecretkeycommand.h
commands/exportsecretsubkeycommand.cpp
commands/exportsecretsubkeycommand.h
commands/genrevokecommand.cpp
commands/genrevokecommand.h
commands/gnupgprocesscommand.cpp
commands/gnupgprocesscommand.h
commands/importcertificatefromclipboardcommand.cpp
commands/importcertificatefromclipboardcommand.h
commands/importcertificatefromdatacommand.cpp
commands/importcertificatefromdatacommand.h
commands/importcertificatefromfilecommand.cpp
commands/importcertificatefromfilecommand.h
commands/importcertificatefromkeyservercommand.cpp
commands/importcertificatefromkeyservercommand.h
commands/importcertificatefrompivcardcommand.cpp
commands/importcertificatefrompivcardcommand.h
commands/importcertificatescommand.cpp
commands/importcertificatescommand.h
commands/importcrlcommand.cpp
commands/importcrlcommand.h
commands/importpaperkeycommand.cpp
commands/importpaperkeycommand.h
commands/keytocardcommand.cpp
commands/keytocardcommand.h
commands/lookupcertificatescommand.cpp
commands/lookupcertificatescommand.h
commands/newcertificatesigningrequestcommand.cpp
commands/newcertificatesigningrequestcommand.h
commands/newopenpgpcertificatecommand.cpp
commands/newopenpgpcertificatecommand.h
commands/openpgpgeneratecardkeycommand.cpp
commands/openpgpgeneratecardkeycommand.h
commands/pivgeneratecardkeycommand.cpp
commands/pivgeneratecardkeycommand.h
commands/refreshcertificatescommand.cpp
commands/refreshcertificatescommand.h
commands/refreshopenpgpcertscommand.cpp
commands/refreshopenpgpcertscommand.h
commands/refreshx509certscommand.cpp
commands/refreshx509certscommand.h
commands/reloadkeyscommand.cpp
commands/reloadkeyscommand.h
commands/revokecertificationcommand.cpp
commands/revokecertificationcommand.h
commands/revokekeycommand.cpp
commands/revokekeycommand.h
commands/revokeuseridcommand.cpp
commands/revokeuseridcommand.h
commands/selftestcommand.cpp
commands/selftestcommand.h
commands/setinitialpincommand.cpp
commands/setinitialpincommand.h
commands/setpivcardapplicationadministrationkeycommand.cpp
commands/setpivcardapplicationadministrationkeycommand.h
commands/setprimaryuseridcommand.cpp
commands/setprimaryuseridcommand.h
commands/signclipboardcommand.cpp
commands/signclipboardcommand.h
commands/signencryptfilescommand.cpp
commands/signencryptfilescommand.h
commands/signencryptfoldercommand.cpp
commands/signencryptfoldercommand.h
commands/viewemailfilescommand.cpp
commands/viewemailfilescommand.h
conf/configuredialog.cpp
conf/configuredialog.h
conf/groupsconfigdialog.cpp
conf/groupsconfigdialog.h
conf/groupsconfigwidget.cpp
conf/groupsconfigwidget.h
crypto/autodecryptverifyfilescontroller.cpp
crypto/autodecryptverifyfilescontroller.h
crypto/certificateresolver.cpp
crypto/certificateresolver.h
crypto/checksumsutils_p.cpp
crypto/checksumsutils_p.h
crypto/controller.cpp
crypto/controller.h
crypto/createchecksumscontroller.cpp
crypto/createchecksumscontroller.h
crypto/decryptverifyemailcontroller.cpp
crypto/decryptverifyemailcontroller.h
crypto/decryptverifyfilescontroller.cpp
crypto/decryptverifyfilescontroller.h
crypto/decryptverifytask.cpp
crypto/decryptverifytask.h
crypto/encryptemailcontroller.cpp
crypto/encryptemailcontroller.h
crypto/encryptemailtask.cpp
crypto/encryptemailtask.h
crypto/gui/certificatelineedit.cpp
crypto/gui/certificatelineedit.h
crypto/gui/certificateselectionline.cpp
crypto/gui/certificateselectionline.h
crypto/gui/decryptverifyfilesdialog.cpp
crypto/gui/decryptverifyfilesdialog.h
crypto/gui/decryptverifyfileswizard.cpp
crypto/gui/decryptverifyfileswizard.h
crypto/gui/decryptverifyoperationwidget.cpp
crypto/gui/decryptverifyoperationwidget.h
crypto/gui/encryptemailwizard.cpp
crypto/gui/encryptemailwizard.h
crypto/gui/newresultpage.cpp
crypto/gui/newresultpage.h
crypto/gui/objectspage.cpp
crypto/gui/objectspage.h
crypto/gui/resolverecipientspage.cpp
crypto/gui/resolverecipientspage.h
crypto/gui/resultitemwidget.cpp
crypto/gui/resultitemwidget.h
crypto/gui/resultlistwidget.cpp
crypto/gui/resultlistwidget.h
crypto/gui/resultpage.cpp
crypto/gui/resultpage.h
crypto/gui/signemailwizard.cpp
crypto/gui/signemailwizard.h
crypto/gui/signencryptemailconflictdialog.cpp
crypto/gui/signencryptemailconflictdialog.h
crypto/gui/signencryptfileswizard.cpp
crypto/gui/signencryptfileswizard.h
crypto/gui/signencryptwidget.cpp
crypto/gui/signencryptwidget.h
crypto/gui/signencryptwizard.cpp
crypto/gui/signencryptwizard.h
crypto/gui/signerresolvepage.cpp
crypto/gui/signerresolvepage.h
crypto/gui/signingcertificateselectiondialog.cpp
crypto/gui/signingcertificateselectiondialog.h
crypto/gui/signingcertificateselectionwidget.cpp
crypto/gui/signingcertificateselectionwidget.h
crypto/gui/unknownrecipientwidget.cpp
crypto/gui/unknownrecipientwidget.h
crypto/gui/verifychecksumsdialog.cpp
crypto/gui/verifychecksumsdialog.h
crypto/gui/wizard.cpp
crypto/gui/wizard.h
crypto/gui/wizardpage.cpp
crypto/gui/wizardpage.h
crypto/newsignencryptemailcontroller.cpp
crypto/newsignencryptemailcontroller.h
crypto/recipient.cpp
crypto/recipient.h
crypto/sender.cpp
crypto/sender.h
crypto/signemailcontroller.cpp
crypto/signemailcontroller.h
crypto/signemailtask.cpp
crypto/signemailtask.h
crypto/signencryptfilescontroller.cpp
crypto/signencryptfilescontroller.h
crypto/signencrypttask.cpp
crypto/signencrypttask.h
crypto/task.cpp
crypto/task.h
crypto/taskcollection.cpp
crypto/taskcollection.h
crypto/verifychecksumscontroller.cpp
crypto/verifychecksumscontroller.h
dialogs/addsubkeydialog.cpp
dialogs/addsubkeydialog.h
dialogs/adduseriddialog.cpp
dialogs/adduseriddialog.h
dialogs/animatedexpander.cpp
dialogs/animatedexpander.h
dialogs/cardinfotab.cpp
dialogs/cardinfotab.h
dialogs/certificatedetailsdialog.cpp
dialogs/certificatedetailsdialog.h
dialogs/certificatedetailsinputwidget.cpp
dialogs/certificatedetailsinputwidget.h
dialogs/certificatedetailswidget.cpp
dialogs/certificatedetailswidget.h
dialogs/certificatedumpwidget.cpp
dialogs/certificatedumpwidget.h
dialogs/certificateselectiondialog.cpp
dialogs/certificateselectiondialog.h
dialogs/certifycertificatedialog.cpp
dialogs/certifycertificatedialog.h
dialogs/certifywidget.cpp
dialogs/certifywidget.h
dialogs/createcsrforcardkeydialog.cpp
dialogs/createcsrforcardkeydialog.h
dialogs/debugdialog.cpp
dialogs/debugdialog.h
dialogs/deletecertificatesdialog.cpp
dialogs/deletecertificatesdialog.h
dialogs/editgroupdialog.cpp
dialogs/editgroupdialog.h
dialogs/expirydialog.cpp
dialogs/expirydialog.h
dialogs/exportdialog.cpp
dialogs/exportdialog.h
dialogs/gencardkeydialog.cpp
dialogs/gencardkeydialog.h
dialogs/groupdetailsdialog.cpp
dialogs/groupdetailsdialog.h
dialogs/lookupcertificatesdialog.cpp
dialogs/lookupcertificatesdialog.h
dialogs/nameandemailwidget.cpp
dialogs/nameandemailwidget.h
dialogs/newopenpgpcertificatedetailsdialog.cpp
dialogs/newopenpgpcertificatedetailsdialog.h
dialogs/pivcardapplicationadministrationkeyinputdialog.cpp
dialogs/pivcardapplicationadministrationkeyinputdialog.h
dialogs/revokekeydialog.cpp
dialogs/revokekeydialog.h
dialogs/selftestdialog.cpp
dialogs/selftestdialog.h
dialogs/setinitialpindialog.cpp
dialogs/setinitialpindialog.h
dialogs/smartcardwindow.cpp
dialogs/smartcardwindow.h
dialogs/subkeyswidget.cpp
dialogs/subkeyswidget.h
dialogs/trustchainwidget.cpp
dialogs/trustchainwidget.h
dialogs/updatenotification.cpp
dialogs/updatenotification.h
dialogs/useridswidget.cpp
dialogs/useridswidget.h
dialogs/weboftrustwidget.cpp
dialogs/weboftrustwidget.h
interfaces/anchorprovider.h
interfaces/focusfirstchild.h
newcertificatewizard/advancedsettingsdialog.cpp
newcertificatewizard/advancedsettingsdialog_p.h
newcertificatewizard/enterdetailspage.cpp
newcertificatewizard/enterdetailspage_p.h
newcertificatewizard/keyalgo.cpp
newcertificatewizard/keyalgo_p.h
newcertificatewizard/keycreationpage.cpp
newcertificatewizard/keycreationpage_p.h
newcertificatewizard/listwidget.cpp
newcertificatewizard/listwidget.h
newcertificatewizard/newcertificatewizard.cpp
newcertificatewizard/newcertificatewizard.h
newcertificatewizard/resultpage.cpp
newcertificatewizard/resultpage_p.h
newcertificatewizard/wizardpage.cpp
newcertificatewizard/wizardpage_p.h
selftest/compliancecheck.cpp
selftest/compliancecheck.h
selftest/enginecheck.cpp
selftest/enginecheck.h
selftest/gpgagentcheck.cpp
selftest/gpgagentcheck.h
selftest/gpgconfcheck.cpp
selftest/gpgconfcheck.h
selftest/libkleopatrarccheck.cpp
selftest/libkleopatrarccheck.h
selftest/selftest.cpp
selftest/selftest.h
smartcard/algorithminfo.h
smartcard/card.cpp
smartcard/card.h
smartcard/deviceinfowatcher.cpp
smartcard/deviceinfowatcher.h
smartcard/keypairinfo.cpp
smartcard/keypairinfo.h
smartcard/netkeycard.cpp
smartcard/netkeycard.h
smartcard/openpgpcard.cpp
smartcard/openpgpcard.h
smartcard/p15card.cpp
smartcard/p15card.h
smartcard/pivcard.cpp
smartcard/pivcard.h
smartcard/readerstatus.cpp
smartcard/readerstatus.h
smartcard/utils.cpp
smartcard/utils.h
utils/accessibility.cpp
utils/accessibility.h
utils/action_data.cpp
utils/action_data.h
utils/applicationstate.cpp
utils/applicationstate.h
utils/archivedefinition.cpp
utils/archivedefinition.h
utils/certificatepair.h
utils/clipboardmenu.cpp
utils/clipboardmenu.h
utils/debug-helpers.cpp
utils/debug-helpers.h
utils/dragqueen.cpp
utils/dragqueen.h
utils/email.cpp
utils/email.h
utils/emptypassphraseprovider.cpp
utils/emptypassphraseprovider.h
utils/expiration.cpp
utils/expiration.h
utils/filedialog.cpp
utils/filedialog.h
utils/gui-helper.cpp
utils/gui-helper.h
utils/headerview.cpp
utils/headerview.h
utils/input.cpp
utils/input.h
utils/iodevicelogger.cpp
utils/iodevicelogger.h
utils/kdpipeiodevice.cpp
utils/kdpipeiodevice.h
utils/keyexportdraghandler.cpp
utils/keyexportdraghandler.h
utils/keyparameters.cpp
utils/keyparameters.h
utils/kuniqueservice.cpp
utils/kuniqueservice.h
utils/log.cpp
utils/log.h
utils/memory-helpers.h
utils/migration.cpp
utils/migration.h
utils/multivalidator.cpp
utils/multivalidator.h
utils/output.cpp
utils/output.h
utils/overwritedialog.cpp
utils/overwritedialog.h
utils/path-helper.cpp
utils/path-helper.h
utils/scrollarea.cpp
utils/scrollarea.h
utils/systemtrayicon.cpp
utils/systemtrayicon.h
utils/tags.cpp
utils/tags.h
utils/types.cpp
utils/types.h
utils/userinfo.cpp
utils/userinfo.h
utils/validation.cpp
utils/validation.h
utils/writecertassuantransaction.cpp
utils/writecertassuantransaction.h
utils/wsastarter.cpp
utils/wsastarter.h
view/anchorcache.cpp
view/anchorcache_p.h
view/cardkeysview.cpp
view/cardkeysview.h
view/errorlabel.cpp
view/errorlabel.h
view/formtextinput.cpp
view/formtextinput.h
view/htmllabel.cpp
view/htmllabel.h
view/infofield.cpp
view/infofield.h
view/keycacheoverlay.cpp
view/keycacheoverlay.h
view/keylistcontroller.cpp
view/keylistcontroller.h
view/keytreeview.cpp
view/keytreeview.h
view/netkeywidget.cpp
view/netkeywidget.h
view/nullpinwidget.cpp
view/nullpinwidget.h
view/openpgpkeycardwidget.cpp
view/openpgpkeycardwidget.h
view/overlaywidget.cpp
view/overlaywidget.h
view/p15cardwidget.cpp
view/p15cardwidget.h
view/padwidget.cpp
view/padwidget.h
view/pgpcardwidget.cpp
view/pgpcardwidget.h
view/pivcardwidget.cpp
view/pivcardwidget.h
view/progressoverlay.cpp
view/progressoverlay.h
view/searchbar.cpp
view/searchbar.h
view/smartcardswidget.cpp
view/smartcardswidget.h
+ view/smartcardwidget.cpp
+ view/smartcardwidget.h
view/tabwidget.cpp
view/tabwidget.h
view/textoverlay.cpp
view/textoverlay.h
view/urllabel.cpp
view/urllabel.h
view/waitwidget.cpp
view/waitwidget.h
view/welcomewidget.cpp
view/welcomewidget.h
aboutdata.cpp
aboutdata.h
kleopatra.qrc
kleopatraapplication.cpp
kleopatraapplication.h
main.cpp
mainwindow.cpp
mainwindow.h
systrayicon.cpp
systrayicon.h
)
if(WIN32)
configure_file (versioninfo.rc.in versioninfo.rc)
configure_file (kleopatra.w32-manifest.in kleopatra.w32-manifest)
set(_kleopatra_SRCS
${CMAKE_CURRENT_BINARY_DIR}/kleopatra.w32-manifest
${CMAKE_CURRENT_BINARY_DIR}/versioninfo.rc
conf/kmessageboxdontaskagainstorage.cpp
conf/kmessageboxdontaskagainstorage.h
${_kleopatra_SRCS}
)
endif()
set (_kleopatra_SRCS conf/kleopageconfigdialog.cpp conf/kleopageconfigdialog.h ${_kleopatra_SRCS})
ecm_qt_declare_logging_category(_kleopatra_SRCS HEADER kleopatra_debug.h IDENTIFIER KLEOPATRA_LOG CATEGORY_NAME org.kde.pim.kleopatra
DESCRIPTION "kleopatra (kleopatra)"
OLD_CATEGORY_NAMES log_kleopatra
EXPORT KLEOPATRA
)
if(KLEO_MODEL_TEST)
add_definitions(-DKLEO_MODEL_TEST)
set(_kleopatra_SRCS ${_kleopatra_SRCS} models/modeltest.cpp)
endif()
ki18n_wrap_ui(_kleopatra_SRCS
dialogs/setinitialpindialog.ui
newcertificatewizard/listwidget.ui
)
kconfig_add_kcfg_files(_kleopatra_SRCS
kcfg/emailoperationspreferences.kcfgc
kcfg/fileoperationspreferences.kcfgc
kcfg/settings.kcfgc
kcfg/smimevalidationpreferences.kcfgc
kcfg/tagspreferences.kcfgc
kcfg/tooltippreferences.kcfgc
)
file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/icons/*-apps-kleopatra.png")
ecm_add_app_icon(_kleopatra_SRCS ICONS ${ICONS_SRCS})
add_executable(kleopatra_bin ${_kleopatra_SRCS} ${_kleopatra_uiserver_SRCS})
# For the ConfigureDialog & KCMs
target_link_libraries(kleopatra_bin kcm_kleopatra_static)
#if (COMPILE_WITH_UNITY_CMAKE_SUPPORT)
# set_target_properties(kleopatra_bin PROPERTIES UNITY_BUILD ON)
#endif()
set_target_properties(kleopatra_bin PROPERTIES OUTPUT_NAME kleopatra)
if (WIN32)
set(_kleopatra_platform_libs "secur32")
endif ()
target_link_libraries(kleopatra_bin
Gpgmepp
KPim${KF_MAJOR_VERSION}::Libkleo
KPim${KF_MAJOR_VERSION}::Mime
KPim${KF_MAJOR_VERSION}::MimeTreeParserWidgets
KF${KF_MAJOR_VERSION}::Codecs
KF${KF_MAJOR_VERSION}::CoreAddons
KF${KF_MAJOR_VERSION}::Crash
KF${KF_MAJOR_VERSION}::I18n
KF${KF_MAJOR_VERSION}::IconThemes
KF${KF_MAJOR_VERSION}::ItemModels
KF${KF_MAJOR_VERSION}::KIOCore
KF${KF_MAJOR_VERSION}::KIOWidgets
KF${KF_MAJOR_VERSION}::WindowSystem
KF${KF_MAJOR_VERSION}::XmlGui
Qt::Network
Qt::PrintSupport # Printing secret keys
kleopatraclientcore
${_kleopatra_extra_libs}
${_kleopatra_mail_libs}
${_kleopatra_uiserver_extra_libs}
${_kleopatra_dbusaddons_libs}
${_kleopatra_platform_libs}
)
if (QT_MAJOR_VERSION STREQUAL "6")
target_link_libraries(kleopatra_bin Qt6::Core5Compat)
target_link_libraries(kleopatra_bin QGpgmeQt6)
else()
target_link_libraries(kleopatra_bin QGpgme)
endif()
install(TARGETS kleopatra_bin ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
install(
PROGRAMS data/org.kde.kleopatra.desktop data/kleopatra_import.desktop
DESTINATION ${KDE_INSTALL_APPDIR}
)
install(FILES data/org.kde.kleopatra.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
install(FILES data/kleopatra-mime.xml DESTINATION ${KDE_INSTALL_MIMEDIR})
install(
PROGRAMS data/kleopatra_signencryptfiles.desktop
data/kleopatra_signencryptfolders.desktop
data/kleopatra_decryptverifyfiles.desktop
data/kleopatra_decryptverifyfolders.desktop
DESTINATION ${KDE_INSTALL_DATADIR}/kio/servicemenus
)
diff --git a/src/view/netkeywidget.cpp b/src/view/netkeywidget.cpp
index 04b2d242f..ef2faa53a 100644
--- a/src/view/netkeywidget.cpp
+++ b/src/view/netkeywidget.cpp
@@ -1,280 +1,280 @@
/* view/netkeywidget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2017 Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "netkeywidget.h"
#include "cardkeysview.h"
#include "kleopatraapplication.h"
#include "nullpinwidget.h"
#include "systrayicon.h"
#include "kleopatra_debug.h"
#include "smartcard/netkeycard.h"
#include "smartcard/readerstatus.h"
#include "commands/changepincommand.h"
#include "commands/createcsrforcardkeycommand.h"
#include "commands/createopenpgpkeyfromcardkeyscommand.h"
#include <Libkleo/Algorithm>
#include <Libkleo/Compliance>
#include <Libkleo/Debug>
#include <Libkleo/KeyCache>
#include <Libkleo/KeyHelpers>
#include <Libkleo/KeyListModel>
#include <KLocalizedString>
#include <KMessageBox>
#include <KSeparator>
#include <QHBoxLayout>
#include <QInputDialog>
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QVBoxLayout>
#include <gpgme++/engineinfo.h>
using namespace Kleo;
using namespace Kleo::SmartCard;
using namespace Kleo::Commands;
NetKeyWidget::NetKeyWidget(QWidget *parent)
- : QWidget(parent)
+ : SmartCardWidget(parent)
{
auto vLay = new QVBoxLayout;
// Set up the scroll are
mArea = new QScrollArea{this};
mArea->setFocusPolicy(Qt::NoFocus);
mArea->setFrameShape(QFrame::NoFrame);
mArea->setWidgetResizable(true);
auto mAreaWidget = new QWidget;
mAreaWidget->setLayout(vLay);
mArea->setWidget(mAreaWidget);
auto scrollLay = new QVBoxLayout(this);
scrollLay->setContentsMargins(0, 0, 0, 0);
scrollLay->addWidget(mArea);
// Add general widgets
mVersionLabel = new QLabel{this};
mVersionLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
vLay->addWidget(mVersionLabel, 0, Qt::AlignLeft);
{
auto hLay1 = new QHBoxLayout;
auto label = new QLabel(i18nc("@label", "Serial number:"));
mSerialNumberLabel = new QLabel{this};
mSerialNumberLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
label->setBuddy(mSerialNumberLabel);
hLay1->addWidget(label);
hLay1->addWidget(mSerialNumberLabel);
hLay1->addStretch(1);
vLay->addLayout(hLay1);
}
mNullPinWidget = new NullPinWidget{this};
vLay->addWidget(mNullPinWidget);
mErrorLabel = new QLabel{this};
mErrorLabel->setVisible(false);
vLay->addWidget(mErrorLabel);
vLay->addWidget(new KSeparator(Qt::Horizontal));
mCardKeysView = new CardKeysView{this};
vLay->addWidget(mCardKeysView);
// The action area
vLay->addWidget(new KSeparator(Qt::Horizontal));
vLay->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Actions:"))), 0, Qt::AlignLeft);
auto actionLayout = new QHBoxLayout();
if (CreateOpenPGPKeyFromCardKeysCommand::isSupported()) {
mKeyForCardKeysButton = new QPushButton(this);
mKeyForCardKeysButton->setText(i18nc("@action:button", "Create OpenPGP Key"));
mKeyForCardKeysButton->setToolTip(i18nc("@info:tooltip", "Create an OpenPGP key for the keys stored on the card."));
actionLayout->addWidget(mKeyForCardKeysButton);
connect(mKeyForCardKeysButton, &QPushButton::clicked, this, &NetKeyWidget::createKeyFromCardKeys);
}
if (!(engineInfo(GpgME::GpgSMEngine).engineVersion() < "2.2.26")) { // see https://dev.gnupg.org/T5184
mCreateCSRButton = new QPushButton(this);
mCreateCSRButton->setText(i18nc("@action:button", "Create CSR"));
mCreateCSRButton->setToolTip(i18nc("@info:tooltip", "Create a certificate signing request for a key stored on the card."));
mCreateCSRButton->setEnabled(false);
actionLayout->addWidget(mCreateCSRButton);
connect(mCreateCSRButton, &QPushButton::clicked, this, [this]() {
createCSR();
});
}
mChangeNKSPINBtn = new QPushButton{this};
mChangeNKSPINBtn->setText(i18nc("@action:button NKS is an identifier for a type of keys on a NetKey card", "Change NKS PIN"));
mChangeSigGPINBtn = new QPushButton{this};
mChangeSigGPINBtn->setText(i18nc("@action:button SigG is an identifier for a type of keys on a NetKey card", "Change SigG PIN"));
connect(mChangeNKSPINBtn, &QPushButton::clicked, this, [this]() {
doChangePin(NetKeyCard::nksPinKeyRef());
});
connect(mChangeSigGPINBtn, &QPushButton::clicked, this, [this]() {
doChangePin(NetKeyCard::sigGPinKeyRef());
});
actionLayout->addWidget(mChangeNKSPINBtn);
actionLayout->addWidget(mChangeSigGPINBtn);
actionLayout->addStretch(1);
vLay->addLayout(actionLayout);
vLay->addStretch(1);
}
NetKeyWidget::~NetKeyWidget() = default;
namespace
{
std::vector<KeyPairInfo> getKeysSuitableForCSRCreation(const NetKeyCard *netKeyCard)
{
if (netKeyCard->hasNKSNullPin()) {
return {};
}
std::vector<KeyPairInfo> keys;
Kleo::copy_if(netKeyCard->keyInfos(), std::back_inserter(keys), [](const auto &keyInfo) {
if (keyInfo.keyRef.substr(0, 9) == "NKS-SIGG.") {
// SigG certificates for qualified signatures are issued with the physical cards;
// it's not possible to request a certificate for them
return false;
}
return keyInfo.canSign() //
&& (keyInfo.keyRef.substr(0, 9) == "NKS-NKS3.") //
&& DeVSCompliance::algorithmIsCompliant(keyInfo.algorithm);
});
return keys;
}
}
void NetKeyWidget::setCard(const NetKeyCard *card)
{
mSerialNumber = card->serialNumber();
mVersionLabel->setText(i18nc("1 is a Version number", "NetKey v%1 Card", card->appVersion()));
mSerialNumberLabel->setText(card->displaySerialNumber());
mNullPinWidget->setSerialNumber(mSerialNumber);
/* According to users of NetKey Cards it is fairly uncommon
* to use SigG Certificates at all. So it should be optional to set the pins. */
mNullPinWidget->setVisible(card->hasNKSNullPin() /*|| card->hasSigGNullPin()*/);
mNullPinWidget->setSigGVisible(false /*card->hasSigGNullPin()*/);
mNullPinWidget->setNKSVisible(card->hasNKSNullPin());
mChangeNKSPINBtn->setEnabled(!card->hasNKSNullPin());
if (card->hasSigGNullPin()) {
mChangeSigGPINBtn->setText(i18nc("SigG is an identifier for a type of keys on a NetKey card", "Set SigG PIN"));
} else {
mChangeSigGPINBtn->setText(i18nc("SigG is an identifier for a type of keys on a NetKey card", "Change SigG PIN"));
}
const auto errMsg = card->errorMsg();
if (!errMsg.isEmpty()) {
mErrorLabel->setText(QStringLiteral("<b>%1:</b> %2").arg(i18n("Error"), errMsg));
mErrorLabel->setVisible(true);
} else {
mErrorLabel->setVisible(false);
}
if (mKeyForCardKeysButton) {
mKeyForCardKeysButton->setEnabled(!card->hasNKSNullPin() && card->hasSigningKey() && card->hasEncryptionKey()
&& DeVSCompliance::algorithmIsCompliant(card->keyInfo(card->signingKeyRef()).algorithm)
&& DeVSCompliance::algorithmIsCompliant(card->keyInfo(card->encryptionKeyRef()).algorithm));
}
if (mCreateCSRButton) {
mCreateCSRButton->setEnabled(!getKeysSuitableForCSRCreation(card).empty());
}
mCardKeysView->setCard(card);
}
void NetKeyWidget::doChangePin(const std::string &keyRef)
{
const auto netKeyCard = ReaderStatus::instance()->getCard<NetKeyCard>(mSerialNumber);
if (!netKeyCard) {
KMessageBox::error(this, i18n("Failed to find the smartcard with the serial number: %1", QString::fromStdString(mSerialNumber)));
return;
}
auto cmd = new ChangePinCommand(mSerialNumber, NetKeyCard::AppName, this);
this->setEnabled(false);
connect(cmd, &ChangePinCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->setKeyRef(keyRef);
if ((keyRef == NetKeyCard::nksPinKeyRef() && netKeyCard->hasNKSNullPin()) //
|| (keyRef == NetKeyCard::sigGPinKeyRef() && netKeyCard->hasSigGNullPin())) {
cmd->setMode(ChangePinCommand::NullPinMode);
}
cmd->start();
}
void NetKeyWidget::createKeyFromCardKeys()
{
auto cmd = new CreateOpenPGPKeyFromCardKeysCommand(mSerialNumber, NetKeyCard::AppName, this);
this->setEnabled(false);
connect(cmd, &CreateOpenPGPKeyFromCardKeysCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->start();
}
namespace
{
std::string getKeyRef(const std::vector<KeyPairInfo> &keys, QWidget *parent)
{
QStringList options;
for (const auto &key : keys) {
options << QStringLiteral("%1 - %2").arg(QString::fromStdString(key.keyRef), QString::fromStdString(key.grip));
}
bool ok;
const QString choice = QInputDialog::getItem(parent,
i18n("Select Key"),
i18n("Please select the key you want to create a certificate signing request for:"),
options,
/* current= */ 0,
/* editable= */ false,
&ok);
return ok ? keys[options.indexOf(choice)].keyRef : std::string();
}
}
void NetKeyWidget::createCSR()
{
const auto netKeyCard = ReaderStatus::instance()->getCard<NetKeyCard>(mSerialNumber);
if (!netKeyCard) {
KMessageBox::error(this, i18n("Failed to find the smartcard with the serial number: %1", QString::fromStdString(mSerialNumber)));
return;
}
const auto suitableKeys = getKeysSuitableForCSRCreation(netKeyCard.get());
if (suitableKeys.empty()) {
KMessageBox::error(this, i18n("Sorry! No keys suitable for creating a certificate signing request found on the smartcard."));
return;
}
const auto keyRef = getKeyRef(suitableKeys, this);
if (keyRef.empty()) {
return;
}
auto cmd = new CreateCSRForCardKeyCommand(keyRef, mSerialNumber, NetKeyCard::AppName, this);
this->setEnabled(false);
connect(cmd, &CreateCSRForCardKeyCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->start();
}
diff --git a/src/view/netkeywidget.h b/src/view/netkeywidget.h
index 1dbf73924..b98149cd8 100644
--- a/src/view/netkeywidget.h
+++ b/src/view/netkeywidget.h
@@ -1,62 +1,60 @@
/* view/netkeywidget.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2017 Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
-#include <Libkleo/Predicates>
+#include "smartcardwidget.h"
-#include <QWidget>
+#include <Libkleo/Predicates>
#include <gpgme++/error.h>
#include <set>
#include <string>
#include <vector>
class QLabel;
class QPushButton;
class QScrollArea;
namespace Kleo
{
class NullPinWidget;
class CardKeysView;
namespace SmartCard
{
class NetKeyCard;
}
-class NetKeyWidget : public QWidget
+class NetKeyWidget : public SmartCardWidget
{
Q_OBJECT
public:
explicit NetKeyWidget(QWidget *parent = nullptr);
~NetKeyWidget() override;
void setCard(const SmartCard::NetKeyCard *card);
private:
void doChangePin(const std::string &keyRef);
void createKeyFromCardKeys();
void createCSR();
private:
- std::string mSerialNumber;
-
QLabel *mSerialNumberLabel = nullptr;
QLabel *mVersionLabel = nullptr;
QLabel *mErrorLabel = nullptr;
NullPinWidget *mNullPinWidget = nullptr;
QPushButton *mKeyForCardKeysButton = nullptr;
QPushButton *mCreateCSRButton = nullptr;
QPushButton *mChangeNKSPINBtn = nullptr;
QPushButton *mChangeSigGPINBtn = nullptr;
CardKeysView *mCardKeysView = nullptr;
QScrollArea *mArea = nullptr;
};
} // namespace Kleo
diff --git a/src/view/p15cardwidget.cpp b/src/view/p15cardwidget.cpp
index 614bb615c..69cc8d0c3 100644
--- a/src/view/p15cardwidget.cpp
+++ b/src/view/p15cardwidget.cpp
@@ -1,185 +1,185 @@
/* view/p15cardwiget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Andre Heinecke <aheinecke@g10code.com>
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "p15cardwidget.h"
#include "cardkeysview.h"
#include "openpgpkeycardwidget.h"
#include "settings.h"
#include "smartcard/openpgpcard.h"
#include "smartcard/p15card.h"
#include "smartcard/readerstatus.h"
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QStringList>
#include <QVBoxLayout>
#include <KLocalizedString>
#include <KSeparator>
#include <Libkleo/Compat>
#include <Libkleo/Formatting>
#include <Libkleo/GnuPG>
#include <Libkleo/KeyCache>
#include <QGpgME/CryptoConfig>
#include <QGpgME/ImportFromKeyserverJob>
#include <QGpgME/KeyListJob>
#include <QGpgME/Protocol>
#include <gpgme++/importresult.h>
#include <gpgme++/keylistresult.h>
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::SmartCard;
P15CardWidget::P15CardWidget(QWidget *parent)
- : QWidget{parent}
+ : SmartCardWidget{parent}
{
// Set up the scroll area
auto myLayout = new QVBoxLayout(this);
myLayout->setContentsMargins(0, 0, 0, 0);
auto area = new QScrollArea;
area->setFocusPolicy(Qt::NoFocus);
area->setFrameShape(QFrame::NoFrame);
area->setWidgetResizable(true);
myLayout->addWidget(area);
auto areaWidget = new QWidget;
area->setWidget(areaWidget);
auto areaVLay = new QVBoxLayout(areaWidget);
auto cardInfoGrid = new QGridLayout;
{
int row = 0;
// Version and Serialnumber
mVersionLabel = new QLabel{this};
mVersionLabel->setTextInteractionFlags(Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard);
cardInfoGrid->addWidget(mVersionLabel, row++, 0, 1, 2);
cardInfoGrid->addWidget(new QLabel(i18n("Serial number:")), row, 0);
- mSerialNumber = new QLabel{this};
- mSerialNumber->setTextInteractionFlags(Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard);
- cardInfoGrid->addWidget(mSerialNumber, row++, 1);
+ mSerialNumberLabel = new QLabel{this};
+ mSerialNumberLabel->setTextInteractionFlags(Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard);
+ cardInfoGrid->addWidget(mSerialNumberLabel, row++, 1);
cardInfoGrid->setColumnStretch(cardInfoGrid->columnCount(), 1);
}
areaVLay->addLayout(cardInfoGrid);
mStatusLabel = new QLabel{this};
mStatusLabel->setVisible(false);
areaVLay->addWidget(mStatusLabel);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
mOpenPGPKeysSection = new QWidget{this};
{
auto l = new QVBoxLayout{mOpenPGPKeysSection};
l->setContentsMargins(0, 0, 0, 0);
l->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("OpenPGP keys:"))));
mOpenPGPKeysWidget = new OpenPGPKeyCardWidget{this};
mOpenPGPKeysWidget->setAllowedActions(OpenPGPKeyCardWidget::NoAction);
l->addWidget(mOpenPGPKeysWidget);
l->addWidget(new KSeparator(Qt::Horizontal));
}
mOpenPGPKeysSection->setVisible(false);
areaVLay->addWidget(mOpenPGPKeysSection);
mCardKeysView = new CardKeysView{this};
mCardKeysView->setVisible(false);
areaVLay->addWidget(mCardKeysView);
areaVLay->addStretch(1);
}
P15CardWidget::~P15CardWidget() = default;
void P15CardWidget::searchPGPFpr(const std::string &fpr)
{
/* Only do auto import from LDAP */
auto conf = QGpgME::cryptoConfig();
Q_ASSERT(conf);
if (!Settings().alwaysSearchCardOnKeyserver() && !Kleo::keyserver().startsWith(QLatin1String{"ldap"})) {
return;
}
mStatusLabel->setText(i18n("Searching in directory service..."));
mStatusLabel->setVisible(true);
qCDebug(KLEOPATRA_LOG) << "Looking for:" << fpr.c_str() << "on ldap server";
QGpgME::KeyListJob *job = QGpgME::openpgp()->keyListJob(true);
connect(KeyCache::instance().get(), &KeyCache::keysMayHaveChanged, this, [this, fpr]() {
qCDebug(KLEOPATRA_LOG) << "Updating key info after changes";
ReaderStatus::mutableInstance()->updateStatus();
mOpenPGPKeysWidget->update(nullptr);
});
connect(job, &QGpgME::KeyListJob::result, job, [this](GpgME::KeyListResult, std::vector<GpgME::Key> keys, QString, GpgME::Error) {
if (keys.size() == 1) {
auto importJob = QGpgME::openpgp()->importFromKeyserverJob();
qCDebug(KLEOPATRA_LOG) << "Importing: " << keys[0].primaryFingerprint();
connect(importJob, &QGpgME::ImportFromKeyserverJob::result, importJob, [this](GpgME::ImportResult, QString, GpgME::Error) {
qCDebug(KLEOPATRA_LOG) << "import job done";
mStatusLabel->setText(i18n("Automatic import finished."));
});
importJob->start(keys);
} else if (keys.size() > 1) {
qCDebug(KLEOPATRA_LOG) << "Multiple keys found on server";
mStatusLabel->setText(i18n("Error multiple keys found on server."));
} else {
qCDebug(KLEOPATRA_LOG) << "No key found";
mStatusLabel->setText(i18n("Key not found in directory service."));
}
});
job->start(QStringList() << QString::fromStdString(fpr));
}
void P15CardWidget::setCard(const P15Card *card)
{
- mCardSerialNumber = card->serialNumber();
+ mSerialNumber = card->serialNumber();
mVersionLabel->setText(i18nc("%1 is a smartcard manufacturer", "%1 PKCS#15 card", QString::fromStdString(card->manufacturer())));
- mSerialNumber->setText(card->displaySerialNumber());
- mSerialNumber->setToolTip(QString::fromStdString(card->serialNumber()));
+ mSerialNumberLabel->setText(card->displaySerialNumber());
+ mSerialNumberLabel->setToolTip(QString::fromStdString(card->serialNumber()));
const auto sigInfo = card->keyInfo(card->signingKeyRef());
if (!sigInfo.grip.empty()) {
const auto key = KeyCache::instance()->findSubkeyByKeyGrip(sigInfo.grip, GpgME::OpenPGP).parent();
if (key.isNull()) {
qCDebug(KLEOPATRA_LOG) << "Failed to find key for grip:" << sigInfo.grip.c_str();
const auto pgpSigFpr = card->keyFingerprint(OpenPGPCard::pgpSigKeyRef());
if (!pgpSigFpr.empty()) {
qCDebug(KLEOPATRA_LOG) << "Should be pgp key:" << pgpSigFpr.c_str();
searchPGPFpr(pgpSigFpr);
}
} else {
mStatusLabel->setVisible(false);
}
}
const bool cardHasOpenPGPKeys = (!card->keyFingerprint(OpenPGPCard::pgpSigKeyRef()).empty() //
|| !card->keyFingerprint(OpenPGPCard::pgpEncKeyRef()).empty());
mOpenPGPKeysSection->setVisible(cardHasOpenPGPKeys);
if (cardHasOpenPGPKeys) {
mOpenPGPKeysWidget->update(card);
}
/* Check if additional keys could be available */
if (!Settings().autoLoadP15Certs()) {
return;
}
mCardKeysView->setVisible(true);
mCardKeysView->setCard(card);
}
diff --git a/src/view/p15cardwidget.h b/src/view/p15cardwidget.h
index 451c1f4e4..26a494025 100644
--- a/src/view/p15cardwidget.h
+++ b/src/view/p15cardwidget.h
@@ -1,49 +1,47 @@
/* view/p15cardwiget.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2021 g10 Code GmbH
SPDX-FileContributor: Andre Heinecke <aheinecke@g10code.com>
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
-#include <QWidget>
+#include "smartcardwidget.h"
class QLabel;
namespace Kleo
{
class CardKeysView;
class OpenPGPKeyCardWidget;
namespace SmartCard
{
class P15Card;
}
-class P15CardWidget : public QWidget
+class P15CardWidget : public SmartCardWidget
{
Q_OBJECT
public:
explicit P15CardWidget(QWidget *parent = nullptr);
~P15CardWidget() override;
void setCard(const SmartCard::P15Card *card);
private:
void searchPGPFpr(const std::string &fpr);
private:
- std::string mCardSerialNumber;
-
QLabel *mVersionLabel = nullptr;
- QLabel *mSerialNumber = nullptr;
+ QLabel *mSerialNumberLabel = nullptr;
QLabel *mStatusLabel = nullptr;
QWidget *mOpenPGPKeysSection = nullptr;
OpenPGPKeyCardWidget *mOpenPGPKeysWidget = nullptr;
CardKeysView *mCardKeysView = nullptr;
};
}
diff --git a/src/view/pgpcardwidget.cpp b/src/view/pgpcardwidget.cpp
index a88a4d1ac..2a9d6f76c 100644
--- a/src/view/pgpcardwidget.cpp
+++ b/src/view/pgpcardwidget.cpp
@@ -1,538 +1,538 @@
/* view/pgpcardwiget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2020, 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "pgpcardwidget.h"
#include "openpgpkeycardwidget.h"
#include "kleopatra_debug.h"
#include "commands/createcsrforcardkeycommand.h"
#include "commands/openpgpgeneratecardkeycommand.h"
#include "smartcard/algorithminfo.h"
#include "smartcard/openpgpcard.h"
#include "smartcard/readerstatus.h"
#include "smartcard/utils.h"
#include "dialogs/gencardkeydialog.h"
#include <utils/qt-cxx20-compat.h>
#include <Libkleo/Compliance>
#include <Libkleo/GnuPG>
#include <QFileDialog>
#include <QFileInfo>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QInputDialog>
#include <QLabel>
#include <QProgressDialog>
#include <QPushButton>
#include <QScrollArea>
#include <QThread>
#include <QVBoxLayout>
#include <KLocalizedString>
#include <KMessageBox>
#include <KSeparator>
#include <Libkleo/Formatting>
#include <Libkleo/KeyCache>
#include <gpgme++/context.h>
#include <gpgme++/data.h>
#include <QGpgME/DataProvider>
#include <gpgme++/gpggencardkeyinteractor.h>
using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::SmartCard;
namespace
{
class GenKeyThread : public QThread
{
Q_OBJECT
public:
explicit GenKeyThread(const GenCardKeyDialog::KeyParams &params, const std::string &serial)
: mSerial(serial)
, mParams(params)
{
}
GpgME::Error error()
{
return mErr;
}
std::string bkpFile()
{
return mBkpFile;
}
protected:
void run() override
{
// the index of the curves in this list has to match the enum values
// minus 1 of GpgGenCardKeyInteractor::Curve
static const std::vector<std::string> curves = {
"curve25519",
"curve448",
"nistp256",
"nistp384",
"nistp521",
"brainpoolP256r1",
"brainpoolP384r1",
"brainpoolP512r1",
"secp256k1", // keep it, even if we don't support it in Kleopatra
};
auto ei = std::make_unique<GpgME::GpgGenCardKeyInteractor>(mSerial);
if (mParams.algorithm.starts_with("rsa")) {
ei->setAlgo(GpgME::GpgGenCardKeyInteractor::RSA);
ei->setKeySize(QByteArray::fromStdString(mParams.algorithm.substr(3)).toInt());
} else {
ei->setAlgo(GpgME::GpgGenCardKeyInteractor::ECC);
const auto curveIt = std::find(curves.cbegin(), curves.cend(), mParams.algorithm);
if (curveIt != curves.end()) {
ei->setCurve(static_cast<GpgME::GpgGenCardKeyInteractor::Curve>(curveIt - curves.cbegin() + 1));
} else {
qCWarning(KLEOPATRA_LOG) << this << __func__ << "Invalid curve name:" << mParams.algorithm;
mErr = GpgME::Error::fromCode(GPG_ERR_INV_VALUE);
return;
}
}
ei->setNameUtf8(mParams.name.toStdString());
ei->setEmailUtf8(mParams.email.toStdString());
ei->setDoBackup(mParams.backup);
const auto ctx = std::shared_ptr<GpgME::Context>(GpgME::Context::createForProtocol(GpgME::OpenPGP));
ctx->setFlag("extended-edit", "1"); // we want to be able to select all curves
QGpgME::QByteArrayDataProvider dp;
GpgME::Data data(&dp);
mErr = ctx->cardEdit(GpgME::Key(), std::move(ei), data);
mBkpFile = static_cast<GpgME::GpgGenCardKeyInteractor *>(ctx->lastCardEditInteractor())->backupFileName();
}
private:
GpgME::Error mErr;
std::string mSerial;
GenCardKeyDialog::KeyParams mParams;
std::string mBkpFile;
};
} // Namespace
PGPCardWidget::PGPCardWidget(QWidget *parent)
- : QWidget(parent)
+ : SmartCardWidget(parent)
{
// Set up the scroll area
auto myLayout = new QVBoxLayout(this);
myLayout->setContentsMargins(0, 0, 0, 0);
auto area = new QScrollArea;
area->setFocusPolicy(Qt::NoFocus);
area->setFrameShape(QFrame::NoFrame);
area->setWidgetResizable(true);
myLayout->addWidget(area);
auto areaWidget = new QWidget;
area->setWidget(areaWidget);
auto areaVLay = new QVBoxLayout(areaWidget);
auto cardInfoGrid = new QGridLayout;
{
int row = 0;
// Version and Serialnumber
mVersionLabel = new QLabel{this};
mVersionLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
cardInfoGrid->addWidget(mVersionLabel, row, 0, 1, 2);
row++;
cardInfoGrid->addWidget(new QLabel(i18n("Serial number:")), row, 0);
- mSerialNumber = new QLabel{this};
- mSerialNumber->setTextInteractionFlags(Qt::TextBrowserInteraction);
- cardInfoGrid->addWidget(mSerialNumber, row, 1);
+ mSerialNumberLabel = new QLabel{this};
+ mSerialNumberLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ cardInfoGrid->addWidget(mSerialNumberLabel, row, 1);
row++;
// Cardholder Row
cardInfoGrid->addWidget(new QLabel(i18nc("The owner of a smartcard. GnuPG refers to this as cardholder.", "Cardholder:")), row, 0);
mCardHolderLabel = new QLabel{this};
mCardHolderLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
cardInfoGrid->addWidget(mCardHolderLabel, row, 1);
{
auto button = new QPushButton{this};
button->setIcon(QIcon::fromTheme(QStringLiteral("cell_edit")));
button->setAccessibleName(i18nc("@action:button", "Edit"));
button->setToolTip(i18n("Change"));
cardInfoGrid->addWidget(button, row, 2);
connect(button, &QPushButton::clicked, this, &PGPCardWidget::changeNameRequested);
}
row++;
// URL Row
cardInfoGrid->addWidget(new QLabel(i18nc("The URL under which a public key that "
"corresponds to a smartcard can be downloaded",
"Pubkey URL:")),
row,
0);
mUrlLabel = new QLabel{this};
mUrlLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
cardInfoGrid->addWidget(mUrlLabel, row, 1);
{
auto button = new QPushButton{this};
button->setIcon(QIcon::fromTheme(QStringLiteral("cell_edit")));
button->setAccessibleName(i18nc("@action:button", "Edit"));
button->setToolTip(i18n("Change"));
cardInfoGrid->addWidget(button, row, 2);
connect(button, &QPushButton::clicked, this, &PGPCardWidget::changeUrlRequested);
}
cardInfoGrid->setColumnStretch(cardInfoGrid->columnCount(), 1);
}
areaVLay->addLayout(cardInfoGrid);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
// The keys
areaVLay->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Keys:"))));
mKeysWidget = new OpenPGPKeyCardWidget{this};
areaVLay->addWidget(mKeysWidget);
connect(mKeysWidget, &OpenPGPKeyCardWidget::createCSRRequested, this, &PGPCardWidget::createCSR);
connect(mKeysWidget, &OpenPGPKeyCardWidget::generateKeyRequested, this, &PGPCardWidget::generateKey);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
areaVLay->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Actions:"))));
auto actionLayout = new QHBoxLayout;
{
auto generateButton = new QPushButton(i18n("Generate New Keys"), this);
generateButton->setToolTip(xi18nc("@info:tooltip",
"<para>Generate three new keys on the smart card and create a new OpenPGP "
"certificate with those keys. Optionally, the encryption key is generated "
"off-card and a backup is created so that you can still access data encrypted "
"with this key in case the card is lost or damaged.</para>"
"<para><emphasis strong='true'>"
"Existing keys on the smart card will be overwritten."
"</emphasis></para>"));
actionLayout->addWidget(generateButton);
connect(generateButton, &QPushButton::clicked, this, &PGPCardWidget::genkeyRequested);
}
{
auto pinButton = new QPushButton(i18n("Change PIN"), this);
pinButton->setToolTip(i18nc("@info:tooltip",
"Change the PIN required for using the keys on the smart card. "
"The PIN must contain at least six characters."));
actionLayout->addWidget(pinButton);
connect(pinButton, &QPushButton::clicked, this, [this]() {
doChangePin(OpenPGPCard::pinKeyRef());
});
}
{
auto unblockButton = new QPushButton(i18n("Unblock Card"), this);
unblockButton->setToolTip(i18nc("@info:tooltip", "Unblock the smart card with the PUK."));
actionLayout->addWidget(unblockButton);
connect(unblockButton, &QPushButton::clicked, this, [this]() {
doChangePin(OpenPGPCard::resetCodeKeyRef());
});
}
{
auto pukButton = new QPushButton(i18n("Change Admin PIN"), this);
pukButton->setToolTip(i18nc("@info:tooltip", "Change the PIN required for administrative operations."));
actionLayout->addWidget(pukButton);
connect(pukButton, &QPushButton::clicked, this, [this]() {
doChangePin(OpenPGPCard::adminPinKeyRef());
});
}
{
auto resetCodeButton = new QPushButton(i18n("Change PUK"), this);
resetCodeButton->setToolTip(i18nc("@info:tooltip",
"Set or change the PUK required to unblock the smart card. "
"The PUK must contain at least eight characters."));
actionLayout->addWidget(resetCodeButton);
connect(resetCodeButton, &QPushButton::clicked, this, [this]() {
doChangePin(OpenPGPCard::resetCodeKeyRef(), ChangePinCommand::ResetMode);
});
}
actionLayout->addStretch(-1);
areaVLay->addLayout(actionLayout);
areaVLay->addStretch(1);
}
void PGPCardWidget::setCard(const OpenPGPCard *card)
{
const QString version = card->displayAppVersion();
mIs21 = card->appVersion() >= 0x0201;
const QString manufacturer = QString::fromStdString(card->manufacturer());
const bool manufacturerIsUnknown = manufacturer.isEmpty() || manufacturer == QLatin1String("unknown");
mVersionLabel->setText(
manufacturerIsUnknown
? i18nc("Placeholder is a version number", "Unknown OpenPGP v%1 card", version)
: i18nc("First placeholder is manufacturer, second placeholder is a version number", "%1 OpenPGP v%2 card", manufacturer, version));
- mSerialNumber->setText(card->displaySerialNumber());
- mRealSerial = card->serialNumber();
+ mSerialNumberLabel->setText(card->displaySerialNumber());
+ mSerialNumber = card->serialNumber();
const auto holder = card->cardHolder();
const auto url = QString::fromStdString(card->pubkeyUrl());
mCardHolderLabel->setText(holder.isEmpty() ? i18n("not set") : holder);
mUrl = url;
mUrlLabel->setText(url.isEmpty() ? i18n("not set") : QStringLiteral("<a href=\"%1\">%1</a>").arg(url.toHtmlEscaped()));
mUrlLabel->setOpenExternalLinks(true);
mKeysWidget->update(card);
mCardIsEmpty = card->keyFingerprint(OpenPGPCard::pgpSigKeyRef()).empty() && card->keyFingerprint(OpenPGPCard::pgpEncKeyRef()).empty()
&& card->keyFingerprint(OpenPGPCard::pgpAuthKeyRef()).empty();
}
void PGPCardWidget::doChangePin(const std::string &keyRef, ChangePinCommand::ChangePinMode mode)
{
- auto cmd = new ChangePinCommand(mRealSerial, OpenPGPCard::AppName, this);
+ auto cmd = new ChangePinCommand(mSerialNumber, OpenPGPCard::AppName, this);
this->setEnabled(false);
connect(cmd, &ChangePinCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->setKeyRef(keyRef);
cmd->setMode(mode);
cmd->start();
}
void PGPCardWidget::doGenKey(GenCardKeyDialog *dlg)
{
- const GpgME::Error err = ReaderStatus::switchCardAndApp(mRealSerial, OpenPGPCard::AppName);
+ const GpgME::Error err = ReaderStatus::switchCardAndApp(mSerialNumber, OpenPGPCard::AppName);
if (err) {
return;
}
const auto params = dlg->getKeyParams();
auto progress = new QProgressDialog(this, Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::Dialog);
progress->setAutoClose(true);
progress->setMinimumDuration(0);
progress->setMaximum(0);
progress->setMinimum(0);
progress->setModal(true);
progress->setCancelButton(nullptr);
progress->setWindowTitle(i18nc("@title:window", "Generating Keys"));
progress->setLabel(new QLabel(i18n("This may take several minutes...")));
- auto workerThread = new GenKeyThread(params, mRealSerial);
+ auto workerThread = new GenKeyThread(params, mSerialNumber);
connect(workerThread, &QThread::finished, this, [this, workerThread, progress] {
progress->accept();
progress->deleteLater();
genKeyDone(workerThread->error(), workerThread->bkpFile());
delete workerThread;
});
workerThread->start();
progress->exec();
}
void PGPCardWidget::genKeyDone(const GpgME::Error &err, const std::string &backup)
{
if (err) {
KMessageBox::error(this, i18nc("@info", "Failed to generate new key: %1", Formatting::errorAsString(err)));
return;
}
if (err.isCanceled()) {
return;
}
if (!backup.empty()) {
const auto bkpFile = QString::fromStdString(backup);
QFileInfo fi(bkpFile);
const auto target =
QFileDialog::getSaveFileName(this, i18n("Save backup of encryption key"), fi.fileName(), QStringLiteral("%1 (*.gpg)").arg(i18n("Backup Key")));
if (!target.isEmpty() && !QFile::copy(bkpFile, target)) {
KMessageBox::error(this, i18nc("@info", "Failed to move backup. The backup key is still stored under: %1", bkpFile));
} else if (!target.isEmpty()) {
QFile::remove(bkpFile);
}
}
KMessageBox::information(this, i18nc("@info", "Successfully generated a new key for this card."), i18nc("@title", "Success"));
ReaderStatus::mutableInstance()->updateStatus();
}
void PGPCardWidget::genkeyRequested()
{
- const auto pgpCard = ReaderStatus::instance()->getCard<OpenPGPCard>(mRealSerial);
+ const auto pgpCard = ReaderStatus::instance()->getCard<OpenPGPCard>(mSerialNumber);
if (!pgpCard) {
- KMessageBox::error(this, i18n("Failed to find the OpenPGP card with the serial number: %1", QString::fromStdString(mRealSerial)));
+ KMessageBox::error(this, i18n("Failed to find the OpenPGP card with the serial number: %1", QString::fromStdString(mSerialNumber)));
return;
}
if (!mCardIsEmpty) {
auto ret = KMessageBox::warningContinueCancel(this,
i18n("The existing keys on this card will be <b>deleted</b> "
"and replaced by new keys.")
+ QStringLiteral("<br/><br/>")
+ i18n("It will no longer be possible to decrypt past communication "
"encrypted for the existing key."),
i18n("Secret Key Deletion"),
KStandardGuiItem::guiItem(KStandardGuiItem::Delete),
KStandardGuiItem::cancel(),
QString(),
KMessageBox::Notify | KMessageBox::Dangerous);
if (ret != KMessageBox::Continue) {
return;
}
}
auto dlg = new GenCardKeyDialog(GenCardKeyDialog::AllKeyAttributes, this);
const auto allowedAlgos = getAllowedAlgorithms(pgpCard->supportedAlgorithms());
if (allowedAlgos.empty()) {
KMessageBox::error(this, i18nc("@info", "You cannot generate keys on this smart card because it doesn't support any of the compliant algorithms."));
return;
}
dlg->setSupportedAlgorithms(allowedAlgos, getPreferredAlgorithm(allowedAlgos));
connect(dlg, &QDialog::accepted, this, [this, dlg]() {
doGenKey(dlg);
dlg->deleteLater();
});
dlg->setModal(true);
dlg->show();
}
void PGPCardWidget::changeNameRequested()
{
QString text = mCardHolderLabel->text();
while (true) {
bool ok = false;
text = QInputDialog::getText(this, i18n("Change cardholder"), i18n("New name:"), QLineEdit::Normal, text, &ok, Qt::WindowFlags(), Qt::ImhLatinOnly);
if (!ok) {
return;
}
// Some additional restrictions imposed by gnupg
if (text.contains(QLatin1Char('<'))) {
KMessageBox::error(this, i18nc("@info", "The \"<\" character may not be used."));
continue;
}
if (text.contains(QLatin1String(" "))) {
KMessageBox::error(this, i18nc("@info", "Double spaces are not allowed"));
continue;
}
if (text.size() > 38) {
KMessageBox::error(this, i18nc("@info", "The size of the name may not exceed 38 characters."));
}
break;
}
auto parts = text.split(QLatin1Char(' '));
const auto lastName = parts.takeLast();
const QString formatted = lastName + QStringLiteral("<<") + parts.join(QLatin1Char('<'));
- const auto pgpCard = ReaderStatus::instance()->getCard<OpenPGPCard>(mRealSerial);
+ const auto pgpCard = ReaderStatus::instance()->getCard<OpenPGPCard>(mSerialNumber);
if (!pgpCard) {
- KMessageBox::error(this, i18n("Failed to find the OpenPGP card with the serial number: %1", QString::fromStdString(mRealSerial)));
+ KMessageBox::error(this, i18n("Failed to find the OpenPGP card with the serial number: %1", QString::fromStdString(mSerialNumber)));
return;
}
const QByteArray command = QByteArrayLiteral("SCD SETATTR DISP-NAME ") + formatted.toUtf8();
ReaderStatus::mutableInstance()->startSimpleTransaction(pgpCard, command, this, [this](const GpgME::Error &err) {
changeNameResult(err);
});
}
void PGPCardWidget::changeNameResult(const GpgME::Error &err)
{
if (err) {
KMessageBox::error(this, i18nc("@info", "Name change failed: %1", Formatting::errorAsString(err)));
return;
}
if (!err.isCanceled()) {
KMessageBox::information(this, i18nc("@info", "Name successfully changed."), i18nc("@title", "Success"));
ReaderStatus::mutableInstance()->updateStatus();
}
}
void PGPCardWidget::changeUrlRequested()
{
QString text = mUrl;
while (true) {
bool ok = false;
text = QInputDialog::getText(this,
i18n("Change the URL where the pubkey can be found"),
i18n("New pubkey URL:"),
QLineEdit::Normal,
text,
&ok,
Qt::WindowFlags(),
Qt::ImhLatinOnly);
if (!ok) {
return;
}
// Some additional restrictions imposed by gnupg
if (text.size() > 254) {
KMessageBox::error(this, i18nc("@info", "The size of the URL may not exceed 254 characters."));
}
break;
}
- const auto pgpCard = ReaderStatus::instance()->getCard<OpenPGPCard>(mRealSerial);
+ const auto pgpCard = ReaderStatus::instance()->getCard<OpenPGPCard>(mSerialNumber);
if (!pgpCard) {
- KMessageBox::error(this, i18n("Failed to find the OpenPGP card with the serial number: %1", QString::fromStdString(mRealSerial)));
+ KMessageBox::error(this, i18n("Failed to find the OpenPGP card with the serial number: %1", QString::fromStdString(mSerialNumber)));
return;
}
const QByteArray command = QByteArrayLiteral("SCD SETATTR PUBKEY-URL ") + text.toUtf8();
ReaderStatus::mutableInstance()->startSimpleTransaction(pgpCard, command, this, [this](const GpgME::Error &err) {
changeUrlResult(err);
});
}
void PGPCardWidget::changeUrlResult(const GpgME::Error &err)
{
if (err) {
KMessageBox::error(this, i18nc("@info", "URL change failed: %1", Formatting::errorAsString(err)));
return;
}
if (!err.isCanceled()) {
KMessageBox::information(this, i18nc("@info", "URL successfully changed."), i18nc("@title", "Success"));
ReaderStatus::mutableInstance()->updateStatus();
}
}
void PGPCardWidget::createCSR(const std::string &keyref)
{
- auto cmd = new CreateCSRForCardKeyCommand(keyref, mRealSerial, OpenPGPCard::AppName, this);
+ auto cmd = new CreateCSRForCardKeyCommand(keyref, mSerialNumber, OpenPGPCard::AppName, this);
this->setEnabled(false);
connect(cmd, &CreateCSRForCardKeyCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->start();
}
void PGPCardWidget::generateKey(const std::string &keyref)
{
- auto cmd = new OpenPGPGenerateCardKeyCommand(keyref, mRealSerial, this);
+ auto cmd = new OpenPGPGenerateCardKeyCommand(keyref, mSerialNumber, this);
this->setEnabled(false);
connect(cmd, &OpenPGPGenerateCardKeyCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->start();
}
#include "pgpcardwidget.moc"
diff --git a/src/view/pgpcardwidget.h b/src/view/pgpcardwidget.h
index e4d3d68bf..86c96de58 100644
--- a/src/view/pgpcardwidget.h
+++ b/src/view/pgpcardwidget.h
@@ -1,67 +1,66 @@
/* view/pgpcardwiget.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2020, 2022 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
-#include "commands/changepincommand.h"
+#include "smartcardwidget.h"
-#include <QWidget>
+#include "commands/changepincommand.h"
#include <gpgme++/error.h>
#include <string>
class QLabel;
namespace Kleo
{
class GenCardKeyDialog;
class OpenPGPKeyCardWidget;
namespace SmartCard
{
struct KeyPairInfo;
class OpenPGPCard;
} // namespace SmartCard
-class PGPCardWidget : public QWidget
+class PGPCardWidget : public SmartCardWidget
{
Q_OBJECT
public:
explicit PGPCardWidget(QWidget *parent = nullptr);
void setCard(const SmartCard::OpenPGPCard *card);
void doGenKey(GenCardKeyDialog *dlg);
void genKeyDone(const GpgME::Error &err, const std::string &backup);
public Q_SLOTS:
void genkeyRequested();
void changeNameRequested();
void changeNameResult(const GpgME::Error &err);
void changeUrlRequested();
void changeUrlResult(const GpgME::Error &err);
void createCSR(const std::string &keyref);
void generateKey(const std::string &keyref);
private:
void doChangePin(const std::string &keyRef, Commands::ChangePinCommand::ChangePinMode mode = Commands::ChangePinCommand::NormalMode);
private:
- QLabel *mSerialNumber = nullptr;
+ QLabel *mSerialNumberLabel = nullptr;
QLabel *mCardHolderLabel = nullptr;
QLabel *mVersionLabel = nullptr;
QLabel *mUrlLabel = nullptr;
OpenPGPKeyCardWidget *mKeysWidget = nullptr;
QString mUrl;
bool mCardIsEmpty = false;
bool mIs21 = false;
- std::string mRealSerial;
};
} // namespace Kleo
diff --git a/src/view/pivcardwidget.cpp b/src/view/pivcardwidget.cpp
index 892909143..a158de073 100644
--- a/src/view/pivcardwidget.cpp
+++ b/src/view/pivcardwidget.cpp
@@ -1,395 +1,395 @@
/* view/pivcardwiget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2020 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "pivcardwidget.h"
#include "tooltippreferences.h"
#include "commands/certificatetopivcardcommand.h"
#include "commands/changepincommand.h"
#include "commands/createcsrforcardkeycommand.h"
#include "commands/createopenpgpkeyfromcardkeyscommand.h"
#include "commands/importcertificatefrompivcardcommand.h"
#include "commands/keytocardcommand.h"
#include "commands/pivgeneratecardkeycommand.h"
#include "commands/setpivcardapplicationadministrationkeycommand.h"
#include "smartcard/pivcard.h"
#include "smartcard/readerstatus.h"
#include <Libkleo/Compliance>
#include <Libkleo/Dn>
#include <Libkleo/Formatting>
#include <Libkleo/KeyCache>
#include <KLocalizedString>
#include <KSeparator>
#include <QFrame>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QVBoxLayout>
using namespace GpgME;
using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::SmartCard;
namespace
{
static void layoutKeyWidgets(QGridLayout *grid, const QString &keyName, const PIVCardWidget::KeyWidgets &keyWidgets)
{
int row = grid->rowCount();
grid->addWidget(new QLabel(keyName), row, 0);
grid->addWidget(keyWidgets.keyGrip, row, 1);
grid->addWidget(keyWidgets.keyAlgorithm, row, 2);
grid->addWidget(keyWidgets.generateButton, row, 3);
if (keyWidgets.writeKeyButton) {
grid->addWidget(keyWidgets.writeKeyButton, row, 4);
}
row++;
grid->addWidget(keyWidgets.certificateInfo, row, 1, 1, 2);
grid->addWidget(keyWidgets.writeCertificateButton, row, 3);
grid->addWidget(keyWidgets.importCertificateButton, row, 4);
if (keyWidgets.createCSRButton) {
grid->addWidget(keyWidgets.createCSRButton, row, 5);
}
}
static int toolTipOptions()
{
using namespace Kleo::Formatting;
static const int validityFlags = Validity | Issuer | ExpiryDates | CertificateUsage;
static const int ownerFlags = Subject | UserIDs | OwnerTrust;
static const int detailsFlags = StorageLocation | CertificateType | SerialNumber | Fingerprint;
const TooltipPreferences prefs;
int flags = KeyID;
flags |= prefs.showValidity() ? validityFlags : 0;
flags |= prefs.showOwnerInformation() ? ownerFlags : 0;
flags |= prefs.showCertificateDetails() ? detailsFlags : 0;
return flags;
}
}
PIVCardWidget::PIVCardWidget(QWidget *parent)
- : QWidget(parent)
+ : SmartCardWidget(parent)
{
// Set up the scroll area
auto myLayout = new QVBoxLayout(this);
myLayout->setContentsMargins(0, 0, 0, 0);
auto area = new QScrollArea;
area->setFocusPolicy(Qt::NoFocus);
area->setFrameShape(QFrame::NoFrame);
area->setWidgetResizable(true);
myLayout->addWidget(area);
auto areaWidget = new QWidget;
area->setWidget(areaWidget);
auto areaVLay = new QVBoxLayout(areaWidget);
auto cardInfoGrid = new QGridLayout;
{
int row = 0;
// Version and Serialnumber
mVersionLabel = new QLabel{this};
mVersionLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
cardInfoGrid->addWidget(mVersionLabel, row++, 0, 1, 2);
cardInfoGrid->addWidget(new QLabel(i18n("Serial number:")), row, 0);
- mSerialNumber = new QLabel{this};
- mSerialNumber->setTextInteractionFlags(Qt::TextBrowserInteraction);
- cardInfoGrid->addWidget(mSerialNumber, row++, 1);
+ mSerialNumberLabel = new QLabel{this};
+ mSerialNumberLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ cardInfoGrid->addWidget(mSerialNumberLabel, row++, 1);
cardInfoGrid->setColumnStretch(cardInfoGrid->columnCount(), 1);
}
areaVLay->addLayout(cardInfoGrid);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
areaVLay->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Keys:")), this));
auto keysGrid = new QGridLayout;
for (const auto &keyInfo : PIVCard::supportedKeys()) {
KeyWidgets keyWidgets = createKeyWidgets(keyInfo);
layoutKeyWidgets(keysGrid, PIVCard::keyDisplayName(keyInfo.keyRef), keyWidgets);
}
areaVLay->addLayout(keysGrid);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
auto actionLayout = new QHBoxLayout;
if (CreateOpenPGPKeyFromCardKeysCommand::isSupported()) {
mKeyForCardKeysButton = new QPushButton(this);
mKeyForCardKeysButton->setText(i18nc("@action:button", "Create OpenPGP Key"));
mKeyForCardKeysButton->setToolTip(i18nc("@info:tooltip", "Create an OpenPGP key for the keys stored on the card."));
actionLayout->addWidget(mKeyForCardKeysButton);
connect(mKeyForCardKeysButton, &QPushButton::clicked, this, &PIVCardWidget::createKeyFromCardKeys);
}
{
auto button = new QPushButton(i18nc("@action:button", "Change PIN"), this);
button->setToolTip(i18nc("@info:tooltip",
"Change the PIV Card Application PIN that activates the PIV Card "
"and enables private key operations using the stored keys."));
actionLayout->addWidget(button);
connect(button, &QPushButton::clicked, this, [this]() {
changePin(PIVCard::pinKeyRef());
});
}
{
auto button = new QPushButton(i18nc("@action:button", "Change PUK"), this);
button->setToolTip(i18nc("@info:tooltip", "Change the PIN Unblocking Key that enables a reset of the PIN."));
actionLayout->addWidget(button);
connect(button, &QPushButton::clicked, this, [this]() {
changePin(PIVCard::pukKeyRef());
});
}
{
auto button = new QPushButton(i18nc("@action:button", "Change Admin Key"), this);
button->setToolTip(i18nc("@info:tooltip",
"Change the PIV Card Application Administration Key that is used by the "
"PIV Card Application to authenticate the PIV Card Application Administrator and by the "
"administrator (resp. Kleopatra) to authenticate the PIV Card Application."));
actionLayout->addWidget(button);
connect(button, &QPushButton::clicked, this, [this]() {
setAdminKey();
});
}
actionLayout->addStretch(-1);
areaVLay->addLayout(actionLayout);
areaVLay->addStretch(1);
}
PIVCardWidget::KeyWidgets PIVCardWidget::createKeyWidgets(const KeyPairInfo &keyInfo)
{
const std::string keyRef = keyInfo.keyRef;
KeyWidgets keyWidgets;
keyWidgets.keyGrip = new QLabel(this);
keyWidgets.keyGrip->setTextInteractionFlags(Qt::TextBrowserInteraction);
keyWidgets.keyAlgorithm = new QLabel(this);
keyWidgets.keyAlgorithm->setTextInteractionFlags(Qt::TextSelectableByMouse);
keyWidgets.generateButton = new QPushButton(i18nc("@action:button", "Generate"), this);
keyWidgets.generateButton->setEnabled(false);
connect(keyWidgets.generateButton, &QPushButton::clicked, this, [this, keyRef]() {
generateKey(keyRef);
});
if (keyRef == PIVCard::cardAuthenticationKeyRef() || keyRef == PIVCard::keyManagementKeyRef()) {
keyWidgets.writeKeyButton = new QPushButton(i18nc("@action:button", "Write Key"), this);
keyWidgets.writeKeyButton->setToolTip(i18nc("@info:tooltip", "Write the key pair of a certificate to the card"));
keyWidgets.writeKeyButton->setEnabled(true);
connect(keyWidgets.writeKeyButton, &QPushButton::clicked, this, [this, keyRef]() {
writeKeyToCard(keyRef);
});
}
keyWidgets.certificateInfo = new QLabel(this);
keyWidgets.certificateInfo->setTextInteractionFlags(Qt::TextBrowserInteraction);
keyWidgets.writeCertificateButton = new QPushButton(i18nc("@action:button", "Write Certificate"), this);
keyWidgets.writeCertificateButton->setToolTip(i18nc("@info:tooltip", "Write the certificate corresponding to this key to the card"));
keyWidgets.writeCertificateButton->setEnabled(false);
connect(keyWidgets.writeCertificateButton, &QPushButton::clicked, this, [this, keyRef]() {
writeCertificateToCard(keyRef);
});
keyWidgets.importCertificateButton = new QPushButton(i18nc("@action:button", "Import Certificate"), this);
keyWidgets.importCertificateButton->setToolTip(i18nc("@info:tooltip", "Import the certificate stored on the card"));
keyWidgets.importCertificateButton->setEnabled(false);
connect(keyWidgets.importCertificateButton, &QPushButton::clicked, this, [this, keyRef]() {
importCertificateFromCard(keyRef);
});
if (keyInfo.canSign() || keyInfo.canEncrypt()) {
keyWidgets.createCSRButton = new QPushButton(i18nc("@action:button", "Create CSR"), this);
keyWidgets.createCSRButton->setToolTip(i18nc("@info:tooltip", "Create a certificate signing request for this key"));
keyWidgets.createCSRButton->setEnabled(false);
connect(keyWidgets.createCSRButton, &QPushButton::clicked, this, [this, keyRef]() {
createCSR(keyRef);
});
}
mKeyWidgets.insert({keyRef, keyWidgets});
return keyWidgets;
}
PIVCardWidget::~PIVCardWidget()
{
}
void PIVCardWidget::setCard(const PIVCard *card)
{
- mCardSerialNumber = card->serialNumber();
+ mSerialNumber = card->serialNumber();
mVersionLabel->setText(i18nc("%1 version number", "PIV v%1 card", card->displayAppVersion()));
- mSerialNumber->setText(card->displaySerialNumber());
- mSerialNumber->setToolTip(QString::fromStdString(card->serialNumber()));
+ mSerialNumberLabel->setText(card->displaySerialNumber());
+ mSerialNumberLabel->setToolTip(QString::fromStdString(card->serialNumber()));
if (card) {
updateCachedValues(PIVCard::pivAuthenticationKeyRef(), card);
updateCachedValues(PIVCard::cardAuthenticationKeyRef(), card);
updateCachedValues(PIVCard::digitalSignatureKeyRef(), card);
updateCachedValues(PIVCard::keyManagementKeyRef(), card);
}
updateKeyWidgets(PIVCard::pivAuthenticationKeyRef());
updateKeyWidgets(PIVCard::cardAuthenticationKeyRef());
updateKeyWidgets(PIVCard::digitalSignatureKeyRef());
updateKeyWidgets(PIVCard::keyManagementKeyRef());
if (mKeyForCardKeysButton) {
mKeyForCardKeysButton->setEnabled(card->hasSigningKey() //
&& card->hasEncryptionKey() //
&& DeVSCompliance::algorithmIsCompliant(card->keyInfo(card->signingKeyRef()).algorithm)
&& DeVSCompliance::algorithmIsCompliant(card->keyInfo(card->encryptionKeyRef()).algorithm));
}
}
void PIVCardWidget::updateCachedValues(const std::string &keyRef, const SmartCard::PIVCard *card)
{
KeyWidgets &widgets = mKeyWidgets.at(keyRef);
widgets.keyInfo = card->keyInfo(keyRef);
widgets.certificateData = card->certificateData(keyRef);
}
void PIVCardWidget::updateKeyWidgets(const std::string &keyRef)
{
const KeyWidgets &widgets = mKeyWidgets.at(keyRef);
const std::string grip = widgets.keyInfo.grip;
if (grip.empty()) {
widgets.certificateInfo->setText(i18nc("@info", "<em>slot empty</em>"));
widgets.certificateInfo->setToolTip(QString());
widgets.keyGrip->setText(QString());
widgets.keyAlgorithm->setText(QString());
widgets.generateButton->setText(i18nc("@action:button", "Generate"));
widgets.generateButton->setToolTip(i18nc("@info:tooltip %1 display name of a key", "Generate %1", PIVCard::keyDisplayName(keyRef)));
if (widgets.createCSRButton) {
widgets.createCSRButton->setEnabled(false);
}
widgets.writeCertificateButton->setEnabled(false);
widgets.importCertificateButton->setEnabled(false);
} else {
const Key certificate = KeyCache::instance()->findSubkeyByKeyGrip(grip, GpgME::CMS).parent();
if (!certificate.isNull()) {
widgets.certificateInfo->setText(i18nc("X.509 certificate DN (validity, created: date)",
"%1 (%2, created: %3)",
DN(certificate.userID(0).id()).prettyDN(),
Formatting::complianceStringShort(certificate),
Formatting::creationDateString(certificate)));
widgets.certificateInfo->setToolTip(Formatting::toolTip(certificate, toolTipOptions()));
widgets.writeCertificateButton->setEnabled(true);
} else {
widgets.certificateInfo->setText(i18nc("@info", "<em>no matching certificate</em>"));
widgets.certificateInfo->setToolTip(QString());
widgets.writeCertificateButton->setEnabled(false);
}
widgets.keyGrip->setText(QString::fromStdString(grip));
const std::string algo = widgets.keyInfo.algorithm;
widgets.keyAlgorithm->setText(algo.empty() ? i18nc("@info unknown key algorithm", "unknown") : QString::fromStdString(algo));
widgets.importCertificateButton->setEnabled(!widgets.certificateData.empty());
widgets.generateButton->setText(i18nc("@action:button", "Replace"));
widgets.generateButton->setToolTip(i18nc("@info:tooltip %1 display name of a key", "Replace %1 with new key", PIVCard::keyDisplayName(keyRef)));
if (widgets.createCSRButton) {
widgets.createCSRButton->setEnabled(DeVSCompliance::algorithmIsCompliant(algo));
}
}
widgets.generateButton->setEnabled(true);
}
void PIVCardWidget::generateKey(const std::string &keyref)
{
- auto cmd = new PIVGenerateCardKeyCommand(mCardSerialNumber, this);
+ auto cmd = new PIVGenerateCardKeyCommand(mSerialNumber, this);
this->setEnabled(false);
connect(cmd, &PIVGenerateCardKeyCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->setKeyRef(keyref);
cmd->start();
}
void PIVCardWidget::createCSR(const std::string &keyref)
{
- auto cmd = new CreateCSRForCardKeyCommand(keyref, mCardSerialNumber, PIVCard::AppName, this);
+ auto cmd = new CreateCSRForCardKeyCommand(keyref, mSerialNumber, PIVCard::AppName, this);
this->setEnabled(false);
connect(cmd, &CreateCSRForCardKeyCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->start();
}
void PIVCardWidget::writeCertificateToCard(const std::string &keyref)
{
- auto cmd = new CertificateToPIVCardCommand(keyref, mCardSerialNumber);
+ auto cmd = new CertificateToPIVCardCommand(keyref, mSerialNumber);
this->setEnabled(false);
connect(cmd, &CertificateToPIVCardCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->setParentWidget(this);
cmd->start();
}
void PIVCardWidget::importCertificateFromCard(const std::string &keyref)
{
- auto cmd = new ImportCertificateFromPIVCardCommand(keyref, mCardSerialNumber);
+ auto cmd = new ImportCertificateFromPIVCardCommand(keyref, mSerialNumber);
this->setEnabled(false);
connect(cmd, &ImportCertificateFromPIVCardCommand::finished, this, [this, keyref]() {
this->updateKeyWidgets(keyref);
this->setEnabled(true);
});
cmd->setParentWidget(this);
cmd->start();
}
void PIVCardWidget::writeKeyToCard(const std::string &keyref)
{
- auto cmd = new KeyToCardCommand(keyref, mCardSerialNumber, PIVCard::AppName);
+ auto cmd = new KeyToCardCommand(keyref, mSerialNumber, PIVCard::AppName);
this->setEnabled(false);
connect(cmd, &KeyToCardCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->setParentWidget(this);
cmd->start();
}
void PIVCardWidget::createKeyFromCardKeys()
{
- auto cmd = new CreateOpenPGPKeyFromCardKeysCommand(mCardSerialNumber, PIVCard::AppName, this);
+ auto cmd = new CreateOpenPGPKeyFromCardKeysCommand(mSerialNumber, PIVCard::AppName, this);
this->setEnabled(false);
connect(cmd, &CreateOpenPGPKeyFromCardKeysCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->start();
}
void PIVCardWidget::changePin(const std::string &keyRef)
{
- auto cmd = new ChangePinCommand(mCardSerialNumber, PIVCard::AppName, this);
+ auto cmd = new ChangePinCommand(mSerialNumber, PIVCard::AppName, this);
this->setEnabled(false);
connect(cmd, &ChangePinCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->setKeyRef(keyRef);
cmd->start();
}
void PIVCardWidget::setAdminKey()
{
- auto cmd = new SetPIVCardApplicationAdministrationKeyCommand(mCardSerialNumber, this);
+ auto cmd = new SetPIVCardApplicationAdministrationKeyCommand(mSerialNumber, this);
this->setEnabled(false);
connect(cmd, &SetPIVCardApplicationAdministrationKeyCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->start();
}
diff --git a/src/view/pivcardwidget.h b/src/view/pivcardwidget.h
index 5db708d77..18333a928 100644
--- a/src/view/pivcardwidget.h
+++ b/src/view/pivcardwidget.h
@@ -1,71 +1,71 @@
/* view/pivcardwiget.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2020 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
+#include "smartcardwidget.h"
+
#include <smartcard/keypairinfo.h>
#include <QMap>
-#include <QWidget>
#include <gpgme++/error.h>
class QLabel;
class QPushButton;
namespace Kleo
{
namespace SmartCard
{
class PIVCard;
} // namespace SmartCard
-class PIVCardWidget : public QWidget
+class PIVCardWidget : public SmartCardWidget
{
Q_OBJECT
public:
explicit PIVCardWidget(QWidget *parent = nullptr);
~PIVCardWidget() override;
void setCard(const SmartCard::PIVCard *card);
struct KeyWidgets {
SmartCard::KeyPairInfo keyInfo;
std::string certificateData;
QLabel *keyGrip = nullptr;
QLabel *keyAlgorithm = nullptr;
QLabel *certificateInfo = nullptr;
QPushButton *generateButton = nullptr;
QPushButton *createCSRButton = nullptr;
QPushButton *writeCertificateButton = nullptr;
QPushButton *importCertificateButton = nullptr;
QPushButton *writeKeyButton = nullptr;
};
private:
KeyWidgets createKeyWidgets(const SmartCard::KeyPairInfo &keyInfo);
void updateCachedValues(const std::string &keyRef, const SmartCard::PIVCard *card);
void updateKeyWidgets(const std::string &keyRef);
void generateKey(const std::string &keyref);
void createCSR(const std::string &keyref);
void writeCertificateToCard(const std::string &keyref);
void importCertificateFromCard(const std::string &keyref);
void writeKeyToCard(const std::string &keyref);
void createKeyFromCardKeys();
void changePin(const std::string &keyRef);
void setAdminKey();
private:
- std::string mCardSerialNumber;
- QLabel *mSerialNumber = nullptr;
+ QLabel *mSerialNumberLabel = nullptr;
QLabel *mVersionLabel = nullptr;
QPushButton *mKeyForCardKeysButton = nullptr;
std::map<std::string, KeyWidgets> mKeyWidgets;
};
} // namespace Kleo
diff --git a/src/view/smartcardswidget.cpp b/src/view/smartcardswidget.cpp
index c3835c3eb..ae4080aeb 100644
--- a/src/view/smartcardswidget.cpp
+++ b/src/view/smartcardswidget.cpp
@@ -1,245 +1,246 @@
/* view/smartcardswidget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-FileCopyrightText: 2020 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "smartcardswidget.h"
#include "smartcard/netkeycard.h"
#include "smartcard/openpgpcard.h"
#include "smartcard/p15card.h"
#include "smartcard/pivcard.h"
#include "smartcard/readerstatus.h"
#include "smartcard/utils.h"
#include "view/netkeywidget.h"
#include "view/p15cardwidget.h"
#include "view/pgpcardwidget.h"
#include "view/pivcardwidget.h"
+#include "view/smartcardwidget.h"
#include "kleopatra_debug.h"
#include <KActionCollection>
#include <KLocalizedString>
#include <QHBoxLayout>
#include <QLabel>
#include <QPointer>
#include <QPushButton>
#include <QStackedWidget>
#include <QTabWidget>
#include <QToolButton>
#include <QVBoxLayout>
using namespace Kleo;
using namespace Kleo::SmartCard;
namespace
{
class PlaceHolderWidget : public QWidget
{
Q_OBJECT
public:
explicit PlaceHolderWidget(QWidget *parent = nullptr)
: QWidget{parent}
{
auto lay = new QVBoxLayout;
lay->addStretch(-1);
const QStringList supported = QStringList() << i18nc("OpenPGP refers to a smartcard protocol", "OpenPGP v2.0 - v3.3")
<< i18nc("Gnuk is a cryptographic token for GnuPG", "Gnuk")
<< i18nc("NetKey refers to a smartcard protocol", "NetKey v3")
<< i18nc("PIV refers to a smartcard protocol", "PIV (requires GnuPG 2.3 or later)")
<< i18nc("CardOS is a smartcard operating system", "CardOS 5 (various apps)");
lay->addWidget(new QLabel(QStringLiteral("\t\t<h3>") + i18n("Please insert a compatible smartcard.") + QStringLiteral("</h3>"), this));
lay->addSpacing(10);
lay->addWidget(new QLabel(QStringLiteral("\t\t") + i18n("Kleopatra currently supports the following card types:") + QStringLiteral("<ul><li>")
+ supported.join(QLatin1String("</li><li>")) + QStringLiteral("</li></ul>"),
this));
lay->addSpacing(10);
{
auto hbox = new QHBoxLayout;
hbox->addStretch(1);
mReloadButton = new QPushButton{i18n("Reload"), this};
hbox->addWidget(mReloadButton);
hbox->addStretch(1);
lay->addLayout(hbox);
}
lay->addStretch(-1);
auto hLay = new QHBoxLayout(this);
hLay->addStretch(-1);
hLay->addLayout(lay);
hLay->addStretch(-1);
lay->addStretch(-1);
connect(mReloadButton, &QPushButton::clicked, this, &PlaceHolderWidget::reload);
}
Q_SIGNALS:
void reload();
private:
QPushButton *mReloadButton = nullptr;
};
} // namespace
class SmartCardsWidget::Private
{
friend class ::Kleo::SmartCardsWidget;
public:
Private(SmartCardsWidget *qq);
void cardAddedOrChanged(const std::string &serialNumber, const std::string &appName);
void cardRemoved(const std::string &serialNumber, const std::string &appName);
private:
template<typename C, typename W>
void cardAddedOrChanged(const std::string &serialNumber);
private:
SmartCardsWidget *const q;
- QMap<std::pair<std::string, std::string>, QPointer<QWidget>> mCardWidgets;
+ QMap<std::pair<std::string, std::string>, QPointer<SmartCardWidget>> mCardWidgets;
PlaceHolderWidget *mPlaceHolderWidget;
QStackedWidget *mStack;
QTabWidget *mTabWidget;
QToolButton *mReloadButton;
};
SmartCardsWidget::Private::Private(SmartCardsWidget *qq)
: q{qq}
{
auto vLay = new QVBoxLayout(q);
mStack = new QStackedWidget{q};
vLay->addWidget(mStack);
mPlaceHolderWidget = new PlaceHolderWidget{q};
mStack->addWidget(mPlaceHolderWidget);
mTabWidget = new QTabWidget{q};
// create "Reload" button after tab widget to ensure correct tab order
mReloadButton = new QToolButton{q};
mTabWidget->setCornerWidget(mReloadButton, Qt::TopRightCorner);
mStack->addWidget(mTabWidget);
mStack->setCurrentWidget(mPlaceHolderWidget);
connect(mPlaceHolderWidget, &PlaceHolderWidget::reload, q, &SmartCardsWidget::reload);
connect(ReaderStatus::instance(), &ReaderStatus::cardAdded, q, [this](const std::string &serialNumber, const std::string &appName) {
cardAddedOrChanged(serialNumber, appName);
});
connect(ReaderStatus::instance(), &ReaderStatus::cardChanged, q, [this](const std::string &serialNumber, const std::string &appName) {
cardAddedOrChanged(serialNumber, appName);
});
connect(ReaderStatus::instance(), &ReaderStatus::cardRemoved, q, [this](const std::string &serialNumber, const std::string &appName) {
cardRemoved(serialNumber, appName);
});
}
void SmartCardsWidget::Private::cardAddedOrChanged(const std::string &serialNumber, const std::string &appName)
{
if (appName == SmartCard::NetKeyCard::AppName) {
cardAddedOrChanged<NetKeyCard, NetKeyWidget>(serialNumber);
} else if (appName == SmartCard::OpenPGPCard::AppName) {
cardAddedOrChanged<OpenPGPCard, PGPCardWidget>(serialNumber);
} else if (appName == SmartCard::PIVCard::AppName) {
cardAddedOrChanged<PIVCard, PIVCardWidget>(serialNumber);
} else if (appName == SmartCard::P15Card::AppName) {
cardAddedOrChanged<P15Card, P15CardWidget>(serialNumber);
} else {
qCWarning(KLEOPATRA_LOG) << "SmartCardsWidget::Private::cardAddedOrChanged:"
<< "App" << appName.c_str() << "is not supported";
}
}
namespace
{
static QString getCardLabel(const std::shared_ptr<Card> &card)
{
if (!card->cardHolder().isEmpty()) {
return i18nc("@title:tab smartcard application - name of card holder - serial number of smartcard",
"%1 - %2 - %3",
displayAppName(card->appName()),
card->cardHolder(),
card->displaySerialNumber());
} else {
return i18nc("@title:tab smartcard application - serial number of smartcard", "%1 - %2", displayAppName(card->appName()), card->displaySerialNumber());
}
}
}
template<typename C, typename W>
void SmartCardsWidget::Private::cardAddedOrChanged(const std::string &serialNumber)
{
const auto card = ReaderStatus::instance()->getCard<C>(serialNumber);
if (!card) {
qCWarning(KLEOPATRA_LOG) << "SmartCardsWidget::Private::cardAddedOrChanged:"
<< "New or changed card" << serialNumber.c_str() << "with app" << C::AppName.c_str() << "not found";
return;
}
W *cardWidget = dynamic_cast<W *>(mCardWidgets.value({serialNumber, C::AppName}).data());
if (!cardWidget) {
cardWidget = new W;
mCardWidgets.insert({serialNumber, C::AppName}, cardWidget);
mTabWidget->addTab(cardWidget, getCardLabel(card));
if (mCardWidgets.size() == 1) {
mStack->setCurrentWidget(mTabWidget);
}
}
cardWidget->setCard(card.get());
}
void SmartCardsWidget::Private::cardRemoved(const std::string &serialNumber, const std::string &appName)
{
QWidget *cardWidget = mCardWidgets.take({serialNumber, appName});
if (cardWidget) {
const int index = mTabWidget->indexOf(cardWidget);
if (index != -1) {
mTabWidget->removeTab(index);
}
delete cardWidget;
}
if (mCardWidgets.empty()) {
mStack->setCurrentWidget(mPlaceHolderWidget);
}
}
SmartCardsWidget::SmartCardsWidget(QWidget *parent)
: QWidget{parent}
, d{std::make_unique<Private>(this)}
{
}
SmartCardsWidget::~SmartCardsWidget() = default;
void SmartCardsWidget::showCards(const std::vector<std::shared_ptr<Kleo::SmartCard::Card>> &cards)
{
for (const auto &card : cards) {
d->cardAddedOrChanged(card->serialNumber(), card->appName());
}
}
void SmartCardsWidget::createActions(KActionCollection *ac)
{
QAction *reloadAction = ac->addAction(KStandardAction::StandardAction::Redisplay, QStringLiteral("reload"), this, &SmartCardsWidget::reload);
reloadAction->setText(i18nc("@action", "Reload"));
reloadAction->setToolTip(i18nc("@info:tooltip", "Reload smart cards"));
d->mReloadButton->setDefaultAction(reloadAction);
}
void SmartCardsWidget::reload()
{
ReaderStatus::mutableInstance()->updateStatus();
}
#include "smartcardswidget.moc"
diff --git a/src/view/smartcardwidget.cpp b/src/view/smartcardwidget.cpp
new file mode 100644
index 000000000..151217b5a
--- /dev/null
+++ b/src/view/smartcardwidget.cpp
@@ -0,0 +1,17 @@
+/* view/smartcardwidget.cpp
+
+ This file is part of Kleopatra, the KDE keymanager
+ SPDX-FileCopyrightText: 2024 g10 Code GmbH
+ SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "smartcardwidget.h"
+
+SmartCardWidget::SmartCardWidget(QWidget *parent)
+ : QWidget{parent}
+{
+}
+
+SmartCardWidget::~SmartCardWidget() = default;
diff --git a/src/view/smartcardwidget.h b/src/view/smartcardwidget.h
new file mode 100644
index 000000000..457f61bfa
--- /dev/null
+++ b/src/view/smartcardwidget.h
@@ -0,0 +1,23 @@
+/* view/smartcardwidget.h
+
+ This file is part of Kleopatra, the KDE keymanager
+ SPDX-FileCopyrightText: 2024 g10 Code GmbH
+ SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+#pragma once
+
+#include <QWidget>
+
+#include <string>
+
+class SmartCardWidget : public QWidget
+{
+public:
+ SmartCardWidget(QWidget *parent = nullptr);
+ ~SmartCardWidget() override;
+
+protected:
+ std::string mSerialNumber;
+};

File Metadata

Mime Type
text/x-diff
Expires
Thu, Mar 19, 5:35 AM (1 d, 3 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
aa/bd/ebd42166aeb279fa0594ba3f0403

Event Timeline