File indexing completed on 2024-06-23 05:14:13

0001 /* -*- mode: c++; c-basic-offset:4 -*-
0002     uiserver/decryptverifycommandfilesbase.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 "decryptverifycommandfilesbase.h"
0013 #include "fileoperationspreferences.h"
0014 
0015 #include <crypto/decryptverifytask.h>
0016 
0017 #include "crypto/autodecryptverifyfilescontroller.h"
0018 #include "crypto/decryptverifyfilescontroller.h"
0019 
0020 #include <utils/input.h>
0021 #include <utils/kleo_assert.h>
0022 #include <utils/output.h>
0023 
0024 #include <Libkleo/Formatting>
0025 #include <Libkleo/Hex>
0026 #include <Libkleo/KeyCache>
0027 #include <Libkleo/KleoException>
0028 #include <Libkleo/Stl_Util>
0029 
0030 #include <gpgme++/decryptionresult.h>
0031 #include <gpgme++/error.h>
0032 #include <gpgme++/key.h>
0033 #include <gpgme++/verificationresult.h>
0034 
0035 #include <KLocalizedString>
0036 
0037 #include <QFileInfo>
0038 
0039 #include <gpg-error.h>
0040 
0041 #include <memory>
0042 
0043 using namespace Kleo;
0044 using namespace Kleo::Crypto;
0045 using namespace Kleo::Formatting;
0046 using namespace GpgME;
0047 
0048 class DecryptVerifyCommandFilesBase::Private : public QObject
0049 {
0050     Q_OBJECT
0051     friend class ::Kleo::DecryptVerifyCommandFilesBase;
0052     DecryptVerifyCommandFilesBase *const q;
0053 
0054 public:
0055     explicit Private(DecryptVerifyCommandFilesBase *qq)
0056         : QObject()
0057         , q(qq)
0058         , controller()
0059     {
0060     }
0061 
0062     ~Private() override
0063     {
0064     }
0065 
0066     void checkForErrors() const;
0067 
0068 public Q_SLOTS:
0069     void slotProgress(const QString &what, int current, int total);
0070     void verificationResult(const GpgME::VerificationResult &);
0071     void slotDone()
0072     {
0073         q->done();
0074     }
0075     void slotError(int err, const QString &details)
0076     {
0077         q->done(err, details);
0078     }
0079 
0080 public:
0081 private:
0082     std::shared_ptr<DecryptVerifyFilesController> controller;
0083 };
0084 
0085 DecryptVerifyCommandFilesBase::DecryptVerifyCommandFilesBase()
0086     : AssuanCommandMixin<DecryptVerifyCommandFilesBase>()
0087     , d(new Private(this))
0088 {
0089 }
0090 
0091 DecryptVerifyCommandFilesBase::~DecryptVerifyCommandFilesBase()
0092 {
0093 }
0094 
0095 int DecryptVerifyCommandFilesBase::doStart()
0096 {
0097     d->checkForErrors();
0098 
0099     FileOperationsPreferences prefs;
0100     if (prefs.autoDecryptVerify()) {
0101         d->controller.reset(new AutoDecryptVerifyFilesController());
0102     } else {
0103         d->controller.reset(new DecryptVerifyFilesController(shared_from_this()));
0104     }
0105 
0106     d->controller->setOperation(operation());
0107     d->controller->setFiles(fileNames());
0108 
0109     QObject::connect(d->controller.get(), &Controller::done, d.get(), &Private::slotDone, Qt::QueuedConnection);
0110     QObject::connect(d->controller.get(), &Controller::error, d.get(), &Private::slotError, Qt::QueuedConnection);
0111     QObject::connect(d->controller.get(), &DecryptVerifyFilesController::verificationResult, d.get(), &Private::verificationResult, Qt::QueuedConnection);
0112 
0113     d->controller->start();
0114 
0115     return 0;
0116 }
0117 
0118 namespace
0119 {
0120 
0121 struct is_file {
0122     bool operator()(const QString &file) const
0123     {
0124         return QFileInfo(file).isFile();
0125     }
0126 };
0127 }
0128 
0129 void DecryptVerifyCommandFilesBase::Private::checkForErrors() const
0130 {
0131     if (!q->senders().empty())
0132         throw Kleo::Exception(q->makeError(GPG_ERR_CONFLICT), i18n("Cannot use SENDER"));
0133 
0134     if (!q->recipients().empty())
0135         throw Kleo::Exception(q->makeError(GPG_ERR_CONFLICT), i18n("Cannot use RECIPIENT"));
0136 
0137     const unsigned int numInputs = q->inputs().size();
0138     const unsigned int numMessages = q->messages().size();
0139     const unsigned int numOutputs = q->outputs().size();
0140 
0141     if (numInputs) {
0142         throw Kleo::Exception(q->makeError(GPG_ERR_CONFLICT), i18n("INPUT present"));
0143     }
0144     if (numMessages) {
0145         throw Kleo::Exception(q->makeError(GPG_ERR_CONFLICT), i18n("MESSAGE present"));
0146     }
0147     if (numOutputs) {
0148         throw Kleo::Exception(q->makeError(GPG_ERR_CONFLICT), i18n("OUTPUT present"));
0149     }
0150     const QStringList fileNames = q->fileNames();
0151     if (fileNames.empty())
0152         throw Exception(makeError(GPG_ERR_ASS_NO_INPUT), i18n("At least one FILE must be present"));
0153     if (!std::all_of(fileNames.cbegin(), fileNames.cend(), is_file()))
0154         throw Exception(makeError(GPG_ERR_INV_ARG), i18n("DECRYPT/VERIFY_FILES cannot use directories as input"));
0155 }
0156 
0157 void DecryptVerifyCommandFilesBase::doCanceled()
0158 {
0159     if (d->controller) {
0160         d->controller->cancel();
0161     }
0162 }
0163 
0164 void DecryptVerifyCommandFilesBase::Private::slotProgress(const QString &what, int current, int total)
0165 {
0166     Q_UNUSED(what)
0167     Q_UNUSED(current)
0168     Q_UNUSED(total)
0169     // ### FIXME report progress, via sendStatus()
0170 }
0171 
0172 void DecryptVerifyCommandFilesBase::Private::verificationResult(const VerificationResult &vResult)
0173 {
0174     try {
0175         const std::vector<Signature> sigs = vResult.signatures();
0176         for (const Signature &sig : sigs) {
0177             const QString s = signatureToString(sig, sig.key(true, true));
0178             const char *color = summaryToString(sig.summary());
0179             q->sendStatusEncoded("SIGSTATUS", color + (' ' + hexencode(s.toUtf8().constData())));
0180         }
0181     } catch (...) {
0182     }
0183 }
0184 
0185 #include "decryptverifycommandfilesbase.moc"