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

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     uiserver/prepencryptcommand.cpp
0003 
0004     This file is part of Kleopatra, the KDE keymanager
0005     SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include <config-kleopatra.h>
0011 
0012 #include "prepencryptcommand.h"
0013 
0014 #include <crypto/newsignencryptemailcontroller.h>
0015 
0016 #include <Libkleo/KleoException>
0017 
0018 #include <KLocalizedString>
0019 
0020 #include <QPointer>
0021 
0022 using namespace Kleo;
0023 using namespace Kleo::Crypto;
0024 
0025 class PrepEncryptCommand::Private : public QObject
0026 {
0027     Q_OBJECT
0028 private:
0029     friend class ::Kleo::PrepEncryptCommand;
0030     PrepEncryptCommand *const q;
0031 
0032 public:
0033     explicit Private(PrepEncryptCommand *qq)
0034         : q(qq)
0035         , controller()
0036     {
0037     }
0038 
0039 private:
0040     void checkForErrors() const;
0041 
0042 public Q_SLOTS:
0043     void slotRecipientsResolved();
0044     void slotError(int, const QString &);
0045 
0046 private:
0047     std::shared_ptr<NewSignEncryptEMailController> controller;
0048 };
0049 
0050 PrepEncryptCommand::PrepEncryptCommand()
0051     : AssuanCommandMixin<PrepEncryptCommand>()
0052     , d(new Private(this))
0053 {
0054 }
0055 
0056 PrepEncryptCommand::~PrepEncryptCommand()
0057 {
0058 }
0059 
0060 void PrepEncryptCommand::Private::checkForErrors() const
0061 {
0062     if (!q->inputs().empty() || !q->outputs().empty() || !q->messages().empty())
0063         throw Exception(makeError(GPG_ERR_CONFLICT), i18n("INPUT/OUTPUT/MESSAGE may only be given after PREP_ENCRYPT"));
0064 
0065     if (q->numFiles())
0066         throw Exception(makeError(GPG_ERR_CONFLICT), i18n("PREP_ENCRYPT is an email mode command, connection seems to be in filemanager mode"));
0067 
0068     if (!q->senders().empty() && !q->informativeSenders())
0069         throw Exception(makeError(GPG_ERR_CONFLICT), i18n("SENDER may not be given prior to PREP_ENCRYPT, except with --info"));
0070 
0071     if (q->recipients().empty() || q->informativeRecipients())
0072         throw Exception(makeError(GPG_ERR_MISSING_VALUE), i18n("No recipients given, or only with --info"));
0073 }
0074 
0075 int PrepEncryptCommand::doStart()
0076 {
0077     removeMemento(NewSignEncryptEMailController::mementoName());
0078 
0079     d->checkForErrors();
0080 
0081     d->controller.reset(new NewSignEncryptEMailController(shared_from_this()));
0082     d->controller->setEncrypting(true);
0083 
0084     const QString session = sessionTitle();
0085     if (!session.isEmpty()) {
0086         d->controller->setSubject(session);
0087     }
0088 
0089     if (hasOption("protocol"))
0090     // --protocol is optional for PREP_ENCRYPT
0091     {
0092         d->controller->setProtocol(checkProtocol(EMail));
0093     }
0094 
0095     d->controller->setSigning(hasOption("expect-sign"));
0096 
0097     QObject::connect(d->controller.get(), &NewSignEncryptEMailController::certificatesResolved, d.get(), &Private::slotRecipientsResolved);
0098     QObject::connect(d->controller.get(), SIGNAL(error(int, QString)), d.get(), SLOT(slotError(int, QString)));
0099 
0100     d->controller->startResolveCertificates(recipients(), senders());
0101 
0102     return 0;
0103 }
0104 
0105 void PrepEncryptCommand::Private::slotRecipientsResolved()
0106 {
0107     // hold local std::shared_ptr to member as q->done() deletes *this
0108     const std::shared_ptr<NewSignEncryptEMailController> cont = controller;
0109     QPointer<Private> that(this);
0110 
0111     try {
0112         q->sendStatus("PROTOCOL", QLatin1StringView(controller->protocolAsString()));
0113         q->registerMemento(NewSignEncryptEMailController::mementoName(), make_typed_memento(controller));
0114         q->done();
0115         return;
0116 
0117     } catch (const Exception &e) {
0118         q->done(e.error(), e.message());
0119     } catch (const std::exception &e) {
0120         q->done(makeError(GPG_ERR_UNEXPECTED),
0121                 i18n("Caught unexpected exception in PrepEncryptCommand::Private::slotRecipientsResolved: %1", QString::fromLocal8Bit(e.what())));
0122     } catch (...) {
0123         q->done(makeError(GPG_ERR_UNEXPECTED), i18n("Caught unknown exception in PrepEncryptCommand::Private::slotRecipientsResolved"));
0124     }
0125     if (that) { // isn't this always deleted here and thus unnecessary?
0126         q->removeMemento(NewSignEncryptEMailController::mementoName());
0127     }
0128     cont->cancel();
0129 }
0130 
0131 void PrepEncryptCommand::Private::slotError(int err, const QString &details)
0132 {
0133     q->done(err, details);
0134 }
0135 
0136 void PrepEncryptCommand::doCanceled()
0137 {
0138     if (d->controller) {
0139         d->controller->cancel();
0140     }
0141 }
0142 
0143 #include "prepencryptcommand.moc"