File indexing completed on 2024-06-02 05:24:12

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     commands/exportopenpgpcerttoprovidercommand.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2022 Felix Tiede
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "command_p.h"
0013 #include "exportopenpgpcerttoprovidercommand.h"
0014 
0015 #ifdef MAILAKONADI_ENABLED
0016 #include <KIdentityManagementCore/Identity>
0017 #include <KIdentityManagementCore/IdentityManager>
0018 #include <Akonadi/MessageQueueJob>
0019 #include <MailTransport/TransportManager>
0020 #endif // MAILAKONADI_ENABLED
0021 
0022 #include <KLocalizedString>
0023 #include <KMessageBox>
0024 
0025 #include <QGpgME/Protocol>
0026 #include <QGpgME/WKSPublishJob>
0027 
0028 #include <QString>
0029 
0030 #include <gpgme++/key.h>
0031 
0032 using namespace Kleo;
0033 using namespace Kleo::Commands;
0034 using namespace GpgME;
0035 using namespace QGpgME;
0036 
0037 #ifdef MAILAKONADI_ENABLED
0038 static const QString identityTransportForAddress(const QString &senderAddress)
0039 {
0040     static const KIdentityManagementCore::IdentityManager *idManager = new KIdentityManagementCore::IdentityManager{true};
0041 
0042     const KIdentityManagementCore::Identity identity = idManager->identityForAddress(senderAddress);
0043     if (identity.isNull()) {
0044         return idManager->defaultIdentity().transport();
0045     } else {
0046         return identity.transport();
0047     }
0048 }
0049 #endif // MAILAKONADI_ENABLED
0050 
0051 ExportOpenPGPCertToProviderCommand::ExportOpenPGPCertToProviderCommand(QAbstractItemView *v, KeyListController *c)
0052     : Command{v, c}
0053 {
0054 }
0055 
0056 ExportOpenPGPCertToProviderCommand::ExportOpenPGPCertToProviderCommand(const UserID &uid)
0057     : Command{uid.parent()}
0058     , uid{uid}
0059 {
0060 }
0061 
0062 ExportOpenPGPCertToProviderCommand::~ExportOpenPGPCertToProviderCommand() = default;
0063 
0064 void ExportOpenPGPCertToProviderCommand::doStart()
0065 {
0066     const QString sender = senderAddress();
0067 
0068 #ifdef MAILAKONADI_ENABLED
0069     const QString transportName = identityTransportForAddress(sender);
0070 
0071     if (transportName.isEmpty()) {
0072         KMessageBox::error(d->parentWidgetOrView(),
0073                            xi18nc("@warning",
0074                                   "<para><email>%1</email> has no usable transport for mailing a key available, "
0075                                   "WKS upload not possible.</para>",
0076                                   sender),
0077                            i18nc("@title:window", "OpenPGP Certificate Export"));
0078         d->canceled();
0079         return;
0080     }
0081 #endif // MAILAKONADI_ENABLED
0082 
0083     if (KMessageBox::warningContinueCancel(d->parentWidgetOrView(),
0084                                            xi18nc("@info",
0085                                                   "<para>Not every mail provider supports WKS, so any key being "
0086                                                   "exported this way may fail individually.</para><para>If exported, "
0087                                                   "a confirmation request mail will be sent to <email>%1</email> "
0088                                                   "which needs to be acknowledged with a mail program to complete the "
0089                                                   "export process.</para><para><application>KMail</application> "
0090                                                   "can handle these mails, but not all mail programs can.</para>"
0091                                                   "<para>Once exported, the standard does not (yet) allow for "
0092                                                   "automated removal of a published key.</para>"
0093                                                   "<para>Are you sure you want to continue?</para>",
0094                                                   sender),
0095                                            i18nc("@title:window", "OpenPGP Certificate Export"),
0096                                            KStandardGuiItem::cont(),
0097                                            KStandardGuiItem::cancel(),
0098                                            QStringLiteral("warn-export-openpgp-wks-unsupported"))
0099         == KMessageBox::Continue) {
0100         wksJob = QGpgME::openpgp()->wksPublishJob();
0101         connect(wksJob, &QGpgME::WKSPublishJob::result, this, &ExportOpenPGPCertToProviderCommand::wksJobResult);
0102         wksJob->startCreate(d->key().primaryFingerprint(), senderAddress());
0103     } else {
0104         d->canceled();
0105     }
0106 }
0107 
0108 void ExportOpenPGPCertToProviderCommand::doCancel()
0109 {
0110     if (wksJob) {
0111         delete wksJob;
0112     }
0113     d->canceled();
0114 }
0115 
0116 void ExportOpenPGPCertToProviderCommand::wksJobResult(const GpgME::Error &error, const QByteArray &returnedData, const QByteArray &returnedError)
0117 {
0118     if (error) {
0119         KMessageBox::error(d->parentWidgetOrView(),
0120                            xi18nc("@error",
0121                                   "<para>An error occurred while trying to export OpenPGP certificates.</para> "
0122                                   "<para>The output from GnuPG WKS client was: <message>%1</message></para>",
0123                                   QString::fromUtf8(returnedError)),
0124                            i18nc("@title:window", "OpenPGP Certificate Export"));
0125         d->canceled();
0126         return;
0127     }
0128 
0129 #ifdef MAILAKONADI_ENABLED
0130     MailTransport::Transport *transport = MailTransport::TransportManager::self()->transportByName(identityTransportForAddress(senderAddress()));
0131 
0132     if (!transport) {
0133         d->canceled();
0134         return;
0135     }
0136 
0137     KMime::Message *msg = new KMime::Message;
0138 
0139     msg->setContent(KMime::CRLFtoLF(returnedData));
0140     msg->parse();
0141 
0142     Akonadi::MessageQueueJob *job = new Akonadi::MessageQueueJob(d->parentWidgetOrView());
0143     job->transportAttribute().setTransportId(transport->id());
0144     job->addressAttribute().setFrom(msg->from()->asUnicodeString());
0145     job->addressAttribute().setTo(msg->to()->displayNames());
0146     job->setMessage(KMime::Message::Ptr{msg});
0147     connect(job, &Akonadi::MessageQueueJob::result, this, [this](const KJob *mailJob) {
0148         if (mailJob->error()) {
0149             KMessageBox::error(d->parentWidgetOrView(),
0150                                xi18nc("@error",
0151                                       "<para>An error occurred when creating the mail to publish key:</para>"
0152                                       "<message>%1</message>",
0153                                       mailJob->errorString()),
0154                                i18nc("@title:window", "OpenPGP Certificate Export"));
0155             d->canceled();
0156         } else {
0157             d->finished();
0158         }
0159     });
0160 
0161     job->start();
0162 #else // MAILAKONADI_ENABLED
0163     Q_UNUSED(returnedData);
0164 #endif // MAILAKONADI_ENABLED
0165 }
0166 
0167 QString ExportOpenPGPCertToProviderCommand::senderAddress() const
0168 {
0169     if (uid.isNull()) {
0170         return QString::fromUtf8(d->key().userID(0).addrSpec().data());
0171     } else {
0172         return QString::fromUtf8(uid.addrSpec().data());
0173     }
0174 }
0175 
0176 #include "moc_exportopenpgpcerttoprovidercommand.cpp"