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 "compositejob.h" 0009 #include "decryptjob.h" 0010 #include "encryptjob.h" 0011 #include "symmydebug.h" 0012 0013 #include <KIO/JobTracker> 0014 #include <KJobTrackerInterface> 0015 #include <KLocalizedString> 0016 #include <KMessageBox> 0017 #include <KNewPasswordDialog> 0018 #include <KPasswordDialog> 0019 0020 #include <QTimer> 0021 0022 namespace Symmy 0023 { 0024 0025 CompositeJob::CompositeJob(const QStringList &filenames, Task task) 0026 : KCompositeJob {} 0027 , m_filenames {filenames} 0028 , m_task {task} 0029 { 0030 setCapabilities(Killable); 0031 KIO::getJobTracker()->registerJob(this); 0032 } 0033 0034 CompositeJob::~CompositeJob() 0035 { 0036 } 0037 0038 void CompositeJob::start() 0039 { 0040 QTimer::singleShot(0, this, &CompositeJob::slotStart); 0041 } 0042 0043 bool CompositeJob::doKill() 0044 { 0045 if (!hasSubjobs()) { 0046 return false; 0047 } 0048 0049 return subjobs().at(0)->kill(); 0050 } 0051 0052 void CompositeJob::slotResult(KJob *job) 0053 { 0054 if (job->error() == KJob::UserDefinedError) { 0055 qCDebug(SYMMY) << "Job failed:" << job->errorText(); 0056 if (task() == Task::Encryption) { 0057 setError(KJob::UserDefinedError); 0058 KMessageBox::error(nullptr, xi18nc("@info", "Encryption operation failed. Please check whether the <application>gpg-agent</application> process is running.")); 0059 emitResult(); 0060 return; 0061 } 0062 0063 auto decryptJob = qobject_cast<Symmy::DecryptJob*>(job); 0064 if (decryptJob) { 0065 qCDebug(SYMMY) << "Subjob failed to decrypt" << decryptJob->ciphertextFilename(); 0066 m_failedDecryptions << decryptJob->ciphertextFilename(); 0067 } 0068 } 0069 0070 removeSubjob(job); 0071 0072 if (hasSubjobs()) { 0073 qCDebug(SYMMY) << "Starting next subjob..."; 0074 startSubjob(); 0075 return; 0076 } 0077 0078 qCDebug(SYMMY) << "Composite job finished"; 0079 0080 if (!m_failedDecryptions.isEmpty()) { 0081 // Nothing was decrypted, mark the composite job as failed. 0082 if (m_failedDecryptions.size() == filenames().size()) { 0083 setError(KJob::UserDefinedError); 0084 KMessageBox::error(nullptr, xi18nc("@info", "Decryption operation failed. Please check whether the decryption key is correct.<nl/>" 0085 "You should also check whether the <application>gpg-agent</application> process is running.")); 0086 } else { 0087 KMessageBox::errorList(nullptr, xi18nc("@info", "Could not decrypt the following ciphertexts.<nl/>Please check whether the decryption key is correct."), m_failedDecryptions); 0088 } 0089 } 0090 0091 emitResult(); 0092 } 0093 0094 void CompositeJob::slotAccepted() 0095 { 0096 for (const auto &filename : qAsConst(m_filenames)) { 0097 Symmy::Job *job = nullptr; 0098 if (task() == Task::Encryption) { 0099 job = new Symmy::EncryptJob(qobject_cast<KNewPasswordDialog*>(m_passwordDialog)->password(), filename); 0100 } else { 0101 job = new Symmy::DecryptJob(qobject_cast<KPasswordDialog*>(m_passwordDialog)->password(), filename); 0102 } 0103 0104 addSubjob(job); 0105 connect(job, SIGNAL(percent(KJob*,ulong)), this, SLOT(slotPercent(KJob*,ulong))); 0106 } 0107 0108 qCDebug(SYMMY) << "Got a passphrase, starting first subjob..."; 0109 startSubjob(); 0110 } 0111 0112 void CompositeJob::slotRejected() 0113 { 0114 qCDebug(SYMMY) << "Passphrase dialog rejected."; 0115 setError(KilledJobError); 0116 emitResult(); 0117 } 0118 0119 void CompositeJob::slotStart() 0120 { 0121 if (filenames().isEmpty()) { 0122 emitResult(); 0123 return; 0124 } 0125 0126 qCDebug(SYMMY) << "Starting composite job..."; 0127 emit description(this, i18n("Asking Passphrase")); 0128 0129 if (task() == Task::Encryption) { 0130 auto passwordDialog = new KNewPasswordDialog {}; 0131 passwordDialog->setPrompt(i18n("Please supply a password or passphrase to be used as encryption key.")); 0132 passwordDialog->setAllowEmptyPasswords(false); 0133 m_passwordDialog = passwordDialog; 0134 } else { 0135 auto passwordDialog = new KPasswordDialog {}; 0136 passwordDialog->setPrompt(i18n("Please supply a password or passphrase to be used as decryption key.")); 0137 m_passwordDialog = passwordDialog; 0138 } 0139 0140 connect(m_passwordDialog, &QDialog::accepted, this, &CompositeJob::slotAccepted); 0141 connect(m_passwordDialog, &QDialog::rejected, this, &CompositeJob::slotRejected); 0142 connect(m_passwordDialog, &QDialog::finished, m_passwordDialog, &QObject::deleteLater); 0143 0144 m_passwordDialog->open(); 0145 } 0146 0147 void CompositeJob::slotPercent(KJob *, unsigned long percent) 0148 { 0149 setPercent(percent); 0150 } 0151 0152 void CompositeJob::startSubjob() 0153 { 0154 auto job = qobject_cast<Symmy::Job*>(subjobs().at(0)); 0155 0156 if (task() == Task::Encryption) { 0157 emit description(this, i18nc("description of an encryption job", "Encrypting"), 0158 qMakePair(i18nc("File used as input of the encryption algorithm", "Plaintext"), job->plaintextFilename()), 0159 qMakePair(i18nc("File created by the encryption algorithm", "Ciphertext"), job->ciphertextFilename())); 0160 } else { 0161 emit description(this, i18nc("description of a decryption job", "Decrypting"), 0162 qMakePair(i18nc("File used as input of the decryption algorithm", "Ciphertext"), job->ciphertextFilename()), 0163 qMakePair(i18nc("File created by the decryption algorithm", "Plaintext"), job->plaintextFilename())); 0164 } 0165 0166 job->start(); 0167 } 0168 0169 QStringList CompositeJob::filenames() const 0170 { 0171 return m_filenames; 0172 } 0173 0174 CompositeJob::Task CompositeJob::task() const 0175 { 0176 return m_task; 0177 } 0178 0179 }