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 }