diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6775d7de2..2a50b491f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,639 +1,641 @@ # 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) 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(KPim6IdentityManagementCore_FOUND AND KPim6MailTransport_FOUND AND KPim6AkonadiMime_FOUND) set(_kleopatra_mail_libs KPim6::IdentityManagementCore # Export OpenPGP keys using WKS KPim6::MailTransport KPim6::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/certificatetocardcommand.cpp commands/certificatetocardcommand.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/togglecertificateenabledcommand.cpp + commands/togglecertificateenabledcommand.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/copytosmartcarddialog.cpp dialogs/copytosmartcarddialog.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/pivcardapplicationadministrationkeyinputdialog.cpp dialogs/pivcardapplicationadministrationkeyinputdialog.h dialogs/revokekeydialog.cpp dialogs/revokekeydialog.h dialogs/revokerswidget.cpp dialogs/revokerswidget.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/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/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/kuniqueservice.cpp utils/kuniqueservice.h utils/log.cpp utils/log.h utils/memory-helpers.h utils/migration.cpp utils/migration.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/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/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 kleopatra_options.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/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 KPim6::Libkleo KPim6::Mime KPim6::MimeTreeParserWidgets KF6::Codecs KF6::CoreAddons KF6::Crash KF6::I18n KF6::IconThemes KF6::ItemModels KF6::KIOCore KF6::KIOWidgets KF6::WindowSystem KF6::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} ) target_link_libraries(kleopatra_bin QGpgmeQt6) 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/commands/togglecertificateenabledcommand.cpp b/src/commands/togglecertificateenabledcommand.cpp new file mode 100644 index 000000000..54f6a9dee --- /dev/null +++ b/src/commands/togglecertificateenabledcommand.cpp @@ -0,0 +1,131 @@ +/* + SPDX-FileCopyrightText: 2024 g10 Code GmbH + SPDX-FileContributor: Tobias Fella <tobias.fella@gnupg.com> + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include "togglecertificateenabledcommand.h" + +#include "command_p.h" + +#include <Libkleo/Formatting> + +#include <QGpgME/Protocol> +#include <QGpgME/QuickJob> + +#include <gpgme++/key.h> + +#include <gpgme.h> + +#include <KLocalizedString> + +using namespace Kleo::Commands; +using namespace GpgME; +using namespace QGpgME; + +class ToggleCertificateEnabledCommand::Private : public Command::Private +{ + ToggleCertificateEnabledCommand *q_func() const + { + return static_cast<ToggleCertificateEnabledCommand *>(q); + } + +public: + explicit Private(ToggleCertificateEnabledCommand *qq, KeyListController *c = nullptr); + ~Private() override; + + void slotResult(const Error &err); + + void createJob(); + QPointer<QuickJob> job; +}; + +ToggleCertificateEnabledCommand::Private *ToggleCertificateEnabledCommand::d_func() +{ + return static_cast<Private *>(d.get()); +} +const ToggleCertificateEnabledCommand::Private *ToggleCertificateEnabledCommand::d_func() const +{ + return static_cast<const Private *>(d.get()); +} + +#define d d_func() +#define q q_func() + +ToggleCertificateEnabledCommand::Private::Private(ToggleCertificateEnabledCommand *qq, KeyListController *c) + : Command::Private{qq, c} +{ +} +ToggleCertificateEnabledCommand::ToggleCertificateEnabledCommand(QAbstractItemView *v, KeyListController *c) + + : Command{v, new Private{this, c}} +{ +} + +ToggleCertificateEnabledCommand::Private::~Private() = default; + +void ToggleCertificateEnabledCommand::Private::slotResult(const Error &err) +{ + if (err.isCanceled()) { + canceled(); + return; + } + + if (err.isCanceled()) { + canceled(); + return; + } + if (err) { + if (key().isDisabled()) { + error(xi18nc("@info", "<para>Failed to enable certificate:</para><para><message>%1</message></para>", Formatting::errorAsString(err))); + } else { + error(xi18nc("@info", "<para>Failed to disable certificate:</para><para><message>%1</message></para>", Formatting::errorAsString(err))); + } + } + finished(); +} + +void ToggleCertificateEnabledCommand::Private::createJob() +{ + Q_ASSERT(!job); + + const auto backend = (key().protocol() == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime(); + + if (!backend) { + return; + } + + const auto j = backend->quickJob(); + if (!j) { + return; + } + + connect(j, &QGpgME::Job::jobProgress, q, &Command::progress); + connect(j, &QuickJob::result, q, [this](const auto &err) { + slotResult(err); + }); + + job = j; +} + +ToggleCertificateEnabledCommand::~ToggleCertificateEnabledCommand() = default; + +void ToggleCertificateEnabledCommand::doStart() +{ + d->createJob(); + + d->job->startSetKeyEnabled(d->key(), d->key().isDisabled()); +} + +void ToggleCertificateEnabledCommand::doCancel() +{ + if (d->job) { + d->job->slotCancel(); + } +} + +#undef d +#undef q + +#include "moc_togglecertificateenabledcommand.cpp" diff --git a/src/commands/togglecertificateenabledcommand.h b/src/commands/togglecertificateenabledcommand.h new file mode 100644 index 000000000..0872e6a2f --- /dev/null +++ b/src/commands/togglecertificateenabledcommand.h @@ -0,0 +1,40 @@ +/* + SPDX-FileCopyrightText: 2024 g10 Code GmbH + SPDX-FileContributor: Tobias Fella <tobias.fella@gnupg.com> + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include <commands/command.h> + +namespace Kleo +{ +namespace Commands +{ + +class ToggleCertificateEnabledCommand : public Command +{ + Q_OBJECT +public: + // explicit ToggleCertificateEnabledCommand(const GpgME::Key &key); + explicit ToggleCertificateEnabledCommand(QAbstractItemView *view, KeyListController *parent); + ~ToggleCertificateEnabledCommand() override; + + static Restrictions restrictions() + { + return OnlyOneKey; + } + +private: + void doStart() override; + void doCancel() override; + + class Private; + inline Private *d_func(); + inline const Private *d_func() const; +}; + +} +} diff --git a/src/kleopatra.rc b/src/kleopatra.rc index 72f838291..e953325f9 100644 --- a/src/kleopatra.rc +++ b/src/kleopatra.rc @@ -1,168 +1,170 @@ <!DOCTYPE gui > -<gui name="kleopatra" version="519" > +<gui name="kleopatra" version="520" > <MenuBar> <Menu name="file"> <text>&File</text> <Action name="file_new_certificate"/> <Action name="file_new_certificate_signing_request"/> <Separator/> <Action name="file_lookup_certificates"/> <Action name="file_import_certificates"/> <Separator/> <Action name="file_export_certificates"/> <Action name="file_export_secret_keys"/> <Action name="file_export_paper_key"/> <Action name="file_export_certificates_to_server"/> <Action name="file_export_certificate_to_provider"/> <Separator/> <Action name="file_decrypt_verify_files"/> <Action name="file_sign_encrypt_files"/> <Action name="file_sign_encrypt_folder"/> <Separator/> <Action name="file_checksum_create_files"/> <Action name="file_checksum_verify_files"/> <Separator/> <Action name="quit" /> </Menu> <Menu name="view"> <text>&View</text> <Action name="view_redisplay"/> <Separator/> <Action name="view_stop_operations"/> <Action name="view_certificate_details"/> <Separator/> <Action name="window_view_hierarchical"/> <Separator/> <Action name="window_expand_all"/> <Action name="window_collapse_all"/> <Separator/> <Action name="view_certificate_overview"/> <Action name="pad_view"/> <Action name="manage_smartcard"/> </Menu> <Menu name="certMenu"> <text>&Certificates</text> <Action name="certificates_refresh"/> <Separator/> <Action name="certificates_change_owner_trust"/> + <Action name="certificates_disable"/> <Action name="certificates_trust_root"/> <Action name="certificates_distrust_root"/> <Separator/> <Action name="certificates_certify_certificate"/> <Action name="certificates_revoke_certification"/> <Separator/> <Action name="certificates_change_expiry"/> <Action name="certificates_change_passphrase"/> <Action name="certificates_add_userid"/> <Separator/> <Action name="certificates_revoke"/> <Action name="certificates_delete"/> <Separator/> <Action name="certificates_create_group"/> <Separator/> <Action name="certificate_to_card"/> </Menu> <Menu name="tools"> <text>&Tools</text> <Action name="tools_start_kwatchgnupg"/> <Action name="tools_debug_view"/> <Separator/> <Action name="tools_refresh_x509_certificates"/> <Action name="tools_refresh_openpgp_certificates"/> <Separator/> <Action name="clipboard_menu"/> <Separator/> <Action name="crl_import_crl"/> <Separator/> <Action name="crl_clear_crl_cache"/> <Action name="crl_dump_crl_cache"/> <Separator/> <Action name="tools_restart_backend"/> </Menu> <Menu name="settings"> <text>&Settings</text> <Action name="colorscheme_menu" group="show_merge"/> <Action name="settings_self_test"/> <Action name="configure_groups" append="configure_merge"/> </Menu> <Menu name="window" append="settings_merge"> <text>&Window</text> <Action name="window_rename_tab"/> <Separator/> <Action name="window_new_tab"/> <Action name="window_duplicate_tab"/> <Action name="window_close_tab"/> <Separator/> <Action name="window_move_tab_left"/> <Action name="window_move_tab_right"/> </Menu> <Menu name="help"> <text>&Help</text> <Action name="help_doc_quickguide"/> <Action name="help_doc_symenc"/> <Action name="help_doc_groups"/> <Action name="help_doc_gpgol"/> <Action name="help_doc_compendium"/> <Menu name="help_more"> <text>&More Documentation</text> <Action name="help_doc_cert_management"/> <Action name="help_doc_smartcard"/> <Action name="help_doc_gnupg"/> </Menu> <Separator/> <Action name="help_doc_approval_manual"/> <Action name="help_doc_vsa"/> <Separator/> <Action name="help_check_updates"/> </Menu> </MenuBar> <ToolBar fullWidth="false" name="mainToolBar" iconText="TextUnderIcon"> <text>Main Toolbar</text> <Action name="file_sign_encrypt_files"/> <Action name="file_decrypt_verify_files"/> <Separator/> <Action name="file_import_certificates"/> <Action name="file_export_certificates"/> <Action name="certificates_certify_certificate"/> <Action name="file_lookup_certificates"/> <Separator/> <Action name="view_certificate_overview"/> <Action name="pad_view"/> <Action name="manage_smartcard"/> <Separator/> <Action name="configure_groups_toolbar"/> </ToolBar> <Menu name="listview_popup"> <text>&Certificates</text> <Action name="certificates_refresh"/> <Separator/> <Action name="certificates_certify_certificate"/> <Action name="certificates_revoke_certification"/> <Action name="certificates_trust_root"/> <Action name="certificates_distrust_root"/> <Action name="certificates_change_owner_trust"/> + <Action name="certificates_disable"/> <Separator/> <Action name="certificates_change_expiry"/> <Action name="certificates_change_passphrase"/> <Action name="certificates_add_userid"/> <Separator/> <Action name="certificates_revoke"/> <Action name="certificates_delete"/> <Separator/> <Action name="certificates_create_group"/> <Separator/> <Action name="file_export_certificates"/> <Action name="file_export_secret_keys"/> <Action name="file_export_paper_key"/> <Action name="file_export_certificates_to_server"/> <Action name="file_export_certificate_to_provider"/> <Action name="certificate_to_card"/> <Separator/> <Action name="cell_copy"/> <Separator/> <Action name="view_certificate_details"/> </Menu> </gui> diff --git a/src/view/keylistcontroller.cpp b/src/view/keylistcontroller.cpp index 42bd12646..5fc56b460 100644 --- a/src/view/keylistcontroller.cpp +++ b/src/view/keylistcontroller.cpp @@ -1,1106 +1,1139 @@ /* -*- mode: c++; c-basic-offset:4 -*- view/keylistcontroller.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB SPDX-FileCopyrightText: 2022 Felix Tiede SPDX-License-Identifier: GPL-2.0-or-later */ #include <config-kleopatra.h> #include "keylistcontroller.h" #include "tabwidget.h" #include <smartcard/readerstatus.h> #include <utils/action_data.h> #include "commands/exportcertificatecommand.h" #include "commands/exportopenpgpcertstoservercommand.h" #include "kleopatra_debug.h" #include "tooltippreferences.h" #include <settings.h> #ifdef MAILAKONADI_ENABLED #include "commands/exportopenpgpcerttoprovidercommand.h" #endif // MAILAKONADI_ENABLED #include "commands/adduseridcommand.h" #include "commands/certificatetocardcommand.h" #include "commands/certifycertificatecommand.h" #include "commands/changeexpirycommand.h" #include "commands/changeownertrustcommand.h" #include "commands/changepassphrasecommand.h" #include "commands/changeroottrustcommand.h" #include "commands/checksumcreatefilescommand.h" #include "commands/checksumverifyfilescommand.h" #include "commands/clearcrlcachecommand.h" #include "commands/creategroupcommand.h" #include "commands/decryptverifyfilescommand.h" #include "commands/deletecertificatescommand.h" #include "commands/detailscommand.h" #include "commands/dumpcertificatecommand.h" #include "commands/dumpcrlcachecommand.h" #include "commands/exportpaperkeycommand.h" #include "commands/exportsecretkeycommand.h" #include "commands/importcertificatefromfilecommand.h" #include "commands/importcrlcommand.h" #include "commands/lookupcertificatescommand.h" #include "commands/newcertificatesigningrequestcommand.h" #include "commands/newopenpgpcertificatecommand.h" #include "commands/refreshcertificatescommand.h" #include "commands/refreshopenpgpcertscommand.h" #include "commands/refreshx509certscommand.h" #include "commands/reloadkeyscommand.h" #include "commands/revokecertificationcommand.h" #include "commands/revokekeycommand.h" #include "commands/signencryptfilescommand.h" #include "commands/signencryptfoldercommand.h" +#include "commands/togglecertificateenabledcommand.h" #include <Libkleo/Algorithm> #include <Libkleo/Formatting> #include <Libkleo/GnuPG> #include <Libkleo/KeyCache> #include <Libkleo/KeyListModel> #include <gpgme++/key.h> #include <KActionCollection> #include <KLocalizedString> #include <QAbstractItemView> #include <QAction> #include <QClipboard> #include <QGuiApplication> #include <QItemSelectionModel> #include <QPointer> #include <algorithm> #include <iterator> using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::SmartCard; using namespace GpgME; namespace ranges = std::ranges; class KeyListController::Private { friend class ::Kleo::KeyListController; KeyListController *const q; public: explicit Private(KeyListController *qq); ~Private(); void connectView(QAbstractItemView *view); void connectCommand(Command *cmd); void connectTabWidget(); void disconnectTabWidget(); void addCommand(Command *cmd) { connectCommand(cmd); commands.insert(ranges::lower_bound(commands, cmd), cmd); } void addView(QAbstractItemView *view) { connectView(view); views.insert(ranges::lower_bound(views, view), view); } void removeView(QAbstractItemView *view) { view->disconnect(q); view->selectionModel()->disconnect(q); std::erase(views, view); } public: void slotDestroyed(QObject *o) { qCDebug(KLEOPATRA_LOG) << (void *)o; std::erase(views, o); std::erase(commands, o); } void slotDoubleClicked(const QModelIndex &idx); void slotActivated(const QModelIndex &idx); void slotSelectionChanged(const QItemSelection &old, const QItemSelection &new_); void slotContextMenu(const QPoint &pos); void slotCommandFinished(); void slotActionTriggered(QAction *action); void slotCurrentViewChanged(QAbstractItemView *view) { if (view && !ranges::binary_search(views, view)) { qCDebug(KLEOPATRA_LOG) << "you need to register view" << view << "before trying to set it as the current view!"; addView(view); } currentView = view; q->enableDisableActions(view ? view->selectionModel() : nullptr); } + void updateActions(KActionCollection *collection); private: int toolTipOptions() const; private: static Command::Restrictions calculateRestrictionsMask(const QItemSelectionModel *sm); private: struct action_item { QPointer<QAction> action; Command::Restrictions restrictions; Command *(*createCommand)(QAbstractItemView *, KeyListController *); }; std::vector<action_item> actions; std::vector<QAbstractItemView *> views; std::vector<Command *> commands; QPointer<QWidget> parentWidget; QPointer<TabWidget> tabWidget; QPointer<QAbstractItemView> currentView; QPointer<AbstractKeyListModel> flatModel, hierarchicalModel; std::vector<QMetaObject::Connection> m_connections; }; KeyListController::Private::Private(KeyListController *qq) : q(qq) , actions() , views() , commands() , parentWidget() , tabWidget() , flatModel() , hierarchicalModel() { } KeyListController::Private::~Private() { } KeyListController::KeyListController(QObject *p) : QObject(p) , d(new Private(this)) { } KeyListController::~KeyListController() { } void KeyListController::addView(QAbstractItemView *view) { if (!view || ranges::binary_search(d->views, view)) { return; } d->addView(view); } void KeyListController::removeView(QAbstractItemView *view) { if (!view || !ranges::binary_search(d->views, view)) { return; } d->removeView(view); } void KeyListController::setCurrentView(QAbstractItemView *view) { d->slotCurrentViewChanged(view); } std::vector<QAbstractItemView *> KeyListController::views() const { return d->views; } void KeyListController::setFlatModel(AbstractKeyListModel *model) { if (model == d->flatModel) { return; } d->flatModel = model; if (model) { model->setToolTipOptions(d->toolTipOptions()); } } void KeyListController::setHierarchicalModel(AbstractKeyListModel *model) { if (model == d->hierarchicalModel) { return; } d->hierarchicalModel = model; if (model) { model->setToolTipOptions(d->toolTipOptions()); } } void KeyListController::setTabWidget(TabWidget *tabWidget) { if (tabWidget == d->tabWidget) { return; } d->disconnectTabWidget(); d->tabWidget = tabWidget; d->connectTabWidget(); d->slotCurrentViewChanged(tabWidget ? tabWidget->currentView() : nullptr); } void KeyListController::setParentWidget(QWidget *parent) { d->parentWidget = parent; } QWidget *KeyListController::parentWidget() const { return d->parentWidget; } void KeyListController::Private::connectTabWidget() { if (!tabWidget) { return; } const auto views = tabWidget->views(); ranges::for_each(views, [this](QAbstractItemView *view) { addView(view); }); m_connections.reserve(3); m_connections.push_back(connect(tabWidget, &TabWidget::viewAdded, q, &KeyListController::addView)); m_connections.push_back(connect(tabWidget, &TabWidget::viewAboutToBeRemoved, q, &KeyListController::removeView)); m_connections.push_back(connect(tabWidget, &TabWidget::currentViewChanged, q, [this](QAbstractItemView *view) { slotCurrentViewChanged(view); })); } void KeyListController::Private::disconnectTabWidget() { if (!tabWidget) { return; } for (const auto &connection : m_connections) { disconnect(connection); } m_connections.clear(); const auto views = tabWidget->views(); ranges::for_each(views, [this](QAbstractItemView *view) { removeView(view); }); } AbstractKeyListModel *KeyListController::flatModel() const { return d->flatModel; } AbstractKeyListModel *KeyListController::hierarchicalModel() const { return d->hierarchicalModel; } QAbstractItemView *KeyListController::currentView() const { return d->currentView; } TabWidget *KeyListController::tabWidget() const { return d->tabWidget; } void KeyListController::createActions(KActionCollection *coll) { const std::vector<action_data> common_and_openpgp_action_data = { // File menu { "file_new_certificate", i18n("New OpenPGP Key Pair..."), i18n("Create a new OpenPGP certificate"), "view-certificate-add", nullptr, nullptr, QStringLiteral("Ctrl+N"), }, { "file_export_certificates", i18n("Export..."), i18n("Export the selected certificate (public key) to a file"), "view-certificate-export", nullptr, nullptr, QStringLiteral("Ctrl+E"), }, { "file_export_certificates_to_server", i18n("Publish on Server..."), keyserver().startsWith(QStringLiteral("ldap:")) || keyserver().startsWith(QStringLiteral("ldaps:")) ? i18n("Publish the selected certificate (public key) to internal directory") : i18n("Publish the selected certificate (public key) on %1", keyserver()), "view-certificate-export-server", nullptr, nullptr, QStringLiteral("Ctrl+Shift+E"), }, #ifdef MAILAKONADI_ENABLED { "file_export_certificate_to_provider", i18n("Publish at Mail Provider..."), i18n("Publish the selected certificate (public key) at mail provider's Web Key Directory if offered"), "view-certificate-export", nullptr, nullptr, QString(), }, #endif // MAILAKONADI_ENABLED { "file_export_secret_keys", i18n("Backup Secret Keys..."), QString(), "view-certificate-export-secret", nullptr, nullptr, QString(), }, { "file_export_paper_key", i18n("Print Secret Key..."), QString(), "document-print", nullptr, nullptr, QString(), }, { "file_lookup_certificates", i18n("Lookup on Server..."), keyserver().startsWith(QStringLiteral("ldap:")) || keyserver().startsWith(QStringLiteral("ldaps:")) ? i18n("Search for certificates in internal directory") : i18n("Search for certificates on %1", keyserver()), "edit-find", nullptr, nullptr, QStringLiteral("Shift+Ctrl+I"), }, { "file_import_certificates", i18n("Import..."), i18n("Import a certificate from a file"), "view-certificate-import", nullptr, nullptr, QStringLiteral("Ctrl+I"), }, { "file_decrypt_verify_files", i18n("Decrypt/Verify..."), i18n("Decrypt and/or verify files"), "document-edit-decrypt-verify", nullptr, nullptr, QString(), }, { "file_sign_encrypt_files", i18n("Sign/Encrypt..."), i18n("Encrypt and/or sign files"), "document-edit-sign-encrypt", nullptr, nullptr, QString(), }, { "file_sign_encrypt_folder", i18n("Sign/Encrypt Folder..."), i18n("Encrypt and/or sign folders"), "folder-edit-sign-encrypt-symbolic", nullptr, nullptr, QString(), }, { "file_checksum_create_files", i18n("Create Checksum Files..."), QString(), nullptr /*"document-checksum-create"*/, nullptr, nullptr, QString(), }, { "file_checksum_verify_files", i18n("Verify Checksum Files..."), QString(), nullptr /*"document-checksum-verify"*/, nullptr, nullptr, QString(), }, // View menu { "view_redisplay", i18n("Redisplay"), QString(), "view-refresh", nullptr, nullptr, QStringLiteral("F5"), }, { "view_stop_operations", i18n("Stop Operation"), QString(), "process-stop", this, [this](bool) { cancelCommands(); }, QStringLiteral("Escape"), RegularQAction, Disabled, }, { "view_certificate_details", i18n("Details"), QString(), "dialog-information", nullptr, nullptr, QString(), }, // Certificate menu { "certificates_revoke", i18n("Revoke Certificate..."), i18n("Revoke the selected OpenPGP certificate"), "view-certificate-revoke", nullptr, nullptr, {}, }, { "certificates_delete", i18n("Delete"), i18n("Delete selected certificates"), "edit-delete", nullptr, nullptr, QStringLiteral("Delete"), }, { "certificates_refresh", i18n("Update Certificates"), i18n("Update selected certificates"), "view-refresh", nullptr, nullptr, QString(), }, { "certificates_certify_certificate", i18n("Certify..."), i18n("Certify the validity of the selected certificate"), "view-certificate-sign", nullptr, nullptr, QString(), }, { "certificates_revoke_certification", i18n("Revoke Certification..."), i18n("Revoke the certification of the selected certificate"), "view-certificate-revoke", nullptr, nullptr, QString(), }, { "certificates_change_expiry", i18n("Change End of Validity Period..."), QString(), nullptr, nullptr, nullptr, QString(), }, { "certificates_change_owner_trust", i18nc("@action:inmenu", "Change Certification Power..."), i18nc("@info:tooltip", "Grant or revoke the certification power of the selected certificate"), nullptr, nullptr, nullptr, QString(), }, + { + "certificates_disable", + i18nc("@action:inmenu", "Disable Certificate"), + i18nc("@action:tooltip", + "Disabling the certificate will hide it when selecting a certificate to sign with or to encrypt for.\nIt will still be listed in the " + "certicate list"), + nullptr, + nullptr, + nullptr, + QString(), + }, { "certificates_change_passphrase", i18n("Change Passphrase..."), QString(), nullptr, nullptr, nullptr, QString(), }, { "certificates_add_userid", i18n("Add User ID..."), QString(), nullptr, nullptr, nullptr, QString(), }, { "certificates_create_group", i18nc("@action:inmenu", "Create Group..."), i18nc("@info:tooltip", "Create a group from the selected certificates"), "resource-group-new", nullptr, nullptr, QString(), }, { "certificate_to_card", i18nc("@action:inmenu", "Copy to Card"), i18nc("@info:tooltip", "Copy the selected certificate to a smartcard"), "auth-sim-locked", nullptr, nullptr, QString(), }, // Tools menu { "tools_refresh_openpgp_certificates", i18n("Refresh OpenPGP Certificates"), QString(), "view-refresh", nullptr, nullptr, QString(), }, // Context Menu { "cell_copy", i18nc("@action:button", "Copy"), QString(), "edit-copy", this, [this](bool) { QGuiApplication::clipboard()->setText(currentView()->currentIndex().data(Kleo::ClipboardRole).toString()); }, QStringLiteral("Ctrl+C"), } // Window menu // (come from TabWidget) // Help menu // (come from MainWindow) }; static const action_data cms_create_csr_action_data = { "file_new_certificate_signing_request", i18n("New S/MIME Certification Request..."), i18n("Create a new S/MIME certificate signing request (CSR)"), "view-certificate-add", nullptr, nullptr, {}, }; static const std::vector<action_data> cms_action_data = { // Certificate menu { "certificates_trust_root", i18n("Trust Root Certificate"), QString(), nullptr, nullptr, nullptr, QString(), }, { "certificates_distrust_root", i18n("Distrust Root Certificate"), QString(), nullptr, nullptr, nullptr, QString(), }, { "certificates_dump_certificate", i18n("Technical Details"), QString(), nullptr, nullptr, nullptr, QString(), }, // Tools menu { "tools_refresh_x509_certificates", i18n("Refresh S/MIME Certificates"), QString(), "view-refresh", nullptr, nullptr, QString(), }, { "crl_clear_crl_cache", i18n("Clear CRL Cache"), QString(), nullptr, nullptr, nullptr, QString(), }, { "crl_dump_crl_cache", i18n("Dump CRL Cache"), QString(), nullptr, nullptr, nullptr, QString(), }, { "crl_import_crl", i18n("Import CRL From File..."), QString(), nullptr, nullptr, nullptr, QString(), }, }; std::vector<action_data> action_data = common_and_openpgp_action_data; if (const Kleo::Settings settings{}; settings.cmsEnabled()) { if (settings.cmsCertificateCreationAllowed()) { action_data.push_back(cms_create_csr_action_data); } action_data.reserve(action_data.size() + cms_action_data.size()); ranges::copy(cms_action_data, std::back_inserter(action_data)); } make_actions_from_data(action_data, coll); if (QAction *action = coll->action(QStringLiteral("view_stop_operations"))) { connect(this, &KeyListController::commandsExecuting, action, &QAction::setEnabled); } // ### somehow make this better... registerActionForCommand<NewOpenPGPCertificateCommand>(coll->action(QStringLiteral("file_new_certificate"))); registerActionForCommand<NewCertificateSigningRequestCommand>(coll->action(QStringLiteral("file_new_certificate_signing_request"))); //--- registerActionForCommand<LookupCertificatesCommand>(coll->action(QStringLiteral("file_lookup_certificates"))); registerActionForCommand<ImportCertificateFromFileCommand>(coll->action(QStringLiteral("file_import_certificates"))); //--- registerActionForCommand<ExportCertificateCommand>(coll->action(QStringLiteral("file_export_certificates"))); registerActionForCommand<ExportSecretKeyCommand>(coll->action(QStringLiteral("file_export_secret_keys"))); registerActionForCommand<ExportPaperKeyCommand>(coll->action(QStringLiteral("file_export_paper_key"))); registerActionForCommand<ExportOpenPGPCertsToServerCommand>(coll->action(QStringLiteral("file_export_certificates_to_server"))); #ifdef MAILAKONADI_ENABLED registerActionForCommand<ExportOpenPGPCertToProviderCommand>(coll->action(QStringLiteral("file_export_certificate_to_provider"))); #endif // MAILAKONADI_ENABLED registerActionForCommand<CertificateToCardCommand>(coll->action(QStringLiteral("certificate_to_card"))); //--- registerActionForCommand<DecryptVerifyFilesCommand>(coll->action(QStringLiteral("file_decrypt_verify_files"))); registerActionForCommand<SignEncryptFilesCommand>(coll->action(QStringLiteral("file_sign_encrypt_files"))); registerActionForCommand<SignEncryptFolderCommand>(coll->action(QStringLiteral("file_sign_encrypt_folder"))); //--- registerActionForCommand<ChecksumCreateFilesCommand>(coll->action(QStringLiteral("file_checksum_create_files"))); registerActionForCommand<ChecksumVerifyFilesCommand>(coll->action(QStringLiteral("file_checksum_verify_files"))); registerActionForCommand<ReloadKeysCommand>(coll->action(QStringLiteral("view_redisplay"))); // coll->action( "view_stop_operations" ) <-- already dealt with in make_actions_from_data() registerActionForCommand<DetailsCommand>(coll->action(QStringLiteral("view_certificate_details"))); registerActionForCommand<ChangeOwnerTrustCommand>(coll->action(QStringLiteral("certificates_change_owner_trust"))); registerActionForCommand<TrustRootCommand>(coll->action(QStringLiteral("certificates_trust_root"))); registerActionForCommand<DistrustRootCommand>(coll->action(QStringLiteral("certificates_distrust_root"))); + registerActionForCommand<ToggleCertificateEnabledCommand>(coll->action(QStringLiteral("certificates_disable"))); //--- registerActionForCommand<CertifyCertificateCommand>(coll->action(QStringLiteral("certificates_certify_certificate"))); if (RevokeCertificationCommand::isSupported()) { registerActionForCommand<RevokeCertificationCommand>(coll->action(QStringLiteral("certificates_revoke_certification"))); } //--- registerActionForCommand<ChangeExpiryCommand>(coll->action(QStringLiteral("certificates_change_expiry"))); registerActionForCommand<ChangePassphraseCommand>(coll->action(QStringLiteral("certificates_change_passphrase"))); registerActionForCommand<AddUserIDCommand>(coll->action(QStringLiteral("certificates_add_userid"))); registerActionForCommand<CreateGroupCommand>(coll->action(QStringLiteral("certificates_create_group"))); //--- registerActionForCommand<RevokeKeyCommand>(coll->action(QStringLiteral("certificates_revoke"))); registerActionForCommand<DeleteCertificatesCommand>(coll->action(QStringLiteral("certificates_delete"))); //--- registerActionForCommand<RefreshCertificatesCommand>(coll->action(QStringLiteral("certificates_refresh"))); //--- registerActionForCommand<DumpCertificateCommand>(coll->action(QStringLiteral("certificates_dump_certificate"))); registerActionForCommand<RefreshX509CertsCommand>(coll->action(QStringLiteral("tools_refresh_x509_certificates"))); registerActionForCommand<RefreshOpenPGPCertsCommand>(coll->action(QStringLiteral("tools_refresh_openpgp_certificates"))); //--- registerActionForCommand<ImportCrlCommand>(coll->action(QStringLiteral("crl_import_crl"))); //--- registerActionForCommand<ClearCrlCacheCommand>(coll->action(QStringLiteral("crl_clear_crl_cache"))); registerActionForCommand<DumpCrlCacheCommand>(coll->action(QStringLiteral("crl_dump_crl_cache"))); enableDisableActions(nullptr); + + connect(KeyCache::instance().get(), &KeyCache::keysMayHaveChanged, this, [this, coll]() { + d->updateActions(coll); + }); + + connect(this, &KeyListController::selectionChanged, this, [coll, this]() { + d->updateActions(coll); + }); } void KeyListController::registerAction(QAction *action, Command::Restrictions restrictions, Command *(*create)(QAbstractItemView *, KeyListController *)) { if (!action) { return; } Q_ASSERT(!action->isCheckable()); // can be added later, for now, disallow const Private::action_item ai = {action, restrictions, create}; connect(action, &QAction::triggered, this, [this, action]() { d->slotActionTriggered(action); }); d->actions.push_back(ai); } void KeyListController::registerCommand(Command *cmd) { if (!cmd || ranges::binary_search(d->commands, cmd)) { return; } d->addCommand(cmd); qCDebug(KLEOPATRA_LOG) << (void *)cmd; if (d->commands.size() == 1) { Q_EMIT commandsExecuting(true); } } bool KeyListController::hasRunningCommands() const { return !d->commands.empty(); } bool KeyListController::shutdownWarningRequired() const { return ranges::any_of(d->commands, std::mem_fn(&Command::warnWhenRunningAtShutdown)); } // slot void KeyListController::cancelCommands() { ranges::for_each(d->commands, std::mem_fn(&Command::cancel)); } void KeyListController::Private::connectView(QAbstractItemView *view) { connect(view, &QObject::destroyed, q, [this](QObject *obj) { slotDestroyed(obj); }); connect(view, &QAbstractItemView::doubleClicked, q, [this](const QModelIndex &index) { slotDoubleClicked(index); }); connect(view, &QAbstractItemView::activated, q, [this](const QModelIndex &index) { slotActivated(index); }); connect(view->selectionModel(), &QItemSelectionModel::selectionChanged, q, [this](const QItemSelection &oldSel, const QItemSelection &newSel) { slotSelectionChanged(oldSel, newSel); + Q_EMIT q->selectionChanged(); }); view->setContextMenuPolicy(Qt::CustomContextMenu); connect(view, &QWidget::customContextMenuRequested, q, [this](const QPoint &pos) { slotContextMenu(pos); }); } void KeyListController::Private::connectCommand(Command *cmd) { if (!cmd) { return; } connect(cmd, &QObject::destroyed, q, [this](QObject *obj) { slotDestroyed(obj); }); connect(cmd, &Command::finished, q, [this] { slotCommandFinished(); }); // connect( cmd, SIGNAL(canceled()), q, SLOT(slotCommandCanceled()) ); connect(cmd, &Command::progress, q, &KeyListController::progress); } void KeyListController::Private::slotDoubleClicked(const QModelIndex &idx) { QAbstractItemView *const view = qobject_cast<QAbstractItemView *>(q->sender()); if (!view || !ranges::binary_search(views, view)) { return; } if (const auto *const keyListModel = dynamic_cast<KeyListModelInterface *>(view->model())) { DetailsCommand *const c = new DetailsCommand{keyListModel->key(idx)}; c->setParentWidget(parentWidget ? parentWidget : view); c->start(); } } void KeyListController::Private::slotActivated(const QModelIndex &idx) { Q_UNUSED(idx) QAbstractItemView *const view = qobject_cast<QAbstractItemView *>(q->sender()); if (!view || !ranges::binary_search(views, view)) { return; } } void KeyListController::Private::slotSelectionChanged(const QItemSelection &old, const QItemSelection &new_) { Q_UNUSED(old) Q_UNUSED(new_) const QItemSelectionModel *const sm = qobject_cast<QItemSelectionModel *>(q->sender()); if (!sm) { return; } q->enableDisableActions(sm); } void KeyListController::Private::slotContextMenu(const QPoint &p) { QAbstractItemView *const view = qobject_cast<QAbstractItemView *>(q->sender()); if (view && ranges::binary_search(views, view)) { Q_EMIT q->contextMenuRequested(view, view->viewport()->mapToGlobal(p)); } else { qCDebug(KLEOPATRA_LOG) << "sender is not a QAbstractItemView*!"; } } void KeyListController::Private::slotCommandFinished() { Command *const cmd = qobject_cast<Command *>(q->sender()); if (!cmd || !ranges::binary_search(commands, cmd)) { return; } qCDebug(KLEOPATRA_LOG) << (void *)cmd; if (commands.size() == 1) { Q_EMIT q->commandsExecuting(false); } } void KeyListController::enableDisableActions(const QItemSelectionModel *sm) const { const Command::Restrictions restrictionsMask = d->calculateRestrictionsMask(sm); for (const Private::action_item &ai : std::as_const(d->actions)) if (ai.action) { ai.action->setEnabled(ai.restrictions == (ai.restrictions & restrictionsMask)); } } static bool all_secret_are_not_owner_trust_ultimate(const std::vector<Key> &keys) { for (const Key &key : keys) if (key.hasSecret() && key.ownerTrust() == Key::Ultimate) { return false; } return true; } Command::Restrictions find_root_restrictions(const std::vector<Key> &keys) { bool trusted = false, untrusted = false; for (const Key &key : keys) if (key.isRoot()) if (key.userID(0).validity() == UserID::Ultimate) { trusted = true; } else { untrusted = true; } else { return Command::NoRestriction; } if (trusted) if (untrusted) { return Command::NoRestriction; } else { return Command::MustBeTrustedRoot; } else if (untrusted) { return Command::MustBeUntrustedRoot; } else { return Command::NoRestriction; } } static bool secretSubkeyDataAvailable(const Subkey &subkey) { return subkey.isSecret() && !subkey.isCardKey(); } Command::Restrictions KeyListController::Private::calculateRestrictionsMask(const QItemSelectionModel *sm) { if (!sm) { return Command::NoRestriction; } const KeyListModelInterface *const m = dynamic_cast<const KeyListModelInterface *>(sm->model()); if (!m) { return Command::NoRestriction; } const std::vector<Key> keys = m->keys(sm->selectedRows()); if (keys.empty()) { return Command::NoRestriction; } Command::Restrictions result = Command::NeedSelection; if (keys.size() == 1) { result |= Command::OnlyOneKey; } // we need to check the primary subkey because Key::hasSecret() is also true if just the secret key stub of an offline key is available const auto primaryKeyCanBeUsedForSecretKeyOperations = [](const auto &k) { return k.subkey(0).isSecret(); }; if (ranges::all_of(keys, primaryKeyCanBeUsedForSecretKeyOperations)) { result |= Command::NeedSecretKey; } if (ranges::all_of(keys, [](const auto &k) { return ranges::any_of(k.subkeys(), &secretSubkeyDataAvailable); })) { result |= Command::NeedSecretSubkeyData; } if ((result & Command::NeedSecretSubkeyData) && ranges::all_of(keys, [](const auto &k) { return secretSubkeyDataAvailable(k.subkey(0)); })) { result |= Command::NeedSecretPrimaryKeyData; } if (ranges::all_of(keys, [](const Key &key) { return key.protocol() == OpenPGP; })) { result |= Command::MustBeOpenPGP; } else if (ranges::all_of(keys, [](const Key &key) { return key.protocol() == CMS; })) { result |= Command::MustBeCMS; } if (ranges::all_of(keys, [](const auto &key) { return !key.isBad(); })) { result |= Command::MustBeValid; } if (all_secret_are_not_owner_trust_ultimate(keys)) { result |= Command::MayOnlyBeSecretKeyIfOwnerTrustIsNotYetUltimate; } result |= find_root_restrictions(keys); if (const ReaderStatus *rs = ReaderStatus::instance()) { if (!rs->firstCardWithNullPin().empty()) { result |= Command::AnyCardHasNullPin; } } { if (keys.size() > 0) { bool hasSignCertify = false; bool hasEncrypt = false; bool hasAuthenticate = false; bool invalid = false; for (const auto &subkey : keys[0].subkeys()) { if (subkey.isCardKey()) { invalid = true; break; } if (subkey.canCertify() && subkey.canSign()) { if (hasSignCertify) { invalid = true; break; } else { hasSignCertify = true; } } else if (subkey.canEncrypt()) { if (hasEncrypt) { invalid = true; break; } else { hasEncrypt = true; } } else if (subkey.canAuthenticate()) { if (hasAuthenticate) { invalid = true; break; } else { hasAuthenticate = true; } } else if (!subkey.canRenc()) { // we don't mind ADSKs invalid = true; break; } } if (hasSignCertify && hasEncrypt && !invalid) { result |= Command::SuitableForCard; } } } return result; } void KeyListController::Private::slotActionTriggered(QAction *sender) { const auto it = ranges::find_if(actions, [sender](const action_item &item) { return item.action == sender; }); if (it != actions.end()) if (Command *const c = it->createCommand(this->currentView, q)) { if (parentWidget) { c->setParentWidget(parentWidget); } c->start(); } else qCDebug(KLEOPATRA_LOG) << "createCommand() == NULL for action(?) \"" << qPrintable(sender->objectName()) << "\""; else { qCDebug(KLEOPATRA_LOG) << "I don't know anything about action(?) \"%s\"", qPrintable(sender->objectName()); } } int KeyListController::Private::toolTipOptions() const { 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; } void KeyListController::updateConfig() { const int opts = d->toolTipOptions(); if (d->flatModel) { d->flatModel->setToolTipOptions(opts); } if (d->hierarchicalModel) { d->hierarchicalModel->setToolTipOptions(opts); } } +void KeyListController::Private::updateActions(KActionCollection *collection) +{ + auto key = q->currentView()->selectionModel()->currentIndex().data(KeyList::KeyRole).value<GpgME::Key>(); + if (key.isInvalid()) { + return; + } + auto action = collection->action(QStringLiteral("certificates_disable")); + action->setText(key.isDisabled() ? i18nc("@action:inmenu", "Enable Certificate") : i18nc("@action:inmenu", "Disable Certificate")); +} + #include "moc_keylistcontroller.cpp" diff --git a/src/view/keylistcontroller.h b/src/view/keylistcontroller.h index 7f44e63ba..dffe86c12 100644 --- a/src/view/keylistcontroller.h +++ b/src/view/keylistcontroller.h @@ -1,98 +1,100 @@ /* -*- mode: c++; c-basic-offset:4 -*- view/keylistcontroller.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once +#include <QItemSelection> #include <QObject> #include <commands/command.h> #include <memory> #include <vector> class QAbstractItemView; class QAction; class QPoint; class QItemSelectionModel; class KActionCollection; namespace Kleo { class AbstractKeyListModel; class Command; class TabWidget; class KeyListController : public QObject { Q_OBJECT public: explicit KeyListController(QObject *parent = nullptr); ~KeyListController() override; std::vector<QAbstractItemView *> views() const; void setFlatModel(AbstractKeyListModel *model); AbstractKeyListModel *flatModel() const; void setHierarchicalModel(AbstractKeyListModel *model); AbstractKeyListModel *hierarchicalModel() const; void setParentWidget(QWidget *parent); QWidget *parentWidget() const; QAbstractItemView *currentView() const; void setTabWidget(TabWidget *tabs); TabWidget *tabWidget() const; void registerCommand(Command *cmd); void createActions(KActionCollection *collection); template<typename T_Command> void registerActionForCommand(QAction *action) { this->registerAction(action, T_Command::restrictions(), &KeyListController::template create<T_Command>); } void enableDisableActions(const QItemSelectionModel *sm) const; bool hasRunningCommands() const; bool shutdownWarningRequired() const; private: void registerAction(QAction *action, Command::Restrictions restrictions, Command *(*create)(QAbstractItemView *, KeyListController *)); template<typename T_Command> static Command *create(QAbstractItemView *v, KeyListController *c) { return new T_Command(v, c); } public Q_SLOTS: void addView(QAbstractItemView *view); void removeView(QAbstractItemView *view); void setCurrentView(QAbstractItemView *view); void cancelCommands(); void updateConfig(); Q_SIGNALS: void progress(int current, int total); void commandsExecuting(bool); void contextMenuRequested(QAbstractItemView *view, const QPoint &p); + void selectionChanged(); private: class Private; const std::unique_ptr<Private> d; }; }