diff --git a/NEWS b/NEWS index 7712c7d9..790e646a 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,9 @@ Noteworthy changes in version 1.21.0 (unreleased) * qt: Allow writing the created archives directly to a file. [T6530] + * qt: Allow reading the signed/encrypted archive to decrypt + or verify directly from a file. [T6530] + * qt: Qt Jobs working with QIODeviceDataProvider now properly handle input-size hints and progress for files larger. 2^32 bytes in 32 bit builds. [T6534] @@ -23,6 +26,8 @@ Noteworthy changes in version 1.21.0 (unreleased) cpp: Data::setFlag NEW. cpp: Data::setSizeHint NEW. qt: Job::startIt NEW. + qt: DecryptVerifyArchiveJob::setInputFile NEW. + qt: DecryptVerifyArchiveJob::inputFile NEW. qt: EncryptArchiveJob::setRecipients NEW. qt: EncryptArchiveJob::recipients NEW. qt: EncryptArchiveJob::setInputPaths NEW. diff --git a/lang/qt/src/decryptverifyarchivejob.cpp b/lang/qt/src/decryptverifyarchivejob.cpp index ebfd36ca..76c1721a 100644 --- a/lang/qt/src/decryptverifyarchivejob.cpp +++ b/lang/qt/src/decryptverifyarchivejob.cpp @@ -56,6 +56,18 @@ bool DecryptVerifyArchiveJob::isSupported() return (gpgVersion >= "2.4.1") || (gpgVersion >= "2.2.42" && gpgVersion < "2.3.0"); } +void DecryptVerifyArchiveJob::setInputFile(const QString &path) +{ + auto d = jobPrivate(this); + d->m_inputFilePath = path; +} + +QString DecryptVerifyArchiveJob::inputFile() const +{ + auto d = jobPrivate(this); + return d->m_inputFilePath; +} + void DecryptVerifyArchiveJob::setOutputDirectory(const QString &outputDirectory) { auto d = jobPrivate(this); diff --git a/lang/qt/src/decryptverifyarchivejob.h b/lang/qt/src/decryptverifyarchivejob.h index 4e72be2d..6d87dd36 100644 --- a/lang/qt/src/decryptverifyarchivejob.h +++ b/lang/qt/src/decryptverifyarchivejob.h @@ -63,6 +63,18 @@ public: static bool isSupported(); + /** + * Sets the path of the file to read the archive from. + * + * Used if the job is started with startIt(). + */ + void setInputFile(const QString &path); + QString inputFile() const; + + /** + * Sets the directory the content of the decrypted archive shall be + * written to. + */ void setOutputDirectory(const QString &outputDirectory); QString outputDirectory() const; diff --git a/lang/qt/src/decryptverifyarchivejob_p.h b/lang/qt/src/decryptverifyarchivejob_p.h index b4e66530..e0823d23 100644 --- a/lang/qt/src/decryptverifyarchivejob_p.h +++ b/lang/qt/src/decryptverifyarchivejob_p.h @@ -41,6 +41,7 @@ namespace QGpgME struct DecryptVerifyArchiveJobPrivate : public JobPrivate { + QString m_inputFilePath; QString m_outputDirectory; }; diff --git a/lang/qt/src/qgpgmedecryptverifyarchivejob.cpp b/lang/qt/src/qgpgmedecryptverifyarchivejob.cpp index 3fd58e35..98ca7403 100644 --- a/lang/qt/src/qgpgmedecryptverifyarchivejob.cpp +++ b/lang/qt/src/qgpgmedecryptverifyarchivejob.cpp @@ -43,6 +43,8 @@ #include "dataprovider.h" #include "decryptverifyarchivejob_p.h" +#include + #include using namespace QGpgME; @@ -64,11 +66,7 @@ public: ~QGpgMEDecryptVerifyArchiveJobPrivate() override = default; private: - GpgME::Error startIt() override - { - Q_ASSERT(!"Not supported by this Job class."); - return Error::fromCode(GPG_ERR_NOT_SUPPORTED); - } + GpgME::Error startIt() override; void startNow() override { @@ -89,19 +87,9 @@ QGpgMEDecryptVerifyArchiveJob::QGpgMEDecryptVerifyArchiveJob(Context *context) } static QGpgMEDecryptVerifyArchiveJob::result_type decrypt_verify(Context *ctx, - QThread *thread, - const std::weak_ptr &cipherText_, + const GpgME::Data &indata, const QString &outputDirectory) { - const std::shared_ptr cipherText = cipherText_.lock(); - const _detail::ToThreadMover ctMover(cipherText, thread); - - QGpgME::QIODeviceDataProvider in{cipherText}; - Data indata(&in); - if (!cipherText->isSequential()) { - indata.setSizeHint(cipherText->size()); - } - Data outdata; if (!outputDirectory.isEmpty()) { outdata.setFileName(outputDirectory.toStdString()); @@ -113,13 +101,39 @@ static QGpgMEDecryptVerifyArchiveJob::result_type decrypt_verify(Context *ctx, return std::make_tuple(res.first, res.second, log, ae); } +static QGpgMEDecryptVerifyArchiveJob::result_type decrypt_verify_from_io_device(Context *ctx, + QThread *thread, + const std::weak_ptr &cipherText_, + const QString &outputDirectory) +{ + const std::shared_ptr cipherText = cipherText_.lock(); + const _detail::ToThreadMover ctMover(cipherText, thread); + QGpgME::QIODeviceDataProvider in{cipherText}; + Data indata(&in); + if (!cipherText->isSequential()) { + indata.setSizeHint(cipherText->size()); + } + + return decrypt_verify(ctx, indata, outputDirectory); +} + +static QGpgMEDecryptVerifyArchiveJob::result_type decrypt_verify_from_file_name(Context *ctx, + const QString &inputFile, + const QString &outputDirectory) +{ + Data indata; + indata.setFileName(QFile::encodeName(inputFile).constData()); + + return decrypt_verify(ctx, indata, outputDirectory); +} + GpgME::Error QGpgMEDecryptVerifyArchiveJob::start(const std::shared_ptr &cipherText) { if (!cipherText) { return Error::fromCode(GPG_ERR_INV_VALUE); } - run(std::bind(&decrypt_verify, + run(std::bind(&decrypt_verify_from_io_device, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, @@ -128,4 +142,17 @@ GpgME::Error QGpgMEDecryptVerifyArchiveJob::start(const std::shared_ptrrun([=](Context *ctx) { + return decrypt_verify_from_file_name(ctx, m_inputFilePath, m_outputDirectory); + }); + + return {}; +} + #include "qgpgmedecryptverifyarchivejob.moc" diff --git a/lang/qt/tests/run-decryptverifyarchivejob.cpp b/lang/qt/tests/run-decryptverifyarchivejob.cpp index cc588fcc..59073458 100644 --- a/lang/qt/tests/run-decryptverifyarchivejob.cpp +++ b/lang/qt/tests/run-decryptverifyarchivejob.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include @@ -85,20 +84,6 @@ CommandLineOptions parseCommandLine(const QStringList &arguments) return options; } -std::shared_ptr createInput(const QString &fileName) -{ - std::shared_ptr input; - - if (!QFile::exists(fileName)) { - qCritical() << "Error: File" << fileName << "does not exist."; - } else { - input.reset(new QFile{fileName}); - input->open(QIODevice::ReadOnly); - } - - return input; -} - int main(int argc, char **argv) { GpgME::initializeLibrary(); @@ -113,16 +98,12 @@ int main(int argc, char **argv) return 1; } - auto input = createInput(options.archiveName); - if (!input) { - return 1; - } - auto job = QGpgME::openpgp()->decryptVerifyArchiveJob(); if (!job) { std::cerr << "Error: Could not create job" << std::endl; return 1; } + job->setInputFile(options.archiveName); job->setOutputDirectory(options.outputDirectory); QObject::connect(job, &QGpgME::DecryptVerifyArchiveJob::result, &app, [](const GpgME::DecryptionResult &decryptionResult, const GpgME::VerificationResult &verificationResult, const QString &auditLog, const GpgME::Error &) { std::cerr << "Diagnostics: " << auditLog << std::endl; @@ -131,7 +112,7 @@ int main(int argc, char **argv) qApp->quit(); }); - const auto err = job->start(input); + const auto err = job->startIt(); if (err) { std::cerr << "Error: Starting the job failed: " << err.asString() << std::endl; return 1;