aboutsummaryrefslogtreecommitdiffstats
path: root/lang/qt/src
diff options
context:
space:
mode:
authorIngo Klöcker <[email protected]>2023-12-22 09:05:16 +0000
committerIngo Klöcker <[email protected]>2023-12-22 09:05:16 +0000
commite77a8ac0cc2ef356ef7e9da2793329432caf7406 (patch)
tree03f18a6d6f94013898e9ffd36cecf28651e1699a /lang/qt/src
parentqt: Support decryption (with verification) directly to/from files (diff)
downloadgpgme-e77a8ac0cc2ef356ef7e9da2793329432caf7406.tar.gz
gpgme-e77a8ac0cc2ef356ef7e9da2793329432caf7406.zip
qt: Support verification of opaque signed data directly to/from files
* lang/qt/src/Makefile.am: Add new files. * lang/qt/src/job.cpp (VerifyOpaqueJob): Move definition of constructor and destructor and inclusion of the moc file to the corresponding .cpp file. * lang/qt/src/verifyopaquejob.cpp: New. * lang/qt/src/verifyopaquejob.h (VerifyOpaqueJob): Add member functions setInputFile, inputFile, setOutputFile, outputFile. * lang/qt/src/verifyopaquejob_p.h: New. * lang/qt/src/qgpgmeverifyopaquejob.cpp (class QGpgMEVerifyOpaqueJobPrivate): New. (QGpgMEVerifyOpaqueJob::QGpgMEVerifyOpaqueJob): Instantiate private job class. (verify_from_filename): New. * lang/qt/tests/Makefile.am: Add new test program. * lang/qt/tests/run-verifyopaquejob.cpp: New. -- This makes it possible to tell gpg to read the input and write the output directly to a specified file bypassing GpgME's Data IO when verifying an opaque signed (or clear signed) file. GnuPG-bug-id: 6550
Diffstat (limited to 'lang/qt/src')
-rw-r--r--lang/qt/src/Makefile.am2
-rw-r--r--lang/qt/src/job.cpp3
-rw-r--r--lang/qt/src/qgpgmeverifyopaquejob.cpp88
-rw-r--r--lang/qt/src/verifyopaquejob.cpp74
-rw-r--r--lang/qt/src/verifyopaquejob.h30
-rw-r--r--lang/qt/src/verifyopaquejob_p.h50
6 files changed, 237 insertions, 10 deletions
diff --git a/lang/qt/src/Makefile.am b/lang/qt/src/Makefile.am
index ef625d89..81e07ce6 100644
--- a/lang/qt/src/Makefile.am
+++ b/lang/qt/src/Makefile.am
@@ -69,6 +69,7 @@ qgpgme_sources = \
signjob.cpp \
dn.cpp cryptoconfig.cpp wkdlookupresult.cpp \
util.cpp \
+ verifyopaquejob.cpp \
wkdrefreshjob.cpp
# If you add one here make sure that you also add one in camelcase
@@ -232,6 +233,7 @@ private_qgpgme_headers = \
signjob_p.h \
threadedjobmixin.h \
util.h \
+ verifyopaquejob_p.h \
wkdrefreshjob_p.h
qgpgme_moc_sources = \
diff --git a/lang/qt/src/job.cpp b/lang/qt/src/job.cpp
index 56088ce3..dbaba195 100644
--- a/lang/qt/src/job.cpp
+++ b/lang/qt/src/job.cpp
@@ -46,7 +46,6 @@
#include "decryptjob.h"
#include "signkeyjob.h"
#include "verifydetachedjob.h"
-#include "verifyopaquejob.h"
#include "keygenerationjob.h"
#include "importjob.h"
#include "importfromkeyserverjob.h"
@@ -163,7 +162,6 @@ make_job_subclass(ListAllKeysJob)
make_job_subclass(DecryptJob)
make_job_subclass(SignKeyJob)
make_job_subclass(VerifyDetachedJob)
-make_job_subclass(VerifyOpaqueJob)
make_job_subclass(KeyGenerationJob)
make_job_subclass(AbstractImportJob)
make_job_subclass_ext(ImportJob, AbstractImportJob)
@@ -197,7 +195,6 @@ make_job_subclass(SetPrimaryUserIDJob)
#include "decryptjob.moc"
#include "signkeyjob.moc"
#include "verifydetachedjob.moc"
-#include "verifyopaquejob.moc"
#include "keygenerationjob.moc"
#include "abstractimportjob.moc"
#include "importjob.moc"
diff --git a/lang/qt/src/qgpgmeverifyopaquejob.cpp b/lang/qt/src/qgpgmeverifyopaquejob.cpp
index 01372e07..2ff53227 100644
--- a/lang/qt/src/qgpgmeverifyopaquejob.cpp
+++ b/lang/qt/src/qgpgmeverifyopaquejob.cpp
@@ -39,22 +39,51 @@
#include "qgpgmeverifyopaquejob.h"
#include "dataprovider.h"
+#include "util.h"
+#include "verifyopaquejob_p.h"
-#include "context.h"
-#include "verificationresult.h"
-#include "data.h"
+#include <context.h>
+#include <data.h>
+#include <verificationresult.h>
#include <QBuffer>
-
+#include <QFile>
#include <cassert>
using namespace QGpgME;
using namespace GpgME;
+namespace
+{
+
+class QGpgMEVerifyOpaqueJobPrivate : public VerifyOpaqueJobPrivate
+{
+ QGpgMEVerifyOpaqueJob *q = nullptr;
+
+public:
+ QGpgMEVerifyOpaqueJobPrivate(QGpgMEVerifyOpaqueJob *qq)
+ : q{qq}
+ {
+ }
+
+ ~QGpgMEVerifyOpaqueJobPrivate() override = default;
+
+private:
+ GpgME::Error startIt() override;
+
+ void startNow() override
+ {
+ q->run();
+ }
+};
+
+}
+
QGpgMEVerifyOpaqueJob::QGpgMEVerifyOpaqueJob(Context *context)
: mixin_type(context)
{
+ setJobPrivate(this, std::unique_ptr<QGpgMEVerifyOpaqueJobPrivate>{new QGpgMEVerifyOpaqueJobPrivate{this}});
lateInitialization();
}
@@ -105,6 +134,41 @@ static QGpgMEVerifyOpaqueJob::result_type verify_opaque_qba(Context *ctx, const
return verify_opaque(ctx, nullptr, buffer, std::shared_ptr<QIODevice>());
}
+static QGpgMEVerifyOpaqueJob::result_type verify_from_filename(Context *ctx,
+ const QString &inputFilePath,
+ const QString &outputFilePath)
+{
+ Data indata;
+#ifdef Q_OS_WIN
+ indata.setFileName(inputFilePath().toUtf8().constData());
+#else
+ indata.setFileName(QFile::encodeName(inputFilePath).constData());
+#endif
+
+ PartialFileGuard partFileGuard{outputFilePath};
+ if (partFileGuard.tempFileName().isEmpty()) {
+ return std::make_tuple(VerificationResult{Error::fromCode(GPG_ERR_EEXIST)}, QByteArray{}, QString{}, Error{});
+ }
+
+ Data outdata;
+#ifdef Q_OS_WIN
+ outdata.setFileName(partFileGuard.tempFileName().toUtf8().constData());
+#else
+ outdata.setFileName(QFile::encodeName(partFileGuard.tempFileName()).constData());
+#endif
+
+ const auto verificationResult = ctx->verifyOpaqueSignature(indata, outdata);
+
+ if (!verificationResult.error().code()) {
+ // the operation succeeded -> save the result under the requested file name
+ partFileGuard.commit();
+ }
+
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(verificationResult, QByteArray{}, log, ae);
+}
+
Error QGpgMEVerifyOpaqueJob::start(const QByteArray &signedData)
{
run(std::bind(&verify_opaque_qba, std::placeholders::_1, signedData));
@@ -124,10 +188,22 @@ GpgME::VerificationResult QGpgME::QGpgMEVerifyOpaqueJob::exec(const QByteArray &
return mResult;
}
-//PENDING(marc) implement showErrorDialog()
-
void QGpgME::QGpgMEVerifyOpaqueJob::resultHook(const result_type &tuple)
{
mResult = std::get<0>(tuple);
}
+
+GpgME::Error QGpgMEVerifyOpaqueJobPrivate::startIt()
+{
+ if (m_inputFilePath.isEmpty() || m_outputFilePath.isEmpty()) {
+ return Error::fromCode(GPG_ERR_INV_VALUE);
+ }
+
+ q->run([=](Context *ctx) {
+ return verify_from_filename(ctx, m_inputFilePath, m_outputFilePath);
+ });
+
+ return {};
+}
+
#include "qgpgmeverifyopaquejob.moc"
diff --git a/lang/qt/src/verifyopaquejob.cpp b/lang/qt/src/verifyopaquejob.cpp
new file mode 100644
index 00000000..1ae8e75b
--- /dev/null
+++ b/lang/qt/src/verifyopaquejob.cpp
@@ -0,0 +1,74 @@
+/*
+ verifyopaquejob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2023 g10 Code GmbH
+ Software engineering by Ingo Klöcker <[email protected]>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "verifyopaquejob.h"
+#include "verifyopaquejob_p.h"
+
+using namespace QGpgME;
+
+VerifyOpaqueJob::VerifyOpaqueJob(QObject *parent)
+ : Job{parent}
+{
+}
+
+VerifyOpaqueJob::~VerifyOpaqueJob() = default;
+
+void VerifyOpaqueJob::setInputFile(const QString &path)
+{
+ auto d = jobPrivate<VerifyOpaqueJobPrivate>(this);
+ d->m_inputFilePath = path;
+}
+
+QString VerifyOpaqueJob::inputFile() const
+{
+ auto d = jobPrivate<VerifyOpaqueJobPrivate>(this);
+ return d->m_inputFilePath;
+}
+
+void VerifyOpaqueJob::setOutputFile(const QString &path)
+{
+ auto d = jobPrivate<VerifyOpaqueJobPrivate>(this);
+ d->m_outputFilePath = path;
+}
+
+QString VerifyOpaqueJob::outputFile() const
+{
+ auto d = jobPrivate<VerifyOpaqueJobPrivate>(this);
+ return d->m_outputFilePath;
+}
+
+#include "verifyopaquejob.moc"
diff --git a/lang/qt/src/verifyopaquejob.h b/lang/qt/src/verifyopaquejob.h
index c9b2247b..8dd73141 100644
--- a/lang/qt/src/verifyopaquejob.h
+++ b/lang/qt/src/verifyopaquejob.h
@@ -61,6 +61,14 @@ namespace QGpgME
VerifyOpaqueJob instance will have scheduled it's own
destruction with a call to QObject::deleteLater().
+ Alternatively, the job can be started with startIt() after setting
+ an input file and an output file. If the job is started this way then
+ the backend reads the input and writes the output directly from/to the
+ specified input file and output file. In this case the plainText value of
+ the result signal will always be empty. This direct IO mode is currently
+ only supported for OpenPGP. Note that startIt() does not schedule the job's
+ destruction if starting the job failed.
+
After result() is emitted, the VerifyOpaqueJob will schedule
it's own destruction by calling QObject::deleteLater().
*/
@@ -70,7 +78,27 @@ class QGPGME_EXPORT VerifyOpaqueJob : public Job
protected:
explicit VerifyOpaqueJob(QObject *parent);
public:
- ~VerifyOpaqueJob();
+ ~VerifyOpaqueJob() override;
+
+ /**
+ * Sets the path of the file to verify.
+ *
+ * Used if the job is started with startIt().
+ */
+ void setInputFile(const QString &path);
+ QString inputFile() const;
+
+ /**
+ * Sets the path of the file to write the result to.
+ *
+ * Used if the job is started with startIt().
+ *
+ * \note If a file with this path exists, then the job will fail, i.e. you
+ * need to delete an existing file that shall be overwritten before you
+ * start the job.
+ */
+ void setOutputFile(const QString &path);
+ QString outputFile() const;
/**
Starts the verification operation. \a signature contains the
diff --git a/lang/qt/src/verifyopaquejob_p.h b/lang/qt/src/verifyopaquejob_p.h
new file mode 100644
index 00000000..3dce6dec
--- /dev/null
+++ b/lang/qt/src/verifyopaquejob_p.h
@@ -0,0 +1,50 @@
+/*
+ verifyopaquejob_p.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2023 g10 Code GmbH
+ Software engineering by Ingo Klöcker <[email protected]>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_VERIFYOPAQUEJOB_P_H__
+#define __QGPGME_VERIFYOPAQUEJOB_P_H__
+
+#include "job_p.h"
+
+namespace QGpgME
+{
+
+struct VerifyOpaqueJobPrivate : public JobPrivate
+{
+ QString m_inputFilePath;
+ QString m_outputFilePath;
+};
+
+}
+
+#endif // __QGPGME_VERIFYOPAQUEJOB_P_H__