File indexing completed on 2024-05-19 05:47:12
0001 /* 0002 * Copyright (C) 2017 Elvis Angelaccio <elvis.angelaccio@kde.org> 0003 * 0004 * This program is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU General Public License 0006 * as published by the Free Software Foundation; either version 2 0007 * of the License, or (at your option) any later version. 0008 * 0009 * This program is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 * GNU General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU General Public License 0015 * along with this program; if not, write to the Free Software 0016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0017 * 0018 */ 0019 0020 #include "compositejob.h" 0021 #include "decryptjob.h" 0022 #include "encryptjob.h" 0023 #include "symmydebug.h" 0024 0025 #include <KIO/JobTracker> 0026 #include <KJobTrackerInterface> 0027 #include <KLocalizedString> 0028 #include <KMessageBox> 0029 #include <KNewPasswordDialog> 0030 #include <KPasswordDialog> 0031 0032 #include <QTimer> 0033 0034 namespace Symmy 0035 { 0036 0037 CompositeJob::CompositeJob(const QStringList &filenames, Task task) 0038 : KCompositeJob {} 0039 , m_filenames {filenames} 0040 , m_task {task} 0041 { 0042 setCapabilities(Killable); 0043 KIO::getJobTracker()->registerJob(this); 0044 } 0045 0046 CompositeJob::~CompositeJob() 0047 { 0048 } 0049 0050 void CompositeJob::start() 0051 { 0052 QTimer::singleShot(0, this, &CompositeJob::slotStart); 0053 } 0054 0055 bool CompositeJob::doKill() 0056 { 0057 if (!hasSubjobs()) { 0058 return false; 0059 } 0060 0061 return subjobs().at(0)->kill(); 0062 } 0063 0064 void CompositeJob::slotResult(KJob *job) 0065 { 0066 if (job->error() == KJob::UserDefinedError) { 0067 qCDebug(SYMMY) << "Job failed:" << job->errorText(); 0068 if (task() == Task::Encryption) { 0069 setError(KJob::UserDefinedError); 0070 KMessageBox::error(nullptr, xi18nc("@info", "Encryption operation failed. Please check whether the <application>gpg-agent</application> process is running.")); 0071 emitResult(); 0072 return; 0073 } 0074 0075 auto decryptJob = qobject_cast<Symmy::DecryptJob*>(job); 0076 if (decryptJob) { 0077 qCDebug(SYMMY) << "Subjob failed to decrypt" << decryptJob->ciphertextFilename(); 0078 m_failedDecryptions << decryptJob->ciphertextFilename(); 0079 } 0080 } 0081 0082 removeSubjob(job); 0083 0084 if (hasSubjobs()) { 0085 qCDebug(SYMMY) << "Starting next subjob..."; 0086 startSubjob(); 0087 return; 0088 } 0089 0090 qCDebug(SYMMY) << "Composite job finished"; 0091 0092 if (!m_failedDecryptions.isEmpty()) { 0093 // Nothing was decrypted, mark the composite job as failed. 0094 if (m_failedDecryptions.size() == filenames().size()) { 0095 setError(KJob::UserDefinedError); 0096 KMessageBox::error(nullptr, xi18nc("@info", "Decryption operation failed. Please check whether the decryption key is correct.<nl/>" 0097 "You should also check whether the <application>gpg-agent</application> process is running.")); 0098 } else { 0099 KMessageBox::errorList(nullptr, xi18nc("@info", "Could not decrypt the following ciphertexts.<nl/>Please check whether the decryption key is correct."), m_failedDecryptions); 0100 } 0101 } 0102 0103 emitResult(); 0104 } 0105 0106 void CompositeJob::slotAccepted() 0107 { 0108 for (const auto &filename : qAsConst(m_filenames)) { 0109 Symmy::Job *job = nullptr; 0110 if (task() == Task::Encryption) { 0111 job = new Symmy::EncryptJob(qobject_cast<KNewPasswordDialog*>(m_passwordDialog)->password(), filename); 0112 } else { 0113 job = new Symmy::DecryptJob(qobject_cast<KPasswordDialog*>(m_passwordDialog)->password(), filename); 0114 } 0115 0116 addSubjob(job); 0117 connect(job, SIGNAL(percent(KJob*,ulong)), this, SLOT(slotPercent(KJob*,ulong))); 0118 } 0119 0120 qCDebug(SYMMY) << "Got a passphrase, starting first subjob..."; 0121 startSubjob(); 0122 } 0123 0124 void CompositeJob::slotRejected() 0125 { 0126 qCDebug(SYMMY) << "Passphrase dialog rejected."; 0127 setError(KilledJobError); 0128 emitResult(); 0129 } 0130 0131 void CompositeJob::slotStart() 0132 { 0133 if (filenames().isEmpty()) { 0134 emitResult(); 0135 return; 0136 } 0137 0138 qCDebug(SYMMY) << "Starting composite job..."; 0139 emit description(this, i18n("Asking Passphrase")); 0140 0141 if (task() == Task::Encryption) { 0142 auto passwordDialog = new KNewPasswordDialog {}; 0143 passwordDialog->setPrompt(i18n("Please supply a password or passphrase to be used as encryption key.")); 0144 passwordDialog->setAllowEmptyPasswords(false); 0145 m_passwordDialog = passwordDialog; 0146 } else { 0147 auto passwordDialog = new KPasswordDialog {}; 0148 passwordDialog->setPrompt(i18n("Please supply a password or passphrase to be used as decryption key.")); 0149 m_passwordDialog = passwordDialog; 0150 } 0151 0152 connect(m_passwordDialog, &QDialog::accepted, this, &CompositeJob::slotAccepted); 0153 connect(m_passwordDialog, &QDialog::rejected, this, &CompositeJob::slotRejected); 0154 connect(m_passwordDialog, &QDialog::finished, m_passwordDialog, &QObject::deleteLater); 0155 0156 m_passwordDialog->open(); 0157 } 0158 0159 void CompositeJob::slotPercent(KJob *, unsigned long percent) 0160 { 0161 setPercent(percent); 0162 } 0163 0164 void CompositeJob::startSubjob() 0165 { 0166 auto job = qobject_cast<Symmy::Job*>(subjobs().at(0)); 0167 0168 if (task() == Task::Encryption) { 0169 emit description(this, i18nc("description of an encryption job", "Encrypting"), 0170 qMakePair(i18nc("File used as input of the encryption algorithm", "Plaintext"), job->plaintextFilename()), 0171 qMakePair(i18nc("File created by the encryption algorithm", "Ciphertext"), job->ciphertextFilename())); 0172 } else { 0173 emit description(this, i18nc("description of a decryption job", "Decrypting"), 0174 qMakePair(i18nc("File used as input of the decryption algorithm", "Ciphertext"), job->ciphertextFilename()), 0175 qMakePair(i18nc("File created by the decryption algorithm", "Plaintext"), job->plaintextFilename())); 0176 } 0177 0178 job->start(); 0179 } 0180 0181 QStringList CompositeJob::filenames() const 0182 { 0183 return m_filenames; 0184 } 0185 0186 CompositeJob::Task CompositeJob::task() const 0187 { 0188 return m_task; 0189 } 0190 0191 }