File indexing completed on 2024-04-21 16:35:04

0001 /*
0002  * SPDX-FileCopyrightText: 2017 Elvis Angelaccio <elvis.angelaccio@kde.org>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  *
0006  */
0007 
0008 #include "decryptjob.h"
0009 #include "symmydebug.h"
0010 
0011 #include <KIO/CopyJob>
0012 
0013 #include <QMimeDatabase>
0014 #include <QTemporaryFile>
0015 
0016 #include <QGpgME/DecryptJob>
0017 #include <QGpgME/Protocol>
0018 
0019 #include <gpgme++/context.h>
0020 #include <gpgme++/key.h>
0021 
0022 using namespace GpgME;
0023 using namespace QGpgME;
0024 
0025 namespace Symmy
0026 {
0027 
0028 DecryptJob::DecryptJob(const QString &passphrase, const QString &ciphertextFilename) : Job {passphrase}
0029 {
0030     m_ciphertext = std::make_shared<QFile>(ciphertextFilename);
0031     m_plaintext = std::make_shared<QTemporaryFile>(plaintextFilename());
0032 }
0033 
0034 DecryptJob::~DecryptJob()
0035 {
0036 }
0037 
0038 QString DecryptJob::ciphertextFilename() const
0039 {
0040     return m_ciphertext->fileName();
0041 }
0042 
0043 QString DecryptJob::plaintextFilename() const
0044 {
0045     auto filename = ciphertextFilename();
0046     const auto pgpSuffixes = QMimeDatabase{}.mimeTypeForName(QStringLiteral("application/pgp-encrypted")).suffixes();
0047     for (const auto &suffix : pgpSuffixes) {
0048         if (filename.endsWith(suffix)) {
0049             filename.chop(suffix.length() + 1); // dot is not included in the suffix
0050             break;
0051         }
0052     }
0053 
0054     return filename;
0055 }
0056 
0057 void DecryptJob::doWork()
0058 {
0059     if (not m_ciphertext->open(QIODevice::ReadOnly | QIODevice::Unbuffered)) {
0060         qCDebug(SYMMY) << "Could not open ciphertext file" << ciphertextFilename();
0061         emitResult();
0062         return;
0063     }
0064 
0065     if (not m_plaintext->open()) {
0066         qCDebug(SYMMY) << "Could not open plaintext file" << m_plaintext->fileName();
0067         emitResult();
0068         return;
0069     }
0070 
0071     auto decryptJob = openpgp()->decryptJob();
0072     auto context = QGpgME::Job::context(decryptJob);
0073     context->setPassphraseProvider(this);
0074     context->setPinentryMode(GpgME::Context::PinentryLoopback);
0075 
0076     setJob(decryptJob);
0077 
0078     connect(decryptJob, &QGpgME::DecryptJob::result, this, &DecryptJob::slotResult);
0079     connect(decryptJob, &QGpgME::Job::progress, this, [this](const QString &, int current, int total) {
0080         const auto ratio = static_cast<float>(current) / total;
0081         setPercent(static_cast<unsigned long>(100 * ratio));
0082     });
0083 
0084     decryptJob->start(m_ciphertext, m_plaintext);
0085 }
0086 
0087 void DecryptJob::slotResult(const DecryptionResult &, const QByteArray &, const QString &, const Error &)
0088 {
0089     qCDebug(SYMMY) << "Decryption job finished, plaintext size:" << m_plaintext->size();
0090 
0091     if (m_plaintext->size() == 0) {
0092         setError(UserDefinedError);
0093         emitResult();
0094         return;
0095     }
0096 
0097     auto plaintextPath = m_plaintext->fileName();
0098     // Drop the ".XXXXXX" suffix of QTemporaryFile.
0099     plaintextPath.chop(7);
0100     qCDebug(SYMMY) << "Moving temporary file" << QUrl::fromLocalFile(m_plaintext->fileName()) << "to" << QUrl::fromLocalFile(plaintextPath);
0101     auto job = KIO::move(QUrl::fromLocalFile(m_plaintext->fileName()), QUrl::fromLocalFile(plaintextPath));
0102     connect(job, &KJob::result, this, &DecryptJob::emitResult);
0103 }
0104 
0105 }