qt: Support reading signed/encrypted archives directly from a file

* lang/qt/src/decryptverifyarchivejob.cpp,
lang/qt/src/decryptverifyarchivejob.h (DecryptVerifyArchiveJob): Add
member functions setInputFile, inputFile.
* lang/qt/src/decryptverifyarchivejob_p.h
(DecryptVerifyArchiveJobPrivate): Add member m_inputFilePath.
* lang/qt/src/qgpgmedecryptverifyarchivejob.cpp (decrypt_verify): Move
creation of indata to decrypt_verify_from_io_device.
(decrypt_verify_from_io_device, decrypt_verify_from_file_name): New.
(QGpgMEDecryptVerifyArchiveJob::start): Use
decrypt_verify_from_io_device instead of decrypt_verify.
(QGpgMEDecryptVerifyArchiveJobPrivate::startIt): Start the job with the
values from member variables.

* lang/qt/tests/run-decryptverifyarchivejob.cpp (createInput): Remove.
(main): Remove creation of input. Make the job read the archive directly
from the given archive name.
--

This makes it possible to tell gpgtar to read the signed/encrypted
archive directly from a specified file bypassing GpgME's Data IO.

GnuPG-bug-id: 6530
This commit is contained in:
Ingo Klöcker 2023-06-21 15:24:00 +02:00
parent 1a9f192ab4
commit 1c2459a592
No known key found for this signature in database
GPG Key ID: F5A5D1692277A1E9
6 changed files with 76 additions and 38 deletions

5
NEWS
View File

@ -11,6 +11,9 @@ Noteworthy changes in version 1.21.0 (unreleased)
* qt: Allow writing the created archives directly to a * qt: Allow writing the created archives directly to a
file. [T6530] 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 * qt: Qt Jobs working with QIODeviceDataProvider now properly
handle input-size hints and progress for files larger. handle input-size hints and progress for files larger.
2^32 bytes in 32 bit builds. [T6534] 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::setFlag NEW.
cpp: Data::setSizeHint NEW. cpp: Data::setSizeHint NEW.
qt: Job::startIt NEW. qt: Job::startIt NEW.
qt: DecryptVerifyArchiveJob::setInputFile NEW.
qt: DecryptVerifyArchiveJob::inputFile NEW.
qt: EncryptArchiveJob::setRecipients NEW. qt: EncryptArchiveJob::setRecipients NEW.
qt: EncryptArchiveJob::recipients NEW. qt: EncryptArchiveJob::recipients NEW.
qt: EncryptArchiveJob::setInputPaths NEW. qt: EncryptArchiveJob::setInputPaths NEW.

View File

@ -56,6 +56,18 @@ bool DecryptVerifyArchiveJob::isSupported()
return (gpgVersion >= "2.4.1") || (gpgVersion >= "2.2.42" && gpgVersion < "2.3.0"); return (gpgVersion >= "2.4.1") || (gpgVersion >= "2.2.42" && gpgVersion < "2.3.0");
} }
void DecryptVerifyArchiveJob::setInputFile(const QString &path)
{
auto d = jobPrivate<DecryptVerifyArchiveJobPrivate>(this);
d->m_inputFilePath = path;
}
QString DecryptVerifyArchiveJob::inputFile() const
{
auto d = jobPrivate<DecryptVerifyArchiveJobPrivate>(this);
return d->m_inputFilePath;
}
void DecryptVerifyArchiveJob::setOutputDirectory(const QString &outputDirectory) void DecryptVerifyArchiveJob::setOutputDirectory(const QString &outputDirectory)
{ {
auto d = jobPrivate<DecryptVerifyArchiveJobPrivate>(this); auto d = jobPrivate<DecryptVerifyArchiveJobPrivate>(this);

View File

@ -63,6 +63,18 @@ public:
static bool isSupported(); 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); void setOutputDirectory(const QString &outputDirectory);
QString outputDirectory() const; QString outputDirectory() const;

View File

@ -41,6 +41,7 @@ namespace QGpgME
struct DecryptVerifyArchiveJobPrivate : public JobPrivate struct DecryptVerifyArchiveJobPrivate : public JobPrivate
{ {
QString m_inputFilePath;
QString m_outputDirectory; QString m_outputDirectory;
}; };

View File

@ -43,6 +43,8 @@
#include "dataprovider.h" #include "dataprovider.h"
#include "decryptverifyarchivejob_p.h" #include "decryptverifyarchivejob_p.h"
#include <QFile>
#include <data.h> #include <data.h>
using namespace QGpgME; using namespace QGpgME;
@ -64,11 +66,7 @@ public:
~QGpgMEDecryptVerifyArchiveJobPrivate() override = default; ~QGpgMEDecryptVerifyArchiveJobPrivate() override = default;
private: private:
GpgME::Error startIt() override GpgME::Error startIt() override;
{
Q_ASSERT(!"Not supported by this Job class.");
return Error::fromCode(GPG_ERR_NOT_SUPPORTED);
}
void startNow() override void startNow() override
{ {
@ -89,19 +87,9 @@ QGpgMEDecryptVerifyArchiveJob::QGpgMEDecryptVerifyArchiveJob(Context *context)
} }
static QGpgMEDecryptVerifyArchiveJob::result_type decrypt_verify(Context *ctx, static QGpgMEDecryptVerifyArchiveJob::result_type decrypt_verify(Context *ctx,
QThread *thread, const GpgME::Data &indata,
const std::weak_ptr<QIODevice> &cipherText_,
const QString &outputDirectory) const QString &outputDirectory)
{ {
const std::shared_ptr<QIODevice> 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; Data outdata;
if (!outputDirectory.isEmpty()) { if (!outputDirectory.isEmpty()) {
outdata.setFileName(outputDirectory.toStdString()); 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); 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<QIODevice> &cipherText_,
const QString &outputDirectory)
{
const std::shared_ptr<QIODevice> 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<QIODevice> &cipherText) GpgME::Error QGpgMEDecryptVerifyArchiveJob::start(const std::shared_ptr<QIODevice> &cipherText)
{ {
if (!cipherText) { if (!cipherText) {
return Error::fromCode(GPG_ERR_INV_VALUE); 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::_1,
std::placeholders::_2, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_3,
@ -128,4 +142,17 @@ GpgME::Error QGpgMEDecryptVerifyArchiveJob::start(const std::shared_ptr<QIODevic
return {}; return {};
} }
GpgME::Error QGpgMEDecryptVerifyArchiveJobPrivate::startIt()
{
if (m_inputFilePath.isEmpty()) {
return Error::fromCode(GPG_ERR_INV_VALUE);
}
q->run([=](Context *ctx) {
return decrypt_verify_from_file_name(ctx, m_inputFilePath, m_outputDirectory);
});
return {};
}
#include "qgpgmedecryptverifyarchivejob.moc" #include "qgpgmedecryptverifyarchivejob.moc"

View File

@ -40,7 +40,6 @@
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QCoreApplication> #include <QCoreApplication>
#include <QDebug> #include <QDebug>
#include <QFile>
#include <context.h> #include <context.h>
#include <decryptionresult.h> #include <decryptionresult.h>
@ -85,20 +84,6 @@ CommandLineOptions parseCommandLine(const QStringList &arguments)
return options; return options;
} }
std::shared_ptr<QIODevice> createInput(const QString &fileName)
{
std::shared_ptr<QFile> 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) int main(int argc, char **argv)
{ {
GpgME::initializeLibrary(); GpgME::initializeLibrary();
@ -113,16 +98,12 @@ int main(int argc, char **argv)
return 1; return 1;
} }
auto input = createInput(options.archiveName);
if (!input) {
return 1;
}
auto job = QGpgME::openpgp()->decryptVerifyArchiveJob(); auto job = QGpgME::openpgp()->decryptVerifyArchiveJob();
if (!job) { if (!job) {
std::cerr << "Error: Could not create job" << std::endl; std::cerr << "Error: Could not create job" << std::endl;
return 1; return 1;
} }
job->setInputFile(options.archiveName);
job->setOutputDirectory(options.outputDirectory); 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 &) { 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; std::cerr << "Diagnostics: " << auditLog << std::endl;
@ -131,7 +112,7 @@ int main(int argc, char **argv)
qApp->quit(); qApp->quit();
}); });
const auto err = job->start(input); const auto err = job->startIt();
if (err) { if (err) {
std::cerr << "Error: Starting the job failed: " << err.asString() << std::endl; std::cerr << "Error: Starting the job failed: " << err.asString() << std::endl;
return 1; return 1;