File indexing completed on 2024-06-23 05:13:45
0001 /* -*- mode: c++; c-basic-offset:4 -*- 0002 commands/revokekeycommand.cpp 0003 0004 This file is part of Kleopatra, the KDE keymanager 0005 SPDX-FileCopyrightText: 2022 g10 Code GmbH 0006 SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de> 0007 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #include <config-kleopatra.h> 0012 0013 #include "command_p.h" 0014 #include "dialogs/revokekeydialog.h" 0015 #include "revokekeycommand.h" 0016 0017 #include <Libkleo/Formatting> 0018 0019 #include <KLocalizedString> 0020 0021 #include <QGpgME/RevokeKeyJob> 0022 0023 #include "kleopatra_debug.h" 0024 #include <QGpgME/Protocol> 0025 0026 using namespace Kleo; 0027 using namespace GpgME; 0028 0029 class RevokeKeyCommand::Private : public Command::Private 0030 { 0031 friend class ::RevokeKeyCommand; 0032 RevokeKeyCommand *q_func() const 0033 { 0034 return static_cast<RevokeKeyCommand *>(q); 0035 } 0036 0037 public: 0038 explicit Private(RevokeKeyCommand *qq, KeyListController *c = nullptr); 0039 ~Private() override; 0040 0041 void start(); 0042 void cancel(); 0043 0044 private: 0045 void ensureDialogCreated(); 0046 void onDialogAccepted(); 0047 void onDialogRejected(); 0048 0049 std::unique_ptr<QGpgME::RevokeKeyJob> startJob(); 0050 void onJobResult(const Error &err); 0051 void showError(const Error &err); 0052 0053 private: 0054 Key key; 0055 QPointer<RevokeKeyDialog> dialog; 0056 QPointer<QGpgME::RevokeKeyJob> job; 0057 }; 0058 0059 RevokeKeyCommand::Private *RevokeKeyCommand::d_func() 0060 { 0061 return static_cast<Private *>(d.get()); 0062 } 0063 const RevokeKeyCommand::Private *RevokeKeyCommand::d_func() const 0064 { 0065 return static_cast<const Private *>(d.get()); 0066 } 0067 0068 #define d d_func() 0069 #define q q_func() 0070 0071 RevokeKeyCommand::Private::Private(RevokeKeyCommand *qq, KeyListController *c) 0072 : Command::Private{qq, c} 0073 { 0074 } 0075 0076 RevokeKeyCommand::Private::~Private() = default; 0077 0078 namespace 0079 { 0080 Key getKey(const std::vector<Key> &keys) 0081 { 0082 if (keys.size() != 1) { 0083 qCWarning(KLEOPATRA_LOG) << "Expected exactly one key, but got" << keys.size(); 0084 return {}; 0085 } 0086 const Key key = keys.front(); 0087 if (key.protocol() != GpgME::OpenPGP) { 0088 qCWarning(KLEOPATRA_LOG) << "Expected OpenPGP key, but got" << Formatting::displayName(key.protocol()) << "key"; 0089 return {}; 0090 } 0091 return key; 0092 } 0093 } 0094 0095 void RevokeKeyCommand::Private::start() 0096 { 0097 key = getKey(keys()); 0098 if (key.isNull()) { 0099 finished(); 0100 return; 0101 } 0102 0103 if (key.isRevoked()) { 0104 information(i18nc("@info", "This key has already been revoked.")); 0105 finished(); 0106 return; 0107 } 0108 0109 ensureDialogCreated(); 0110 Q_ASSERT(dialog); 0111 0112 dialog->setKey(key); 0113 dialog->show(); 0114 } 0115 0116 void RevokeKeyCommand::Private::cancel() 0117 { 0118 if (job) { 0119 job->slotCancel(); 0120 } 0121 job.clear(); 0122 } 0123 0124 void RevokeKeyCommand::Private::ensureDialogCreated() 0125 { 0126 if (dialog) { 0127 return; 0128 } 0129 0130 dialog = new RevokeKeyDialog; 0131 applyWindowID(dialog); 0132 dialog->setAttribute(Qt::WA_DeleteOnClose); 0133 0134 connect(dialog, &QDialog::accepted, q, [this]() { 0135 onDialogAccepted(); 0136 }); 0137 connect(dialog, &QDialog::rejected, q, [this]() { 0138 onDialogRejected(); 0139 }); 0140 } 0141 0142 void RevokeKeyCommand::Private::onDialogAccepted() 0143 { 0144 auto revokeJob = startJob(); 0145 if (!revokeJob) { 0146 finished(); 0147 return; 0148 } 0149 job = revokeJob.release(); 0150 } 0151 0152 void RevokeKeyCommand::Private::onDialogRejected() 0153 { 0154 canceled(); 0155 } 0156 0157 namespace 0158 { 0159 std::vector<std::string> toStdStrings(const QStringList &l) 0160 { 0161 std::vector<std::string> v; 0162 v.reserve(l.size()); 0163 std::transform(std::begin(l), std::end(l), std::back_inserter(v), std::mem_fn(&QString::toStdString)); 0164 return v; 0165 } 0166 0167 auto descriptionToLines(const QString &description) 0168 { 0169 std::vector<std::string> lines; 0170 if (!description.isEmpty()) { 0171 lines = toStdStrings(description.split(QLatin1Char('\n'))); 0172 } 0173 return lines; 0174 } 0175 } 0176 0177 std::unique_ptr<QGpgME::RevokeKeyJob> RevokeKeyCommand::Private::startJob() 0178 { 0179 std::unique_ptr<QGpgME::RevokeKeyJob> revokeJob{QGpgME::openpgp()->revokeKeyJob()}; 0180 Q_ASSERT(revokeJob); 0181 0182 connect(revokeJob.get(), &QGpgME::RevokeKeyJob::result, q, [this](const GpgME::Error &err) { 0183 onJobResult(err); 0184 }); 0185 connect(revokeJob.get(), &QGpgME::Job::jobProgress, q, &Command::progress); 0186 0187 const auto description = descriptionToLines(dialog->description()); 0188 const GpgME::Error err = revokeJob->start(key, dialog->reason(), description); 0189 if (err) { 0190 showError(err); 0191 return {}; 0192 } 0193 Q_EMIT q->info(i18nc("@info:status", "Revoking key...")); 0194 0195 return revokeJob; 0196 } 0197 0198 void RevokeKeyCommand::Private::onJobResult(const Error &err) 0199 { 0200 if (err) { 0201 showError(err); 0202 finished(); 0203 return; 0204 } 0205 0206 if (!err.isCanceled()) { 0207 information(i18nc("@info", "The key was revoked successfully."), i18nc("@title:window", "Key Revoked")); 0208 } 0209 finished(); 0210 } 0211 0212 void RevokeKeyCommand::Private::showError(const Error &err) 0213 { 0214 error(xi18nc("@info", 0215 "<para>An error occurred during the revocation:</para>" 0216 "<para><message>%1</message></para>", 0217 Formatting::errorAsString(err)), 0218 i18nc("@title:window", "Revocation Failed")); 0219 } 0220 0221 RevokeKeyCommand::RevokeKeyCommand(QAbstractItemView *v, KeyListController *c) 0222 : Command{v, new Private{this, c}} 0223 { 0224 } 0225 0226 RevokeKeyCommand::RevokeKeyCommand(const GpgME::Key &key) 0227 : Command{key, new Private{this}} 0228 { 0229 } 0230 0231 RevokeKeyCommand::~RevokeKeyCommand() = default; 0232 0233 void RevokeKeyCommand::doStart() 0234 { 0235 d->start(); 0236 } 0237 0238 void RevokeKeyCommand::doCancel() 0239 { 0240 d->cancel(); 0241 } 0242 0243 #undef d 0244 #undef q 0245 0246 #include "moc_revokekeycommand.cpp"