diff --git a/src/commands/authenticatepivcardapplicationcommand.cpp b/src/commands/authenticatepivcardapplicationcommand.cpp index 4fcb5283a..1eee2c14b 100644 --- a/src/commands/authenticatepivcardapplicationcommand.cpp +++ b/src/commands/authenticatepivcardapplicationcommand.cpp @@ -1,192 +1,192 @@ /* commands/authenticatepivcardapplicationcommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include "authenticatepivcardapplicationcommand.h" #include "cardcommand_p.h" #include "smartcard/pivcard.h" #include "smartcard/readerstatus.h" #include "dialogs/pivcardapplicationadministrationkeyinputdialog.h" #include #include #include #if GPG_ERROR_VERSION_NUMBER >= 0x12400 // 1.36 # define GPG_ERROR_HAS_BAD_AUTH #endif #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Dialogs; using namespace Kleo::SmartCard; using namespace GpgME; class AuthenticatePIVCardApplicationCommand::Private : public CardCommand::Private { friend class ::Kleo::Commands::AuthenticatePIVCardApplicationCommand; AuthenticatePIVCardApplicationCommand *q_func() const { return static_cast(q); } public: explicit Private(AuthenticatePIVCardApplicationCommand *qq, const std::string &serialNumber, QWidget *p); ~Private() override; void init(); private: void slotResult(const Error &err); void slotDialogAccepted(); void slotDialogRejected(); private: void authenticate(const QByteArray& adminKey); void retryAskingForKey(); void ensureDialogCreated(); private: QString prompt; QPointer dialog; }; AuthenticatePIVCardApplicationCommand::Private *AuthenticatePIVCardApplicationCommand::d_func() { return static_cast(d.get()); } const AuthenticatePIVCardApplicationCommand::Private *AuthenticatePIVCardApplicationCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() AuthenticatePIVCardApplicationCommand::Private::Private(AuthenticatePIVCardApplicationCommand *qq, const std::string &serialNumber, QWidget *p) : CardCommand::Private(qq, serialNumber, p) , dialog() { } AuthenticatePIVCardApplicationCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG) << "AuthenticatePIVCardApplicationCommand::Private::~Private()"; } AuthenticatePIVCardApplicationCommand::AuthenticatePIVCardApplicationCommand(const std::string &serialNumber, QWidget *p) : CardCommand(new Private(this, serialNumber, p)) { d->init(); } void AuthenticatePIVCardApplicationCommand::Private::init() { } AuthenticatePIVCardApplicationCommand::~AuthenticatePIVCardApplicationCommand() { qCDebug(KLEOPATRA_LOG) << "AuthenticatePIVCardApplicationCommand::~AuthenticatePIVCardApplicationCommand()"; } void AuthenticatePIVCardApplicationCommand::setPrompt(const QString& prompt) { d->prompt = prompt; } void AuthenticatePIVCardApplicationCommand::doStart() { qCDebug(KLEOPATRA_LOG) << "AuthenticatePIVCardApplicationCommand::doStart()"; // at first, try to authenticate using the default application administration key d->authenticate(QByteArray::fromHex("010203040506070801020304050607080102030405060708")); } void AuthenticatePIVCardApplicationCommand::doCancel() { } void AuthenticatePIVCardApplicationCommand::Private::authenticate(const QByteArray& adminKey) { qCDebug(KLEOPATRA_LOG) << "AuthenticatePIVCardApplicationCommand::authenticate()"; const auto pivCard = SmartCard::ReaderStatus::instance()->getCard(serialNumber()); if (!pivCard) { error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(serialNumber()))); finished(); return; } const QByteArray plusPercentEncodedAdminKey = adminKey.toPercentEncoding().replace(' ', '+'); const QByteArray command = QByteArray("SCD SETATTR AUTH-ADM-KEY ") + plusPercentEncodedAdminKey; ReaderStatus::mutableInstance()->startSimpleTransaction(pivCard, command, q, "slotResult"); } void AuthenticatePIVCardApplicationCommand::Private::slotResult(const Error &err) { qCDebug(KLEOPATRA_LOG) << "AuthenticatePIVCardApplicationCommand::slotResult():" << err.asString() << "(" << err.code() << ")"; if (err.isCanceled()) { canceled(); return; } if (err) { #ifdef GPG_ERROR_HAS_BAD_AUTH if (err.code() == GPG_ERR_BAD_AUTH) { retryAskingForKey(); return; } #endif error(i18nc("@info", "Authenticating to the card failed: %1", QString::fromLatin1(err.asString())), i18nc("@title", "Error")); } finished(); } void AuthenticatePIVCardApplicationCommand::Private::retryAskingForKey() { ensureDialogCreated(); Q_ASSERT(dialog); dialog->show(); } void AuthenticatePIVCardApplicationCommand::Private::ensureDialogCreated() { if (dialog) { return; } dialog = new PIVCardApplicationAdministrationKeyInputDialog(parentWidgetOrView()); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setLabelText(prompt.isEmpty() ? i18n("Please enter the PIV Card Application Administration Key in hex-encoded form.") : prompt); - connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted())); - connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); + connect(dialog, &QDialog::accepted, q, [this]() { slotDialogAccepted(); }); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); } void AuthenticatePIVCardApplicationCommand::Private::slotDialogAccepted() { authenticate(dialog->adminKey()); } void AuthenticatePIVCardApplicationCommand::Private::slotDialogRejected() { canceled(); } #undef d #undef q #include "moc_authenticatepivcardapplicationcommand.cpp" diff --git a/src/commands/authenticatepivcardapplicationcommand.h b/src/commands/authenticatepivcardapplicationcommand.h index 9c184c375..b3ad02c1a 100644 --- a/src/commands/authenticatepivcardapplicationcommand.h +++ b/src/commands/authenticatepivcardapplicationcommand.h @@ -1,47 +1,45 @@ /* commands/authenticatepivcardapplicationcommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "cardcommand.h" namespace GpgME { class Error; } namespace Kleo { namespace Commands { class AuthenticatePIVCardApplicationCommand : public CardCommand { Q_OBJECT public: explicit AuthenticatePIVCardApplicationCommand(const std::string &serialNumber, QWidget *parent); ~AuthenticatePIVCardApplicationCommand() override; void setPrompt(const QString& prompt); private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error)) }; } // namespace Commands } // namespace Kleo diff --git a/src/commands/certifycertificatecommand.cpp b/src/commands/certifycertificatecommand.cpp index 427e06673..d9d4150da 100644 --- a/src/commands/certifycertificatecommand.cpp +++ b/src/commands/certifycertificatecommand.cpp @@ -1,318 +1,317 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/signcertificatecommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-FileCopyrightText: 2019 g10code GmbH SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "certifycertificatecommand.h" #include "newcertificatecommand.h" #include "command_p.h" #include "exportopenpgpcertstoservercommand.h" #include "dialogs/certifycertificatedialog.h" #include "utils/tags.h" #include #include #include #include #include #include #include #include #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::Commands; using namespace GpgME; using namespace QGpgME; class CertifyCertificateCommand::Private : public Command::Private { friend class ::Kleo::Commands::CertifyCertificateCommand; CertifyCertificateCommand *q_func() const { return static_cast(q); } public: explicit Private(CertifyCertificateCommand *qq, KeyListController *c); ~Private() override; void init(); private: void slotDialogRejected(); void slotResult(const Error &err); void slotCertificationPrepared(); private: void ensureDialogCreated(); void createJob(); private: std::vector uids; QPointer dialog; QPointer job; }; CertifyCertificateCommand::Private *CertifyCertificateCommand::d_func() { return static_cast(d.get()); } const CertifyCertificateCommand::Private *CertifyCertificateCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() CertifyCertificateCommand::Private::Private(CertifyCertificateCommand *qq, KeyListController *c) : Command::Private(qq, c), uids(), dialog(), job() { } CertifyCertificateCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG); if (dialog) { delete dialog; dialog = nullptr; } } CertifyCertificateCommand::CertifyCertificateCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } CertifyCertificateCommand::CertifyCertificateCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } CertifyCertificateCommand::CertifyCertificateCommand(const GpgME::Key &key) : Command(key, new Private(this, nullptr)) { d->init(); } CertifyCertificateCommand::CertifyCertificateCommand(const GpgME::UserID &uid) : Command(uid.parent(), new Private(this, nullptr)) { std::vector(1, uid).swap(d->uids); d->init(); } CertifyCertificateCommand::CertifyCertificateCommand(const std::vector &uids) : Command(uids.empty() ? Key() : uids.front().parent(), new Private(this, nullptr)) { d->uids = uids; d->init(); } void CertifyCertificateCommand::Private::init() { } CertifyCertificateCommand::~CertifyCertificateCommand() { qCDebug(KLEOPATRA_LOG); } void CertifyCertificateCommand::doStart() { const std::vector keys = d->keys(); if (keys.size() != 1 || keys.front().protocol() != GpgME::OpenPGP) { d->finished(); return; } std::vector secKeys; Q_FOREACH (const Key &secKey, KeyCache::instance()->secretKeys()) { // Only include usable keys. if (secKey.canCertify() && secKey.protocol() == OpenPGP && !secKey.isRevoked() && !secKey.isExpired() && !secKey.isInvalid()) { secKeys.push_back(secKey); } } if (secKeys.empty()) { auto sel = KMessageBox::questionYesNo(d->parentWidgetOrView(), xi18nc("@info", "To certify other certificates, you first need to create an OpenPGP certificate for yourself.") + QStringLiteral("

") + i18n("Do you wish to create one now?"), i18n("Certification Not Possible")); if (sel == KMessageBox::Yes) { QEventLoop loop; auto cmd = new Commands::NewCertificateCommand(); cmd->setParentWidget(d->parentWidgetOrView()); cmd->setProtocol(GpgME::OpenPGP); - loop.connect(cmd, SIGNAL(finished()), SLOT(quit())); + connect(cmd, &Command::finished, &loop, &QEventLoop::quit); QMetaObject::invokeMethod(cmd, &Commands::NewCertificateCommand::start, Qt::QueuedConnection); loop.exec(); } else { Q_EMIT(canceled()); d->finished(); return; } Q_FOREACH (const Key &secKey, KeyCache::instance()->secretKeys()) { // Check again for secret keys if (secKey.canCertify() && secKey.protocol() == OpenPGP && !secKey.isRevoked() && !secKey.isExpired() && !secKey.isInvalid()) { secKeys.push_back(secKey); } } if (secKeys.empty()) { qCDebug(KLEOPATRA_LOG) << "Sec Keys still empty after keygen."; Q_EMIT(canceled()); d->finished(); return; } } const Key &key = keys.front(); for (const UserID &uid : std::as_const(d->uids)) if (qstricmp(uid.parent().primaryFingerprint(), key.primaryFingerprint()) != 0) { qCWarning(KLEOPATRA_LOG) << "User ID <-> Key mismatch!"; d->finished(); return; } d->ensureDialogCreated(); Q_ASSERT(d->dialog); Key target = d->key(); if (!(target.keyListMode() & GpgME::SignatureNotations)) { target.update(); } d->dialog->setCertificateToCertify(target); if (d->uids.size()) { d->dialog->setSelectedUserIDs(d->uids); } d->dialog->show(); } void CertifyCertificateCommand::Private::slotDialogRejected() { Q_EMIT q->canceled(); finished(); } void CertifyCertificateCommand::Private::slotResult(const Error &err) { if (!err && !err.isCanceled() && dialog && dialog->exportableCertificationSelected() && dialog->sendToServer()) { auto const cmd = new ExportOpenPGPCertsToServerCommand(key()); cmd->start(); } else if (!err) { information(i18n("Certification successful."), i18n("Certification Succeeded")); } else { error(i18n("

An error occurred while trying to certify

" "%1:

\t%2

", Formatting::formatForComboBox(key()), QString::fromUtf8(err.asString())), i18n("Certification Error")); } if (!dialog->tags().isEmpty()) { Tags::enableTags(); } finished(); } void CertifyCertificateCommand::Private::slotCertificationPrepared() { Q_ASSERT(dialog); createJob(); Q_ASSERT(job); job->setExportable(dialog->exportableCertificationSelected()); job->setNonRevocable(dialog->nonRevocableCertificationSelected()); job->setUserIDsToSign(dialog->selectedUserIDs()); job->setSigningKey(dialog->selectedSecretKey()); job->setCheckLevel(dialog->selectedCheckLevel()); if (!dialog->tags().isEmpty()) { // do not set an empty remark to avoid an empty signature notation (GnuPG bug T5142) job->setRemark(dialog->tags()); } job->setDupeOk(true); if (dialog->trustSignatureSelected() && !dialog->trustSignatureDomain().isEmpty()) { // always create level 1 trust signatures with complete trust job->setTrustSignature(TrustSignatureTrust::Complete, 1, dialog->trustSignatureDomain()); } if (!dialog->expirationDate().isNull()) { job->setExpirationDate(dialog->expirationDate()); } if (const Error err = job->start(key())) { slotResult(err); } } void CertifyCertificateCommand::doCancel() { qCDebug(KLEOPATRA_LOG); if (d->job) { d->job->slotCancel(); } } void CertifyCertificateCommand::Private::ensureDialogCreated() { if (dialog) { return; } dialog = new CertifyCertificateDialog; applyWindowID(dialog); - connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); - connect(dialog, SIGNAL(accepted()), q, SLOT(slotCertificationPrepared())); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); + connect(dialog, &QDialog::accepted, q, [this]() { slotCertificationPrepared(); }); } void CertifyCertificateCommand::Private::createJob() { Q_ASSERT(!job); Q_ASSERT(key().protocol() == OpenPGP); const auto backend = QGpgME::openpgp(); if (!backend) { return; } SignKeyJob *const j = backend->signKeyJob(); if (!j) { return; } connect(j, &Job::progress, q, &Command::progress); - connect(j, SIGNAL(result(GpgME::Error)), - q, SLOT(slotResult(GpgME::Error))); + connect(j, &SignKeyJob::result, q, [this](const GpgME::Error &result) { slotResult(result); }); job = j; } #undef d #undef q #include "moc_certifycertificatecommand.cpp" diff --git a/src/commands/certifycertificatecommand.h b/src/commands/certifycertificatecommand.h index 6a0f0a98f..a41670ba0 100644 --- a/src/commands/certifycertificatecommand.h +++ b/src/commands/certifycertificatecommand.h @@ -1,55 +1,52 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/signcertificatecommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include namespace GpgME { class UserID; } namespace Kleo { namespace Commands { class CertifyCertificateCommand : public Command { Q_OBJECT public: explicit CertifyCertificateCommand(QAbstractItemView *view, KeyListController *parent); explicit CertifyCertificateCommand(KeyListController *parent); explicit CertifyCertificateCommand(const GpgME::Key &key); explicit CertifyCertificateCommand(const GpgME::UserID &uid); explicit CertifyCertificateCommand(const std::vector &uids); ~CertifyCertificateCommand() override; /* reimp */ static Restrictions restrictions() { return OnlyOneKey | MustBeOpenPGP; } private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error)) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) - Q_PRIVATE_SLOT(d_func(), void slotCertificationPrepared()) }; } } diff --git a/src/commands/changeexpirycommand.cpp b/src/commands/changeexpirycommand.cpp index ebcddacff..fb0b8a2f9 100644 --- a/src/commands/changeexpirycommand.cpp +++ b/src/commands/changeexpirycommand.cpp @@ -1,287 +1,287 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/changeexpirycommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-FileCopyrightText: 2021 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "changeexpirycommand.h" #include "command_p.h" #include "dialogs/expirydialog.h" #include #include #include #include #include #include #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Dialogs; using namespace GpgME; using namespace QGpgME; namespace { #ifdef QGPGME_SUPPORTS_CHANGING_EXPIRATION_OF_COMPLETE_KEY bool allNotRevokedSubkeysHaveSameExpirationAsPrimaryKey(const Key &key) { Q_ASSERT(!key.isNull() && key.numSubkeys() > 0); const auto subkeys = key.subkeys(); const auto primaryKey = subkeys[0]; if (primaryKey.neverExpires()) { return std::all_of(std::begin(subkeys), std::end(subkeys), [] (const auto &subkey) { // revoked subkeys are ignored by gpg --quick-set-expire when updating the expiration of all subkeys return subkey.isRevoked() || subkey.neverExpires(); }); } const auto primaryExpiration = primaryKey.expirationTime(); return std::all_of(std::begin(subkeys), std::end(subkeys), [primaryExpiration] (const auto &subkey) { // revoked subkeys are ignored by gpg --quick-set-expire when updating the expiration of all subkeys; // check if expiration of subkey is (more or less) the same as the expiration of the primary key return subkey.isRevoked() || (primaryExpiration - 10 <= subkey.expirationTime() && subkey.expirationTime() <= primaryExpiration + 10); }); } #endif } class ChangeExpiryCommand::Private : public Command::Private { friend class ::Kleo::Commands::ChangeExpiryCommand; ChangeExpiryCommand *q_func() const { return static_cast(q); } public: explicit Private(ChangeExpiryCommand *qq, KeyListController *c); ~Private() override; private: void slotDialogAccepted(); void slotDialogRejected(); void slotResult(const Error &err); private: void ensureDialogCreated(ExpiryDialog::Mode mode); void createJob(); void showErrorDialog(const Error &error); void showSuccessDialog(); private: GpgME::Key key; GpgME::Subkey subkey; QPointer dialog; QPointer job; }; ChangeExpiryCommand::Private *ChangeExpiryCommand::d_func() { return static_cast(d.get()); } const ChangeExpiryCommand::Private *ChangeExpiryCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() ChangeExpiryCommand::Private::Private(ChangeExpiryCommand *qq, KeyListController *c) : Command::Private{qq, c} { } ChangeExpiryCommand::Private::~Private() = default; void ChangeExpiryCommand::Private::slotDialogAccepted() { Q_ASSERT(dialog); static const QTime END_OF_DAY{23, 59, 59}; const QDateTime expiry{dialog->dateOfExpiry(), END_OF_DAY}; qCDebug(KLEOPATRA_LOG) << "expiry" << expiry; createJob(); Q_ASSERT(job); #ifdef QGPGME_SUPPORTS_CHANGING_EXPIRATION_OF_COMPLETE_KEY if (subkey.isNull() && dialog->updateExpirationOfAllSubkeys()) { job->setOptions(ChangeExpiryJob::UpdateAllSubkeys); } #endif std::vector subkeys; if (!subkey.isNull() && subkey.keyID() != key.keyID()) { // ignore the primary subkey subkeys.push_back(subkey); } if (const Error err = job->start(key, expiry, subkeys)) { showErrorDialog(err); finished(); } } void ChangeExpiryCommand::Private::slotDialogRejected() { Q_EMIT q->canceled(); finished(); } void ChangeExpiryCommand::Private::slotResult(const Error &err) { if (err.isCanceled()) ; else if (err) { showErrorDialog(err); } else { showSuccessDialog(); } finished(); } void ChangeExpiryCommand::Private::ensureDialogCreated(ExpiryDialog::Mode mode) { if (dialog) { return; } dialog = new ExpiryDialog{mode}; applyWindowID(dialog); dialog->setAttribute(Qt::WA_DeleteOnClose); - connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted())); - connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); + connect(dialog, &QDialog::accepted, q, [this]() { slotDialogAccepted(); }); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); } void ChangeExpiryCommand::Private::createJob() { Q_ASSERT(!job); const auto backend = (key.protocol() == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime(); if (!backend) { return; } ChangeExpiryJob *const j = backend->changeExpiryJob(); if (!j) { return; } connect(j, &Job::progress, q, &Command::progress); connect(j, &ChangeExpiryJob::result, q, [this] (const auto &err) { slotResult(err); }); job = j; } void ChangeExpiryCommand::Private::showErrorDialog(const Error &err) { error(i18n("

An error occurred while trying to change " "the expiry date for %1:

%2

", Formatting::formatForComboBox(key), QString::fromLocal8Bit(err.asString())), i18n("Expiry Date Change Error")); } void ChangeExpiryCommand::Private::showSuccessDialog() { information(i18n("Expiry date changed successfully."), i18n("Expiry Date Change Succeeded")); } ChangeExpiryCommand::ChangeExpiryCommand(KeyListController *c) : Command{new Private{this, c}} { } ChangeExpiryCommand::ChangeExpiryCommand(QAbstractItemView *v, KeyListController *c) : Command{v, new Private{this, c}} { } ChangeExpiryCommand::ChangeExpiryCommand(const GpgME::Key &key) : Command{key, new Private{this, nullptr}} { } ChangeExpiryCommand::~ChangeExpiryCommand() = default; void ChangeExpiryCommand::setSubkey(const GpgME::Subkey &subkey) { d->subkey = subkey; } void ChangeExpiryCommand::doStart() { const std::vector keys = d->keys(); if (keys.size() != 1 || keys.front().protocol() != GpgME::OpenPGP || !keys.front().hasSecret() || keys.front().subkey(0).isNull()) { d->finished(); return; } d->key = keys.front(); if (!d->subkey.isNull() && d->subkey.parent().primaryFingerprint() != d->key.primaryFingerprint()) { qDebug() << "Invalid subkey" << d->subkey.fingerprint() << ": Not a subkey of key" << d->key.primaryFingerprint(); d->finished(); return; } ExpiryDialog::Mode mode; if (!d->subkey.isNull()) { mode = ExpiryDialog::Mode::UpdateIndividualSubkey; } else if (d->key.numSubkeys() == 1) { mode = ExpiryDialog::Mode::UpdateCertificateWithoutSubkeys; } else { mode = ExpiryDialog::Mode::UpdateCertificateWithSubkeys; } d->ensureDialogCreated(mode); Q_ASSERT(d->dialog); const Subkey subkey = !d->subkey.isNull() ? d->subkey : d->key.subkey(0); d->dialog->setDateOfExpiry(subkey.neverExpires() ? QDate() : QDateTime::fromSecsSinceEpoch(subkey.expirationTime()).date()); #ifdef QGPGME_SUPPORTS_CHANGING_EXPIRATION_OF_COMPLETE_KEY if (mode == ExpiryDialog::Mode::UpdateCertificateWithSubkeys) { d->dialog->setUpdateExpirationOfAllSubkeys(allNotRevokedSubkeysHaveSameExpirationAsPrimaryKey(d->key)); } #endif d->dialog->show(); } void ChangeExpiryCommand::doCancel() { if (d->job) { d->job->slotCancel(); } } #undef d #undef q #include "moc_changeexpirycommand.cpp" diff --git a/src/commands/changeexpirycommand.h b/src/commands/changeexpirycommand.h index a716c2c29..61283ea1d 100644 --- a/src/commands/changeexpirycommand.h +++ b/src/commands/changeexpirycommand.h @@ -1,55 +1,52 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/changeexpirycommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include namespace GpgME { class Subkey; } namespace Kleo { namespace Commands { class ChangeExpiryCommand : public Command { Q_OBJECT public: explicit ChangeExpiryCommand(QAbstractItemView *view, KeyListController *parent); explicit ChangeExpiryCommand(KeyListController *parent); explicit ChangeExpiryCommand(const GpgME::Key &key); ~ChangeExpiryCommand() override; /* reimp */ static Restrictions restrictions() { return OnlyOneKey | MustBeOpenPGP | NeedSecretKey; } void setSubkey(const GpgME::Subkey &subkey); private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error)) - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) }; } } diff --git a/src/commands/changeownertrustcommand.cpp b/src/commands/changeownertrustcommand.cpp index 2617ef415..3ab189725 100644 --- a/src/commands/changeownertrustcommand.cpp +++ b/src/commands/changeownertrustcommand.cpp @@ -1,239 +1,238 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/changeownertrustcommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "changeownertrustcommand.h" #include "command_p.h" #include #include #include #include #include #include #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Dialogs; using namespace GpgME; using namespace QGpgME; class ChangeOwnerTrustCommand::Private : public Command::Private { friend class ::Kleo::Commands::ChangeOwnerTrustCommand; ChangeOwnerTrustCommand *q_func() const { return static_cast(q); } public: explicit Private(ChangeOwnerTrustCommand *qq, KeyListController *c); ~Private() override; void init(); private: void slotDialogAccepted(); void slotDialogRejected(); void slotResult(const Error &err); private: void ensureDialogCreated(); void createJob(); void showErrorDialog(const Error &error); void showSuccessDialog(); private: QPointer dialog; QPointer job; }; ChangeOwnerTrustCommand::Private *ChangeOwnerTrustCommand::d_func() { return static_cast(d.get()); } const ChangeOwnerTrustCommand::Private *ChangeOwnerTrustCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() ChangeOwnerTrustCommand::Private::Private(ChangeOwnerTrustCommand *qq, KeyListController *c) : Command::Private(qq, c), dialog(), job() { } ChangeOwnerTrustCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG); } ChangeOwnerTrustCommand::ChangeOwnerTrustCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } ChangeOwnerTrustCommand::ChangeOwnerTrustCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } ChangeOwnerTrustCommand::ChangeOwnerTrustCommand(const Key &key) : Command(key, new Private(this, nullptr)) { d->init(); } void ChangeOwnerTrustCommand::Private::init() { } ChangeOwnerTrustCommand::~ChangeOwnerTrustCommand() { qCDebug(KLEOPATRA_LOG); } void ChangeOwnerTrustCommand::doStart() { if (d->keys().size() != 1) { d->finished(); return; } const Key key = d->key(); if (key.protocol() != GpgME::OpenPGP || (key.hasSecret() && key.ownerTrust() == Key::Ultimate)) { d->finished(); return; } d->ensureDialogCreated(); Q_ASSERT(d->dialog); d->dialog->setHasSecretKey(key.hasSecret()); d->dialog->setFormattedCertificateName(Formatting::formatForComboBox(key)); d->dialog->setOwnerTrust(key.ownerTrust()); d->dialog->show(); } void ChangeOwnerTrustCommand::Private::slotDialogAccepted() { Q_ASSERT(dialog); const Key::OwnerTrust trust = dialog->ownerTrust(); qCDebug(KLEOPATRA_LOG) << "trust " << trust; createJob(); Q_ASSERT(job); if (const Error err = job->start(key(), trust)) { showErrorDialog(err); finished(); } } void ChangeOwnerTrustCommand::Private::slotDialogRejected() { Q_EMIT q->canceled(); finished(); } void ChangeOwnerTrustCommand::Private::slotResult(const Error &err) { if (err.isCanceled()) ; else if (err) { showErrorDialog(err); } else { showSuccessDialog(); } finished(); } void ChangeOwnerTrustCommand::doCancel() { qCDebug(KLEOPATRA_LOG); if (d->job) { d->job->slotCancel(); } } void ChangeOwnerTrustCommand::Private::ensureDialogCreated() { if (dialog) { return; } dialog = new OwnerTrustDialog; applyWindowID(dialog); dialog->setAttribute(Qt::WA_DeleteOnClose); - connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted())); - connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); + connect(dialog, &QDialog::accepted, q, [this]() { slotDialogAccepted(); }); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); } void ChangeOwnerTrustCommand::Private::createJob() { Q_ASSERT(!job); const auto backend = (key().protocol() == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime(); if (!backend) { return; } ChangeOwnerTrustJob *const j = backend->changeOwnerTrustJob(); if (!j) { return; } connect(j, &Job::progress, q, &Command::progress); - connect(j, SIGNAL(result(GpgME::Error)), - q, SLOT(slotResult(GpgME::Error))); + connect(j, &ChangeOwnerTrustJob::result, q, [this](const GpgME::Error &result) { slotResult(result); }); job = j; } void ChangeOwnerTrustCommand::Private::showErrorDialog(const Error &err) { error(i18n("

An error occurred while trying to change " "the certification trust for %1:

%2

", Formatting::formatForComboBox(key()), QString::fromLocal8Bit(err.asString())), i18n("Certification Trust Change Error")); } void ChangeOwnerTrustCommand::Private::showSuccessDialog() { information(i18n("Certification trust changed successfully."), i18n("Certification Trust Change Succeeded")); } #undef d #undef q #include "moc_changeownertrustcommand.cpp" diff --git a/src/commands/changeownertrustcommand.h b/src/commands/changeownertrustcommand.h index e5e05ff5f..927e6d516 100644 --- a/src/commands/changeownertrustcommand.h +++ b/src/commands/changeownertrustcommand.h @@ -1,48 +1,45 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/changeownertrustcommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include namespace Kleo { namespace Commands { class ChangeOwnerTrustCommand : public Command { Q_OBJECT public: explicit ChangeOwnerTrustCommand(QAbstractItemView *view, KeyListController *parent); explicit ChangeOwnerTrustCommand(KeyListController *parent); explicit ChangeOwnerTrustCommand(const GpgME::Key &key); ~ChangeOwnerTrustCommand() override; /* reimp */ static Restrictions restrictions() { return OnlyOneKey | MustBeOpenPGP | MayOnlyBeSecretKeyIfOwnerTrustIsNotYetUltimate; } private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error)) - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) }; } } diff --git a/src/commands/changepassphrasecommand.cpp b/src/commands/changepassphrasecommand.cpp index c5d0e01ae..3252b7a8b 100644 --- a/src/commands/changepassphrasecommand.cpp +++ b/src/commands/changepassphrasecommand.cpp @@ -1,202 +1,201 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/changepassphrasecommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "changepassphrasecommand.h" #include "command_p.h" #include #include #include #include #include #include "kleopatra_debug.h" #include using namespace Kleo; using namespace Kleo::Commands; using namespace GpgME; using namespace QGpgME; class ChangePassphraseCommand::Private : public Command::Private { friend class ::Kleo::Commands::ChangePassphraseCommand; ChangePassphraseCommand *q_func() const { return static_cast(q); } public: explicit Private(ChangePassphraseCommand *qq, KeyListController *c); ~Private() override; void init(); private: void slotResult(const Error &err); private: void createJob(); void startJob(); void showErrorDialog(const Error &error); void showSuccessDialog(); private: GpgME::Key key; QPointer job; }; ChangePassphraseCommand::Private *ChangePassphraseCommand::d_func() { return static_cast(d.get()); } const ChangePassphraseCommand::Private *ChangePassphraseCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() ChangePassphraseCommand::Private::Private(ChangePassphraseCommand *qq, KeyListController *c) : Command::Private(qq, c), key(), job() { } ChangePassphraseCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG); } ChangePassphraseCommand::ChangePassphraseCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } ChangePassphraseCommand::ChangePassphraseCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } ChangePassphraseCommand::ChangePassphraseCommand(const GpgME::Key &key) : Command(key, new Private(this, nullptr)) { d->init(); } void ChangePassphraseCommand::Private::init() { } ChangePassphraseCommand::~ChangePassphraseCommand() { qCDebug(KLEOPATRA_LOG); } void ChangePassphraseCommand::doStart() { const std::vector keys = d->keys(); if (keys.size() != 1 || !keys.front().hasSecret()) { d->finished(); return; } d->key = keys.front(); d->createJob(); d->startJob(); } void ChangePassphraseCommand::Private::startJob() { const Error err = job ? job->start(key) : Error::fromCode(GPG_ERR_NOT_SUPPORTED) ; if (err) { showErrorDialog(err); finished(); } } void ChangePassphraseCommand::Private::slotResult(const Error &err) { if (err.isCanceled()) ; else if (err) { showErrorDialog(err); } else { showSuccessDialog(); } finished(); } void ChangePassphraseCommand::doCancel() { qCDebug(KLEOPATRA_LOG); if (d->job) { d->job->slotCancel(); } } void ChangePassphraseCommand::Private::createJob() { Q_ASSERT(!job); const auto backend = (key.protocol() == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime(); if (!backend) { return; } ChangePasswdJob *const j = backend->changePasswdJob(); if (!j) { return; } connect(j, &Job::progress, q, &Command::progress); - connect(j, SIGNAL(result(GpgME::Error)), - q, SLOT(slotResult(GpgME::Error))); + connect(j, &ChangePasswdJob::result, q, [this](const GpgME::Error &result) { slotResult(result); }); job = j; } void ChangePassphraseCommand::Private::showErrorDialog(const Error &err) { error(i18n("

An error occurred while trying to change " "the passphrase for %1:

%2

", Formatting::formatForComboBox(key), QString::fromLocal8Bit(err.asString())), i18n("Passphrase Change Error")); } void ChangePassphraseCommand::Private::showSuccessDialog() { information(i18n("Passphrase changed successfully."), i18n("Passphrase Change Succeeded")); } #undef d #undef q #include "moc_changepassphrasecommand.cpp" diff --git a/src/commands/changepassphrasecommand.h b/src/commands/changepassphrasecommand.h index b4b79e9ee..ceb91675d 100644 --- a/src/commands/changepassphrasecommand.h +++ b/src/commands/changepassphrasecommand.h @@ -1,46 +1,45 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/changepassphrasecommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include namespace Kleo { namespace Commands { class ChangePassphraseCommand : public Command { Q_OBJECT public: explicit ChangePassphraseCommand(QAbstractItemView *view, KeyListController *parent); explicit ChangePassphraseCommand(KeyListController *parent); explicit ChangePassphraseCommand(const GpgME::Key &key); ~ChangePassphraseCommand() override; /* reimp */ static Restrictions restrictions() { return OnlyOneKey | NeedSecretKeyData; } private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error)) }; } } diff --git a/src/commands/changeroottrustcommand.cpp b/src/commands/changeroottrustcommand.cpp index fae96b2d3..96fa5764c 100644 --- a/src/commands/changeroottrustcommand.cpp +++ b/src/commands/changeroottrustcommand.cpp @@ -1,360 +1,360 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/changeroottrustcommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "changeroottrustcommand.h" #include "command_p.h" #include #include #include "kleopatra_debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Kleo; using namespace Kleo::Commands; using namespace GpgME; class ChangeRootTrustCommand::Private : public QThread, public Command::Private { Q_OBJECT private: friend class ::Kleo::Commands::ChangeRootTrustCommand; ChangeRootTrustCommand *q_func() const { return static_cast(q); } public: explicit Private(ChangeRootTrustCommand *qq, KeyListController *c) : QThread(), Command::Private(qq, c), mutex(), trust(Key::Ultimate), trustListFile(QDir(gnupgHomeDirectory()).absoluteFilePath(QStringLiteral("trustlist.txt"))), canceled(false) { } private: void init() { q->setWarnWhenRunningAtShutdown(false); - connect(this, SIGNAL(finished()), q_func(), SLOT(slotOperationFinished())); + connect(this, &QThread::finished, this, &ChangeRootTrustCommand::Private::slotOperationFinished); } void run() override; private: void slotOperationFinished() { KeyCache::mutableInstance()->enableFileSystemWatcher(true); if (error.isEmpty()) { KeyCache::mutableInstance()->reload(GpgME::CMS); } else Command::Private::error(i18n("Failed to update the trust database:\n" "%1", error), i18n("Root Trust Update Failed")); Command::Private::finished(); } private: mutable QMutex mutex; Key::OwnerTrust trust; QString trustListFile; QString gpgConfPath; QString error; volatile bool canceled; }; ChangeRootTrustCommand::Private *ChangeRootTrustCommand::d_func() { return static_cast(d.get()); } const ChangeRootTrustCommand::Private *ChangeRootTrustCommand::d_func() const { return static_cast(d.get()); } #define q q_func() #define d d_func() ChangeRootTrustCommand::ChangeRootTrustCommand(KeyListController *p) : Command(new Private(this, p)) { d->init(); } ChangeRootTrustCommand::ChangeRootTrustCommand(QAbstractItemView *v, KeyListController *p) : Command(v, new Private(this, p)) { d->init(); } ChangeRootTrustCommand::ChangeRootTrustCommand(const GpgME::Key &key, KeyListController *p) : Command(new Private(this, p)) { Q_ASSERT(!key.isNull()); d->init(); setKey(key); } ChangeRootTrustCommand::ChangeRootTrustCommand(const GpgME::Key &key, QAbstractItemView *v, KeyListController *p) : Command(v, new Private(this, p)) { Q_ASSERT(!key.isNull()); d->init(); setKey(key); } ChangeRootTrustCommand::~ChangeRootTrustCommand() {} void ChangeRootTrustCommand::setTrust(Key::OwnerTrust trust) { Q_ASSERT(!d->isRunning()); const QMutexLocker locker(&d->mutex); d->trust = trust; } Key::OwnerTrust ChangeRootTrustCommand::trust() const { const QMutexLocker locker(&d->mutex); return d->trust; } void ChangeRootTrustCommand::setTrustListFile(const QString &trustListFile) { Q_ASSERT(!d->isRunning()); const QMutexLocker locker(&d->mutex); d->trustListFile = trustListFile; } QString ChangeRootTrustCommand::trustListFile() const { const QMutexLocker locker(&d->mutex); return d->trustListFile; } void ChangeRootTrustCommand::doStart() { const std::vector keys = d->keys(); Key key; if (keys.size() == 1) { key = keys.front(); } else { qCWarning(KLEOPATRA_LOG) << "can only work with one certificate at a time"; } if (key.isNull()) { d->Command::Private::finished(); return; } d->gpgConfPath = gpgConfPath(); KeyCache::mutableInstance()->enableFileSystemWatcher(false); d->start(); } void ChangeRootTrustCommand::doCancel() { const QMutexLocker locker(&d->mutex); d->canceled = true; } static QString change_trust_file(const QString &trustListFile, const QString &key, Key::OwnerTrust trust); static QString run_gpgconf_reload_gpg_agent(const QString &gpgConfPath); void ChangeRootTrustCommand::Private::run() { QMutexLocker locker(&mutex); const QString key = QString::fromLatin1(keys().front().primaryFingerprint()); const Key::OwnerTrust trust = this->trust; const QString trustListFile = this->trustListFile; const QString gpgConfPath = this->gpgConfPath; locker.unlock(); QString err = change_trust_file(trustListFile, key, trust); if (err.isEmpty()) { err = run_gpgconf_reload_gpg_agent(gpgConfPath); } locker.relock(); this->error = err; } static QString add_colons(const QString &fpr) { QString result; result.reserve(fpr.size() / 2 * 3 + 1); bool needColon = false; for (QChar ch : fpr) { result += ch; if (needColon) { result += QLatin1Char(':'); } needColon = !needColon; } if (result.endsWith(QLatin1Char(':'))) { result.chop(1); } return result; } namespace { // fix stupid default-finalize behaviour... class KFixedSaveFile : public QSaveFile { public: explicit KFixedSaveFile(const QString &fileName) : QSaveFile(fileName) {} ~KFixedSaveFile() override { cancelWriting(); } }; } // static QString change_trust_file(const QString &trustListFile, const QString &key, Key::OwnerTrust trust) { QList trustListFileContents; { QFile in(trustListFile); if (in.exists()) { // non-existence is not fatal... if (in.open(QIODevice::ReadOnly)) { trustListFileContents = in.readAll().split('\n'); } else { // ...but failure to open an existing file _is_ return i18n("Cannot open existing file \"%1\" for reading: %2", trustListFile, in.errorString()); } } // close, so KSaveFile doesn't clobber the original } KFixedSaveFile out(trustListFile); if (!out.open(QIODevice::WriteOnly)) return i18n("Cannot open file \"%1\" for reading and writing: %2", out.fileName() /*sic!*/, out.errorString()); if (!out.setPermissions(QFile::ReadOwner | QFile::WriteOwner)) return i18n("Cannot set restrictive permissions on file %1: %2", out.fileName() /*sic!*/, out.errorString()); const QString keyColon = add_colons(key); qCDebug(KLEOPATRA_LOG) << qPrintable(key) << " -> " << qPrintable(keyColon); // ( 1) ( 2 ) ( 3 )( 4) QRegExp rx(QLatin1String("\\s*(!?)\\s*([a-fA-F0-9]{40}|(?:[a-fA-F0-9]{2}:){19}[a-fA-F0-9]{2})\\s*([SsPp*])(.*)")); bool found = false; for (const QByteArray &rawLine : std::as_const(trustListFileContents)) { const QString line = QString::fromLatin1(rawLine.data(), rawLine.size()); if (!rx.exactMatch(line)) { qCDebug(KLEOPATRA_LOG) << "line \"" << rawLine.data() << "\" does not match"; out.write(rawLine + '\n'); continue; } const QString cap2 = rx.cap(2); if (cap2 != key && cap2 != keyColon) { qCDebug(KLEOPATRA_LOG) << qPrintable(key) << " != " << qPrintable(cap2) << " != " << qPrintable(keyColon); out.write(rawLine + '\n'); continue; } found = true; const bool disabled = rx.cap(1) == QLatin1Char('!'); const QByteArray flags = rx.cap(3).toLatin1(); const QByteArray rests = rx.cap(4).toLatin1(); if (trust == Key::Ultimate) if (!disabled) { // unchanged out.write(rawLine + '\n'); } else { out.write(keyColon.toLatin1() + ' ' + flags + rests + '\n'); } else if (trust == Key::Never) { if (disabled) { // unchanged out.write(rawLine + '\n'); } else { out.write('!' + keyColon.toLatin1() + ' ' + flags + rests + '\n'); } } // else: trust == Key::Unknown // -> don't write - ie.erase } if (!found) { // add if (trust == Key::Ultimate) { out.write(keyColon.toLatin1() + ' ' + 'S' + '\n'); } else if (trust == Key::Never) { out.write('!' + keyColon.toLatin1() + ' ' + 'S' + '\n'); } } if (!out.commit()) return i18n("Failed to move file %1 to its final destination, %2: %3", out.fileName(), trustListFile, out.errorString()); return QString(); } // static QString run_gpgconf_reload_gpg_agent(const QString &gpgConfPath) { if (gpgConfPath.isEmpty()) { return i18n("Could not find gpgconf executable"); } QProcess p; p.start(gpgConfPath, QStringList() << QStringLiteral("--reload") << QStringLiteral("gpg-agent")); qCDebug(KLEOPATRA_LOG) << "starting " << qPrintable(gpgConfPath) << " --reload gpg-agent"; p.waitForFinished(-1); qCDebug(KLEOPATRA_LOG) << "done"; if (p.error() == QProcess::UnknownError) { return QString(); } else { return i18n("\"gpgconf --reload gpg-agent\" failed: %1", p.errorString()); } } #undef q_func #undef d_func #include "moc_changeroottrustcommand.cpp" #include "changeroottrustcommand.moc" diff --git a/src/commands/changeroottrustcommand.h b/src/commands/changeroottrustcommand.h index 1edba3429..190326750 100644 --- a/src/commands/changeroottrustcommand.h +++ b/src/commands/changeroottrustcommand.h @@ -1,117 +1,116 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/changeroottrustcommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include namespace Kleo { namespace Commands { class ChangeRootTrustCommand : public Command { Q_OBJECT public: explicit ChangeRootTrustCommand(KeyListController *parent); explicit ChangeRootTrustCommand(QAbstractItemView *view, KeyListController *parent); explicit ChangeRootTrustCommand(const GpgME::Key &key, KeyListController *parent); explicit ChangeRootTrustCommand(const GpgME::Key &key, QAbstractItemView *view, KeyListController *parent); ~ChangeRootTrustCommand() override; void setTrust(GpgME::Key::OwnerTrust trust); GpgME::Key::OwnerTrust trust() const; void setTrustListFile(const QString &file); QString trustListFile() const; /* reimp */ static Restrictions restrictions() { return OnlyOneKey | MustBeCMS | MustBeRoot; } private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotOperationFinished()) }; class TrustRootCommand : public ChangeRootTrustCommand { public: explicit TrustRootCommand(KeyListController *parent) : ChangeRootTrustCommand(parent) { setTrust(GpgME::Key::Ultimate); } explicit TrustRootCommand(QAbstractItemView *view, KeyListController *parent) : ChangeRootTrustCommand(view, parent) { setTrust(GpgME::Key::Ultimate); } explicit TrustRootCommand(const GpgME::Key &key, KeyListController *parent) : ChangeRootTrustCommand(key, parent) { setTrust(GpgME::Key::Ultimate); } explicit TrustRootCommand(const GpgME::Key &key, QAbstractItemView *view, KeyListController *parent) : ChangeRootTrustCommand(key, view, parent) { setTrust(GpgME::Key::Ultimate); } /* reimp */ static Restrictions restrictions() { return ChangeRootTrustCommand::restrictions() | MustBeUntrustedRoot; } }; class DistrustRootCommand : public ChangeRootTrustCommand { public: explicit DistrustRootCommand(KeyListController *parent) : ChangeRootTrustCommand(parent) { setTrust(GpgME::Key::Never); } explicit DistrustRootCommand(QAbstractItemView *view, KeyListController *parent) : ChangeRootTrustCommand(view, parent) { setTrust(GpgME::Key::Never); } explicit DistrustRootCommand(const GpgME::Key &key, KeyListController *parent) : ChangeRootTrustCommand(key, parent) { setTrust(GpgME::Key::Never); } explicit DistrustRootCommand(const GpgME::Key &key, QAbstractItemView *view, KeyListController *parent) : ChangeRootTrustCommand(key, view, parent) { setTrust(GpgME::Key::Never); } /* reimp */ static Restrictions restrictions() { return ChangeRootTrustCommand::restrictions() | MustBeTrustedRoot; } }; } } diff --git a/src/commands/checksumverifyfilescommand.cpp b/src/commands/checksumverifyfilescommand.cpp index d367762b3..77b8e04c1 100644 --- a/src/commands/checksumverifyfilescommand.cpp +++ b/src/commands/checksumverifyfilescommand.cpp @@ -1,170 +1,170 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/checksumverifyfilescommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "checksumverifyfilescommand.h" #include "command_p.h" #include #include #include #include #include "kleopatra_debug.h" #include using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Crypto; class ChecksumVerifyFilesCommand::Private : public Command::Private { friend class ::Kleo::Commands::ChecksumVerifyFilesCommand; ChecksumVerifyFilesCommand *q_func() const { return static_cast(q); } public: explicit Private(ChecksumVerifyFilesCommand *qq, KeyListController *c); ~Private() override; QStringList selectFiles() const; void init(); private: void slotControllerDone() { finished(); } void slotControllerError(int, const QString &) { finished(); } private: QStringList files; std::shared_ptr shared_qq; VerifyChecksumsController controller; }; ChecksumVerifyFilesCommand::Private *ChecksumVerifyFilesCommand::d_func() { return static_cast(d.get()); } const ChecksumVerifyFilesCommand::Private *ChecksumVerifyFilesCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() ChecksumVerifyFilesCommand::Private::Private(ChecksumVerifyFilesCommand *qq, KeyListController *c) : Command::Private(qq, c), files(), shared_qq(qq, [](ChecksumVerifyFilesCommand *){}), controller() { } ChecksumVerifyFilesCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG); } ChecksumVerifyFilesCommand::ChecksumVerifyFilesCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } ChecksumVerifyFilesCommand::ChecksumVerifyFilesCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } ChecksumVerifyFilesCommand::ChecksumVerifyFilesCommand(const QStringList &files, KeyListController *c) : Command(new Private(this, c)) { d->init(); d->files = files; } ChecksumVerifyFilesCommand::ChecksumVerifyFilesCommand(const QStringList &files, QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); d->files = files; } void ChecksumVerifyFilesCommand::Private::init() { controller.setExecutionContext(shared_qq); - connect(&controller, SIGNAL(done()), q, SLOT(slotControllerDone())); - connect(&controller, SIGNAL(error(int,QString)), q, SLOT(slotControllerError(int,QString))); + connect(&controller, &Controller::done, q, [this]() { slotControllerDone(); }); + connect(&controller, &Controller::error, q, [this](int err, const QString &details) { slotControllerError(err, details); }); } ChecksumVerifyFilesCommand::~ChecksumVerifyFilesCommand() { qCDebug(KLEOPATRA_LOG); } void ChecksumVerifyFilesCommand::setFiles(const QStringList &files) { d->files = files; } void ChecksumVerifyFilesCommand::doStart() { try { if (d->files.empty()) { d->files = d->selectFiles(); } if (d->files.empty()) { d->finished(); return; } d->controller.setFiles(d->files); d->controller.start(); } catch (const std::exception &e) { d->information(i18n("An error occurred: %1", QString::fromLocal8Bit(e.what())), i18n("Verify Checksum Files Error")); d->finished(); } } void ChecksumVerifyFilesCommand::doCancel() { qCDebug(KLEOPATRA_LOG); d->controller.cancel(); } QStringList ChecksumVerifyFilesCommand::Private::selectFiles() const { return FileDialog::getOpenFileNames(parentWidgetOrView(), i18n("Select One or More Checksum Files"), QStringLiteral("chk")); } #undef d #undef q #include "moc_checksumverifyfilescommand.cpp" diff --git a/src/commands/checksumverifyfilescommand.h b/src/commands/checksumverifyfilescommand.h index 0a82ada0a..a009fd73a 100644 --- a/src/commands/checksumverifyfilescommand.h +++ b/src/commands/checksumverifyfilescommand.h @@ -1,51 +1,49 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/checksumverifyfilescommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include #include #include namespace Kleo { namespace Commands { class ChecksumVerifyFilesCommand : public Command { Q_OBJECT public: explicit ChecksumVerifyFilesCommand(QAbstractItemView *view, KeyListController *parent); explicit ChecksumVerifyFilesCommand(KeyListController *parent); explicit ChecksumVerifyFilesCommand(const QStringList &files, QAbstractItemView *view, KeyListController *parent); explicit ChecksumVerifyFilesCommand(const QStringList &files, KeyListController *parent); ~ChecksumVerifyFilesCommand() override; void setFiles(const QStringList &files); private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotControllerDone()) - Q_PRIVATE_SLOT(d_func(), void slotControllerError(int, QString)) }; } } diff --git a/src/commands/createcsrforcardkeycommand.cpp b/src/commands/createcsrforcardkeycommand.cpp index 2612eb6bb..fe38b4718 100644 --- a/src/commands/createcsrforcardkeycommand.cpp +++ b/src/commands/createcsrforcardkeycommand.cpp @@ -1,296 +1,297 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/createcsrforcardkeycommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "createcsrforcardkeycommand.h" #include "cardcommand_p.h" #include "dialogs/createcsrforcardkeydialog.h" #include "smartcard/netkeycard.h" #include "smartcard/openpgpcard.h" #include "smartcard/pivcard.h" #include "smartcard/readerstatus.h" #include "utils/filedialog.h" #include "utils/keyparameters.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Dialogs; using namespace Kleo::SmartCard; using namespace GpgME; using namespace QGpgME; class CreateCSRForCardKeyCommand::Private : public CardCommand::Private { friend class ::Kleo::Commands::CreateCSRForCardKeyCommand; CreateCSRForCardKeyCommand *q_func() const { return static_cast(q); } public: explicit Private(CreateCSRForCardKeyCommand *qq, const std::string &keyRef, const std::string &serialNumber, const std::string &appName, QWidget *parent); ~Private() override; private: void start(); void slotDialogAccepted(); void slotDialogRejected(); void slotResult(const KeyGenerationResult &result, const QByteArray &request); QUrl saveRequest(const QByteArray &request); void ensureDialogCreated(); private: std::string appName; std::string keyRef; QStringList keyUsages; QPointer dialog; }; CreateCSRForCardKeyCommand::Private *CreateCSRForCardKeyCommand::d_func() { return static_cast(d.get()); } const CreateCSRForCardKeyCommand::Private *CreateCSRForCardKeyCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() CreateCSRForCardKeyCommand::Private::Private(CreateCSRForCardKeyCommand *qq, const std::string &keyRef_, const std::string &serialNumber, const std::string &appName_, QWidget *parent) : CardCommand::Private(qq, serialNumber, parent) , appName(appName_) , keyRef(keyRef_) { } CreateCSRForCardKeyCommand::Private::~Private() { } namespace { QStringList getKeyUsages(const KeyPairInfo &keyInfo) { // note: gpgsm does not support creating CSRs for authentication certificates QStringList usages; if (keyInfo.canCertify()) { usages.push_back(QStringLiteral("cert")); } if (keyInfo.canSign()) { usages.push_back(QStringLiteral("sign")); } if (keyInfo.canEncrypt()) { usages.push_back(QStringLiteral("encrypt")); } return usages; } } void CreateCSRForCardKeyCommand::Private::start() { if (appName != NetKeyCard::AppName && appName != OpenPGPCard::AppName && appName != PIVCard::AppName) { qCWarning(KLEOPATRA_LOG) << "CreateCSRForCardKeyCommand does not support card application" << QString::fromStdString(appName); finished(); return; } const auto card = ReaderStatus::instance()->getCard(serialNumber(), appName); if (!card) { error(i18n("Failed to find the smartcard with the serial number: %1", QString::fromStdString(serialNumber()))); finished(); return; } const KeyPairInfo &keyInfo = card->keyInfo(keyRef); keyUsages = getKeyUsages(keyInfo); ensureDialogCreated(); dialog->setWindowTitle(i18n("Certificate Details")); if (!card->cardHolder().isEmpty()) { dialog->setName(card->cardHolder()); } dialog->show(); } void CreateCSRForCardKeyCommand::Private::slotDialogAccepted() { const Error err = ReaderStatus::switchCardAndApp(serialNumber(), appName); if (err) { finished(); return; } const auto backend = smime(); if (!backend) { finished(); return; } KeyGenerationJob *const job = backend->keyGenerationJob(); if (!job) { finished(); return; } Job::context(job)->setArmor(true); - connect(job, SIGNAL(result(const GpgME::KeyGenerationResult &, const QByteArray &)), - q, SLOT(slotResult(const GpgME::KeyGenerationResult &, const QByteArray &))); + connect(job, &KeyGenerationJob::result, q, [this](const GpgME::KeyGenerationResult &result, const QByteArray &pubKeyData) { + slotResult(result, pubKeyData); + }); KeyParameters keyParameters(KeyParameters::CMS); keyParameters.setKeyType(QString::fromStdString(keyRef)); keyParameters.setKeyUsages(keyUsages); keyParameters.setDN(dialog->dn()); keyParameters.setEmail(dialog->email()); if (const Error err = job->start(keyParameters.toString())) { error(i18nc("@info", "Creating a CSR for the card key failed:\n%1", QString::fromUtf8(err.asString())), i18nc("@title", "Error")); finished(); } } void CreateCSRForCardKeyCommand::Private::slotDialogRejected() { canceled(); } void CreateCSRForCardKeyCommand::Private::slotResult(const KeyGenerationResult &result, const QByteArray &request) { if (result.error().isCanceled()) { // do nothing } else if (result.error()) { error(i18nc("@info", "Creating a CSR for the card key failed:\n%1", QString::fromUtf8(result.error().asString())), i18nc("@title", "Error")); } else { const QUrl url = saveRequest(request); if (!url.isEmpty()) { information(xi18nc("@info", "Successfully wrote request to %1." "You should now send the request to the Certification Authority (CA).", url.toLocalFile()), i18nc("@title", "Request Saved")); } } finished(); } namespace { struct SaveToFileResult { QUrl url; QString errorMessage; }; SaveToFileResult saveRequestToFile(const QString &filename, const QByteArray &request, QIODevice::OpenMode mode) { QFile file(filename); if (file.open(mode)) { const auto bytesWritten = file.write(request); if (bytesWritten < request.size()) { return { QUrl(), file.errorString() }; } return { QUrl::fromLocalFile(file.fileName()), QString() }; } return { QUrl(), file.errorString() }; } } QUrl CreateCSRForCardKeyCommand::Private::saveRequest(const QByteArray &request) { const QString proposedFilename = QLatin1String("request_%1.p10").arg(QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd_HHmmss"))); while (true) { const QString filePath = FileDialog::getSaveFileNameEx( parentWidgetOrView(), i18nc("@title", "Save Request"), QStringLiteral("save_csr"), proposedFilename, i18n("PKCS#10 Requests (*.p10)")); if (filePath.isEmpty()) { // user canceled the dialog return QUrl(); } const auto result = saveRequestToFile(filePath, request, QIODevice::NewOnly); if (result.url.isEmpty()) { qCDebug(KLEOPATRA_LOG) << "Writing request to file" << filePath << "failed:" << result.errorMessage; error(xi18nc("@info", "Saving the request failed.%1", result.errorMessage), i18nc("@title", "Error Saving Request")); } else { return result.url; } } } void CreateCSRForCardKeyCommand::Private::ensureDialogCreated() { if (dialog) { return; } dialog = new CreateCSRForCardKeyDialog; applyWindowID(dialog); dialog->setAttribute(Qt::WA_DeleteOnClose); - connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted())); - connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); + connect(dialog, &QDialog::accepted, q, [this]() { slotDialogAccepted(); }); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); } CreateCSRForCardKeyCommand::CreateCSRForCardKeyCommand(const std::string &keyRef, const std::string &serialNumber, const std::string &appName, QWidget *parent) : CardCommand(new Private(this, keyRef, serialNumber, appName, parent)) { } CreateCSRForCardKeyCommand::~CreateCSRForCardKeyCommand() { } void CreateCSRForCardKeyCommand::doStart() { d->start(); } void CreateCSRForCardKeyCommand::doCancel() { } #undef d #undef q #include "moc_createcsrforcardkeycommand.cpp" diff --git a/src/commands/createcsrforcardkeycommand.h b/src/commands/createcsrforcardkeycommand.h index f91244584..0db45e887 100644 --- a/src/commands/createcsrforcardkeycommand.h +++ b/src/commands/createcsrforcardkeycommand.h @@ -1,42 +1,39 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/createcsrforcardkeycommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "cardcommand.h" namespace Kleo { namespace Commands { class CreateCSRForCardKeyCommand : public CardCommand { Q_OBJECT public: explicit CreateCSRForCardKeyCommand(const std::string &keyRef, const std::string &serialNumber, const std::string &appName, QWidget *parent = nullptr); ~CreateCSRForCardKeyCommand() override; private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) - Q_PRIVATE_SLOT(d_func(), void slotResult(const GpgME::KeyGenerationResult &, const QByteArray &)) }; } // namespace Commands } // namespace Kleo diff --git a/src/commands/createopenpgpkeyfromcardkeyscommand.cpp b/src/commands/createopenpgpkeyfromcardkeyscommand.cpp index 7b39e96a4..aaf3b24c6 100644 --- a/src/commands/createopenpgpkeyfromcardkeyscommand.cpp +++ b/src/commands/createopenpgpkeyfromcardkeyscommand.cpp @@ -1,221 +1,220 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/createopenpgpkeyfromcardkeyscommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "createopenpgpkeyfromcardkeyscommand.h" #include "cardcommand_p.h" #include "dialogs/adduseriddialog.h" #include "smartcard/netkeycard.h" #include "smartcard/openpgpcard.h" #include "smartcard/pivcard.h" #include "smartcard/readerstatus.h" #include #include #include #include #include #include #include #include #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::SmartCard; using namespace GpgME; using namespace QGpgME; class CreateOpenPGPKeyFromCardKeysCommand::Private : public CardCommand::Private { friend class ::Kleo::Commands::CreateOpenPGPKeyFromCardKeysCommand; CreateOpenPGPKeyFromCardKeysCommand *q_func() const { return static_cast(q); } public: explicit Private(CreateOpenPGPKeyFromCardKeysCommand *qq, const std::string &serialNumber, const std::string &appName, QWidget *parent); ~Private() override; private: void start(); void slotDialogAccepted(); void slotDialogRejected(); void slotResult(const Error &err); void ensureDialogCreated(); private: std::string appName; QPointer dialog; }; CreateOpenPGPKeyFromCardKeysCommand::Private *CreateOpenPGPKeyFromCardKeysCommand::d_func() { return static_cast(d.get()); } const CreateOpenPGPKeyFromCardKeysCommand::Private *CreateOpenPGPKeyFromCardKeysCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() CreateOpenPGPKeyFromCardKeysCommand::Private::Private(CreateOpenPGPKeyFromCardKeysCommand *qq, const std::string &serialNumber, const std::string &appName_, QWidget *parent) : CardCommand::Private(qq, serialNumber, parent) , appName(appName_) { } CreateOpenPGPKeyFromCardKeysCommand::Private::~Private() { } void CreateOpenPGPKeyFromCardKeysCommand::Private::start() { if (appName != NetKeyCard::AppName && appName != OpenPGPCard::AppName && appName != PIVCard::AppName) { qCWarning(KLEOPATRA_LOG) << "CreateOpenPGPKeyFromCardKeysCommand does not support card application" << QString::fromStdString(appName); finished(); return; } const auto card = ReaderStatus::instance()->getCard(serialNumber(), appName); if (!card) { error(i18n("Failed to find the smartcard with the serial number: %1", QString::fromStdString(serialNumber()))); finished(); return; } const auto signingKeyGrip = card->keyInfo(card->signingKeyRef()).grip; const Key signingKey = KeyCache::instance()->findSubkeyByKeyGrip(signingKeyGrip, OpenPGP).parent(); if (!signingKey.isNull()) { const QString message = i18nc("@info", "

There is already an OpenPGP key corresponding to the signing key on this card:

%1

" "

Do you still want to create an OpenPGP key for the card keys?

", Formatting::summaryLine(signingKey)); const auto choice = KMessageBox::warningContinueCancel(parentWidgetOrView(), message, i18nc("@title:window", "Create OpenPGP Key"), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), QString(), KMessageBox::Notify); if (choice != KMessageBox::Continue) { finished(); return; } } ensureDialogCreated(); dialog->setWindowTitle(i18n("Enter User ID")); dialog->setName(card->cardHolder()); dialog->show(); } void CreateOpenPGPKeyFromCardKeysCommand::Private::slotDialogAccepted() { const Error err = ReaderStatus::switchCardAndApp(serialNumber(), appName); if (err) { finished(); return; } const auto backend = openpgp(); if (!backend) { finished(); return; } QuickJob *const job = backend->quickJob(); if (!job) { finished(); return; } - connect(job, SIGNAL(result(GpgME::Error)), - q, SLOT(slotResult(GpgME::Error))); + connect(job, &QGpgME::QuickJob::result, q, [this](const GpgME::Error &error) { slotResult(error); }); const QString userID = Formatting::prettyNameAndEMail(OpenPGP, QString(), dialog->name(), dialog->email()); const QDateTime expires = QDateTime(); const unsigned int flags = GPGME_CREATE_FORCE; job->startCreate(userID, "card", expires, Key(), flags); } void CreateOpenPGPKeyFromCardKeysCommand::Private::slotDialogRejected() { canceled(); } void CreateOpenPGPKeyFromCardKeysCommand::Private::slotResult(const Error &err) { if (err.isCanceled()) { // do nothing } else if (err) { error(i18nc("@info", "Creating an OpenPGP key from the card keys failed: %1", QString::fromUtf8(err.asString())), i18nc("@title", "Error")); } else { information(i18nc("@info", "Successfully generated an OpenPGP key from the card keys."), i18nc("@title", "Success")); } finished(); } void CreateOpenPGPKeyFromCardKeysCommand::Private::ensureDialogCreated() { if (dialog) { return; } dialog = new AddUserIDDialog; applyWindowID(dialog); dialog->setAttribute(Qt::WA_DeleteOnClose); - connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted())); - connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); + connect(dialog, &QDialog::accepted, q, [this]() { slotDialogAccepted(); }); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); } CreateOpenPGPKeyFromCardKeysCommand::CreateOpenPGPKeyFromCardKeysCommand(const std::string &serialNumber, const std::string &appName, QWidget *parent) : CardCommand(new Private(this, serialNumber, appName, parent)) { } CreateOpenPGPKeyFromCardKeysCommand::~CreateOpenPGPKeyFromCardKeysCommand() { } // static bool CreateOpenPGPKeyFromCardKeysCommand::isSupported() { return !(engineInfo(GpgEngine).engineVersion() < "2.3.0"); } void CreateOpenPGPKeyFromCardKeysCommand::doStart() { d->start(); } void CreateOpenPGPKeyFromCardKeysCommand::doCancel() { } #undef d #undef q #include "moc_createopenpgpkeyfromcardkeyscommand.cpp" diff --git a/src/commands/createopenpgpkeyfromcardkeyscommand.h b/src/commands/createopenpgpkeyfromcardkeyscommand.h index dd27d224b..787f69081 100644 --- a/src/commands/createopenpgpkeyfromcardkeyscommand.h +++ b/src/commands/createopenpgpkeyfromcardkeyscommand.h @@ -1,44 +1,41 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/createopenpgpkeyfromcardkeyscommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include namespace Kleo { namespace Commands { class CreateOpenPGPKeyFromCardKeysCommand : public CardCommand { Q_OBJECT public: explicit CreateOpenPGPKeyFromCardKeysCommand(const std::string &serialNumber, const std::string &appName, QWidget *parent = nullptr); ~CreateOpenPGPKeyFromCardKeysCommand() override; static bool isSupported(); private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) - Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error)) }; } // namespace Commands } // namespace Kleo diff --git a/src/commands/decryptverifyclipboardcommand.cpp b/src/commands/decryptverifyclipboardcommand.cpp index 57160fa63..adac6db82 100644 --- a/src/commands/decryptverifyclipboardcommand.cpp +++ b/src/commands/decryptverifyclipboardcommand.cpp @@ -1,173 +1,173 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/decryptverifyclipboardcommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "decryptverifyclipboardcommand.h" #ifndef QT_NO_CLIPBOARD #include "command_p.h" #include #include #include #include #include #include #include "kleopatra_debug.h" #include using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Crypto; class DecryptVerifyClipboardCommand::Private : public Command::Private { friend class ::Kleo::Commands::DecryptVerifyClipboardCommand; DecryptVerifyClipboardCommand *q_func() const { return static_cast(q); } public: explicit Private(DecryptVerifyClipboardCommand *qq, KeyListController *c); ~Private() override; void init(); private: void slotControllerDone() { finished(); } void slotControllerError(int, const QString &) { finished(); } private: std::shared_ptr shared_qq; std::shared_ptr input; DecryptVerifyEMailController controller; }; DecryptVerifyClipboardCommand::Private *DecryptVerifyClipboardCommand::d_func() { return static_cast(d.get()); } const DecryptVerifyClipboardCommand::Private *DecryptVerifyClipboardCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() DecryptVerifyClipboardCommand::Private::Private(DecryptVerifyClipboardCommand *qq, KeyListController *c) : Command::Private(qq, c), shared_qq(qq, [](DecryptVerifyClipboardCommand*){}), input(), controller() { } DecryptVerifyClipboardCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG); } DecryptVerifyClipboardCommand::DecryptVerifyClipboardCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } DecryptVerifyClipboardCommand::DecryptVerifyClipboardCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } void DecryptVerifyClipboardCommand::Private::init() { controller.setExecutionContext(shared_qq); - connect(&controller, SIGNAL(done()), q, SLOT(slotControllerDone())); - connect(&controller, SIGNAL(error(int,QString)), q, SLOT(slotControllerError(int,QString))); + connect(&controller, &Controller::done, q, [this]() { slotControllerDone(); }); + connect(&controller, &Controller::error, q, [this](int err, const QString &details) { slotControllerError(err, details); }); } DecryptVerifyClipboardCommand::~DecryptVerifyClipboardCommand() { qCDebug(KLEOPATRA_LOG); } // static bool DecryptVerifyClipboardCommand::canDecryptVerifyCurrentClipboard() { try { return Input::createFromClipboard()->classification() & (Class::CipherText | Class::ClearsignedMessage | Class::OpaqueSignature); } catch (...) {} return false; } void DecryptVerifyClipboardCommand::doStart() { try { const std::shared_ptr input = Input::createFromClipboard(); const unsigned int classification = input->classification(); if (classification & (Class::ClearsignedMessage | Class::OpaqueSignature)) { d->controller.setOperation(Verify); d->controller.setVerificationMode(Opaque); } else if (classification & Class::CipherText) { d->controller.setOperation(DecryptVerify); } else { d->information(i18n("The clipboard does not appear to " "contain a signature or encrypted text."), i18n("Decrypt/Verify Clipboard Error")); d->finished(); return; } d->controller.setProtocol(findProtocol(classification)); d->controller.setInput(input); d->controller.setOutput(Output::createFromClipboard()); d->controller.start(); } catch (const std::exception &e) { d->information(i18n("An error occurred: %1", QString::fromLocal8Bit(e.what())), i18n("Decrypt/Verify Clipboard Error")); d->finished(); } } void DecryptVerifyClipboardCommand::doCancel() { qCDebug(KLEOPATRA_LOG); d->controller.cancel(); } #undef d #undef q #include "moc_decryptverifyclipboardcommand.cpp" #endif // QT_NO_CLIPBOARD diff --git a/src/commands/decryptverifyclipboardcommand.h b/src/commands/decryptverifyclipboardcommand.h index 1149a7158..a2bbb37d0 100644 --- a/src/commands/decryptverifyclipboardcommand.h +++ b/src/commands/decryptverifyclipboardcommand.h @@ -1,49 +1,47 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/decryptverifyclipboardcommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #ifndef QT_NO_CLIPBOARD #include namespace Kleo { namespace Commands { class DecryptVerifyClipboardCommand : public Command { Q_OBJECT public: explicit DecryptVerifyClipboardCommand(QAbstractItemView *view, KeyListController *parent); explicit DecryptVerifyClipboardCommand(KeyListController *parent); ~DecryptVerifyClipboardCommand() override; static bool canDecryptVerifyCurrentClipboard(); private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotControllerDone()) - Q_PRIVATE_SLOT(d_func(), void slotControllerError(int, QString)) }; } } #endif // QT_NO_CLIPBOARD diff --git a/src/commands/decryptverifyfilescommand.cpp b/src/commands/decryptverifyfilescommand.cpp index 7411b5b4c..2207f2de9 100644 --- a/src/commands/decryptverifyfilescommand.cpp +++ b/src/commands/decryptverifyfilescommand.cpp @@ -1,193 +1,193 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/decryptverifyfilescommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "decryptverifyfilescommand.h" #include "fileoperationspreferences.h" #include "command_p.h" #include "crypto/decryptverifyfilescontroller.h" #include "crypto/autodecryptverifyfilescontroller.h" #include #include #include #include "kleopatra_debug.h" #include using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Crypto; class DecryptVerifyFilesCommand::Private : public Command::Private { friend class ::Kleo::Commands::DecryptVerifyFilesCommand; DecryptVerifyFilesCommand *q_func() const { return static_cast(q); } public: explicit Private(DecryptVerifyFilesCommand *qq, KeyListController *c, bool forceManualMode=false); ~Private() override; QStringList selectFiles() const; void init(); private: void slotControllerDone() { finished(); } void slotControllerError(int, const QString &msg) { KMessageBox::error(parentWidgetOrView(), msg, i18n("Decrypt/Verify Failed")); finished(); } private: QStringList files; std::shared_ptr shared_qq; DecryptVerifyFilesController *mController; }; DecryptVerifyFilesCommand::Private *DecryptVerifyFilesCommand::d_func() { return static_cast(d.get()); } const DecryptVerifyFilesCommand::Private *DecryptVerifyFilesCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() DecryptVerifyFilesCommand::Private::Private(DecryptVerifyFilesCommand *qq, KeyListController *c, bool forceManualMode) : Command::Private(qq, c), files(), shared_qq(qq, [](DecryptVerifyFilesCommand*){}) { FileOperationsPreferences prefs; if (!forceManualMode && GpgME::hasFeature(0, GpgME::BinaryAndFineGrainedIdentify) && prefs.autoDecryptVerify()) { mController = new AutoDecryptVerifyFilesController(); } else { mController = new DecryptVerifyFilesController(); } } DecryptVerifyFilesCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG); delete mController; } DecryptVerifyFilesCommand::DecryptVerifyFilesCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } DecryptVerifyFilesCommand::DecryptVerifyFilesCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } DecryptVerifyFilesCommand::DecryptVerifyFilesCommand(const QStringList &files, KeyListController *c, bool forceManualMode) : Command(new Private(this, c, forceManualMode)) { d->init(); d->files = files; } DecryptVerifyFilesCommand::DecryptVerifyFilesCommand(const QStringList &files, QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); d->files = files; } void DecryptVerifyFilesCommand::Private::init() { mController->setExecutionContext(shared_qq); - connect(mController, SIGNAL(done()), q, SLOT(slotControllerDone())); - connect(mController, SIGNAL(error(int,QString)), q, SLOT(slotControllerError(int,QString))); + connect(mController, &Controller::done, q, [this]() { slotControllerDone(); }); + connect(mController, &Controller::error, q, [this](int err, const QString &details) { slotControllerError(err, details); }); } DecryptVerifyFilesCommand::~DecryptVerifyFilesCommand() { qCDebug(KLEOPATRA_LOG); } void DecryptVerifyFilesCommand::setFiles(const QStringList &files) { d->files = files; } void DecryptVerifyFilesCommand::setOperation(DecryptVerifyOperation op) { try { d->mController->setOperation(op); } catch (...) {} } DecryptVerifyOperation DecryptVerifyFilesCommand::operation() const { return d->mController->operation(); } void DecryptVerifyFilesCommand::doStart() { try { if (d->files.empty()) { d->files = d->selectFiles(); } if (d->files.empty()) { d->finished(); return; } d->mController->setFiles(d->files); d->mController->start(); } catch (const std::exception &e) { d->information(i18n("An error occurred: %1", QString::fromLocal8Bit(e.what())), i18n("Decrypt/Verify Files Error")); d->finished(); } } void DecryptVerifyFilesCommand::doCancel() { qCDebug(KLEOPATRA_LOG); d->mController->cancel(); } QStringList DecryptVerifyFilesCommand::Private::selectFiles() const { return FileDialog::getOpenFileNames(parentWidgetOrView(), i18n("Select One or More Files to Decrypt and/or Verify"), QStringLiteral("enc")); } #undef d #undef q #include "moc_decryptverifyfilescommand.cpp" diff --git a/src/commands/deletecertificatescommand.cpp b/src/commands/deletecertificatescommand.cpp index e9131b9f6..a25e08c38 100644 --- a/src/commands/deletecertificatescommand.cpp +++ b/src/commands/deletecertificatescommand.cpp @@ -1,389 +1,390 @@ /* -*- mode: c++; c-basic-offset:4 -*- deleteCertificatescommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "deletecertificatescommand.h" #include "command_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace GpgME; using namespace Kleo; using namespace Kleo::Dialogs; using namespace QGpgME; class DeleteCertificatesCommand::Private : public Command::Private { friend class ::Kleo::DeleteCertificatesCommand; DeleteCertificatesCommand *q_func() const { return static_cast(q); } public: explicit Private(DeleteCertificatesCommand *qq, KeyListController *c); ~Private() override; void startDeleteJob(GpgME::Protocol protocol); void cancelJobs(); void pgpDeleteResult(const GpgME::Error &); void cmsDeleteResult(const GpgME::Error &); void showErrorsAndFinish(); bool canDelete(GpgME::Protocol proto) const { if (const auto cbp = (proto == GpgME::OpenPGP ? QGpgME::openpgp() : QGpgME::smime())) if (DeleteJob *const job = cbp->deleteJob()) { job->slotCancel(); return true; } return false; } void ensureDialogCreated() { if (dialog) { return; } dialog = new DeleteCertificatesDialog; applyWindowID(dialog); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setWindowTitle(i18nc("@title:window", "Delete Certificates")); - connect(dialog, SIGNAL(accepted()), q_func(), SLOT(slotDialogAccepted())); - connect(dialog, SIGNAL(rejected()), q_func(), SLOT(slotDialogRejected())); + connect(dialog, &QDialog::accepted, q_func(), [this]() { slotDialogAccepted(); }); + connect(dialog, &QDialog::rejected, q_func(), [this]() { slotDialogRejected(); }); } void ensureDialogShown() { if (dialog) { dialog->show(); } } void slotDialogAccepted(); void slotDialogRejected() { canceled(); } private: QPointer dialog; QPointer cmsJob, pgpJob; GpgME::Error cmsError, pgpError; std::vector cmsKeys, pgpKeys; }; DeleteCertificatesCommand::Private *DeleteCertificatesCommand::d_func() { return static_cast(d.get()); } const DeleteCertificatesCommand::Private *DeleteCertificatesCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() DeleteCertificatesCommand::Private::Private(DeleteCertificatesCommand *qq, KeyListController *c) : Command::Private(qq, c) { } DeleteCertificatesCommand::Private::~Private() {} DeleteCertificatesCommand::DeleteCertificatesCommand(KeyListController *p) : Command(new Private(this, p)) { } DeleteCertificatesCommand::DeleteCertificatesCommand(QAbstractItemView *v, KeyListController *p) : Command(v, new Private(this, p)) { } DeleteCertificatesCommand::~DeleteCertificatesCommand() {} namespace { enum Action { Nothing = 0, Failure = 1, ClearCMS = 2, ClearPGP = 4 }; // const unsigned int errorCase = // openpgp.empty() << 3U | d->canDelete( OpenPGP ) << 2U | // cms.empty() << 1U | d->canDelete( CMS ) << 0U ; static const struct { const KLazyLocalizedString text; Action actions; } deletionErrorCases[16] = { // if havePGP // if cantPGP // if haveCMS {kli18n("Neither the OpenPGP nor the CMS " "backends support certificate deletion.\n" "Check your installation."), Failure}, // cantCMS {kli18n("The OpenPGP backend does not support " "certificate deletion.\n" "Check your installation.\n" "Only the selected CMS certificates " "will be deleted."), ClearPGP}, // canCMS // if !haveCMS {kli18n("The OpenPGP backend does not support " "certificate deletion.\n" "Check your installation."), Failure}, {kli18n("The OpenPGP backend does not support " "certificate deletion.\n" "Check your installation."), Failure}, // if canPGP // if haveCMS {kli18n("The CMS backend does not support " "certificate deletion.\n" "Check your installation.\n" "Only the selected OpenPGP certificates " "will be deleted."), ClearCMS}, // cantCMS {KLazyLocalizedString(), Nothing}, // canCMS // if !haveCMS {KLazyLocalizedString(), Nothing}, // cantCMS {KLazyLocalizedString(), Nothing}, // canCMS // if !havePGP // if cantPGP // if haveCMS {kli18n("The CMS backend does not support " "certificate deletion.\n" "Check your installation."), Failure}, // cantCMS {KLazyLocalizedString(), Nothing}, // canCMS // if !haveCMS {KLazyLocalizedString(), Nothing}, // cantCMS {KLazyLocalizedString(), Nothing}, // canCMS // if canPGP // if haveCMS {kli18n("The CMS backend does not support " "certificate deletion.\n" "Check your installation."), Failure}, // cantCMS {KLazyLocalizedString(), Nothing}, // canCMS // if !haveCMS {KLazyLocalizedString(), Nothing}, // cantCMS {KLazyLocalizedString(), Nothing}, // canCMS }; } // anon namespace void DeleteCertificatesCommand::doStart() { std::vector selected = d->keys(); if (selected.empty()) { d->finished(); return; } std::sort(selected.begin(), selected.end(), _detail::ByFingerprint()); // Calculate the closure of the selected keys (those that need to // be deleted with them, though not selected themselves): std::vector toBeDeleted = KeyCache::instance()->findSubjects(selected); std::sort(toBeDeleted.begin(), toBeDeleted.end(), _detail::ByFingerprint()); std::vector unselected; unselected.reserve(toBeDeleted.size()); std::set_difference(toBeDeleted.begin(), toBeDeleted.end(), selected.begin(), selected.end(), std::back_inserter(unselected), _detail::ByFingerprint()); d->ensureDialogCreated(); d->dialog->setSelectedKeys(selected); d->dialog->setUnselectedKeys(unselected); d->ensureDialogShown(); } void DeleteCertificatesCommand::Private::slotDialogAccepted() { std::vector keys = dialog->keys(); Q_ASSERT(!keys.empty()); auto pgpBegin = keys.begin(); auto pgpEnd = std::stable_partition(pgpBegin, keys.end(), [](const GpgME::Key &key) { return key.protocol() != GpgME::CMS; }); auto cmsBegin = pgpEnd; auto cmsEnd = keys.end(); std::vector openpgp(pgpBegin, pgpEnd); std::vector cms(cmsBegin, cmsEnd); const unsigned int errorCase = openpgp.empty() << 3U | canDelete(OpenPGP) << 2U | cms.empty() << 1U | canDelete(CMS) << 0U; if (const unsigned int actions = deletionErrorCases[errorCase].actions) { information(KLocalizedString(deletionErrorCases[errorCase].text).toString(), (actions & Failure) ? i18n("Certificate Deletion Failed") : i18n("Certificate Deletion Problem")); if (actions & ClearCMS) { cms.clear(); } if (actions & ClearPGP) { openpgp.clear(); } if (actions & Failure) { canceled(); return; } } Q_ASSERT(!openpgp.empty() || !cms.empty()); pgpKeys.swap(openpgp); cmsKeys.swap(cms); if (!pgpKeys.empty()) { startDeleteJob(GpgME::OpenPGP); } if (!cmsKeys.empty()) { startDeleteJob(GpgME::CMS); } if ((pgpKeys.empty() || pgpError.code()) && (cmsKeys.empty() || cmsError.code())) { showErrorsAndFinish(); } } void DeleteCertificatesCommand::Private::startDeleteJob(GpgME::Protocol protocol) { Q_ASSERT(protocol != GpgME::UnknownProtocol); const std::vector &keys = protocol == CMS ? cmsKeys : pgpKeys; const auto backend = (protocol == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime(); Q_ASSERT(backend); std::unique_ptr job(new MultiDeleteJob(backend)); - if (protocol == CMS) - connect(job.get(), SIGNAL(result(GpgME::Error,GpgME::Key)), - q_func(), SLOT(cmsDeleteResult(GpgME::Error))); - else - connect(job.get(), SIGNAL(result(GpgME::Error,GpgME::Key)), - q_func(), SLOT(pgpDeleteResult(GpgME::Error))); + connect(job.get(), &QGpgME::MultiDeleteJob::result, q_func(), [this, protocol](const GpgME::Error &result) { + if (protocol == CMS) { + cmsDeleteResult(result); + } else { + pgpDeleteResult(result); + } + }); connect(job.get(), &Job::progress, q, &Command::progress); if (const Error err = job->start(keys, true /*allowSecretKeyDeletion*/)) { (protocol == CMS ? cmsError : pgpError) = err; } else { (protocol == CMS ? cmsJob : pgpJob) = job.release(); } } void DeleteCertificatesCommand::Private::showErrorsAndFinish() { Q_ASSERT(!pgpJob); Q_ASSERT(!cmsJob); if (pgpError || cmsError) { QString pgpErrorString; if (pgpError) { pgpErrorString = i18n("OpenPGP backend: %1", QString::fromLocal8Bit(pgpError.asString())); } QString cmsErrorString; if (cmsError) { cmsErrorString = i18n("CMS backend: %1", QString::fromLocal8Bit(cmsError.asString())); } const QString msg = i18n("

An error occurred while trying to delete " "the certificate:

" "

%1

", pgpError ? cmsError ? pgpErrorString + QLatin1String("
") + cmsErrorString : pgpErrorString : cmsErrorString); error(msg, i18n("Certificate Deletion Failed")); } else if (!pgpError.isCanceled() && !cmsError.isCanceled()) { std::vector keys = pgpKeys; keys.insert(keys.end(), cmsKeys.begin(), cmsKeys.end()); KeyCache::mutableInstance()->remove(keys); } finished(); } void DeleteCertificatesCommand::doCancel() { d->cancelJobs(); } void DeleteCertificatesCommand::Private::pgpDeleteResult(const Error &err) { pgpError = err; pgpJob = nullptr; if (!cmsJob) { showErrorsAndFinish(); } } void DeleteCertificatesCommand::Private::cmsDeleteResult(const Error &err) { cmsError = err; cmsJob = nullptr; if (!pgpJob) { showErrorsAndFinish(); } } void DeleteCertificatesCommand::Private::cancelJobs() { if (cmsJob) { cmsJob->slotCancel(); } if (pgpJob) { pgpJob->slotCancel(); } } #undef d #undef q #include "moc_deletecertificatescommand.cpp" diff --git a/src/commands/deletecertificatescommand.h b/src/commands/deletecertificatescommand.h index 576ca561a..eafbd7993 100644 --- a/src/commands/deletecertificatescommand.h +++ b/src/commands/deletecertificatescommand.h @@ -1,44 +1,40 @@ /* -*- mode: c++; c-basic-offset:4 -*- deletecertificatescommand.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 "command.h" namespace Kleo { class DeleteCertificatesCommand : public Command { Q_OBJECT public: explicit DeleteCertificatesCommand(QAbstractItemView *view, KeyListController *parent); explicit DeleteCertificatesCommand(KeyListController *parent); ~DeleteCertificatesCommand() override; /* reimp */ static Restrictions restrictions() { return NeedSelection; } private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) - Q_PRIVATE_SLOT(d_func(), void pgpDeleteResult(GpgME::Error)) - Q_PRIVATE_SLOT(d_func(), void cmsDeleteResult(GpgME::Error)) }; } diff --git a/src/commands/dumpcertificatecommand.cpp b/src/commands/dumpcertificatecommand.cpp index cc5ad0c29..55ff5d327 100644 --- a/src/commands/dumpcertificatecommand.cpp +++ b/src/commands/dumpcertificatecommand.cpp @@ -1,344 +1,340 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/dumpcertificatecommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "dumpcertificatecommand.h" #include "command_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const int PROCESS_TERMINATE_TIMEOUT = 5000; // milliseconds namespace { class DumpCertificateDialog : public QDialog { Q_OBJECT public: explicit DumpCertificateDialog(QWidget *parent = nullptr) : QDialog(parent), ui(this) { resize(600, 500); } Q_SIGNALS: void updateRequested(); public Q_SLOTS: void append(const QString &line) { ui.logTextWidget.append(line); ui.logTextWidget.ensureCursorVisible(); } void clear() { ui.logTextWidget.clear(); } private: struct Ui { QTextEdit logTextWidget; QPushButton updateButton, closeButton; QVBoxLayout vlay; QHBoxLayout hlay; explicit Ui(DumpCertificateDialog *q) : logTextWidget(q), updateButton(i18nc("@action:button Update the log text widget", "&Update"), q), closeButton(q), vlay(q), hlay() { KGuiItem::assign(&closeButton, KStandardGuiItem::close()); KDAB_SET_OBJECT_NAME(logTextWidget); KDAB_SET_OBJECT_NAME(updateButton); KDAB_SET_OBJECT_NAME(closeButton); KDAB_SET_OBJECT_NAME(vlay); KDAB_SET_OBJECT_NAME(hlay); logTextWidget.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); logTextWidget.setReadOnly(true); logTextWidget.setWordWrapMode(QTextOption::NoWrap); vlay.addWidget(&logTextWidget, 1); vlay.addLayout(&hlay); hlay.addWidget(&updateButton); hlay.addStretch(1); hlay.addWidget(&closeButton); connect(&updateButton, &QAbstractButton::clicked, q, &DumpCertificateDialog::updateRequested); connect(&closeButton, &QAbstractButton::clicked, q, &QWidget::close); } } ui; }; } using namespace Kleo; using namespace Kleo::Commands; static QByteArray chomped(QByteArray ba) { while (ba.endsWith('\n') || ba.endsWith('\r')) { ba.chop(1); } return ba; } class DumpCertificateCommand::Private : Command::Private { friend class ::Kleo::Commands::DumpCertificateCommand; DumpCertificateCommand *q_func() const { return static_cast(q); } public: explicit Private(DumpCertificateCommand *qq, KeyListController *c); ~Private() override; QString errorString() const { return QString::fromLocal8Bit(errorBuffer); } private: void init(); void refreshView(); private: void slotProcessFinished(int, QProcess::ExitStatus); void slotProcessReadyReadStandardOutput() { while (process.canReadLine()) { const QString line = Kleo::stringFromGpgOutput(chomped(process.readLine())); if (dialog) { dialog->append(line); } outputBuffer.push_back(line); } } void slotProcessReadyReadStandardError() { errorBuffer += process.readAllStandardError(); } void slotUpdateRequested() { if (process.state() == QProcess::NotRunning) { refreshView(); } } void slotDialogDestroyed() { dialog = nullptr; if (process.state() != QProcess::NotRunning) { q->cancel(); } else { finished(); } } private: QPointer dialog; KProcess process; QByteArray errorBuffer; QStringList outputBuffer; bool useDialog; bool canceled; }; DumpCertificateCommand::Private *DumpCertificateCommand::d_func() { return static_cast(d.get()); } const DumpCertificateCommand::Private *DumpCertificateCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() DumpCertificateCommand::Private::Private(DumpCertificateCommand *qq, KeyListController *c) : Command::Private(qq, c), process(), errorBuffer(), outputBuffer(), useDialog(true), canceled(false) { process.setOutputChannelMode(KProcess::SeparateChannels); process.setReadChannel(KProcess::StandardOutput); } DumpCertificateCommand::Private::~Private() { if (dialog && !dialog->isVisible()) { delete dialog; } } DumpCertificateCommand::DumpCertificateCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } DumpCertificateCommand::DumpCertificateCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } DumpCertificateCommand::DumpCertificateCommand(const GpgME::Key &k) : Command(k, new Private(this, nullptr)) { d->init(); } void DumpCertificateCommand::Private::init() { - connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)), - q, SLOT(slotProcessFinished(int,QProcess::ExitStatus))); - connect(&process, SIGNAL(readyReadStandardError()), - q, SLOT(slotProcessReadyReadStandardError())); - connect(&process, SIGNAL(readyReadStandardOutput()), - q, SLOT(slotProcessReadyReadStandardOutput())); + connect(&process, &QProcess::finished, q, [this](int exitCode, QProcess::ExitStatus status) { slotProcessFinished(exitCode, status); }); + connect(&process, &QProcess::readyReadStandardError, q, [this]() { slotProcessReadyReadStandardError(); }); + connect(&process, &QProcess::readyReadStandardOutput, q, [this] { slotProcessReadyReadStandardOutput(); }); + if (!key().isNull()) { process << gpgSmPath() << QStringLiteral("--dump-cert") << QLatin1String(key().primaryFingerprint()); } } DumpCertificateCommand::~DumpCertificateCommand() {} void DumpCertificateCommand::setUseDialog(bool use) { d->useDialog = use; } bool DumpCertificateCommand::useDialog() const { return d->useDialog; } QStringList DumpCertificateCommand::output() const { return d->outputBuffer; } void DumpCertificateCommand::doStart() { const std::vector keys = d->keys(); if (keys.size() != 1 || keys.front().protocol() != GpgME::CMS) { d->finished(); return; } if (d->useDialog) { d->dialog = new DumpCertificateDialog; d->dialog->setAttribute(Qt::WA_DeleteOnClose); d->dialog->setWindowTitle(i18nc("@title:window", "Certificate Dump")); - connect(d->dialog, SIGNAL(updateRequested()), - this, SLOT(slotUpdateRequested())); - connect(d->dialog, SIGNAL(destroyed()), - this, SLOT(slotDialogDestroyed())); + connect(d->dialog, &DumpCertificateDialog::updateRequested, this, [this]() { d->slotUpdateRequested(); }); + connect(d->dialog, &QObject::destroyed, this, [this]() { d->slotDialogDestroyed(); }); } d->refreshView(); } void DumpCertificateCommand::Private::refreshView() { if (dialog) { dialog->clear(); } errorBuffer.clear(); outputBuffer.clear(); process.start(); if (process.waitForStarted()) { if (dialog) { dialog->show(); } } else { KMessageBox::error(dialog ? static_cast(dialog) : parentWidgetOrView(), i18n("Unable to start process gpgsm. " "Please check your installation."), i18n("Dump Certificate Error")); finished(); } } void DumpCertificateCommand::doCancel() { d->canceled = true; if (d->process.state() != QProcess::NotRunning) { d->process.terminate(); QTimer::singleShot(PROCESS_TERMINATE_TIMEOUT, &d->process, &QProcess::kill); } if (d->dialog) { d->dialog->close(); } d->dialog = nullptr; } void DumpCertificateCommand::Private::slotProcessFinished(int code, QProcess::ExitStatus status) { if (!canceled) { if (status == QProcess::CrashExit) KMessageBox::error(dialog, i18n("The GpgSM process that tried to dump the certificate " "ended prematurely because of an unexpected error. " "Please check the output of gpgsm --dump-cert %1 for details.", QLatin1String(key().primaryFingerprint())), i18n("Dump Certificate Error")); else if (code) KMessageBox::error(dialog, i18n("An error occurred while trying to dump the certificate. " "The output from GpgSM was:\n%1", errorString()), i18n("Dump Certificate Error")); } if (!useDialog) { slotDialogDestroyed(); } } #undef d #undef q #include "moc_dumpcertificatecommand.cpp" #include "dumpcertificatecommand.moc" diff --git a/src/commands/dumpcrlcachecommand.cpp b/src/commands/dumpcrlcachecommand.cpp index 21af003ac..2df8e3f55 100644 --- a/src/commands/dumpcrlcachecommand.cpp +++ b/src/commands/dumpcrlcachecommand.cpp @@ -1,351 +1,346 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/dumpcrlcachecommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "dumpcrlcachecommand.h" #include "command_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const int PROCESS_TERMINATE_TIMEOUT = 5000; // milliseconds namespace { class DumpCrlCacheDialog : public QDialog { Q_OBJECT public: explicit DumpCrlCacheDialog(QWidget *parent = nullptr) : QDialog(parent), ui(this), mWithRevocations(false) { readConfig(); } ~DumpCrlCacheDialog() override { writeConfig(); } Q_SIGNALS: void updateRequested(); public Q_SLOTS: void append(const QString &line) { ui.logTextWidget.append(line); ui.logTextWidget.ensureCursorVisible(); } void clear() { ui.logTextWidget.clear(); } public: void setWithRevocations (bool value) { mWithRevocations = value; } Q_REQUIRED_RESULT bool withRevocations () { return mWithRevocations; } private: void readConfig() { KConfigGroup dialog(KSharedConfig::openStateConfig(), "DumpCrlCacheDialog"); const QSize size = dialog.readEntry("Size", QSize(600, 400)); if (size.isValid()) { resize(size); } } void writeConfig() { KConfigGroup dialog(KSharedConfig::openStateConfig(), "DumpCrlCacheDialog"); dialog.writeEntry("Size", size()); dialog.sync(); } struct Ui { QTextEdit logTextWidget; QPushButton updateButton, closeButton, revocationsButton; QVBoxLayout vlay; QHBoxLayout hlay; explicit Ui(DumpCrlCacheDialog *q) : logTextWidget(q), updateButton(i18nc("@action:button Update the log text widget", "&Update"), q), closeButton(q), vlay(q), hlay() { KGuiItem::assign(&closeButton, KStandardGuiItem::close()); KDAB_SET_OBJECT_NAME(logTextWidget); KDAB_SET_OBJECT_NAME(updateButton); KDAB_SET_OBJECT_NAME(closeButton); KDAB_SET_OBJECT_NAME(vlay); KDAB_SET_OBJECT_NAME(hlay); logTextWidget.setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); logTextWidget.setReadOnly(true); vlay.addWidget(&logTextWidget, 1); vlay.addLayout(&hlay); revocationsButton.setText(i18n("Show Entries")); hlay.addWidget(&updateButton); hlay.addWidget(&revocationsButton); hlay.addStretch(1); hlay.addWidget(&closeButton); connect(&updateButton, &QAbstractButton::clicked, q, &DumpCrlCacheDialog::updateRequested); connect(&closeButton, &QAbstractButton::clicked, q, &QWidget::close); connect(&revocationsButton, &QAbstractButton::clicked, q, [q, this] () { q->mWithRevocations = true; revocationsButton.setEnabled(false); q->updateRequested(); }); } } ui; bool mWithRevocations; }; } using namespace Kleo; using namespace Kleo::Commands; static QByteArray chomped(QByteArray ba) { while (ba.endsWith('\n') || ba.endsWith('\r')) { ba.chop(1); } return ba; } class DumpCrlCacheCommand::Private : Command::Private { friend class ::Kleo::Commands::DumpCrlCacheCommand; DumpCrlCacheCommand *q_func() const { return static_cast(q); } public: explicit Private(DumpCrlCacheCommand *qq, KeyListController *c); ~Private() override; QString errorString() const { return QString::fromLocal8Bit(errorBuffer); } private: void init(); void refreshView(); private: void slotProcessFinished(int, QProcess::ExitStatus); void slotProcessReadyReadStandardOutput() { static int count; while (process.canReadLine()) { if (!dialog) { break; } const QByteArray line = chomped(process.readLine()); if (!line.size()) { continue; } if (!dialog->withRevocations() && line.contains("reasons")) { count++; continue; } else if (count) { dialog->append (QLatin1Char(' ') + i18nc("Count of revocations in a CRL", "Entries:") + QStringLiteral("\t\t%1\n").arg(count)); count = 0; } dialog->append(stringFromGpgOutput(line)); } } void slotProcessReadyReadStandardError() { errorBuffer += process.readAllStandardError(); } void slotUpdateRequested() { if (process.state() == QProcess::NotRunning) { refreshView(); } } void slotDialogDestroyed() { dialog = nullptr; if (process.state() != QProcess::NotRunning) { q->cancel(); } else { finished(); } } private: DumpCrlCacheDialog *dialog; KProcess process; QByteArray errorBuffer; bool canceled; }; DumpCrlCacheCommand::Private *DumpCrlCacheCommand::d_func() { return static_cast(d.get()); } const DumpCrlCacheCommand::Private *DumpCrlCacheCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() DumpCrlCacheCommand::Private::Private(DumpCrlCacheCommand *qq, KeyListController *c) : Command::Private(qq, c), dialog(nullptr), process(), errorBuffer(), canceled(false) { process.setOutputChannelMode(KProcess::SeparateChannels); process.setReadChannel(KProcess::StandardOutput); process << gpgSmPath() << QStringLiteral("--call-dirmngr") << QStringLiteral("listcrls"); } DumpCrlCacheCommand::Private::~Private() { if (dialog && !dialog->isVisible()) { delete dialog; } } DumpCrlCacheCommand::DumpCrlCacheCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } DumpCrlCacheCommand::DumpCrlCacheCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } void DumpCrlCacheCommand::Private::init() { - connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)), - q, SLOT(slotProcessFinished(int,QProcess::ExitStatus))); - connect(&process, SIGNAL(readyReadStandardError()), - q, SLOT(slotProcessReadyReadStandardError())); - connect(&process, SIGNAL(readyReadStandardOutput()), - q, SLOT(slotProcessReadyReadStandardOutput())); + connect(&process, &QProcess::finished, q, [this](int exitCode, QProcess::ExitStatus status) { slotProcessFinished(exitCode, status); }); + connect(&process, &QProcess::readyReadStandardError, q, [this]() { slotProcessReadyReadStandardError(); }); + connect(&process, &QProcess::readyReadStandardOutput, q, [this] { slotProcessReadyReadStandardOutput(); }); } DumpCrlCacheCommand::~DumpCrlCacheCommand() {} void DumpCrlCacheCommand::doStart() { d->dialog = new DumpCrlCacheDialog; d->dialog->setAttribute(Qt::WA_DeleteOnClose); d->dialog->setWindowTitle(i18nc("@title:window", "CRL Cache Dump")); - connect(d->dialog, SIGNAL(updateRequested()), - this, SLOT(slotUpdateRequested())); - connect(d->dialog, SIGNAL(destroyed()), - this, SLOT(slotDialogDestroyed())); + connect(d->dialog, &DumpCrlCacheDialog::updateRequested, this, [this]() { d->slotUpdateRequested(); }); + connect(d->dialog, &QObject::destroyed, this, [this]() { d->slotDialogDestroyed(); }); d->refreshView(); } void DumpCrlCacheCommand::Private::refreshView() { dialog->clear(); process.start(); if (process.waitForStarted()) { dialog->show(); } else { KMessageBox::error(dialog ? static_cast(dialog) : parentWidgetOrView(), i18n("Unable to start process gpgsm. " "Please check your installation."), i18n("Dump CRL Cache Error")); finished(); } } void DumpCrlCacheCommand::doCancel() { d->canceled = true; if (d->process.state() != QProcess::NotRunning) { d->process.terminate(); QTimer::singleShot(PROCESS_TERMINATE_TIMEOUT, &d->process, &QProcess::kill); } if (d->dialog) { d->dialog->close(); } d->dialog = nullptr; } void DumpCrlCacheCommand::Private::slotProcessFinished(int code, QProcess::ExitStatus status) { if (!canceled) { if (status == QProcess::CrashExit) KMessageBox::error(dialog, i18n("The GpgSM process that tried to dump the CRL cache " "ended prematurely because of an unexpected error. " "Please check the output of gpgsm --call-dirmngr listcrls for details."), i18n("Dump CRL Cache Error")); else if (code) KMessageBox::error(dialog, i18n("An error occurred while trying to dump the CRL cache. " "The output from GpgSM was:\n%1", errorString()), i18n("Dump CRL Cache Error")); } } #undef d #undef q #include "moc_dumpcrlcachecommand.cpp" #include "dumpcrlcachecommand.moc" diff --git a/src/commands/dumpcrlcachecommand.h b/src/commands/dumpcrlcachecommand.h index 472fc90b5..fd9ee60f3 100644 --- a/src/commands/dumpcrlcachecommand.h +++ b/src/commands/dumpcrlcachecommand.h @@ -1,44 +1,39 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/dumpcrlcachecommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include namespace Kleo { namespace Commands { class DumpCrlCacheCommand : public Command { Q_OBJECT public: explicit DumpCrlCacheCommand(QAbstractItemView *view, KeyListController *parent); explicit DumpCrlCacheCommand(KeyListController *parent); ~DumpCrlCacheCommand() override; private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotProcessFinished(int, QProcess::ExitStatus)) - Q_PRIVATE_SLOT(d_func(), void slotProcessReadyReadStandardOutput()) - Q_PRIVATE_SLOT(d_func(), void slotProcessReadyReadStandardError()) - Q_PRIVATE_SLOT(d_func(), void slotUpdateRequested()) - Q_PRIVATE_SLOT(d_func(), void slotDialogDestroyed()) }; } } diff --git a/src/commands/encryptclipboardcommand.cpp b/src/commands/encryptclipboardcommand.cpp index 77e48d09a..5da77f442 100644 --- a/src/commands/encryptclipboardcommand.cpp +++ b/src/commands/encryptclipboardcommand.cpp @@ -1,178 +1,177 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/encryptclipboardcommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "encryptclipboardcommand.h" #ifndef QT_NO_CLIPBOARD #include "command_p.h" #include #include #include #include #include #include #include "kleopatra_debug.h" #include #include #include #include using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Crypto; class EncryptClipboardCommand::Private : public Command::Private { friend class ::Kleo::Commands::EncryptClipboardCommand; EncryptClipboardCommand *q_func() const { return static_cast(q); } public: explicit Private(EncryptClipboardCommand *qq, KeyListController *c); ~Private() override; void init(); private: void slotRecipientsResolved(); void slotControllerDone() { finished(); } void slotControllerError(int, const QString &) { finished(); } private: std::shared_ptr shared_qq; std::shared_ptr input; EncryptEMailController controller; }; EncryptClipboardCommand::Private *EncryptClipboardCommand::d_func() { return static_cast(d.get()); } const EncryptClipboardCommand::Private *EncryptClipboardCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() EncryptClipboardCommand::Private::Private(EncryptClipboardCommand *qq, KeyListController *c) : Command::Private(qq, c), shared_qq(qq, [](EncryptClipboardCommand*){}), input(), controller(EncryptEMailController::ClipboardMode) { if (!Settings{}.cmsEnabled()) { controller.setProtocol(GpgME::OpenPGP); } } EncryptClipboardCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG); } EncryptClipboardCommand::EncryptClipboardCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } EncryptClipboardCommand::EncryptClipboardCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } void EncryptClipboardCommand::Private::init() { controller.setExecutionContext(shared_qq); - connect(&controller, SIGNAL(done()), q, SLOT(slotControllerDone())); - connect(&controller, SIGNAL(error(int,QString)), q, SLOT(slotControllerError(int,QString))); + connect(&controller, &Controller::done, q, [this]() { slotControllerDone(); }); + connect(&controller, &Controller::error, q, [this](int err, const QString &details) { slotControllerError(err, details); }); } EncryptClipboardCommand::~EncryptClipboardCommand() { qCDebug(KLEOPATRA_LOG); } // static bool EncryptClipboardCommand::canEncryptCurrentClipboard() { if (const QClipboard *clip = QApplication::clipboard()) if (const QMimeData *mime = clip->mimeData()) { return mime->hasText(); } return false; } void EncryptClipboardCommand::doStart() { try { // snapshot clipboard content here, in case it's being changed... d->input = Input::createFromClipboard(); - connect(&d->controller, SIGNAL(recipientsResolved()), - this, SLOT(slotRecipientsResolved())); + connect(&d->controller, &EncryptEMailController::recipientsResolved, this, [this]() { d->slotRecipientsResolved(); }); d->controller.startResolveRecipients(); } catch (const std::exception &e) { d->information(i18n("An error occurred: %1", QString::fromLocal8Bit(e.what())), i18n("Encrypt Clipboard Error")); d->finished(); } } void EncryptClipboardCommand::Private::slotRecipientsResolved() { try { controller.setInputAndOutput(input, Output::createFromClipboard()); input.reset(); // no longer needed, so don't keep a reference controller.start(); } catch (const std::exception &e) { information(i18n("An error occurred: %1", QString::fromLocal8Bit(e.what())), i18n("Encrypt Clipboard Error")); finished(); } } void EncryptClipboardCommand::doCancel() { qCDebug(KLEOPATRA_LOG); d->controller.cancel(); } #undef d #undef q #include "moc_encryptclipboardcommand.cpp" #endif // QT_NO_CLIPBOARD diff --git a/src/commands/encryptclipboardcommand.h b/src/commands/encryptclipboardcommand.h index 195db2098..0143293fe 100644 --- a/src/commands/encryptclipboardcommand.h +++ b/src/commands/encryptclipboardcommand.h @@ -1,50 +1,47 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/encryptclipboardcommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #ifndef QT_NO_CLIPBOARD #include namespace Kleo { namespace Commands { class EncryptClipboardCommand : public Command { Q_OBJECT public: explicit EncryptClipboardCommand(QAbstractItemView *view, KeyListController *parent); explicit EncryptClipboardCommand(KeyListController *parent); ~EncryptClipboardCommand() override; static bool canEncryptCurrentClipboard(); private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotRecipientsResolved()) - Q_PRIVATE_SLOT(d_func(), void slotControllerDone()) - Q_PRIVATE_SLOT(d_func(), void slotControllerError(int, QString)) }; } } #endif // QT_NO_CLIPBOARD diff --git a/src/commands/exportcertificatecommand.cpp b/src/commands/exportcertificatecommand.cpp index 07fd0abd9..2e4a456ef 100644 --- a/src/commands/exportcertificatecommand.cpp +++ b/src/commands/exportcertificatecommand.cpp @@ -1,360 +1,361 @@ /* -*- mode: c++; c-basic-offset:4 -*- exportcertificatecommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB SPDX-FileCopyrightText: 2021 g10 Code GmbH SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "exportcertificatecommand.h" #include "fileoperationspreferences.h" #include "command_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Kleo; using namespace GpgME; using namespace QGpgME; class ExportCertificateCommand::Private : public Command::Private { friend class ::ExportCertificateCommand; ExportCertificateCommand *q_func() const { return static_cast(q); } public: explicit Private(ExportCertificateCommand *qq, KeyListController *c); ~Private() override; void startExportJob(GpgME::Protocol protocol, const std::vector &keys); void cancelJobs(); void exportResult(const GpgME::Error &, const QByteArray &); void showError(const GpgME::Error &error); bool requestFileNames(GpgME::Protocol prot); void finishedIfLastJob(); private: QMap fileNames; uint jobsPending = 0; QMap outFileForSender; QPointer cmsJob; QPointer pgpJob; }; ExportCertificateCommand::Private *ExportCertificateCommand::d_func() { return static_cast(d.get()); } const ExportCertificateCommand::Private *ExportCertificateCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() ExportCertificateCommand::Private::Private(ExportCertificateCommand *qq, KeyListController *c) : Command::Private(qq, c) { } ExportCertificateCommand::Private::~Private() {} ExportCertificateCommand::ExportCertificateCommand(KeyListController *p) : Command(new Private(this, p)) { } ExportCertificateCommand::ExportCertificateCommand(QAbstractItemView *v, KeyListController *p) : Command(v, new Private(this, p)) { } ExportCertificateCommand::ExportCertificateCommand(const Key &key) : Command(key, new Private(this, nullptr)) { } ExportCertificateCommand::~ExportCertificateCommand() {} void ExportCertificateCommand::setOpenPGPFileName(const QString &fileName) { if (!d->jobsPending) { d->fileNames[OpenPGP] = fileName; } } QString ExportCertificateCommand::openPGPFileName() const { return d->fileNames[OpenPGP]; } void ExportCertificateCommand::setX509FileName(const QString &fileName) { if (!d->jobsPending) { d->fileNames[CMS] = fileName; } } QString ExportCertificateCommand::x509FileName() const { return d->fileNames[CMS]; } void ExportCertificateCommand::doStart() { std::vector keys = d->keys(); if (keys.empty()) { return; } const auto firstCms = std::partition(keys.begin(), keys.end(), [](const GpgME::Key &key) { return key.protocol() != GpgME::CMS; }); std::vector openpgp, cms; std::copy(keys.begin(), firstCms, std::back_inserter(openpgp)); std::copy(firstCms, keys.end(), std::back_inserter(cms)); Q_ASSERT(!openpgp.empty() || !cms.empty()); const bool haveBoth = !cms.empty() && !openpgp.empty(); const GpgME::Protocol prot = haveBoth ? UnknownProtocol : (!cms.empty() ? CMS : OpenPGP); if (!d->requestFileNames(prot)) { Q_EMIT canceled(); d->finished(); } else { if (!openpgp.empty()) { d->startExportJob(GpgME::OpenPGP, openpgp); } if (!cms.empty()) { d->startExportJob(GpgME::CMS, cms); } } } bool ExportCertificateCommand::Private::requestFileNames(GpgME::Protocol protocol) { if (protocol == UnknownProtocol) { if (!fileNames[GpgME::OpenPGP].isEmpty() && !fileNames[GpgME::CMS].isEmpty()) { return true; } /* Unknown protocol ask for first PGP Export file name */ if (fileNames[GpgME::OpenPGP].isEmpty() && !requestFileNames(GpgME::OpenPGP)) { return false; } /* And then for CMS */ return requestFileNames(GpgME::CMS); } if (!fileNames[protocol].isEmpty()) { return true; } KConfigGroup config(KSharedConfig::openConfig(), "ExportDialog"); const auto lastDir = config.readEntry("LastDirectory", QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); QString proposedFileName = lastDir + QLatin1Char('/'); if (keys().size() == 1) { const bool usePGPFileExt = FileOperationsPreferences().usePGPFileExt(); const auto key = keys().front(); auto name = Formatting::prettyName(key); if (name.isEmpty()) { name = Formatting::prettyEMail(key); } /* Not translated so it's better to use in tutorials etc. */ proposedFileName += QStringLiteral("%1_%2_public.%3").arg(name).arg( Formatting::prettyKeyID(key.shortKeyID())).arg( QString::fromLatin1(outputFileExtension(protocol == OpenPGP ? Class::OpenPGP | Class::Ascii | Class::Certificate : Class::CMS | Class::Ascii | Class::Certificate, usePGPFileExt))); } if (protocol == GpgME::CMS) { if (!fileNames[GpgME::OpenPGP].isEmpty()) { /* If the user has already selected a PGP file name then use that as basis * for a proposal for the S/MIME file. */ proposedFileName = fileNames[GpgME::OpenPGP]; proposedFileName.replace(QRegExp(QStringLiteral(".asc$")), QStringLiteral(".pem")); proposedFileName.replace(QRegExp(QStringLiteral(".gpg$")), QStringLiteral(".der")); proposedFileName.replace(QRegExp(QStringLiteral(".pgp$")), QStringLiteral(".der")); } } if (proposedFileName.isEmpty()) { proposedFileName = lastDir; proposedFileName += i18nc("A generic filename for exported certificates", "certificates"); proposedFileName += protocol == GpgME::OpenPGP ? QStringLiteral(".asc") : QStringLiteral(".pem"); } auto fname = FileDialog::getSaveFileNameEx(parentWidgetOrView(), i18nc("1 is protocol", "Export %1 Certificates", Formatting::displayName(protocol)), QStringLiteral("imp"), proposedFileName, protocol == GpgME::OpenPGP ? i18n("OpenPGP Certificates") + QLatin1String(" (*.asc *.gpg *.pgp)") : i18n("S/MIME Certificates") + QLatin1String(" (*.pem *.der)")); if (!fname.isEmpty() && protocol == GpgME::CMS && fileNames[GpgME::OpenPGP] == fname) { KMessageBox::error(parentWidgetOrView(), i18n("You have to select different filenames for different protocols."), i18n("Export Error")); return false; } const QFileInfo fi(fname); if (fi.suffix().isEmpty()) { fname += protocol == GpgME::OpenPGP ? QStringLiteral(".asc") : QStringLiteral(".pem"); } fileNames[protocol] = fname; config.writeEntry("LastDirectory", fi.absolutePath()); return !fname.isEmpty(); } void ExportCertificateCommand::Private::startExportJob(GpgME::Protocol protocol, const std::vector &keys) { Q_ASSERT(protocol != GpgME::UnknownProtocol); const QGpgME::Protocol *const backend = (protocol == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime(); Q_ASSERT(backend); const QString fileName = fileNames[protocol]; const bool binary = protocol == GpgME::OpenPGP ? fileName.endsWith(QLatin1String(".gpg"), Qt::CaseInsensitive) || fileName.endsWith(QLatin1String(".pgp"), Qt::CaseInsensitive) : fileName.endsWith(QLatin1String(".der"), Qt::CaseInsensitive); std::unique_ptr job(backend->publicKeyExportJob(!binary)); Q_ASSERT(job.get()); - connect(job.get(), SIGNAL(result(GpgME::Error,QByteArray)), - q, SLOT(exportResult(GpgME::Error,QByteArray))); + connect(job.get(), &QGpgME::ExportJob::result, q, [this](const GpgME::Error &result, const QByteArray &keyData) { + exportResult(result, keyData); + }); connect(job.get(), &Job::progress, q, &Command::progress); QStringList fingerprints; fingerprints.reserve(keys.size()); for (const Key &i : keys) { fingerprints << QLatin1String(i.primaryFingerprint()); } const GpgME::Error err = job->start(fingerprints); if (err) { showError(err); finished(); return; } Q_EMIT q->info(i18n("Exporting certificates...")); ++jobsPending; const QPointer exportJob(job.release()); outFileForSender[exportJob.data()] = fileName; (protocol == CMS ? cmsJob : pgpJob) = exportJob; } void ExportCertificateCommand::Private::showError(const GpgME::Error &err) { Q_ASSERT(err); const QString msg = i18n("

An error occurred while trying to export " "the certificate:

" "

%1

", QString::fromLocal8Bit(err.asString())); error(msg, i18n("Certificate Export Failed")); } void ExportCertificateCommand::doCancel() { d->cancelJobs(); } void ExportCertificateCommand::Private::finishedIfLastJob() { if (jobsPending <= 0) { finished(); } } static bool write_complete(QIODevice &iod, const QByteArray &data) { qint64 total = 0; qint64 toWrite = data.size(); while (total < toWrite) { const qint64 written = iod.write(data.data() + total, toWrite); if (written < 0) { return false; } total += written; toWrite -= written; } return true; } void ExportCertificateCommand::Private::exportResult(const GpgME::Error &err, const QByteArray &data) { Q_ASSERT(jobsPending > 0); --jobsPending; Q_ASSERT(outFileForSender.contains(q->sender())); const QString outFile = outFileForSender[q->sender()]; if (err) { showError(err); finishedIfLastJob(); return; } QSaveFile savefile(outFile); //TODO: use KIO const QString writeErrorMsg = i18n("Could not write to file %1.", outFile); const QString errorCaption = i18n("Certificate Export Failed"); if (!savefile.open(QIODevice::WriteOnly)) { error(writeErrorMsg, errorCaption); finishedIfLastJob(); return; } if (!write_complete(savefile, data) || !savefile.commit()) { error(writeErrorMsg, errorCaption); } finishedIfLastJob(); } void ExportCertificateCommand::Private::cancelJobs() { if (cmsJob) { cmsJob->slotCancel(); } if (pgpJob) { pgpJob->slotCancel(); } } #undef d #undef q #include "moc_exportcertificatecommand.cpp" diff --git a/src/commands/exportcertificatecommand.h b/src/commands/exportcertificatecommand.h index d7a91fe90..e9b12c421 100644 --- a/src/commands/exportcertificatecommand.h +++ b/src/commands/exportcertificatecommand.h @@ -1,48 +1,47 @@ /* -*- mode: c++; c-basic-offset:4 -*- exportcertificatecommand.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 "command.h" namespace Kleo { class ExportCertificateCommand : public Command { Q_OBJECT public: explicit ExportCertificateCommand(QAbstractItemView *view, KeyListController *parent); explicit ExportCertificateCommand(KeyListController *parent); explicit ExportCertificateCommand(const GpgME::Key &key); ~ExportCertificateCommand() override; /* reimp */ static Restrictions restrictions() { return NeedSelection; } void setOpenPGPFileName(const QString &fileName); QString openPGPFileName() const; void setX509FileName(const QString &fileName); QString x509FileName() const; private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void exportResult(GpgME::Error, QByteArray)) }; } diff --git a/src/commands/genrevokecommand.cpp b/src/commands/genrevokecommand.cpp index 082c66724..6b149533b 100644 --- a/src/commands/genrevokecommand.cpp +++ b/src/commands/genrevokecommand.cpp @@ -1,189 +1,188 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/genrevokecommand.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-License-Identifier: GPL-2.0-or-later */ #include #include "genrevokecommand.h" #include #include #include #include #include #include #include #include #include #include "kleopatra_debug.h" #include "command_p.h" using namespace Kleo; using namespace Kleo::Commands; using namespace GpgME; GenRevokeCommand::GenRevokeCommand(QAbstractItemView *v, KeyListController *c) : GnuPGProcessCommand(v, c) { } GenRevokeCommand::GenRevokeCommand(KeyListController *c) : GnuPGProcessCommand(c) { } GenRevokeCommand::GenRevokeCommand(const Key &key) : GnuPGProcessCommand(key) { } // Fixup the revocation certificate similar to GnuPG void GenRevokeCommand::postSuccessHook(QWidget *parentWidget) { QFile f(mOutputFileName); if (!f.open(QIODevice::ReadOnly)) { // Should never happen because in this case we would not have had a success. KMessageBox::error(parentWidget, errorCaption(), QStringLiteral("Failed to access the created output file.")); return; } const QString revCert = QString::fromLocal8Bit(f.readAll()); f.close(); if (!f.open(QIODevice::WriteOnly)) { KMessageBox::error(parentWidget, errorCaption(), QStringLiteral("Failed to write to the created output file.")); return; } QTextStream s(&f); s << i18n("This is a revocation certificate for the OpenPGP key:") << "\n\n " << Formatting::prettyNameAndEMail(d->key()) << "\n Fingerprint: " << d->key().primaryFingerprint() << "\n\n" << i18n("A revocation certificate is a kind of \"kill switch\" to publicly\n" "declare that a key shall not anymore be used. It is not possible\n" "to retract such a revocation certificate once it has been published.") << "\n\n" << i18n("Use it to revoke this key in case of a compromise or loss of\n" "the secret key.") << "\n\n" << i18n("To avoid an accidental use of this file, a colon has been inserted\n" "before the 5 dashes below. Remove this colon with a text editor\n" "before importing and publishing this revocation certificate.") << "\n\n:" << revCert; s.flush(); qCDebug(KLEOPATRA_LOG) << "revocation certificate stored as:" << mOutputFileName; f.close(); KMessageBox::information(d->parentWidgetOrView(), i18nc("@info", "Certificate successfully created.

" "Note:
To prevent accidental import of the revocation
" "it is required to manually edit the certificate
" "before it can be imported."), i18n("Revocation certificate created")); } /* Well not much to do with GnuPGProcessCommand anymore I guess.. */ void GenRevokeCommand::doStart() { while (mOutputFileName.isEmpty()) { mOutputFileName = QFileDialog::getSaveFileName(d->parentWidgetOrView(), i18n("Generate revocation certificate"), QString(), QStringLiteral("%1 (*.rev)").arg(i18n("Revocation Certificates "))); if (mOutputFileName.isEmpty()) { d->finished(); return; } if (!mOutputFileName.endsWith(QLatin1String(".rev"))) { mOutputFileName += QLatin1String(".rev"); } if (QFileInfo(mOutputFileName).exists()) { auto sel = KMessageBox::questionYesNo(d->parentWidgetOrView(), i18n("The file %1 already exists.\n" "Overwrite?", mOutputFileName), i18n("Overwrite Existing File?")); if (sel == KMessageBox::No) { mOutputFileName = QString(); } } } auto proc = process(); // We do custom io - disconnect(proc, SIGNAL(readyReadStandardError()), - this, SLOT(slotProcessReadyReadStandardError())); + disconnect(proc, &QProcess::readyReadStandardError, this, nullptr); proc->setReadChannel(QProcess::StandardOutput); GnuPGProcessCommand::doStart(); connect(proc, &QProcess::readyReadStandardOutput, this, [proc] () { while (proc->canReadLine()) { const QString line = QString::fromUtf8(proc->readLine()).trimmed(); // Command-fd is a stable interface, while this is all kind of hacky we // are on a deadline :-/ if (line == QLatin1String("[GNUPG:] GET_BOOL gen_revoke.okay")) { proc->write("y\n"); } else if (line == QLatin1String("[GNUPG:] GET_LINE ask_revocation_reason.code")) { proc->write("0\n"); } else if (line == QLatin1String("[GNUPG:] GET_LINE ask_revocation_reason.text")) { proc->write("\n"); } else if (line == QLatin1String("[GNUPG:] GET_BOOL openfile.overwrite.okay")) { // We asked before proc->write("y\n"); } else if (line == QLatin1String("[GNUPG:] GET_BOOL ask_revocation_reason.okay")) { proc->write("y\n"); } } }); } QStringList GenRevokeCommand::arguments() const { const Key key = d->key(); QStringList result; result << gpgPath() << QStringLiteral("--command-fd") << QStringLiteral("0") << QStringLiteral("--status-fd") << QStringLiteral("1") << QStringLiteral("-o") << mOutputFileName << QStringLiteral("--gen-revoke") << QLatin1String(key.primaryFingerprint()); return result; } QString GenRevokeCommand::errorCaption() const { return i18nc("@title:window", "Error creating revocation certificate"); } QString GenRevokeCommand::crashExitMessage(const QStringList &) const { // We show a success message so a failure is either the user aborted // or a bug. qCDebug(KLEOPATRA_LOG) << "Crash exit of GenRevokeCommand"; return QString(); } QString GenRevokeCommand::errorExitMessage(const QStringList &) const { // We show a success message so a failure is either the user aborted // or a bug. qCDebug(KLEOPATRA_LOG) << "Error exit of GenRevokeCommand"; return QString(); } diff --git a/src/commands/gnupgprocesscommand.cpp b/src/commands/gnupgprocesscommand.cpp index c5ac41e90..70402df67 100644 --- a/src/commands/gnupgprocesscommand.cpp +++ b/src/commands/gnupgprocesscommand.cpp @@ -1,381 +1,379 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/gnupgprocesscommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "gnupgprocesscommand.h" #include "command_p.h" #include #include "kleopatra_debug.h" #include #include #include #include #include #include #include #include #include #include #include #include static const int PROCESS_TERMINATE_TIMEOUT = 5000; // milliseconds using namespace Kleo; using namespace Kleo::Commands; namespace { class OutputDialog : public QDialog { Q_OBJECT public: explicit OutputDialog(QWidget *parent = nullptr) : QDialog(parent), vlay(this), logTextWidget(this), buttonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Close, Qt::Horizontal, this) { KDAB_SET_OBJECT_NAME(vlay); KDAB_SET_OBJECT_NAME(logTextWidget); KDAB_SET_OBJECT_NAME(buttonBox); logTextWidget.setReadOnly(true); vlay.addWidget(&logTextWidget, 1); vlay.addWidget(&buttonBox); connect(closeButton(), &QAbstractButton::clicked, this, &QWidget::close); connect(cancelButton(), &QAbstractButton::clicked, this, &OutputDialog::slotCancelClicked); resize(600, 500); } Q_SIGNALS: void cancelRequested(); public Q_SLOTS: void message(const QString &s) { logTextWidget.append(s); logTextWidget.ensureCursorVisible(); } void setComplete(bool complete) { cancelButton()->setVisible(!complete); } private Q_SLOTS: void slotCancelClicked() { cancelButton()->hide(); Q_EMIT cancelRequested(); } private: QAbstractButton *closeButton() const { return buttonBox.button(QDialogButtonBox::Close); } QAbstractButton *cancelButton() const { return buttonBox.button(QDialogButtonBox::Cancel); } private: QVBoxLayout vlay; QTextEdit logTextWidget; QDialogButtonBox buttonBox; }; } class GnuPGProcessCommand::Private : Command::Private { friend class ::Kleo::Commands::GnuPGProcessCommand; GnuPGProcessCommand *q_func() const { return static_cast(q); } public: explicit Private(GnuPGProcessCommand *qq, KeyListController *c); ~Private() override; private: void init(); void ensureDialogCreated() { if (!showsOutputWindow) { return; } if (!dialog) { dialog = new OutputDialog; dialog->setAttribute(Qt::WA_DeleteOnClose); applyWindowID(dialog); connect(dialog.data(), &OutputDialog::cancelRequested, q, &Command::cancel); dialog->setWindowTitle(i18nc("@title:window", "Subprocess Diagnostics")); } } void ensureDialogVisible() { if (!showsOutputWindow) { return; } ensureDialogCreated(); if (dialog->isVisible()) { dialog->raise(); } else { dialog->show(); } #ifdef Q_OS_WIN KWindowSystem::forceActiveWindow(dialog->winId()); #endif } void message(const QString &msg) { if (dialog) { dialog->message(msg); } else { qCDebug(KLEOPATRA_LOG) << msg; } } private: void slotProcessFinished(int, QProcess::ExitStatus); void slotProcessReadyReadStandardError(); private: QProcess process; QPointer dialog; QStringList arguments; QByteArray errorBuffer; bool ignoresSuccessOrFailure; bool showsOutputWindow; bool canceled; }; GnuPGProcessCommand::Private *GnuPGProcessCommand::d_func() { return static_cast(d.get()); } const GnuPGProcessCommand::Private *GnuPGProcessCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() GnuPGProcessCommand::Private::Private(GnuPGProcessCommand *qq, KeyListController *c) : Command::Private(qq, c), process(), dialog(), errorBuffer(), ignoresSuccessOrFailure(false), showsOutputWindow(false), canceled(false) { process.setReadChannel(QProcess::StandardError); } GnuPGProcessCommand::Private::~Private() {} GnuPGProcessCommand::GnuPGProcessCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } GnuPGProcessCommand::GnuPGProcessCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } GnuPGProcessCommand::GnuPGProcessCommand(const GpgME::Key &key) : Command(key, new Private(this, nullptr)) { d->init(); } void GnuPGProcessCommand::Private::init() { - connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)), - q, SLOT(slotProcessFinished(int,QProcess::ExitStatus))); - connect(&process, SIGNAL(readyReadStandardError()), - q, SLOT(slotProcessReadyReadStandardError())); + connect(&process, &QProcess::finished, q, [this](int exitCode, QProcess::ExitStatus status) { slotProcessFinished(exitCode, status); }); + connect(&process, &QProcess::readyReadStandardError, q, [this]() { slotProcessReadyReadStandardError(); }); } GnuPGProcessCommand::~GnuPGProcessCommand() {} QDialog *GnuPGProcessCommand::dialog() const { return d->dialog; } bool GnuPGProcessCommand::preStartHook(QWidget *) const { return true; } void GnuPGProcessCommand::postSuccessHook(QWidget *) { } void GnuPGProcessCommand::doStart() { if (!preStartHook(d->parentWidgetOrView())) { d->finished(); return; } d->arguments = arguments(); d->process.setProgram(d->arguments.takeFirst()); d->process.setArguments(d->arguments); // Historically code using this expects arguments first to be the program. d->arguments.prepend(d->process.program()); d->process.start(); if (!d->process.waitForStarted()) { d->error(i18n("Unable to start process %1. " "Please check your installation.", d->arguments[0]), errorCaption()); d->finished(); } else { d->ensureDialogVisible(); d->message(i18n("Starting %1...", d->arguments.join(QLatin1Char(' ')))); } } void GnuPGProcessCommand::doCancel() { d->canceled = true; if (d->process.state() != QProcess::NotRunning) { d->process.terminate(); QTimer::singleShot(PROCESS_TERMINATE_TIMEOUT, &d->process, &QProcess::kill); } } void GnuPGProcessCommand::Private::slotProcessFinished(int code, QProcess::ExitStatus status) { if (!canceled) { if (status == QProcess::CrashExit) { const QString msg = q->crashExitMessage(arguments); if (!msg.isEmpty()) { error(msg, q->errorCaption()); } } else if (ignoresSuccessOrFailure) { if (dialog) { message(i18n("Process finished")); } else { ; } } else if (code) { const QString msg = q->errorExitMessage(arguments); if (!msg.isEmpty()) { error(q->errorExitMessage(arguments), q->errorCaption()); } } else { q->postSuccessHook(parentWidgetOrView()); const QString successMessage = q->successMessage(arguments); if (!successMessage.isNull()) { if (dialog) { message(successMessage); } else { information(successMessage, q->successCaption()); } } } } if (dialog) { dialog->setComplete(true); } finished(); } void GnuPGProcessCommand::Private::slotProcessReadyReadStandardError() { auto ba = process.readAllStandardError(); errorBuffer += ba; while (ba.endsWith('\n') || ba.endsWith('\r')) { ba.chop(1); } message(Kleo::stringFromGpgOutput(ba)); } QString GnuPGProcessCommand::errorString() const { return Kleo::stringFromGpgOutput(d->errorBuffer); } void GnuPGProcessCommand::setIgnoresSuccessOrFailure(bool ignores) { d->ignoresSuccessOrFailure = ignores; } bool GnuPGProcessCommand::ignoresSuccessOrFailure() const { return d->ignoresSuccessOrFailure; } void GnuPGProcessCommand::setShowsOutputWindow(bool show) { if (show == d->showsOutputWindow) { return; } d->showsOutputWindow = show; if (show) { d->ensureDialogCreated(); } else { if (d->dialog) { d->dialog->deleteLater(); } d->dialog = nullptr; } } bool GnuPGProcessCommand::showsOutputWindow() const { return d->showsOutputWindow; } QProcess *GnuPGProcessCommand::process() { return &d->process; } QString GnuPGProcessCommand::successCaption() const { return QString(); } QString GnuPGProcessCommand::successMessage(const QStringList &args) const { Q_UNUSED(args) return QString(); } #undef d #undef q #include "moc_gnupgprocesscommand.cpp" #include "gnupgprocesscommand.moc" diff --git a/src/commands/gnupgprocesscommand.h b/src/commands/gnupgprocesscommand.h index 33cd30325..a9caf4e98 100644 --- a/src/commands/gnupgprocesscommand.h +++ b/src/commands/gnupgprocesscommand.h @@ -1,71 +1,69 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/gnupgprocesscommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include class QString; class QProcess; namespace Kleo { namespace Commands { class GnuPGProcessCommand : public Command { Q_OBJECT protected: explicit GnuPGProcessCommand(QAbstractItemView *view, KeyListController *parent); explicit GnuPGProcessCommand(KeyListController *parent); explicit GnuPGProcessCommand(const GpgME::Key &key); ~GnuPGProcessCommand() override; public: QDialog *dialog() const; void setShowsOutputWindow(bool show); private: virtual bool preStartHook(QWidget *parentWidget) const; virtual QStringList arguments() const = 0; virtual QString errorCaption() const = 0; virtual QString successCaption() const; virtual QString crashExitMessage(const QStringList &args) const = 0; virtual QString errorExitMessage(const QStringList &args) const = 0; virtual QString successMessage(const QStringList &args) const; virtual void postSuccessHook(QWidget *parentWidget); protected: QString errorString() const; void setIgnoresSuccessOrFailure(bool ignore); bool ignoresSuccessOrFailure() const; bool showsOutputWindow() const; QProcess *process(); void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotProcessFinished(int, QProcess::ExitStatus)) - Q_PRIVATE_SLOT(d_func(), void slotProcessReadyReadStandardError()) }; } } diff --git a/src/commands/importcertificatescommand.cpp b/src/commands/importcertificatescommand.cpp index c0e2ef694..a4c1685f0 100644 --- a/src/commands/importcertificatescommand.cpp +++ b/src/commands/importcertificatescommand.cpp @@ -1,1009 +1,1007 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/importcertificatescommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007, 2008 Klarälvdalens Datakonsult AB SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik SPDX-FileContributor: Intevation GmbH SPDX-FileCopyrightText: 2021, 2022 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "importcertificatescommand.h" #include "importcertificatescommand_p.h" #include "certifycertificatecommand.h" #include #include "kleopatra_debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef QGPGME_SUPPORTS_RECEIVING_KEYS_BY_KEY_ID #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include // for Qt::escape #include #include #include #include using namespace GpgME; using namespace Kleo; using namespace QGpgME; bool operator==(const ImportJobData &lhs, const ImportJobData &rhs) { return lhs.job == rhs.job; } namespace { make_comparator_str(ByImportFingerprint, .fingerprint()); class ImportResultProxyModel : public AbstractKeyListSortFilterProxyModel { Q_OBJECT public: ImportResultProxyModel(const std::vector &results, QObject *parent = nullptr) : AbstractKeyListSortFilterProxyModel(parent) { updateFindCache(results); } ~ImportResultProxyModel() override {} ImportResultProxyModel *clone() const override { // compiler-generated copy ctor is fine! return new ImportResultProxyModel(*this); } void setImportResults(const std::vector &results) { updateFindCache(results); invalidateFilter(); } protected: QVariant data(const QModelIndex &index, int role) const override { if (!index.isValid() || role != Qt::ToolTipRole) { return AbstractKeyListSortFilterProxyModel::data(index, role); } const QString fpr = index.data(KeyList::FingerprintRole).toString(); // find information: const std::vector::const_iterator it = Kleo::binary_find(m_importsByFingerprint.begin(), m_importsByFingerprint.end(), fpr.toLatin1().constData(), ByImportFingerprint()); if (it == m_importsByFingerprint.end()) { return AbstractKeyListSortFilterProxyModel::data(index, role); } else { QStringList rv; const auto ids = m_idsByFingerprint[it->fingerprint()]; rv.reserve(ids.size()); std::copy(ids.cbegin(), ids.cend(), std::back_inserter(rv)); return Formatting::importMetaData(*it, rv); } } bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override { // // 0. Keep parents of matching children: // const QModelIndex index = sourceModel()->index(source_row, 0, source_parent); Q_ASSERT(index.isValid()); for (int i = 0, end = sourceModel()->rowCount(index); i != end; ++i) if (filterAcceptsRow(i, index)) { return true; } // // 1. Check that this is an imported key: // const QString fpr = index.data(KeyList::FingerprintRole).toString(); return std::binary_search(m_importsByFingerprint.begin(), m_importsByFingerprint.end(), fpr.toLatin1().constData(), ByImportFingerprint()); } private: void updateFindCache(const std::vector &results) { m_importsByFingerprint.clear(); m_idsByFingerprint.clear(); m_results = results; for (const auto &r : results) { const std::vector imports = r.result.imports(); m_importsByFingerprint.insert(m_importsByFingerprint.end(), imports.begin(), imports.end()); for (std::vector::const_iterator it = imports.begin(), end = imports.end(); it != end; ++it) { m_idsByFingerprint[it->fingerprint()].insert(r.id); } } std::sort(m_importsByFingerprint.begin(), m_importsByFingerprint.end(), ByImportFingerprint()); } private: mutable std::vector m_importsByFingerprint; mutable std::map< const char *, std::set, ByImportFingerprint > m_idsByFingerprint; std::vector m_results; }; bool importFailed(const ImportResultData &r) { // ignore GPG_ERR_EOF error to handle the "failed" import of files // without X.509 certificates by gpgsm gracefully return r.result.error() && r.result.error().code() != GPG_ERR_EOF; } bool importWasCanceled(const ImportResultData &r) { return r.result.error().isCanceled(); } } ImportCertificatesCommand::Private::Private(ImportCertificatesCommand *qq, KeyListController *c) : Command::Private(qq, c) , progressWindowTitle{i18nc("@title:window", "Importing Certificates")} , progressLabelText{i18n("Importing certificates... (this can take a while)")} { } ImportCertificatesCommand::Private::~Private() { if (progressDialog) { delete progressDialog; } } #define d d_func() #define q q_func() ImportCertificatesCommand::ImportCertificatesCommand(KeyListController *p) : Command(new Private(this, p)) { } ImportCertificatesCommand::ImportCertificatesCommand(QAbstractItemView *v, KeyListController *p) : Command(v, new Private(this, p)) { } ImportCertificatesCommand::~ImportCertificatesCommand() = default; static QString format_ids(const std::vector &ids) { QStringList escapedIds; for (const QString &id : ids) { if (!id.isEmpty()) { escapedIds << id.toHtmlEscaped(); } } return escapedIds.join(QLatin1String("
")); } static QString make_tooltip(const std::vector &results) { if (results.empty()) { return {}; } std::vector ids; ids.reserve(results.size()); std::transform(std::begin(results), std::end(results), std::back_inserter(ids), [](const auto &r) { return r.id; }); std::sort(std::begin(ids), std::end(ids)); ids.erase(std::unique(std::begin(ids), std::end(ids)), std::end(ids)); if (ids.size() == 1) if (ids.front().isEmpty()) { return {}; } else return i18nc("@info:tooltip", "Imported Certificates from %1", ids.front().toHtmlEscaped()); else return i18nc("@info:tooltip", "Imported certificates from these sources:
%1", format_ids(ids)); } void ImportCertificatesCommand::Private::setImportResultProxyModel(const std::vector &results) { if (std::none_of(std::begin(results), std::end(results), [](const auto &r) { return r.result.numConsidered() > 0; })) { return; } q->addTemporaryView(i18nc("@title:tab", "Imported Certificates"), new ImportResultProxyModel(results), make_tooltip(results)); if (QTreeView *const tv = qobject_cast(parentWidgetOrView())) { tv->expandAll(); } } int sum(const std::vector &res, int (ImportResult::*fun)() const) { return kdtools::accumulate_transform(res.begin(), res.end(), std::mem_fn(fun), 0); } static QString make_report(const std::vector &results, const std::vector &groups) { const KLocalizedString normalLine = ki18n("%1%2"); const KLocalizedString boldLine = ki18n("%1%2"); const KLocalizedString headerLine = ki18n("%1"); std::vector res; res.reserve(results.size()); std::transform(std::begin(results), std::end(results), std::back_inserter(res), [](const auto &r) { return r.result; }); const auto numProcessedCertificates = sum(res, &ImportResult::numConsidered); QStringList lines; if (numProcessedCertificates > 0 || groups.size() == 0) { lines.push_back(headerLine.subs(i18n("Certificates")).toString()); lines.push_back(normalLine.subs(i18n("Total number processed:")) .subs(numProcessedCertificates).toString()); lines.push_back(normalLine.subs(i18n("Imported:")) .subs(sum(res, &ImportResult::numImported)).toString()); if (const int n = sum(res, &ImportResult::newSignatures)) lines.push_back(normalLine.subs(i18n("New signatures:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::newUserIDs)) lines.push_back(normalLine.subs(i18n("New user IDs:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::numKeysWithoutUserID)) lines.push_back(normalLine.subs(i18n("Certificates without user IDs:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::newSubkeys)) lines.push_back(normalLine.subs(i18n("New subkeys:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::newRevocations)) lines.push_back(boldLine.subs(i18n("Newly revoked:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::notImported)) lines.push_back(boldLine.subs(i18n("Not imported:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::numUnchanged)) lines.push_back(normalLine.subs(i18n("Unchanged:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::numSecretKeysConsidered)) lines.push_back(normalLine.subs(i18n("Secret keys processed:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::numSecretKeysImported)) lines.push_back(normalLine.subs(i18n("Secret keys imported:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::numSecretKeysConsidered) - sum(res, &ImportResult::numSecretKeysImported) - sum(res, &ImportResult::numSecretKeysUnchanged)) if (n > 0) lines.push_back(boldLine.subs(i18n("Secret keys not imported:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::numSecretKeysUnchanged)) lines.push_back(normalLine.subs(i18n("Secret keys unchanged:")) .subs(n).toString()); if (const int n = sum(res, &ImportResult::numV3KeysSkipped)) lines.push_back(normalLine.subs(i18n("Deprecated PGP-2 keys skipped:")) .subs(n).toString()); } if (!lines.empty()) { lines.push_back(headerLine.subs(QLatin1String{" "}).toString()); } if (groups.size() > 0) { const auto newGroups = std::count_if(std::begin(groups), std::end(groups), [](const auto &g) { return g.status == ImportedGroup::Status::New; }); const auto updatedGroups = groups.size() - newGroups; lines.push_back(headerLine.subs(i18n("Certificate Groups")).toString()); lines.push_back(normalLine.subs(i18n("Total number processed:")) .subs(groups.size()).toString()); lines.push_back(normalLine.subs(i18n("New groups:")) .subs(newGroups).toString()); lines.push_back(normalLine.subs(i18n("Updated groups:")) .subs(updatedGroups).toString()); } return lines.join(QLatin1String{}); } static QString make_message_report(const std::vector &res, const std::vector &groups) { QString report{QLatin1String{""}}; if (res.empty()) { report += i18n("No imports (should not happen, please report a bug)."); } else { const bool singleSource = (res.size() == 1) || (res.size() == 2 && res[0].id == res[1].id); const QString title = singleSource && !res.front().id.isEmpty() ? i18n("Detailed results of importing %1:", res.front().id) : i18n("Detailed results of import:"); report += QLatin1String{"

"} + title + QLatin1String{"

"}; report += QLatin1String{"

"}; report += make_report(res, groups); report += QLatin1String{"

"}; } report += QLatin1String{""}; return report; } // Returns false on error, true if please certify was shown. bool ImportCertificatesCommand::Private::showPleaseCertify(const GpgME::Import &imp) { const char *fpr = imp.fingerprint(); if (!fpr) { // WTF qCWarning(KLEOPATRA_LOG) << "Import without fingerprint"; return false; } // Exactly one public key imported. Let's see if it is openpgp. We are async here so // we can just fetch it. auto ctx = GpgME::Context::createForProtocol(GpgME::OpenPGP); if (!ctx) { // WTF qCWarning(KLEOPATRA_LOG) << "Failed to create OpenPGP proto"; return false; } GpgME::Error err; auto key = ctx->key(fpr, err, false); delete ctx; if (key.isNull() || err) { // No such key most likely not OpenPGP return false; } for (const auto &uid: key.userIDs()) { if (uid.validity() >= GpgME::UserID::Marginal) { // Already marginal so don't bug the user return false; } } const QStringList suggestions = QStringList() << i18n("A phone call to the person.") << i18n("Using a business card.") << i18n("Confirming it on a trusted website."); auto sel = KMessageBox::questionYesNo(parentWidgetOrView(), i18n("In order to mark the certificate as valid (green) it needs to be certified.") + QStringLiteral("
") + i18n("Certifying means that you check the Fingerprint.") + QStringLiteral("
") + i18n("Some suggestions to do this are:") + QStringLiteral("
    • %1").arg(suggestions.join(QStringLiteral("
      "))) + QStringLiteral("
  • ") + i18n("Do you wish to start this process now?"), i18nc("@title", "You have imported a new certificate (public key)"), KStandardGuiItem::yes(), KStandardGuiItem::no(), QStringLiteral("CertifyQuestion")); if (sel == KMessageBox::Yes) { QEventLoop loop; auto cmd = new Commands::CertifyCertificateCommand(key); cmd->setParentWidget(parentWidgetOrView()); - loop.connect(cmd, SIGNAL(finished()), SLOT(quit())); + connect(cmd, &Command::finished, &loop, &QEventLoop::quit); QMetaObject::invokeMethod(cmd, &Commands::CertifyCertificateCommand::start, Qt::QueuedConnection); loop.exec(); } return true; } void ImportCertificatesCommand::Private::showDetails(const std::vector &res, const std::vector &groups) { if (res.size() == 1 && res[0].result.numImported() == 1 && res[0].result.imports().size() == 1) { if (showPleaseCertify(res[0].result.imports()[0])) { return; } } setImportResultProxyModel(res); information(make_message_report(res, groups), i18n("Certificate Import Result")); } static QString make_error_message(const Error &err, const QString &id) { Q_ASSERT(err); Q_ASSERT(!err.isCanceled()); return id.isEmpty() ? i18n("

    An error occurred while trying " "to import the certificate:

    " "

    %1

    ", QString::fromLocal8Bit(err.asString())) : i18n("

    An error occurred while trying " "to import the certificate %1:

    " "

    %2

    ", id, QString::fromLocal8Bit(err.asString())); } void ImportCertificatesCommand::Private::showError(QWidget *parent, const Error &err, const QString &id) { if (parent) { KMessageBox::error(parent, make_error_message(err, id), i18n("Certificate Import Failed")); } else { showError(err, id); } } void ImportCertificatesCommand::Private::showError(const Error &err, const QString &id) { error(make_error_message(err, id), i18n("Certificate Import Failed")); } void ImportCertificatesCommand::Private::setWaitForMoreJobs(bool wait) { if (wait == waitForMoreJobs) { return; } waitForMoreJobs = wait; if (!waitForMoreJobs) { tryToFinish(); } } void ImportCertificatesCommand::Private::importResult(const ImportResult &result, QGpgME::Job *finishedJob) { if (!finishedJob) { finishedJob = qobject_cast(q->sender()); } Q_ASSERT(finishedJob); auto it = std::find_if(std::cbegin(jobs), std::cend(jobs), [finishedJob](const auto &job) { return job.job == finishedJob; }); Q_ASSERT(it != std::cend(jobs)); if (it == std::cend(jobs)) { qCWarning(KLEOPATRA_LOG) << __func__ << "Error: Finished job not found"; return; } const auto job = *it; jobs.erase(std::remove(std::begin(jobs), std::end(jobs), job), std::end(jobs)); increaseProgressValue(); importResult({job.id, job.protocol, job.type, result}); } void ImportCertificatesCommand::Private::importResult(const ImportResultData &result) { qCDebug(KLEOPATRA_LOG) << __func__ << result.id; results.push_back(result); tryToFinish(); } static void handleOwnerTrust(const std::vector &results) { //iterate over all imported certificates for (const auto &r: results) { //when a new certificate got a secret key if (r.result.numSecretKeysImported() >= 1) { const char *fingerPr = r.result.imports()[0].fingerprint(); GpgME::Error err; QScopedPointer ctx(Context::createForProtocol(GpgME::Protocol::OpenPGP)); if (!ctx){ qCWarning(KLEOPATRA_LOG) << "Failed to get context"; continue; } const Key toTrustOwner = ctx->key(fingerPr, err , false); if (toTrustOwner.isNull()) { return; } QStringList uids; const auto toTrustOwnerUserIDs{toTrustOwner.userIDs()}; uids.reserve(toTrustOwnerUserIDs.size()); for (const UserID &uid : toTrustOwnerUserIDs) { uids << Formatting::prettyNameAndEMail(uid); } const QString str = xi18nc("@info", "You have imported a Secret Key." "The key has the fingerprint:" "%1" "" "And claims the user IDs:" "%2" "" "Is this your own key? (Set trust level to ultimate)", QString::fromUtf8(fingerPr), uids.join(QLatin1String(""))); int k = KMessageBox::questionYesNo(nullptr, str, i18nc("@title:window", "Secret key imported")); if (k == KMessageBox::Yes) { //To use the ChangeOwnerTrustJob over //the CryptoBackendFactory const QGpgME::Protocol *const backend = QGpgME::openpgp(); if (!backend){ qCWarning(KLEOPATRA_LOG) << "Failed to get CryptoBackend"; return; } ChangeOwnerTrustJob *const j = backend->changeOwnerTrustJob(); j->start(toTrustOwner, Key::Ultimate); } } } } static void validateImportedCertificate(const GpgME::Import &import) { if (const auto fpr = import.fingerprint()) { auto key = KeyCache::instance()->findByFingerprint(fpr); if (!key.isNull()) { // this triggers a keylisting with validation for this certificate key.update(); } else { qCWarning(KLEOPATRA_LOG) << __func__ << "Certificate with fingerprint" << fpr << "not found"; } } } static void handleExternalCMSImports(const std::vector &results) { // For external CMS Imports we have to manually do a keylist // with validation to get the intermediate and root ca imported // automatically if trusted-certs and extra-certs are used. for (const auto &r : results) { if (r.protocol == GpgME::CMS && r.type == ImportType::External && !importFailed(r) && !importWasCanceled(r)) { const auto imports = r.result.imports(); std::for_each(std::begin(imports), std::end(imports), &validateImportedCertificate); } } } void ImportCertificatesCommand::Private::processResults() { importGroups(); #ifdef QGPGME_SUPPORTS_RECEIVING_KEYS_BY_KEY_ID if (Settings{}.retrieveSignerKeysAfterImport() && !importingSignerKeys) { importingSignerKeys = true; const auto missingSignerKeys = getMissingSignerKeyIds(results); if (!missingSignerKeys.empty()) { importSignerKeys(missingSignerKeys); return; } } #endif handleExternalCMSImports(results); // ensure that the progress dialog is closed before we show any other dialogs setProgressToMaximum(); handleOwnerTrust(results); showDetails(results, importedGroups); auto tv = dynamic_cast (view()); if (!tv) { qCDebug(KLEOPATRA_LOG) << "Failed to find treeview"; } else { tv->expandAll(); } finished(); } void ImportCertificatesCommand::Private::tryToFinish() { if (waitForMoreJobs || !jobs.empty()) { return; } auto keyCache = KeyCache::mutableInstance(); keyListConnection = connect(keyCache.get(), &KeyCache::keyListingDone, q, [this]() { keyCacheUpdated(); }); keyCache->startKeyListing(); } void ImportCertificatesCommand::Private::keyCacheUpdated() { disconnect(keyListConnection); keyCacheAutoRefreshSuspension.reset(); const auto allIds = std::accumulate(std::cbegin(results), std::cend(results), std::set{}, [](auto &allIds, const auto &r) { allIds.insert(r.id); return allIds; }); const auto canceledIds = std::accumulate(std::cbegin(results), std::cend(results), std::set{}, [](auto &canceledIds, const auto &r) { if (importWasCanceled(r)) { canceledIds.insert(r.id); } return canceledIds; }); const auto totalConsidered = std::accumulate(std::cbegin(results), std::cend(results), 0, [](auto totalConsidered, const auto &r) { return totalConsidered + r.result.numConsidered(); }); if (totalConsidered == 0 && canceledIds.size() == allIds.size()) { // nothing was considered for import and at least one import per id was // canceled => treat the command as canceled canceled(); return; } if (std::any_of(std::cbegin(results), std::cend(results), &importFailed)) { // ensure that the progress dialog is closed before we show any other dialogs setProgressToMaximum(); setImportResultProxyModel(results); for (const auto &r : results) { if (importFailed(r)) { showError(r.result.error(), r.id); } } finished(); return; } processResults(); } static ImportedGroup storeGroup(const KeyGroup &group, const QString &id) { const auto status = KeyCache::instance()->group(group.id()).isNull() ? ImportedGroup::Status::New : ImportedGroup::Status::Updated; if (status == ImportedGroup::Status::New) { KeyCache::mutableInstance()->insert(group); } else { KeyCache::mutableInstance()->update(group); } return {id, group, status}; } void ImportCertificatesCommand::Private::importGroups() { for (const auto &path : filesToImportGroupsFrom) { const bool certificateImportSucceeded = std::any_of(std::cbegin(results), std::cend(results), [path](const auto &r) { return r.id == path && !importFailed(r) && !importWasCanceled(r); }); if (certificateImportSucceeded) { qCDebug(KLEOPATRA_LOG) << __func__ << "Importing groups from file" << path; const auto groups = readKeyGroups(path); std::transform(std::begin(groups), std::end(groups), std::back_inserter(importedGroups), [path](const auto &group) { return storeGroup(group, path); }); } increaseProgressValue(); } filesToImportGroupsFrom.clear(); } static auto accumulateNewKeys(std::vector &fingerprints, const std::vector &imports) { return std::accumulate(std::begin(imports), std::end(imports), fingerprints, [](auto &fingerprints, const auto &import) { if (import.status() == Import::NewKey) { fingerprints.push_back(import.fingerprint()); } return fingerprints; }); } static auto accumulateNewOpenPGPKeys(const std::vector &results) { return std::accumulate(std::begin(results), std::end(results), std::vector{}, [](auto &fingerprints, const auto &r) { if (r.protocol == GpgME::OpenPGP) { fingerprints = accumulateNewKeys(fingerprints, r.result.imports()); } return fingerprints; }); } std::set ImportCertificatesCommand::Private::getMissingSignerKeyIds(const std::vector &results) { auto newOpenPGPKeys = KeyCache::instance()->findByFingerprint(accumulateNewOpenPGPKeys(results)); // update all new OpenPGP keys to get information about certifications std::for_each(std::begin(newOpenPGPKeys), std::end(newOpenPGPKeys), std::mem_fn(&Key::update)); auto missingSignerKeyIds = Kleo::getMissingSignerKeyIds(newOpenPGPKeys); return missingSignerKeyIds; } void ImportCertificatesCommand::Private::importSignerKeys(const std::set &keyIds) { Q_ASSERT(!keyIds.empty()); setProgressLabelText(i18np("Fetching 1 signer key... (this can take a while)", "Fetching %1 signer keys... (this can take a while)", keyIds.size())); setWaitForMoreJobs(true); // start one import per key id to allow canceling the key retrieval without // losing already retrieved keys for (const auto &keyId : keyIds) { startImport(GpgME::OpenPGP, {keyId}, QStringLiteral("Retrieve Signer Keys")); } setWaitForMoreJobs(false); } static std::unique_ptr get_import_job(GpgME::Protocol protocol) { Q_ASSERT(protocol != UnknownProtocol); if (const auto backend = (protocol == GpgME::OpenPGP ? QGpgME::openpgp() : QGpgME::smime())) { return std::unique_ptr(backend->importJob()); } else { return std::unique_ptr(); } } void ImportCertificatesCommand::Private::startImport(GpgME::Protocol protocol, const QByteArray &data, const QString &id, const ImportOptions &options) { Q_ASSERT(protocol != UnknownProtocol); if (std::find(nonWorkingProtocols.cbegin(), nonWorkingProtocols.cend(), protocol) != nonWorkingProtocols.cend()) { return; } std::unique_ptr job = get_import_job(protocol); if (!job.get()) { nonWorkingProtocols.push_back(protocol); error(i18n("The type of this certificate (%1) is not supported by this Kleopatra installation.", Formatting::displayName(protocol)), i18n("Certificate Import Failed")); importResult({id, protocol, ImportType::Local, ImportResult{}}); return; } keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh(); std::vector connections = { - connect(job.get(), SIGNAL(result(GpgME::ImportResult)), - q, SLOT(importResult(GpgME::ImportResult))), + connect(job.get(), &AbstractImportJob::result, q, [this](const GpgME::ImportResult &result) { importResult(result); }), connect(job.get(), &Job::progress, q, &Command::progress) }; #ifdef QGPGME_SUPPORTS_IMPORT_WITH_FILTER job->setImportFilter(options.importFilter); #endif #ifdef QGPGME_SUPPORTS_IMPORT_WITH_KEY_ORIGIN job->setKeyOrigin(options.keyOrigin, options.keyOriginUrl); #endif const GpgME::Error err = job->start(data); if (err.code()) { importResult({id, protocol, ImportType::Local, ImportResult{err}}); } else { increaseProgressMaximum(); jobs.push_back({id, protocol, ImportType::Local, job.release(), connections}); } } static std::unique_ptr get_import_from_keyserver_job(GpgME::Protocol protocol) { Q_ASSERT(protocol != UnknownProtocol); if (const auto backend = (protocol == GpgME::OpenPGP ? QGpgME::openpgp() : QGpgME::smime())) { return std::unique_ptr(backend->importFromKeyserverJob()); } else { return std::unique_ptr(); } } void ImportCertificatesCommand::Private::startImport(GpgME::Protocol protocol, const std::vector &keys, const QString &id) { Q_ASSERT(protocol != UnknownProtocol); if (std::find(nonWorkingProtocols.cbegin(), nonWorkingProtocols.cend(), protocol) != nonWorkingProtocols.cend()) { return; } std::unique_ptr job = get_import_from_keyserver_job(protocol); if (!job.get()) { nonWorkingProtocols.push_back(protocol); error(i18n("The type of this certificate (%1) is not supported by this Kleopatra installation.", Formatting::displayName(protocol)), i18n("Certificate Import Failed")); importResult({id, protocol, ImportType::External, ImportResult{}}); return; } keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh(); std::vector connections = { - connect(job.get(), SIGNAL(result(GpgME::ImportResult)), - q, SLOT(importResult(GpgME::ImportResult))), + connect(job.get(), &AbstractImportJob::result, q, [this](const GpgME::ImportResult &result) { importResult(result); }), connect(job.get(), &Job::progress, q, &Command::progress) }; const GpgME::Error err = job->start(keys); if (err.code()) { importResult({id, protocol, ImportType::External, ImportResult{err}}); } else { increaseProgressMaximum(); jobs.push_back({id, protocol, ImportType::External, job.release(), connections}); } } static auto get_receive_keys_job(GpgME::Protocol protocol) { Q_ASSERT(protocol != UnknownProtocol); #ifdef QGPGME_SUPPORTS_RECEIVING_KEYS_BY_KEY_ID std::unique_ptr job{}; if (const auto backend = (protocol == GpgME::OpenPGP ? QGpgME::openpgp() : QGpgME::smime())) { job.reset(backend->receiveKeysJob()); } return job; #else return std::unique_ptr{}; #endif } void ImportCertificatesCommand::Private::startImport(GpgME::Protocol protocol, const QStringList &keyIds, const QString &id) { Q_ASSERT(protocol != UnknownProtocol); auto job = get_receive_keys_job(protocol); if (!job.get()) { qCWarning(KLEOPATRA_LOG) << "Failed to get ReceiveKeysJob for protocol" << Formatting::displayName(protocol); importResult({id, protocol, ImportType::External, ImportResult{}}); return; } #ifdef QGPGME_SUPPORTS_RECEIVING_KEYS_BY_KEY_ID keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh(); std::vector connections = { connect(job.get(), SIGNAL(result(GpgME::ImportResult)), q, SLOT(importResult(GpgME::ImportResult))), connect(job.get(), &Job::progress, q, &Command::progress) }; const GpgME::Error err = job->start(keyIds); if (err.code()) { importResult({id, protocol, ImportType::External, ImportResult{err}}); } else { increaseProgressMaximum(); jobs.push_back({id, protocol, ImportType::External, job.release(), connections}); } #endif } void ImportCertificatesCommand::Private::importGroupsFromFile(const QString &filename) { increaseProgressMaximum(); filesToImportGroupsFrom.push_back(filename); } void ImportCertificatesCommand::Private::setUpProgressDialog() { if (progressDialog) { return; } progressDialog = new QProgressDialog{parentWidgetOrView()}; progressDialog->setModal(true); progressDialog->setWindowTitle(progressWindowTitle); progressDialog->setLabelText(progressLabelText); progressDialog->setMinimumDuration(1000); progressDialog->setMaximum(1); progressDialog->setValue(0); connect(progressDialog, &QProgressDialog::canceled, q, &Command::cancel); connect(q, &Command::finished, progressDialog, [this]() { progressDialog->accept(); }); } void ImportCertificatesCommand::Private::setProgressWindowTitle(const QString &title) { if (progressDialog) { progressDialog->setWindowTitle(title); } else { progressWindowTitle = title; } } void ImportCertificatesCommand::Private::setProgressLabelText(const QString &text) { if (progressDialog) { progressDialog->setLabelText(text); } else { progressLabelText = text; } } void ImportCertificatesCommand::Private::increaseProgressMaximum() { setUpProgressDialog(); progressDialog->setMaximum(progressDialog->maximum() + 1); qCDebug(KLEOPATRA_LOG) << __func__ << "progress:" << progressDialog->value() << "/" << progressDialog->maximum(); } void ImportCertificatesCommand::Private::increaseProgressValue() { progressDialog->setValue(progressDialog->value() + 1); qCDebug(KLEOPATRA_LOG) << __func__ << "progress:" << progressDialog->value() << "/" << progressDialog->maximum(); } void ImportCertificatesCommand::Private::setProgressToMaximum() { qCDebug(KLEOPATRA_LOG) << __func__; progressDialog->setValue(progressDialog->maximum()); } static void disconnectConnection(const QMetaObject::Connection &connection) { // trivial function for disconnecting a signal-slot connection because // using a lambda seems to confuse older GCC / MinGW and unnecessarily // capturing 'this' generates warnings QObject::disconnect(connection); } void ImportCertificatesCommand::doCancel() { const auto jobsToCancel = d->jobs; std::for_each(std::begin(jobsToCancel), std::end(jobsToCancel), [this](const auto &job) { qCDebug(KLEOPATRA_LOG) << "Canceling job" << job.job; std::for_each(std::cbegin(job.connections), std::cend(job.connections), &disconnectConnection); job.job->slotCancel(); d->importResult(ImportResult{Error::fromCode(GPG_ERR_CANCELED)}, job.job); }); } #undef d #undef q #include "moc_importcertificatescommand.cpp" #include "importcertificatescommand.moc" diff --git a/src/commands/importcrlcommand.cpp b/src/commands/importcrlcommand.cpp index e2170f5aa..f0d79b11c 100644 --- a/src/commands/importcrlcommand.cpp +++ b/src/commands/importcrlcommand.cpp @@ -1,216 +1,214 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/importcrlcommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "importcrlcommand.h" #include "command_p.h" #include #include #include #include #include #include #include static const int PROCESS_TERMINATE_TIMEOUT = 5000; // milliseconds using namespace Kleo; using namespace Kleo::Commands; class ImportCrlCommand::Private : Command::Private { friend class ::Kleo::Commands::ImportCrlCommand; ImportCrlCommand *q_func() const { return static_cast(q); } public: explicit Private(ImportCrlCommand *qq, KeyListController *c); ~Private() override; Q_REQUIRED_RESULT QString errorString() const { return stringFromGpgOutput(errorBuffer); } private: void init(); #ifndef QT_NO_FILEDIALOG QStringList getFileNames() { // loadcrl can only work with DER encoded files // (verified with dirmngr 1.0.3) const QString filter = QStringLiteral("%1 (*.crl *.arl *-crl.der *-arl.der)").arg(i18n("Certificate Revocation Lists, DER encoded")); return QFileDialog::getOpenFileNames(parentWidgetOrView(), i18n("Select CRL File to Import"), QString(), filter); } #endif // QT_NO_FILEDIALOG private: void slotProcessFinished(int, QProcess::ExitStatus); void slotProcessReadyReadStandardError(); private: QStringList files; QProcess process; QByteArray errorBuffer; bool canceled; bool firstRun; }; ImportCrlCommand::Private *ImportCrlCommand::d_func() { return static_cast(d.get()); } const ImportCrlCommand::Private *ImportCrlCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() ImportCrlCommand::Private::Private(ImportCrlCommand *qq, KeyListController *c) : Command::Private(qq, c), files(), process(), errorBuffer(), canceled(false), firstRun(true) { process.setProgram (gpgSmPath()); process.setArguments(QStringList() << QStringLiteral("--call-dirmngr") << QStringLiteral("loadcrl")); } ImportCrlCommand::Private::~Private() {} ImportCrlCommand::ImportCrlCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } ImportCrlCommand::ImportCrlCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } ImportCrlCommand::ImportCrlCommand(const QStringList &files, KeyListController *c) : Command(new Private(this, c)) { d->init(); d->files = files; } ImportCrlCommand::ImportCrlCommand(const QStringList &files, QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); d->files = files; } void ImportCrlCommand::Private::init() { - connect(&process, SIGNAL(finished(int,QProcess::ExitStatus)), - q, SLOT(slotProcessFinished(int,QProcess::ExitStatus))); - connect(&process, SIGNAL(readyReadStandardError()), - q, SLOT(slotProcessReadyReadStandardError())); + connect(&process, &QProcess::finished, q, [this](int exitCode, QProcess::ExitStatus status) { slotProcessFinished(exitCode, status); }); + connect(&process, &QProcess::readyReadStandardError, q, [this]() { slotProcessReadyReadStandardError(); }); } ImportCrlCommand::~ImportCrlCommand() {} void ImportCrlCommand::setFiles(const QStringList &files) { d->files = files; } void ImportCrlCommand::doStart() { #ifndef QT_NO_FILEDIALOG if (d->files.empty()) { d->files = d->getFileNames(); } #endif // QT_NO_FILEDIALOG if (d->files.empty()) { Q_EMIT canceled(); d->finished(); return; } auto args = d->process.arguments(); if (!d->firstRun) { /* remove the last file */ args.pop_back(); } args << d->files.takeFirst(); d->process.setArguments(args); d->process.start(); d->firstRun = false; if (!d->process.waitForStarted()) { d->error(i18n("Unable to start process dirmngr. " "Please check your installation."), i18n("Clear CRL Cache Error")); d->finished(); } } void ImportCrlCommand::doCancel() { d->canceled = true; if (d->process.state() != QProcess::NotRunning) { d->process.terminate(); QTimer::singleShot(PROCESS_TERMINATE_TIMEOUT, &d->process, &QProcess::kill); } } void ImportCrlCommand::Private::slotProcessFinished(int code, QProcess::ExitStatus status) { if (!canceled) { if (status == QProcess::CrashExit) error(i18n("The GpgSM process that tried to import the CRL file " "ended prematurely because of an unexpected error. " "Please check the output of gpgsm --call-dirmngr loadcrl for details."), i18n("Import CRL Error")); else if (code) error(i18n("An error occurred while trying to import the CRL file. " "The output from gpgsm was:\n%1", errorString()), i18n("Import CRL Error")); else if (files.empty()) information(i18n("CRL file imported successfully."), i18n("Import CRL Finished")); } if (!files.empty()) { q->doStart(); return; } finished(); } void ImportCrlCommand::Private::slotProcessReadyReadStandardError() { errorBuffer += process.readAllStandardError(); } #undef d #undef q #include "moc_importcrlcommand.cpp" diff --git a/src/commands/importcrlcommand.h b/src/commands/importcrlcommand.h index 6dca0f14b..8114f9dd5 100644 --- a/src/commands/importcrlcommand.h +++ b/src/commands/importcrlcommand.h @@ -1,47 +1,45 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/importcrlcommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include namespace Kleo { namespace Commands { class ImportCrlCommand : public Command { Q_OBJECT public: explicit ImportCrlCommand(QAbstractItemView *view, KeyListController *parent); explicit ImportCrlCommand(KeyListController *parent); explicit ImportCrlCommand(const QStringList &files, QAbstractItemView *view, KeyListController *parent); explicit ImportCrlCommand(const QStringList &files, KeyListController *parent); ~ImportCrlCommand() override; void setFiles(const QStringList &files); private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotProcessFinished(int, QProcess::ExitStatus)) - Q_PRIVATE_SLOT(d_func(), void slotProcessReadyReadStandardError()) }; } } diff --git a/src/commands/lookupcertificatescommand.cpp b/src/commands/lookupcertificatescommand.cpp index b76d2a56e..41a8da1f7 100644 --- a/src/commands/lookupcertificatescommand.cpp +++ b/src/commands/lookupcertificatescommand.cpp @@ -1,622 +1,616 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/lookupcertificatescommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008, 2009 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "lookupcertificatescommand.h" #include "importcertificatescommand_p.h" #include "detailscommand.h" #include #include "view/tabwidget.h" #include #include #include #include #include #include #include #include #include #include #ifdef QGPGME_SUPPORTS_WKDLOOKUP # include # include #endif #include #include #include #include #include #include #include "kleopatra_debug.h" #include #include #include #include #include using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Dialogs; using namespace GpgME; using namespace QGpgME; static QDebug operator<<(QDebug s, const GpgME::Key &key) { if (key.primaryFingerprint()) { return s << Formatting::summaryLine(key) << "fpr:" << key.primaryFingerprint(); } else { return s << Formatting::summaryLine(key) << "id:" << key.keyID(); } } class LookupCertificatesCommand::Private : public ImportCertificatesCommand::Private { friend class ::Kleo::Commands::LookupCertificatesCommand; LookupCertificatesCommand *q_func() const { return static_cast(q); } public: explicit Private(LookupCertificatesCommand *qq, KeyListController *c); ~Private() override; void init(); private: void slotSearchTextChanged(const QString &str); void slotNextKey(const Key &key); void slotKeyListResult(const KeyListResult &result); #ifdef QGPGME_SUPPORTS_WKDLOOKUP void slotWKDLookupResult(const WKDLookupResult &result); #endif void tryToFinishKeyLookup(); void slotImportRequested(const std::vector &keys); void slotDetailsRequested(const Key &key); void slotSaveAsRequested(const std::vector &keys); void slotDialogRejected() { canceled(); } private: using ImportCertificatesCommand::Private::showError; void showError(QWidget *parent, const KeyListResult &result); void showResult(QWidget *parent, const KeyListResult &result); void createDialog(); KeyListJob *createKeyListJob(GpgME::Protocol proto) const { const auto cbp = (proto == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime(); return cbp ? cbp->keyListJob(true) : nullptr; } #ifdef QGPGME_SUPPORTS_WKDLOOKUP WKDLookupJob *createWKDLookupJob() const { const auto cbp = QGpgME::openpgp(); return cbp ? cbp->wkdLookupJob() : nullptr; } #endif ImportFromKeyserverJob *createImportJob(GpgME::Protocol proto) const { const auto cbp = (proto == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime(); return cbp ? cbp->importFromKeyserverJob() : nullptr; } void startKeyListJob(GpgME::Protocol proto, const QString &str); #ifdef QGPGME_SUPPORTS_WKDLOOKUP void startWKDLookupJob(const QString &str); #endif bool checkConfig() const; QWidget *dialogOrParentWidgetOrView() const { if (dialog) { return dialog; } else { return parentWidgetOrView(); } } private: GpgME::Protocol protocol = GpgME::UnknownProtocol; QString query; bool autoStartLookup = false; QPointer dialog; struct KeyListingVariables { QPointer cms, openpgp; #ifdef QGPGME_SUPPORTS_WKDLOOKUP QPointer wkdJob; #endif QString pattern; KeyListResult result; std::vector keys; int numKeysWithoutUserId = 0; std::set wkdKeyFingerprints; QByteArray wkdKeyData; QString wkdSource; bool cmsKeysHaveNoFingerprints = false; bool openPgpKeysHaveNoFingerprints = false; void reset() { *this = KeyListingVariables(); } } keyListing; }; LookupCertificatesCommand::Private *LookupCertificatesCommand::d_func() { return static_cast(d.get()); } const LookupCertificatesCommand::Private *LookupCertificatesCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() LookupCertificatesCommand::Private::Private(LookupCertificatesCommand *qq, KeyListController *c) : ImportCertificatesCommand::Private(qq, c), dialog() { if (!Settings{}.cmsEnabled()) { protocol = GpgME::OpenPGP; } } LookupCertificatesCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG); delete dialog; } LookupCertificatesCommand::LookupCertificatesCommand(KeyListController *c) : ImportCertificatesCommand(new Private(this, c)) { d->init(); } LookupCertificatesCommand::LookupCertificatesCommand(const QString &query, KeyListController *c) : ImportCertificatesCommand(new Private(this, c)) { d->init(); d->query = query; d->autoStartLookup = true; } LookupCertificatesCommand::LookupCertificatesCommand(QAbstractItemView *v, KeyListController *c) : ImportCertificatesCommand(v, new Private(this, c)) { d->init(); if (c->tabWidget()) { d->query = c->tabWidget()->stringFilter(); // do not start the lookup automatically to prevent unwanted leaking // of information } } void LookupCertificatesCommand::Private::init() { } LookupCertificatesCommand::~LookupCertificatesCommand() { qCDebug(KLEOPATRA_LOG); } void LookupCertificatesCommand::setProtocol(GpgME::Protocol protocol) { d->protocol = protocol; } GpgME::Protocol LookupCertificatesCommand::protocol() const { return d->protocol; } void LookupCertificatesCommand::doStart() { if (!d->checkConfig()) { d->finished(); return; } d->createDialog(); Q_ASSERT(d->dialog); // if we have a prespecified query, load it into find field // and start the search, if auto-start is enabled if (!d->query.isEmpty()) { d->dialog->setSearchText(d->query); if (d->autoStartLookup) { d->slotSearchTextChanged(d->query); } } else { d->dialog->setPassive(false); } d->dialog->show(); } void LookupCertificatesCommand::Private::createDialog() { if (dialog) { return; } dialog = new LookupCertificatesDialog; applyWindowID(dialog); dialog->setAttribute(Qt::WA_DeleteOnClose); - connect(dialog, SIGNAL(searchTextChanged(QString)), - q, SLOT(slotSearchTextChanged(QString))); - connect(dialog, SIGNAL(saveAsRequested(std::vector)), - q, SLOT(slotSaveAsRequested(std::vector))); - connect(dialog, SIGNAL(importRequested(std::vector)), - q, SLOT(slotImportRequested(std::vector))); - connect(dialog, SIGNAL(detailsRequested(GpgME::Key)), - q, SLOT(slotDetailsRequested(GpgME::Key))); - connect(dialog, SIGNAL(rejected()), - q, SLOT(slotDialogRejected())); + connect(dialog, &LookupCertificatesDialog::searchTextChanged, q, [this](const QString &text) { slotSearchTextChanged(text); }); + using CertsVec = std::vector; + connect(dialog, &LookupCertificatesDialog::saveAsRequested, q, [this](const CertsVec &certs) { slotSaveAsRequested(certs); }); + connect(dialog, &LookupCertificatesDialog::importRequested, q, [this](const CertsVec &certs) { slotImportRequested(certs); }); + connect(dialog, &LookupCertificatesDialog::detailsRequested, q, [this](const GpgME::Key &gpgKey) { slotDetailsRequested(gpgKey); }); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); } static auto searchTextToEmailAddress(const QString &s) { return QString::fromStdString(UserID::addrSpecFromString(s.toStdString().c_str())); } void LookupCertificatesCommand::Private::slotSearchTextChanged(const QString &str) { // pressing return might trigger both search and dialog destruction (search focused and default key set) // On Windows, the dialog is then destroyed before this slot is called if (dialog) { //thus test dialog->setPassive(true); dialog->setCertificates(std::vector()); dialog->showInformation({}); } query = str; keyListing.reset(); keyListing.pattern = str; if (protocol != GpgME::OpenPGP) { startKeyListJob(CMS, str); } if (protocol != GpgME::CMS) { const QRegExp rx(QLatin1String("(?:0x|0X)?[0-9a-fA-F]{6,}")); if (rx.exactMatch(query) && !str.startsWith(QLatin1String("0x"), Qt::CaseInsensitive)) { qCDebug(KLEOPATRA_LOG) << "Adding 0x prefix to query"; startKeyListJob(OpenPGP, QStringLiteral("0x") + str); } else { startKeyListJob(OpenPGP, str); #ifdef QGPGME_SUPPORTS_WKDLOOKUP if (str.contains(QLatin1Char{'@'}) && !searchTextToEmailAddress(str).isEmpty()) { startWKDLookupJob(str); } #endif } } } void LookupCertificatesCommand::Private::startKeyListJob(GpgME::Protocol proto, const QString &str) { KeyListJob *const klj = createKeyListJob(proto); if (!klj) { return; } - connect(klj, SIGNAL(result(GpgME::KeyListResult)), - q, SLOT(slotKeyListResult(GpgME::KeyListResult))); - connect(klj, SIGNAL(nextKey(GpgME::Key)), - q, SLOT(slotNextKey(GpgME::Key))); + connect(klj, &QGpgME::KeyListJob::result, q, [this](const GpgME::KeyListResult &result) { slotKeyListResult(result); }); + connect(klj, &QGpgME::KeyListJob::nextKey, q, [this](const GpgME::Key &key) { slotNextKey(key); }); if (const Error err = klj->start(QStringList(str))) { keyListing.result.mergeWith(KeyListResult(err)); } else if (proto == CMS) { keyListing.cms = klj; } else { keyListing.openpgp = klj; } } #ifdef QGPGME_SUPPORTS_WKDLOOKUP void LookupCertificatesCommand::Private::startWKDLookupJob(const QString &str) { const auto job = createWKDLookupJob(); if (!job) { qCDebug(KLEOPATRA_LOG) << "Failed to create WKDLookupJob"; return; } connect(job, &WKDLookupJob::result, q, [this](const WKDLookupResult &result) { slotWKDLookupResult(result); }); if (const Error err = job->start(str)) { keyListing.result.mergeWith(KeyListResult{err}); } else { keyListing.wkdJob = job; } } #endif void LookupCertificatesCommand::Private::slotNextKey(const Key &key) { if (!key.primaryFingerprint()) { qCDebug(KLEOPATRA_LOG) << __func__ << "ignoring key without fingerprint" << key; if (q->sender() == keyListing.cms) { keyListing.cmsKeysHaveNoFingerprints = true; } else if (q->sender() == keyListing.openpgp) { keyListing.openPgpKeysHaveNoFingerprints = true; } } else if (key.numUserIDs() == 0) { qCDebug(KLEOPATRA_LOG) << __func__ << "ignoring key without user IDs" << key; keyListing.numKeysWithoutUserId++; } else { qCDebug(KLEOPATRA_LOG) << __func__ << "got key" << key; keyListing.keys.push_back(key); } } void LookupCertificatesCommand::Private::slotKeyListResult(const KeyListResult &r) { if (q->sender() == keyListing.cms) { keyListing.cms = nullptr; } else if (q->sender() == keyListing.openpgp) { keyListing.openpgp = nullptr; } else { qCDebug(KLEOPATRA_LOG) << "unknown sender()" << q->sender(); } keyListing.result.mergeWith(r); tryToFinishKeyLookup(); } #ifdef QGPGME_SUPPORTS_WKDLOOKUP static auto removeKeysNotMatchingEmail(const std::vector &keys, const std::string &email) { std::vector filteredKeys; const auto addrSpec = UserID::addrSpecFromString(email.c_str()); std::copy_if(std::begin(keys), std::end(keys), std::back_inserter(filteredKeys), [addrSpec](const auto &key) { const auto uids = key.userIDs(); return std::any_of(std::begin(uids), std::end(uids), [addrSpec](const auto &uid) { return uid.addrSpec() == addrSpec; }); }); return filteredKeys; } void LookupCertificatesCommand::Private::slotWKDLookupResult(const WKDLookupResult &result) { if (q->sender() == keyListing.wkdJob) { keyListing.wkdJob = nullptr; } else { qCDebug(KLEOPATRA_LOG) << __func__ << "unknown sender()" << q->sender(); } keyListing.result.mergeWith(KeyListResult{result.error()}); const auto keys = removeKeysNotMatchingEmail(result.keyData().toKeys(GpgME::OpenPGP), result.pattern()); if (!keys.empty()) { keyListing.wkdKeyData = QByteArray::fromStdString(result.keyData().toString()); keyListing.wkdSource = QString::fromStdString(result.source()); std::copy(std::begin(keys), std::end(keys), std::back_inserter(keyListing.keys)); // remember the keys retrieved via WKD for import std::transform(std::begin(keys), std::end(keys), std::inserter(keyListing.wkdKeyFingerprints, std::begin(keyListing.wkdKeyFingerprints)), [](const auto &k) { return k.primaryFingerprint(); }); } tryToFinishKeyLookup(); } #endif namespace { void showKeysWithoutFingerprintsNotification(QWidget *parent, GpgME::Protocol protocol) { if (protocol != GpgME::CMS && protocol != GpgME::OpenPGP) { return; } QString message; if (protocol == GpgME::CMS) { message = xi18nc("@info", "One of the X.509 directory services returned certificates without " "fingerprints. Those certificates are ignored because fingerprints " "are required as unique identifiers for certificates." "You may want to configure a different X.509 directory service " "in the configuration dialog."); } else { message = xi18nc("@info", "The OpenPGP keyserver returned certificates without " "fingerprints. Those certificates are ignored because fingerprints " "are required as unique identifiers for certificates." "You may want to configure a different OpenPGP keyserver " "in the configuration dialog."); } KMessageBox::information(parent, message, i18nc("@title", "Invalid Server Reply"), QStringLiteral("certificates-lookup-missing-fingerprints")); } } void LookupCertificatesCommand::Private::tryToFinishKeyLookup() { if (keyListing.cms || keyListing.openpgp #ifdef QGPGME_SUPPORTS_WKDLOOKUP || keyListing.wkdJob #endif ) { // still waiting for jobs to complete return; } if (keyListing.result.error() && !keyListing.result.error().isCanceled()) { showError(dialog, keyListing.result); } if (keyListing.result.isTruncated()) { showResult(dialog, keyListing.result); } if (keyListing.cmsKeysHaveNoFingerprints) { showKeysWithoutFingerprintsNotification(dialog, GpgME::CMS); } if (keyListing.openPgpKeysHaveNoFingerprints) { showKeysWithoutFingerprintsNotification(dialog, GpgME::OpenPGP); } if (dialog) { dialog->setPassive(false); dialog->setCertificates(keyListing.keys); if (keyListing.numKeysWithoutUserId > 0) { dialog->showInformation(i18ncp("@info", "One certificate without name and email address was ignored.", "%1 certificates without name and email address were ignored.", keyListing.numKeysWithoutUserId)); } } else { finished(); } } void LookupCertificatesCommand::Private::slotImportRequested(const std::vector &keys) { dialog = nullptr; Q_ASSERT(!keys.empty()); Q_ASSERT(std::none_of(keys.cbegin(), keys.cend(), [](const Key &key) { return key.isNull(); })); std::vector wkdKeys, otherKeys; otherKeys.reserve(keys.size()); kdtools::separate_if(std::begin(keys), std::end(keys), std::back_inserter(wkdKeys), std::back_inserter(otherKeys), [this](const auto &key) { return key.primaryFingerprint() && keyListing.wkdKeyFingerprints.find(key.primaryFingerprint()) != std::end(keyListing.wkdKeyFingerprints); }); std::vector pgp, cms; pgp.reserve(otherKeys.size()); cms.reserve(otherKeys.size()); kdtools::separate_if(otherKeys.begin(), otherKeys.end(), std::back_inserter(pgp), std::back_inserter(cms), [](const Key &key) { return key.protocol() == GpgME::OpenPGP; }); setWaitForMoreJobs(true); if (!wkdKeys.empty()) { // set an import filter, so that only user IDs matching the email address used for the WKD lookup are imported const QString importFilter = QLatin1String{"keep-uid=mbox = "} + searchTextToEmailAddress(keyListing.pattern); startImport(OpenPGP, keyListing.wkdKeyData, keyListing.wkdSource, {importFilter, Key::OriginWKD, keyListing.wkdSource}); } if (!pgp.empty()) { startImport(OpenPGP, pgp, i18nc(R"(@title %1:"OpenPGP" or "S/MIME")", "%1 Certificate Server", Formatting::displayName(OpenPGP))); } if (!cms.empty()) { startImport(CMS, cms, i18nc(R"(@title %1:"OpenPGP" or "S/MIME")", "%1 Certificate Server", Formatting::displayName(CMS))); } setWaitForMoreJobs(false); } void LookupCertificatesCommand::Private::slotSaveAsRequested(const std::vector &keys) { Q_UNUSED(keys) qCDebug(KLEOPATRA_LOG) << "not implemented"; } void LookupCertificatesCommand::Private::slotDetailsRequested(const Key &key) { Command *const cmd = new DetailsCommand(key, view(), controller()); cmd->setParentWidget(dialogOrParentWidgetOrView()); cmd->start(); } void LookupCertificatesCommand::doCancel() { ImportCertificatesCommand::doCancel(); if (QDialog *const dlg = d->dialog) { d->dialog = nullptr; dlg->close(); } } void LookupCertificatesCommand::Private::showError(QWidget *parent, const KeyListResult &result) { if (!result.error()) { return; } KMessageBox::information(parent, i18nc("@info", "Failed to search on certificate server. The error returned was:\n%1", QString::fromLocal8Bit(result.error().asString()))); } void LookupCertificatesCommand::Private::showResult(QWidget *parent, const KeyListResult &result) { if (result.isTruncated()) KMessageBox::information(parent, xi18nc("@info", "The query result has been truncated." "Either the local or a remote limit on " "the maximum number of returned hits has " "been exceeded." "You can try to increase the local limit " "in the configuration dialog, but if one " "of the configured servers is the limiting " "factor, you have to refine your search."), i18nc("@title", "Result Truncated"), QStringLiteral("lookup-certificates-truncated-result")); } bool LookupCertificatesCommand::Private::checkConfig() const { const bool haveOrDontNeedOpenPGPServer = haveKeyserverConfigured() || (protocol == GpgME::CMS); const bool haveOrDontNeedCMSServer = haveX509DirectoryServerConfigured() || (protocol == GpgME::OpenPGP); const bool ok = haveOrDontNeedOpenPGPServer || haveOrDontNeedCMSServer; if (!ok) information(xi18nc("@info", "You do not have any directory servers configured." "You need to configure at least one directory server to " "search on one." "You can configure directory servers here: " "Settings->Configure Kleopatra."), i18nc("@title", "No Directory Servers Configured")); return ok; } #undef d #undef q #include "moc_lookupcertificatescommand.cpp" diff --git a/src/commands/lookupcertificatescommand.h b/src/commands/lookupcertificatescommand.h index 8f80bb1dd..3bfb3e495 100644 --- a/src/commands/lookupcertificatescommand.h +++ b/src/commands/lookupcertificatescommand.h @@ -1,52 +1,45 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/lookupcertificatescommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include namespace Kleo { namespace Commands { class LookupCertificatesCommand : public ImportCertificatesCommand { Q_OBJECT public: explicit LookupCertificatesCommand(QAbstractItemView *view, KeyListController *parent); explicit LookupCertificatesCommand(KeyListController *parent); explicit LookupCertificatesCommand(const QString &fingerPrint, KeyListController *parent); ~LookupCertificatesCommand() override; void setProtocol(GpgME::Protocol protocol); GpgME::Protocol protocol() const; private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotSearchTextChanged(QString)) - Q_PRIVATE_SLOT(d_func(), void slotNextKey(GpgME::Key)) - Q_PRIVATE_SLOT(d_func(), void slotKeyListResult(GpgME::KeyListResult)) - Q_PRIVATE_SLOT(d_func(), void slotImportRequested(std::vector)) - Q_PRIVATE_SLOT(d_func(), void slotDetailsRequested(GpgME::Key)) - Q_PRIVATE_SLOT(d_func(), void slotSaveAsRequested(std::vector)) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) }; } } diff --git a/src/commands/newcertificatecommand.cpp b/src/commands/newcertificatecommand.cpp index 6cd7632a5..44d5571a4 100644 --- a/src/commands/newcertificatecommand.cpp +++ b/src/commands/newcertificatecommand.cpp @@ -1,166 +1,166 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/newcertificatecommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "newcertificatecommand.h" #include "command_p.h" #include #include using namespace Kleo; using namespace Kleo::Commands; using namespace GpgME; class NewCertificateCommand::Private : public Command::Private { friend class ::Kleo::Commands::NewCertificateCommand; NewCertificateCommand *q_func() const { return static_cast(q); } public: explicit Private(NewCertificateCommand *qq, KeyListController *c); ~Private() override; void init(); private: void slotDialogRejected(); void slotDialogAccepted(); private: void ensureDialogCreated(); private: Protocol protocol; QPointer dialog; }; NewCertificateCommand::Private *NewCertificateCommand::d_func() { return static_cast(d.get()); } const NewCertificateCommand::Private *NewCertificateCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() NewCertificateCommand::Private::Private(NewCertificateCommand *qq, KeyListController *c) : Command::Private(qq, c), protocol(UnknownProtocol), dialog() { } NewCertificateCommand::Private::~Private() {} NewCertificateCommand::NewCertificateCommand() : Command(new Private(this, nullptr)) { d->init(); } NewCertificateCommand::NewCertificateCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } NewCertificateCommand::NewCertificateCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } void NewCertificateCommand::Private::init() { } NewCertificateCommand::~NewCertificateCommand() {} void NewCertificateCommand::setProtocol(Protocol proto) { d->protocol = proto; if (d->dialog) { d->dialog->setProtocol(proto); } } Protocol NewCertificateCommand::protocol() const { if (d->dialog) { return d->dialog->protocol(); } else { return d->protocol; } } void NewCertificateCommand::doStart() { d->ensureDialogCreated(); Q_ASSERT(d->dialog); const Kleo::Settings settings{}; const auto cmsAllowed = settings.cmsEnabled() && settings.cmsCertificateCreationAllowed(); if (d->protocol == UnknownProtocol && !cmsAllowed) { d->protocol = GpgME::OpenPGP; } if (d->protocol != UnknownProtocol) { d->dialog->setProtocol(d->protocol); } d->dialog->show(); } void NewCertificateCommand::Private::slotDialogRejected() { Q_EMIT q->canceled(); finished(); } void NewCertificateCommand::Private::slotDialogAccepted() { finished(); } void NewCertificateCommand::doCancel() { if (d->dialog) { d->dialog->close(); } } void NewCertificateCommand::Private::ensureDialogCreated() { if (dialog) { return; } dialog = new NewCertificateWizard; applyWindowID(dialog); dialog->setAttribute(Qt::WA_DeleteOnClose); - connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); - connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted())); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); + connect(dialog, &QDialog::accepted, q, [this]() { slotDialogAccepted(); }); } #undef d #undef q #include "moc_newcertificatecommand.cpp" diff --git a/src/commands/newcertificatecommand.h b/src/commands/newcertificatecommand.h index 393c47ab0..97f6e6089 100644 --- a/src/commands/newcertificatecommand.h +++ b/src/commands/newcertificatecommand.h @@ -1,47 +1,45 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/newcertificatecommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include namespace Kleo { namespace Commands { class NewCertificateCommand : public Command { Q_OBJECT public: explicit NewCertificateCommand(QAbstractItemView *view, KeyListController *parent); explicit NewCertificateCommand(KeyListController *parent); explicit NewCertificateCommand(); ~NewCertificateCommand() override; void setProtocol(GpgME::Protocol proto); GpgME::Protocol protocol() const; private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) }; } } diff --git a/src/commands/pivgeneratecardkeycommand.cpp b/src/commands/pivgeneratecardkeycommand.cpp index fc78b9d4c..c061ff6ce 100644 --- a/src/commands/pivgeneratecardkeycommand.cpp +++ b/src/commands/pivgeneratecardkeycommand.cpp @@ -1,254 +1,254 @@ /* commands/pivgeneratecardkeycommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include "pivgeneratecardkeycommand.h" #include "cardcommand_p.h" #include "smartcard/pivcard.h" #include "smartcard/readerstatus.h" #include "commands/authenticatepivcardapplicationcommand.h" #include "dialogs/gencardkeydialog.h" #include #include #include #if GPG_ERROR_VERSION_NUMBER >= 0x12400 // 1.36 # define GPG_ERROR_HAS_NO_AUTH #endif #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::SmartCard; using namespace GpgME; class PIVGenerateCardKeyCommand::Private : public CardCommand::Private { friend class ::Kleo::Commands::PIVGenerateCardKeyCommand; PIVGenerateCardKeyCommand *q_func() const { return static_cast(q); } public: explicit Private(PIVGenerateCardKeyCommand *qq, const std::string &serialNumber, QWidget *p); ~Private() override; void init(); private: void slotDialogAccepted(); void slotDialogRejected(); void slotResult(const Error &err); private: void authenticate(); void authenticationFinished(); void authenticationCanceled(); void generateKey(); void ensureDialogCreated(); private: std::string keyRef; bool overwriteExistingKey = false; std::string algorithm; QPointer dialog; bool hasBeenCanceled = false; }; PIVGenerateCardKeyCommand::Private *PIVGenerateCardKeyCommand::d_func() { return static_cast(d.get()); } const PIVGenerateCardKeyCommand::Private *PIVGenerateCardKeyCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() PIVGenerateCardKeyCommand::Private::Private(PIVGenerateCardKeyCommand *qq, const std::string &serialNumber, QWidget *p) : CardCommand::Private(qq, serialNumber, p) , dialog() { } PIVGenerateCardKeyCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG) << "PIVGenerateCardKeyCommand::Private::~Private()"; } PIVGenerateCardKeyCommand::PIVGenerateCardKeyCommand(const std::string &serialNumber, QWidget *p) : CardCommand(new Private(this, serialNumber, p)) { d->init(); } void PIVGenerateCardKeyCommand::Private::init() { } PIVGenerateCardKeyCommand::~PIVGenerateCardKeyCommand() { qCDebug(KLEOPATRA_LOG) << "PIVGenerateCardKeyCommand::~PIVGenerateCardKeyCommand()"; } void PIVGenerateCardKeyCommand::setKeyRef(const std::string &keyRef) { d->keyRef = keyRef; } void PIVGenerateCardKeyCommand::doStart() { qCDebug(KLEOPATRA_LOG) << "PIVGenerateCardKeyCommand::doStart()"; // check if key exists auto pivCard = ReaderStatus::instance()->getCard(d->serialNumber()); if (!pivCard) { d->error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(d->serialNumber()))); d->finished(); return; } auto existingKey = pivCard->keyInfo(d->keyRef).grip; if (!existingKey.empty()) { const QString warningText = i18nc("@info", "

    This card already contains a key in this slot. Continuing will overwrite that key.

    " "

    If there is no backup the existing key will be irrecoverably lost.

    ") + i18n("The existing key has the ID:") + QStringLiteral("
    %1
    ").arg(QString::fromStdString(existingKey)) + (d->keyRef == PIVCard::keyManagementKeyRef() ? i18n("It will no longer be possible to decrypt past communication encrypted for the existing key.") : QString()); const auto choice = KMessageBox::warningContinueCancel(d->parentWidgetOrView(), warningText, i18nc("@title:window", "Overwrite existing key"), KStandardGuiItem::cont(), KStandardGuiItem::cancel(), QString(), KMessageBox::Notify | KMessageBox::Dangerous); if (choice != KMessageBox::Continue) { d->finished(); return; } d->overwriteExistingKey = true; } d->ensureDialogCreated(); Q_ASSERT(d->dialog); d->dialog->show(); } void PIVGenerateCardKeyCommand::doCancel() { } void PIVGenerateCardKeyCommand::Private::authenticate() { qCDebug(KLEOPATRA_LOG) << "PIVGenerateCardKeyCommand::authenticate()"; auto cmd = new AuthenticatePIVCardApplicationCommand(serialNumber(), parentWidgetOrView()); connect(cmd, &AuthenticatePIVCardApplicationCommand::finished, q, [this]() { authenticationFinished(); }); connect(cmd, &AuthenticatePIVCardApplicationCommand::canceled, q, [this]() { authenticationCanceled(); }); cmd->start(); } void PIVGenerateCardKeyCommand::Private::authenticationFinished() { qCDebug(KLEOPATRA_LOG) << "PIVGenerateCardKeyCommand::authenticationFinished()"; if (!hasBeenCanceled) { generateKey(); } } void PIVGenerateCardKeyCommand::Private::authenticationCanceled() { qCDebug(KLEOPATRA_LOG) << "PIVGenerateCardKeyCommand::authenticationCanceled()"; hasBeenCanceled = true; canceled(); } void PIVGenerateCardKeyCommand::Private::generateKey() { qCDebug(KLEOPATRA_LOG) << "PIVGenerateCardKeyCommand::generateKey()"; auto pivCard = ReaderStatus::instance()->getCard(serialNumber()); if (!pivCard) { error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(serialNumber()))); finished(); return; } QByteArrayList command; command << "SCD GENKEY"; if (overwriteExistingKey) { command << "--force"; } if (!algorithm.empty()) { command << "--algo=" + QByteArray::fromStdString(algorithm); } command << "--" << QByteArray::fromStdString(keyRef); ReaderStatus::mutableInstance()->startSimpleTransaction(pivCard, command.join(' '), q, "slotResult"); } void PIVGenerateCardKeyCommand::Private::slotResult(const GpgME::Error& err) { qCDebug(KLEOPATRA_LOG) << "PIVGenerateCardKeyCommand::slotResult():" << err.asString() << "(" << err.code() << ")"; if (err) { #ifdef GPG_ERROR_HAS_NO_AUTH if (err.code() == GPG_ERR_NO_AUTH) { authenticate(); return; } #endif error(i18nc("@info", "Generating key failed: %1", QString::fromLatin1(err.asString())), i18nc("@title", "Error")); } else if (!err.isCanceled()) { information(i18nc("@info", "Key successfully generated."), i18nc("@title", "Success")); ReaderStatus::mutableInstance()->updateStatus(); } finished(); } void PIVGenerateCardKeyCommand::Private::slotDialogAccepted() { algorithm = dialog->getKeyParams().algorithm; // assume that we are already authenticated to the card generateKey(); } void PIVGenerateCardKeyCommand::Private::slotDialogRejected() { finished(); } void PIVGenerateCardKeyCommand::Private::ensureDialogCreated() { if (dialog) { return; } dialog = new GenCardKeyDialog(GenCardKeyDialog::KeyAlgorithm, parentWidgetOrView()); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setSupportedAlgorithms(PIVCard::supportedAlgorithms(keyRef), "rsa2048"); - connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted())); - connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); + connect(dialog, &QDialog::accepted, q, [this]() { slotDialogAccepted(); }); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); } #undef d #undef q #include "moc_pivgeneratecardkeycommand.cpp" diff --git a/src/commands/pivgeneratecardkeycommand.h b/src/commands/pivgeneratecardkeycommand.h index 2aae3fc85..ed1148a69 100644 --- a/src/commands/pivgeneratecardkeycommand.h +++ b/src/commands/pivgeneratecardkeycommand.h @@ -1,47 +1,45 @@ /* commands/pivgeneratecardkeycommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "cardcommand.h" namespace GpgME { class Error; } namespace Kleo { namespace Commands { class PIVGenerateCardKeyCommand : public CardCommand { Q_OBJECT public: explicit PIVGenerateCardKeyCommand(const std::string &serialNumber, QWidget *parent); ~PIVGenerateCardKeyCommand() override; void setKeyRef(const std::string &keyref); private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error)) }; } // namespace Commands } // namespace Kleo diff --git a/src/commands/reloadkeyscommand.cpp b/src/commands/reloadkeyscommand.cpp index bbaa36ccc..1151062a9 100644 --- a/src/commands/reloadkeyscommand.cpp +++ b/src/commands/reloadkeyscommand.cpp @@ -1,97 +1,99 @@ /* -*- mode: c++; c-basic-offset:4 -*- reloadkeyscommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "reloadkeyscommand.h" #include "smartcard/readerstatus.h" #include "command_p.h" #include #include "kleopatra_debug.h" #include using namespace Kleo; using namespace GpgME; class ReloadKeysCommand::Private : public Command::Private { friend class ::Kleo::ReloadKeysCommand; public: Private(ReloadKeysCommand *qq, KeyListController *controller); ~Private() override; void keyListingDone(const KeyListResult &result); }; ReloadKeysCommand::Private *ReloadKeysCommand::d_func() { return static_cast(d.get()); } const ReloadKeysCommand::Private *ReloadKeysCommand::d_func() const { return static_cast(d.get()); } ReloadKeysCommand::ReloadKeysCommand(KeyListController *p) : Command(new Private(this, p)) { } ReloadKeysCommand::ReloadKeysCommand(QAbstractItemView *v, KeyListController *p) : Command(v, new Private(this, p)) { } ReloadKeysCommand::~ReloadKeysCommand() {} ReloadKeysCommand::Private::Private(ReloadKeysCommand *qq, KeyListController *controller) : Command::Private(qq, controller) { } ReloadKeysCommand::Private::~Private() {} void ReloadKeysCommand::Private::keyListingDone(const KeyListResult &result) { if (result.error()) { // ### Show error message here? qCritical() << "Error occurred during key listing: " << result.error().asString(); } finished(); } #define d d_func() void ReloadKeysCommand::doStart() { const auto view = d->parentWidgetOrView(); if (view && !view->isVisible()) { // Small hack to make redisplay also work nicely when the keylist // is not currently the active widget. SmartCard::ReaderStatus::mutableInstance()->updateStatus(); d->finished(); return; } - connect(KeyCache::mutableInstance().get(), SIGNAL(keyListingDone(GpgME::KeyListResult)), - this, SLOT(keyListingDone(GpgME::KeyListResult))); + connect(KeyCache::instance().get(), &KeyCache::keyListingDone, this, [this](const GpgME::KeyListResult &result) { + d->keyListingDone(result); + }); + KeyCache::mutableInstance()->startKeyListing(); } void ReloadKeysCommand::doCancel() { KeyCache::mutableInstance()->cancelKeyListing(); } #undef d #include "moc_reloadkeyscommand.cpp" diff --git a/src/commands/revokecertificationcommand.cpp b/src/commands/revokecertificationcommand.cpp index b3c26dfab..48b0c9b91 100644 --- a/src/commands/revokecertificationcommand.cpp +++ b/src/commands/revokecertificationcommand.cpp @@ -1,253 +1,252 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/revokecertificationcommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "revokecertificationcommand.h" #include "command_p.h" #include "exportopenpgpcertstoservercommand.h" #include "dialogs/revokecertificationdialog.h" #include #include #include #include #include #include #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::Commands; using namespace GpgME; using namespace QGpgME; class RevokeCertificationCommand::Private : public Command::Private { friend class ::Kleo::Commands::RevokeCertificationCommand; RevokeCertificationCommand *q_func() const { return static_cast(q); } public: explicit Private(RevokeCertificationCommand *qq, KeyListController *c); ~Private() override; void init(); private: void slotDialogAccepted(); void slotDialogRejected(); void slotResult(const Error &err); private: void ensureDialogCreated(); QGpgME::QuickJob *createJob(); private: Key certificationKey; Key certificationTarget; std::vector uids; QPointer dialog; QPointer job; }; RevokeCertificationCommand::Private *RevokeCertificationCommand::d_func() { return static_cast(d.get()); } const RevokeCertificationCommand::Private *RevokeCertificationCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() RevokeCertificationCommand::Private::Private(RevokeCertificationCommand *qq, KeyListController *c) : Command::Private(qq, c) { } RevokeCertificationCommand::Private::~Private() { } void RevokeCertificationCommand::Private::init() { const std::vector keys_ = keys(); if (keys_.size() != 1) { qCWarning(KLEOPATRA_LOG) << "RevokeCertificationCommand::Private::init: Expected exactly one key, but got" << keys_.size(); return; } if (keys_.front().protocol() != GpgME::OpenPGP) { qCWarning(KLEOPATRA_LOG) << "RevokeCertificationCommand::Private::init: Expected OpenPGP key, but got" << keys_.front().protocolAsString(); return; } certificationTarget = keys_.front(); } void RevokeCertificationCommand::Private::slotDialogAccepted() { const auto certificationKey = dialog->selectedCertificationKey(); const auto selectedUserIDs = dialog->selectedUserIDs(); if (certificationKey.isNull() || selectedUserIDs.empty()) { qCDebug(KLEOPATRA_LOG) << "No certification key or no user IDs selected -> skipping revocation"; finished(); return; } job = createJob(); if (!job) { qCDebug(KLEOPATRA_LOG) << "Failed to create QuickJob"; finished(); return; } job->startRevokeSignature(certificationTarget, dialog->selectedCertificationKey(), dialog->selectedUserIDs()); } void RevokeCertificationCommand::Private::slotDialogRejected() { canceled(); } void RevokeCertificationCommand::Private::slotResult(const Error &err) { if (err.isCanceled()) { // do nothing } else if (err) { error(i18n("

    An error occurred while trying to revoke the certification of

    " "%1:

    \t%2

    ", Formatting::formatForComboBox(certificationTarget), QString::fromUtf8(err.asString())), i18n("Revocation Error")); } else { information(i18n("Revocation successful."), i18n("Revocation Succeeded")); if (dialog && dialog->sendToServer()) { auto const cmd = new ExportOpenPGPCertsToServerCommand(certificationTarget); cmd->start(); } } finished(); } void RevokeCertificationCommand::Private::ensureDialogCreated() { if (dialog) { return; } dialog = new RevokeCertificationDialog; applyWindowID(dialog); dialog->setAttribute(Qt::WA_DeleteOnClose); - connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted())); - connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); + connect(dialog, &QDialog::accepted, q, [this]() { slotDialogAccepted(); }); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); } QGpgME::QuickJob *RevokeCertificationCommand::Private::createJob() { Q_ASSERT(!job); Q_ASSERT(certificationTarget.protocol() == OpenPGP); const auto backend = QGpgME::openpgp(); if (!backend) { return nullptr; } QuickJob *const j = backend->quickJob(); if (j) { connect(j, &Job::progress, q, &Command::progress); - connect(j, SIGNAL(result(GpgME::Error)), - q, SLOT(slotResult(GpgME::Error))); + connect(j, &QGpgME::QuickJob::result, q, [this](const GpgME::Error &error) { slotResult(error); }); } return j; } RevokeCertificationCommand::RevokeCertificationCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } RevokeCertificationCommand::RevokeCertificationCommand(const GpgME::UserID &uid) : Command(uid.parent(), new Private(this, nullptr)) { std::vector(1, uid).swap(d->uids); d->init(); } RevokeCertificationCommand::RevokeCertificationCommand(const GpgME::UserID::Signature &signature) : Command(signature.parent().parent(), new Private(this, nullptr)) { std::vector(1, signature.parent()).swap(d->uids); d->certificationKey = KeyCache::instance()->findByKeyIDOrFingerprint(signature.signerKeyID()); d->init(); } RevokeCertificationCommand::~RevokeCertificationCommand() { qCDebug(KLEOPATRA_LOG) << "~RevokeCertificationCommand()"; } // static bool RevokeCertificationCommand::isSupported() { return engineInfo(GpgEngine).engineVersion() >= "2.2.24"; } void RevokeCertificationCommand::doStart() { if (d->certificationTarget.isNull()) { d->finished(); return; } for (const UserID &uid : std::as_const(d->uids)) if (qstricmp(uid.parent().primaryFingerprint(), d->certificationTarget.primaryFingerprint()) != 0) { qCWarning(KLEOPATRA_LOG) << "User ID <-> Key mismatch!"; d->finished(); return; } d->ensureDialogCreated(); Q_ASSERT(d->dialog); d->dialog->setCertificateToRevoke(d->certificationTarget); if (!d->uids.empty()) { d->dialog->setSelectedUserIDs(d->uids); } if (!d->certificationKey.isNull()) { d->dialog->setSelectedCertificationKey(d->certificationKey); } d->dialog->show(); } void RevokeCertificationCommand::doCancel() { qCDebug(KLEOPATRA_LOG) << "RevokeCertificationCommand::doCancel()"; if (d->job) { d->job->slotCancel(); } } #undef d #undef q #include "moc_revokecertificationcommand.cpp" diff --git a/src/commands/revokecertificationcommand.h b/src/commands/revokecertificationcommand.h index 073c44721..2f4f12fce 100644 --- a/src/commands/revokecertificationcommand.h +++ b/src/commands/revokecertificationcommand.h @@ -1,53 +1,50 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/revokecertificationcommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include namespace Kleo { namespace Commands { class RevokeCertificationCommand : public Command { Q_OBJECT public: explicit RevokeCertificationCommand(QAbstractItemView *view, KeyListController *parent); explicit RevokeCertificationCommand(const GpgME::UserID &uid); explicit RevokeCertificationCommand(const GpgME::UserID::Signature &signature); ~RevokeCertificationCommand() override; /* reimp */ static Restrictions restrictions() { return OnlyOneKey | MustBeOpenPGP; } static bool isSupported(); private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error)) - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) }; } // namespace Commands } // namespace Kleo diff --git a/src/commands/selftestcommand.cpp b/src/commands/selftestcommand.cpp index 4f9e20b81..9c52570bc 100644 --- a/src/commands/selftestcommand.cpp +++ b/src/commands/selftestcommand.cpp @@ -1,272 +1,269 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/selftestcommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "selftestcommand.h" #include "command_p.h" #include #include "kleopatra_debug.h" #ifdef Q_OS_WIN # include #endif #include #include #ifdef HAVE_KLEOPATRACLIENT_LIBRARY # include #endif #include #include #include #include #include #include #include #include #include using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Dialogs; static const char *const components[] = { nullptr, // gpgconf "gpg", "gpg-agent", "scdaemon", "gpgsm", "dirmngr", }; static const unsigned int numComponents = sizeof components / sizeof * components; class SelfTestCommand::Private : Command::Private { friend class ::Kleo::Commands::SelfTestCommand; SelfTestCommand *q_func() const { return static_cast(q); } public: explicit Private(SelfTestCommand *qq, KeyListController *c); ~Private() override; private: void init(); void ensureDialogCreated() { if (dialog) { return; } dialog = new SelfTestDialog; applyWindowID(dialog); dialog->setAttribute(Qt::WA_DeleteOnClose); - connect(dialog, SIGNAL(updateRequested()), - q_func(), SLOT(slotUpdateRequested())); - connect(dialog, SIGNAL(accepted()), - q_func(), SLOT(slotDialogAccepted())); - connect(dialog, SIGNAL(rejected()), - q_func(), SLOT(slotDialogRejected())); + connect(dialog, &SelfTestDialog::updateRequested, q_func(), [this]() { slotUpdateRequested(); }); + connect(dialog, &QDialog::accepted, q_func(), [this]() { slotDialogAccepted(); }); + connect(dialog, &QDialog::rejected, q_func(), [this]() { slotDialogRejected(); }); dialog->setRunAtStartUp(runAtStartUp()); dialog->setAutomaticMode(automatic); } void ensureDialogShown() { ensureDialogCreated(); if (dialog->isVisible()) { dialog->raise(); } else { dialog->show(); } } bool runAtStartUp() const { const KConfigGroup config(KSharedConfig::openConfig(), "Self-Test"); return config.readEntry("run-at-startup", true); } void setRunAtStartUp(bool on) { KConfigGroup config(KSharedConfig::openConfig(), "Self-Test"); config.writeEntry("run-at-startup", on); } void runTests() { std::vector< std::shared_ptr > tests; #if defined(Q_OS_WIN) qCDebug(KLEOPATRA_LOG) << "Checking Windows Registry..."; tests.push_back(makeGpgProgramRegistryCheckSelfTest()); #if defined(HAVE_KLEOPATRACLIENT_LIBRARY) qCDebug(KLEOPATRA_LOG) << "Checking Ui Server connectivity..."; tests.push_back(makeUiServerConnectivitySelfTest()); #endif #endif qCDebug(KLEOPATRA_LOG) << "Checking gpg installation..."; tests.push_back(makeGpgEngineCheckSelfTest()); qCDebug(KLEOPATRA_LOG) << "Checking gpgsm installation..."; tests.push_back(makeGpgSmEngineCheckSelfTest()); qCDebug(KLEOPATRA_LOG) << "Checking gpgconf installation..."; tests.push_back(makeGpgConfEngineCheckSelfTest()); for (unsigned int i = 0; i < numComponents; ++i) { qCDebug(KLEOPATRA_LOG) << "Checking configuration of:" << components[i]; tests.push_back(makeGpgConfCheckConfigurationSelfTest(components[i])); } #ifndef Q_OS_WIN tests.push_back(makeGpgAgentConnectivitySelfTest()); #endif tests.push_back(makeDeVSComplianceCheckSelfTest()); tests.push_back(makeLibKleopatraRcSelfTest()); if (!dialog && std::none_of(tests.cbegin(), tests.cend(), [](const std::shared_ptr &test) { return test->failed(); })) { finished(); return; } ensureDialogCreated(); dialog->clear(); dialog->addSelfTests(tests); ensureDialogShown(); } private: void slotDialogAccepted() { setRunAtStartUp(dialog->runAtStartUp()); finished(); } void slotDialogRejected() { if (automatic) { canceled = true; Command::Private::canceled(); } else { slotDialogAccepted(); } } void slotUpdateRequested() { const auto conf = QGpgME::cryptoConfig(); if (conf) { conf->clear(); } runTests(); } private: QPointer dialog; bool canceled; bool automatic; }; SelfTestCommand::Private *SelfTestCommand::d_func() { return static_cast(d.get()); } const SelfTestCommand::Private *SelfTestCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() SelfTestCommand::Private::Private(SelfTestCommand *qq, KeyListController *c) : Command::Private(qq, c), dialog(), canceled(false), automatic(false) { } SelfTestCommand::Private::~Private() { } SelfTestCommand::SelfTestCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } SelfTestCommand::SelfTestCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } void SelfTestCommand::Private::init() { } SelfTestCommand::~SelfTestCommand() {} void SelfTestCommand::setAutomaticMode(bool on) { d->automatic = on; if (d->dialog) { d->dialog->setAutomaticMode(on); } } bool SelfTestCommand::isCanceled() const { return d->canceled; } void SelfTestCommand::doStart() { if (d->automatic) { if (!d->runAtStartUp()) { d->finished(); return; } } else { d->ensureDialogCreated(); } d->runTests(); } void SelfTestCommand::doCancel() { d->canceled = true; if (d->dialog) { d->dialog->close(); } d->dialog = nullptr; } #undef d #undef q #include "moc_selftestcommand.cpp" diff --git a/src/commands/selftestcommand.h b/src/commands/selftestcommand.h index 2eb53c81d..3a4273937 100644 --- a/src/commands/selftestcommand.h +++ b/src/commands/selftestcommand.h @@ -1,46 +1,43 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/selftestcommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include namespace Kleo { namespace Commands { class SelfTestCommand : public Command { Q_OBJECT public: explicit SelfTestCommand(QAbstractItemView *view, KeyListController *parent); explicit SelfTestCommand(KeyListController *parent); ~SelfTestCommand() override; void setAutomaticMode(bool automatic); bool isCanceled() const; private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotUpdateRequested()) - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) }; } } diff --git a/src/commands/setinitialpincommand.h b/src/commands/setinitialpincommand.h index 0f7238d5e..7e72af26a 100644 --- a/src/commands/setinitialpincommand.h +++ b/src/commands/setinitialpincommand.h @@ -1,49 +1,47 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/setinitialpincommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include namespace Kleo { namespace Commands { class SetInitialPinCommand : public CardCommand { Q_OBJECT public: SetInitialPinCommand(const std::string &serialNumber); ~SetInitialPinCommand() override; /* reimp */ static Restrictions restrictions() { return AnyCardHasNullPin; } QDialog *dialog() const; private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) Q_PRIVATE_SLOT(d_func(), void slotNksPinRequested()) Q_PRIVATE_SLOT(d_func(), void slotSigGPinRequested()) }; } } diff --git a/src/commands/setpivcardapplicationadministrationkeycommand.cpp b/src/commands/setpivcardapplicationadministrationkeycommand.cpp index 9791814ec..f3cbb8cb4 100644 --- a/src/commands/setpivcardapplicationadministrationkeycommand.cpp +++ b/src/commands/setpivcardapplicationadministrationkeycommand.cpp @@ -1,220 +1,220 @@ /* commands/setpivcardapplicationadministrationkeycommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include "setpivcardapplicationadministrationkeycommand.h" #include "cardcommand_p.h" #include "smartcard/pivcard.h" #include "smartcard/readerstatus.h" #include "commands/authenticatepivcardapplicationcommand.h" #include "dialogs/pivcardapplicationadministrationkeyinputdialog.h" #include #include #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Dialogs; using namespace Kleo::SmartCard; using namespace GpgME; class SetPIVCardApplicationAdministrationKeyCommand::Private : public CardCommand::Private { friend class ::Kleo::Commands::SetPIVCardApplicationAdministrationKeyCommand; SetPIVCardApplicationAdministrationKeyCommand *q_func() const { return static_cast(q); } public: explicit Private(SetPIVCardApplicationAdministrationKeyCommand *qq, const std::string &serialNumber, QWidget *p); ~Private() override; void init(); private: void slotDialogAccepted(); void slotDialogRejected(); void slotResult(const Error &err); private: void authenticate(); void authenticationFinished(); void authenticationCanceled(); void setAdminKey(); void ensureDialogCreated(); private: QByteArray newAdminKey; QPointer dialog; bool hasBeenCanceled = false; }; SetPIVCardApplicationAdministrationKeyCommand::Private *SetPIVCardApplicationAdministrationKeyCommand::d_func() { return static_cast(d.get()); } const SetPIVCardApplicationAdministrationKeyCommand::Private *SetPIVCardApplicationAdministrationKeyCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() SetPIVCardApplicationAdministrationKeyCommand::Private::Private(SetPIVCardApplicationAdministrationKeyCommand *qq, const std::string &serialNumber, QWidget *p) : CardCommand::Private(qq, serialNumber, p) , dialog() { } SetPIVCardApplicationAdministrationKeyCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::Private::~Private()"; } SetPIVCardApplicationAdministrationKeyCommand::SetPIVCardApplicationAdministrationKeyCommand(const std::string &serialNumber, QWidget *p) : CardCommand(new Private(this, serialNumber, p)) { d->init(); } void SetPIVCardApplicationAdministrationKeyCommand::Private::init() { } SetPIVCardApplicationAdministrationKeyCommand::~SetPIVCardApplicationAdministrationKeyCommand() { qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::~SetPIVCardApplicationAdministrationKeyCommand()"; } void SetPIVCardApplicationAdministrationKeyCommand::doStart() { qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::doStart()"; d->authenticate(); } void SetPIVCardApplicationAdministrationKeyCommand::doCancel() { } void SetPIVCardApplicationAdministrationKeyCommand::Private::authenticate() { qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::authenticate()"; auto cmd = new AuthenticatePIVCardApplicationCommand(serialNumber(), parentWidgetOrView()); cmd->setPrompt(i18n("Please enter the old PIV Card Application Administration Key in hex-encoded form.")); connect(cmd, &AuthenticatePIVCardApplicationCommand::finished, q, [this]() { authenticationFinished(); }); connect(cmd, &AuthenticatePIVCardApplicationCommand::canceled, q, [this]() { authenticationCanceled(); }); cmd->start(); } void SetPIVCardApplicationAdministrationKeyCommand::Private::authenticationFinished() { qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::authenticationFinished()"; if (!hasBeenCanceled) { setAdminKey(); } } void SetPIVCardApplicationAdministrationKeyCommand::Private::authenticationCanceled() { qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::authenticationCanceled()"; hasBeenCanceled = true; canceled(); } void SetPIVCardApplicationAdministrationKeyCommand::Private::setAdminKey() { qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::setAdminKey()"; ensureDialogCreated(); Q_ASSERT(dialog); dialog->show(); } void SetPIVCardApplicationAdministrationKeyCommand::Private::ensureDialogCreated() { if (dialog) { return; } dialog = new PIVCardApplicationAdministrationKeyInputDialog(parentWidgetOrView()); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->setLabelText(newAdminKey.isEmpty() ? i18n("Please enter the new PIV Card Application Administration Key in hex-encoded form. " "The key needs to consist of 24 bytes, i.e. 48 hex-characters.") : i18n("Please enter the new PIV Card Application Administration Key again.")); - connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted())); - connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected())); + connect(dialog, &QDialog::accepted, q, [this]() { slotDialogAccepted(); }); + connect(dialog, &QDialog::rejected, q, [this]() { slotDialogRejected(); }); } void SetPIVCardApplicationAdministrationKeyCommand::Private::slotDialogAccepted() { if (newAdminKey.isEmpty()) { newAdminKey = dialog->adminKey(); dialog = nullptr; setAdminKey(); return; } const QByteArray newAdminKey2 = dialog->adminKey(); if (newAdminKey != newAdminKey2) { error(i18nc("@info", "The two keys you have entered do not match. Please retry."), i18nc("@title", "Error")); newAdminKey.clear(); dialog = nullptr; setAdminKey(); return; } auto pivCard = ReaderStatus::instance()->getCard(serialNumber()); if (!pivCard) { error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(serialNumber()))); finished(); return; } const QByteArray plusPercentEncodedAdminKey = newAdminKey.toPercentEncoding().replace(' ', '+'); const QByteArray command = QByteArray("SCD SETATTR SET-ADM-KEY ") + plusPercentEncodedAdminKey; ReaderStatus::mutableInstance()->startSimpleTransaction(pivCard, command, q, "slotResult"); } void SetPIVCardApplicationAdministrationKeyCommand::Private::slotDialogRejected() { finished(); } void SetPIVCardApplicationAdministrationKeyCommand::Private::slotResult(const GpgME::Error& err) { qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::slotResult():" << err.asString() << "(" << err.code() << ")"; if (err) { error(i18nc("@info", "Setting the PIV Card Application Administration Key failed: %1", QString::fromLatin1(err.asString())), i18nc("@title", "Error")); } else if (!err.isCanceled()) { information(i18nc("@info", "PIV Card Application Administration Key set successfully."), i18nc("@title", "Success")); ReaderStatus::mutableInstance()->updateStatus(); } finished(); } #undef d #undef q #include "moc_setpivcardapplicationadministrationkeycommand.cpp" diff --git a/src/commands/setpivcardapplicationadministrationkeycommand.h b/src/commands/setpivcardapplicationadministrationkeycommand.h index 987e01db8..13f516c86 100644 --- a/src/commands/setpivcardapplicationadministrationkeycommand.h +++ b/src/commands/setpivcardapplicationadministrationkeycommand.h @@ -1,45 +1,43 @@ /* commands/setpivcardapplicationadministrationkeycommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "cardcommand.h" namespace GpgME { class Error; } namespace Kleo { namespace Commands { class SetPIVCardApplicationAdministrationKeyCommand : public CardCommand { Q_OBJECT public: explicit SetPIVCardApplicationAdministrationKeyCommand(const std::string &serialNumber, QWidget *parent); ~SetPIVCardApplicationAdministrationKeyCommand() override; private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted()) - Q_PRIVATE_SLOT(d_func(), void slotDialogRejected()) Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error)) }; } // namespace Commands } // namespace Kleo diff --git a/src/commands/signclipboardcommand.cpp b/src/commands/signclipboardcommand.cpp index adebbf210..47c7a0fcf 100644 --- a/src/commands/signclipboardcommand.cpp +++ b/src/commands/signclipboardcommand.cpp @@ -1,179 +1,178 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/signclipboardcommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "signclipboardcommand.h" #ifndef QT_NO_CLIPBOARD #include "command_p.h" #include #include #include #include #include #include "kleopatra_debug.h" #include #include #include #include using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Crypto; class SignClipboardCommand::Private : public Command::Private { friend class ::Kleo::Commands::SignClipboardCommand; SignClipboardCommand *q_func() const { return static_cast(q); } public: explicit Private(SignClipboardCommand *qq, KeyListController *c); ~Private() override; void init(); private: void slotSignersResolved(); void slotControllerDone() { finished(); } void slotControllerError(int, const QString &) { finished(); } private: std::shared_ptr shared_qq; std::shared_ptr input; SignEMailController controller; }; SignClipboardCommand::Private *SignClipboardCommand::d_func() { return static_cast(d.get()); } const SignClipboardCommand::Private *SignClipboardCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() SignClipboardCommand::Private::Private(SignClipboardCommand *qq, KeyListController *c) : Command::Private(qq, c), shared_qq(qq, [](SignClipboardCommand*){}), input(), controller(SignEMailController::ClipboardMode) { } SignClipboardCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG); } SignClipboardCommand::SignClipboardCommand(GpgME::Protocol protocol, KeyListController *c) : Command(new Private(this, c)) { d->init(); d->controller.setProtocol(protocol); } SignClipboardCommand::SignClipboardCommand(GpgME::Protocol protocol, QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); d->controller.setProtocol(protocol); } void SignClipboardCommand::Private::init() { controller.setExecutionContext(shared_qq); controller.setDetachedSignature(false); - connect(&controller, SIGNAL(done()), q, SLOT(slotControllerDone())); - connect(&controller, SIGNAL(error(int,QString)), q, SLOT(slotControllerError(int,QString))); + connect(&controller, &Controller::done, q, [this]() { slotControllerDone(); }); + connect(&controller, &Controller::error, q, [this](int err, const QString &details) { slotControllerError(err, details); }); } SignClipboardCommand::~SignClipboardCommand() { qCDebug(KLEOPATRA_LOG); } // static bool SignClipboardCommand::canSignCurrentClipboard() { bool canSign = false; if (const QClipboard *const clip = QApplication::clipboard()) { if (const QMimeData *const mime = clip->mimeData()) { canSign = mime->hasText(); } } return canSign; } void SignClipboardCommand::doStart() { try { // snapshot clipboard content here, in case it's being changed... d->input = Input::createFromClipboard(); - connect(&d->controller, SIGNAL(signersResolved()), - this, SLOT(slotSignersResolved())); + connect(&d->controller, &SignEMailController::signersResolved, this, [this]() { d->slotSignersResolved(); }); d->controller.startResolveSigners(); } catch (const std::exception &e) { d->information(i18n("An error occurred: %1", QString::fromLocal8Bit(e.what())), i18n("Sign Clipboard Error")); d->finished(); } } void SignClipboardCommand::Private::slotSignersResolved() { try { controller.setInputAndOutput(input, Output::createFromClipboard()); input.reset(); // no longer needed, so don't keep a reference controller.start(); } catch (const std::exception &e) { information(i18n("An error occurred: %1", QString::fromLocal8Bit(e.what())), i18n("Sign Clipboard Error")); finished(); } } void SignClipboardCommand::doCancel() { qCDebug(KLEOPATRA_LOG); d->controller.cancel(); } #undef d #undef q #include "moc_signclipboardcommand.cpp" #endif // QT_NO_CLIPBOARD diff --git a/src/commands/signclipboardcommand.h b/src/commands/signclipboardcommand.h index e6aafdb5e..856cf7571 100644 --- a/src/commands/signclipboardcommand.h +++ b/src/commands/signclipboardcommand.h @@ -1,52 +1,49 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/signclipboardcommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #ifndef QT_NO_CLIPBOARD #include #include namespace Kleo { namespace Commands { class SignClipboardCommand : public Command { Q_OBJECT public: explicit SignClipboardCommand(GpgME::Protocol protocol, QAbstractItemView *view, KeyListController *parent); explicit SignClipboardCommand(GpgME::Protocol protocol, KeyListController *parent); ~SignClipboardCommand() override; static bool canSignCurrentClipboard(); private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotSignersResolved()) - Q_PRIVATE_SLOT(d_func(), void slotControllerDone()) - Q_PRIVATE_SLOT(d_func(), void slotControllerError(int, QString)) }; } } #endif // QT_NO_CLIPBOARD diff --git a/src/commands/signencryptfilescommand.cpp b/src/commands/signencryptfilescommand.cpp index a4436841e..c3a408699 100644 --- a/src/commands/signencryptfilescommand.cpp +++ b/src/commands/signencryptfilescommand.cpp @@ -1,291 +1,291 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/signencryptfilescommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "signencryptfilescommand.h" #include "command_p.h" #include #include #include #include #include "kleopatra_debug.h" #include using namespace Kleo; using namespace Kleo::Commands; using namespace Kleo::Crypto; class SignEncryptFilesCommand::Private : public Command::Private { friend class ::Kleo::Commands::SignEncryptFilesCommand; SignEncryptFilesCommand *q_func() const { return static_cast(q); } public: explicit Private(SignEncryptFilesCommand *qq, KeyListController *c); ~Private() override; QStringList selectFiles() const; void init(); private: void slotControllerDone() { finished(); } void slotControllerError(int, const QString &) { finished(); } private: QStringList files; std::shared_ptr shared_qq; SignEncryptFilesController controller; }; SignEncryptFilesCommand::Private *SignEncryptFilesCommand::d_func() { return static_cast(d.get()); } const SignEncryptFilesCommand::Private *SignEncryptFilesCommand::d_func() const { return static_cast(d.get()); } #define d d_func() #define q q_func() SignEncryptFilesCommand::Private::Private(SignEncryptFilesCommand *qq, KeyListController *c) : Command::Private(qq, c), files(), shared_qq(qq, [](SignEncryptFilesCommand*){}), controller() { controller.setOperationMode(SignEncryptFilesController::SignSelected | SignEncryptFilesController::EncryptSelected | SignEncryptFilesController::ArchiveAllowed); } SignEncryptFilesCommand::Private::~Private() { qCDebug(KLEOPATRA_LOG); } SignEncryptFilesCommand::SignEncryptFilesCommand(KeyListController *c) : Command(new Private(this, c)) { d->init(); } SignEncryptFilesCommand::SignEncryptFilesCommand(QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); } SignEncryptFilesCommand::SignEncryptFilesCommand(const QStringList &files, KeyListController *c) : Command(new Private(this, c)) { d->init(); d->files = files; } SignEncryptFilesCommand::SignEncryptFilesCommand(const QStringList &files, QAbstractItemView *v, KeyListController *c) : Command(v, new Private(this, c)) { d->init(); d->files = files; } void SignEncryptFilesCommand::Private::init() { controller.setExecutionContext(shared_qq); - connect(&controller, SIGNAL(done()), q, SLOT(slotControllerDone())); - connect(&controller, SIGNAL(error(int,QString)), q, SLOT(slotControllerError(int,QString))); + connect(&controller, &Controller::done, q, [this]() { slotControllerDone(); }); + connect(&controller, &Controller::error, q, [this](int err, const QString &details) { slotControllerError(err, details); }); } SignEncryptFilesCommand::~SignEncryptFilesCommand() { qCDebug(KLEOPATRA_LOG); } void SignEncryptFilesCommand::setFiles(const QStringList &files) { d->files = files; } void SignEncryptFilesCommand::setSigningPolicy(Policy policy) { unsigned int mode = d->controller.operationMode(); mode &= ~SignEncryptFilesController::SignMask; switch (policy) { case NoPolicy: case Allow: mode |= SignEncryptFilesController::SignAllowed; break; case Deny: mode |= SignEncryptFilesController::SignDisallowed; break; case Force: mode |= SignEncryptFilesController::SignSelected; break; } try { d->controller.setOperationMode(mode); } catch (...) {} } Policy SignEncryptFilesCommand::signingPolicy() const { const unsigned int mode = d->controller.operationMode(); switch (mode & SignEncryptFilesController::SignMask) { default: Q_ASSERT(!"This should not happen!"); return NoPolicy; case SignEncryptFilesController::SignAllowed: return Allow; case SignEncryptFilesController::SignSelected: return Force; case SignEncryptFilesController::SignDisallowed: return Deny; } } void SignEncryptFilesCommand::setEncryptionPolicy(Policy policy) { unsigned int mode = d->controller.operationMode(); mode &= ~SignEncryptFilesController::EncryptMask; switch (policy) { case NoPolicy: case Allow: mode |= SignEncryptFilesController::EncryptAllowed; break; case Deny: mode |= SignEncryptFilesController::EncryptDisallowed; break; case Force: mode |= SignEncryptFilesController::EncryptSelected; break; } try { d->controller.setOperationMode(mode); } catch (...) {} } Policy SignEncryptFilesCommand::encryptionPolicy() const { const unsigned int mode = d->controller.operationMode(); switch (mode & SignEncryptFilesController::EncryptMask) { default: Q_ASSERT(!"This should not happen!"); return NoPolicy; case SignEncryptFilesController::EncryptAllowed: return Allow; case SignEncryptFilesController::EncryptSelected: return Force; case SignEncryptFilesController::EncryptDisallowed: return Deny; } } void SignEncryptFilesCommand::setArchivePolicy(Policy policy) { unsigned int mode = d->controller.operationMode(); mode &= ~SignEncryptFilesController::ArchiveMask; switch (policy) { case NoPolicy: case Allow: mode |= SignEncryptFilesController::ArchiveAllowed; break; case Deny: mode |= SignEncryptFilesController::ArchiveDisallowed; break; case Force: mode |= SignEncryptFilesController::ArchiveForced; break; } d->controller.setOperationMode(mode); } Policy SignEncryptFilesCommand::archivePolicy() const { const unsigned int mode = d->controller.operationMode(); switch (mode & SignEncryptFilesController::ArchiveMask) { case SignEncryptFilesController::ArchiveAllowed: return Allow; case SignEncryptFilesController::ArchiveForced: return Force; case SignEncryptFilesController::ArchiveDisallowed: return Deny; default: Q_ASSERT(!"This should not happen!"); return NoPolicy; } } void SignEncryptFilesCommand::setProtocol(GpgME::Protocol proto) { d->controller.setProtocol(proto); } GpgME::Protocol SignEncryptFilesCommand::protocol() const { return d->controller.protocol(); } void SignEncryptFilesCommand::doStart() { try { if (d->files.empty()) { d->files = selectFiles(); } if (d->files.empty()) { d->finished(); return; } d->controller.setFiles(d->files); d->controller.start(); } catch (const std::exception &e) { d->information(i18n("An error occurred: %1", QString::fromLocal8Bit(e.what())), i18n("Sign/Encrypt Files Error")); d->finished(); } } void SignEncryptFilesCommand::doCancel() { qCDebug(KLEOPATRA_LOG); d->controller.cancel(); } QStringList SignEncryptFilesCommand::selectFiles() const { return FileDialog::getOpenFileNames(d->parentWidgetOrView(), i18n("Select One or More Files to Sign and/or Encrypt"), QStringLiteral("enc")); } #undef d #undef q #include "moc_signencryptfilescommand.cpp" diff --git a/src/commands/signencryptfilescommand.h b/src/commands/signencryptfilescommand.h index bc5589792..5eb2f6a72 100644 --- a/src/commands/signencryptfilescommand.h +++ b/src/commands/signencryptfilescommand.h @@ -1,66 +1,64 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/signencryptfilescommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include #include #include #include namespace Kleo { namespace Commands { class SignEncryptFilesCommand : public Command { Q_OBJECT public: explicit SignEncryptFilesCommand(QAbstractItemView *view, KeyListController *parent); explicit SignEncryptFilesCommand(KeyListController *parent); explicit SignEncryptFilesCommand(const QStringList &files, QAbstractItemView *view, KeyListController *parent); explicit SignEncryptFilesCommand(const QStringList &files, KeyListController *parent); ~SignEncryptFilesCommand() override; void setFiles(const QStringList &files); void setSigningPolicy(Policy policy); Policy signingPolicy() const; void setEncryptionPolicy(Policy force); Policy encryptionPolicy() const; void setArchivePolicy(Policy force); Policy archivePolicy() const; void setProtocol(GpgME::Protocol protocol); GpgME::Protocol protocol() const; protected: virtual QStringList selectFiles() const; private: void doStart() override; void doCancel() override; private: class Private; inline Private *d_func(); inline const Private *d_func() const; - Q_PRIVATE_SLOT(d_func(), void slotControllerDone()) - Q_PRIVATE_SLOT(d_func(), void slotControllerError(int, QString)) }; } }