qt: Support writing/reading signed/encrypted files directly to/from file
* lang/qt/src/Makefile.am: Add new files. * lang/qt/src/job.cpp (EncryptJob, SignJob, SignEncryptJob): Move definition of constructor and destructor and inclusion of the moc file to the corresponding .cpp files. * lang/qt/src/encryptjob.cpp (EncryptJob): Define constructor. Define destructor as default. Include moc file. * lang/qt/src/encryptjob.cpp, lang/qt/src/encryptjob.h (EncryptJob): Add member functions setRecipients, recipients, setInputFile, inputFile, setOutputFile, outputFile, setEncryptionFlags, encryptionFlags. * lang/qt/src/encryptjob_p.h (EncryptJobPrivate): Add members m_recipients, m_inputFilePath, m_outputFilePath, m_encryptionFlags. * lang/qt/src/qgpgmeencryptjob.cpp (encrypt_to_filename): New. (QGpgMEEncryptJobPrivate::startIt): Start the job with the values from the member variables. * lang/qt/src/qgpgmesignencryptjob.cpp (sign_encrypt_to_filename): New. (QGpgMESignEncryptJobPrivate::startIt): Start the job with the values from the member variables. * lang/qt/src/qgpgmesignjob.cpp (class QGpgMESignJobPrivate): New. (QGpgMESignJob::QGpgMESignJob): Instantiate private job class. (sign_to_filename): New. * lang/qt/src/signencryptjob.cpp (SignEncryptJob): Define constructor. Define destructor as default. Include moc file. * lang/qt/src/signencryptjob.cpp, lang/qt/src/signencryptjob.h (SignEncryptJob): Add member functions setSigners, signers, setRecipients, recipients, setInputFile, inputFile, setOutputFile, outputFile, setEncryptionFlags, encryptionFlags. * lang/qt/src/signencryptjob_p.h (SignEncryptJobPrivate): Add members m_signers, m_recipients, m_inputFilePath, m_outputFilePath, m_encryptionFlags. * lang/qt/src/signjob.cpp: New. * lang/qt/src/signjob.h (SignJob): Add member functions setSigners, signers, setInputFile, inputFile, setOutputFile, outputFile, setSigningFlags, signingFlags. * lang/qt/src/signjob_p.h: New. * lang/qt/tests/Makefile.am: Add new test programs. * lang/qt/tests/run-encryptjob.cpp: New. * lang/qt/tests/run-signjob.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 signing and/or encrypting a file. GnuPG-bug-id: 6550
This commit is contained in:
parent
b166958b86
commit
a44d84772d
@ -65,6 +65,7 @@ qgpgme_sources = \
|
||||
signarchivejob.cpp \
|
||||
signencryptjob.cpp \
|
||||
signencryptarchivejob.cpp \
|
||||
signjob.cpp \
|
||||
dn.cpp cryptoconfig.cpp wkdlookupresult.cpp \
|
||||
util.cpp \
|
||||
wkdrefreshjob.cpp
|
||||
@ -226,6 +227,7 @@ private_qgpgme_headers = \
|
||||
signarchivejob_p.h \
|
||||
signencryptjob_p.h \
|
||||
signencryptarchivejob_p.h \
|
||||
signjob_p.h \
|
||||
threadedjobmixin.h \
|
||||
util.h \
|
||||
wkdrefreshjob_p.h
|
||||
|
@ -40,6 +40,13 @@
|
||||
|
||||
using namespace QGpgME;
|
||||
|
||||
EncryptJob::EncryptJob(QObject *parent)
|
||||
: Job{parent}
|
||||
{
|
||||
}
|
||||
|
||||
EncryptJob::~EncryptJob() = default;
|
||||
|
||||
void EncryptJob::setFileName(const QString &fileName)
|
||||
{
|
||||
auto d = jobPrivate<EncryptJobPrivate>(this);
|
||||
@ -63,3 +70,53 @@ GpgME::Data::Encoding EncryptJob::inputEncoding() const
|
||||
auto d = jobPrivate<EncryptJobPrivate>(this);
|
||||
return d->m_inputEncoding;
|
||||
}
|
||||
|
||||
void EncryptJob::setRecipients(const std::vector<GpgME::Key> &recipients)
|
||||
{
|
||||
auto d = jobPrivate<EncryptJobPrivate>(this);
|
||||
d->m_recipients = recipients;
|
||||
}
|
||||
|
||||
std::vector<GpgME::Key> EncryptJob::recipients() const
|
||||
{
|
||||
auto d = jobPrivate<EncryptJobPrivate>(this);
|
||||
return d->m_recipients;
|
||||
}
|
||||
|
||||
void EncryptJob::setInputFile(const QString &path)
|
||||
{
|
||||
auto d = jobPrivate<EncryptJobPrivate>(this);
|
||||
d->m_inputFilePath = path;
|
||||
}
|
||||
|
||||
QString EncryptJob::inputFile() const
|
||||
{
|
||||
auto d = jobPrivate<EncryptJobPrivate>(this);
|
||||
return d->m_inputFilePath;
|
||||
}
|
||||
|
||||
void EncryptJob::setOutputFile(const QString &path)
|
||||
{
|
||||
auto d = jobPrivate<EncryptJobPrivate>(this);
|
||||
d->m_outputFilePath = path;
|
||||
}
|
||||
|
||||
QString EncryptJob::outputFile() const
|
||||
{
|
||||
auto d = jobPrivate<EncryptJobPrivate>(this);
|
||||
return d->m_outputFilePath;
|
||||
}
|
||||
|
||||
void EncryptJob::setEncryptionFlags(GpgME::Context::EncryptionFlags flags)
|
||||
{
|
||||
auto d = jobPrivate<EncryptJobPrivate>(this);
|
||||
d->m_encryptionFlags = static_cast<GpgME::Context::EncryptionFlags>(flags | GpgME::Context::EncryptFile);
|
||||
}
|
||||
|
||||
GpgME::Context::EncryptionFlags EncryptJob::encryptionFlags() const
|
||||
{
|
||||
auto d = jobPrivate<EncryptJobPrivate>(this);
|
||||
return d->m_encryptionFlags;
|
||||
}
|
||||
|
||||
#include "encryptjob.moc"
|
||||
|
@ -72,6 +72,15 @@ namespace QGpgME
|
||||
EncryptJob 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 and, optionally, recipients or flags.
|
||||
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 cipherText 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 EncryptJob will schedule it's own
|
||||
destruction by calling QObject::deleteLater().
|
||||
*/
|
||||
@ -81,14 +90,63 @@ class QGPGME_EXPORT EncryptJob : public Job
|
||||
protected:
|
||||
explicit EncryptJob(QObject *parent);
|
||||
public:
|
||||
~EncryptJob();
|
||||
~EncryptJob() override;
|
||||
|
||||
/**
|
||||
* Sets the file name to embed in the encryption result.
|
||||
*
|
||||
* This is only used if one of the start() functions is used.
|
||||
*/
|
||||
void setFileName(const QString &fileName);
|
||||
QString fileName() const;
|
||||
|
||||
/**
|
||||
* Sets the encoding of the plaintext.
|
||||
*
|
||||
* This is only used if one of the start() functions is used.
|
||||
*/
|
||||
void setInputEncoding(GpgME::Data::Encoding);
|
||||
GpgME::Data::Encoding inputEncoding() const;
|
||||
|
||||
/**
|
||||
* Sets the keys to use for encryption.
|
||||
*
|
||||
* Used if the job is started with startIt().
|
||||
*/
|
||||
void setRecipients(const std::vector<GpgME::Key> &recipients);
|
||||
std::vector<GpgME::Key> recipients() const;
|
||||
|
||||
/**
|
||||
* Sets the path of the file to encrypt.
|
||||
*
|
||||
* 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 encryption 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;
|
||||
|
||||
/**
|
||||
* Sets the flags to use for encryption.
|
||||
*
|
||||
* Defaults to \c EncryptFile.
|
||||
*
|
||||
* Used if the job is started with startIt(). The \c EncryptFile flag is
|
||||
* always assumed set.
|
||||
*/
|
||||
void setEncryptionFlags(GpgME::Context::EncryptionFlags flags);
|
||||
GpgME::Context::EncryptionFlags encryptionFlags() const;
|
||||
|
||||
/**
|
||||
Starts the encryption operation. \a recipients is the a list of
|
||||
keys to encrypt \a plainText to. Empty (null) keys are
|
||||
|
@ -35,15 +35,24 @@
|
||||
#define __QGPGME_ENCRYPTJOB_P_H__
|
||||
|
||||
#include "job_p.h"
|
||||
#include "data.h"
|
||||
|
||||
#include <data.h>
|
||||
#include <key.h>
|
||||
|
||||
namespace QGpgME
|
||||
{
|
||||
|
||||
struct EncryptJobPrivate : public JobPrivate
|
||||
{
|
||||
// used by start() functions
|
||||
QString m_fileName;
|
||||
GpgME::Data::Encoding m_inputEncoding;
|
||||
|
||||
// used by startIt()
|
||||
std::vector<GpgME::Key> m_recipients;
|
||||
QString m_inputFilePath;
|
||||
QString m_outputFilePath;
|
||||
GpgME::Context::EncryptionFlags m_encryptionFlags = GpgME::Context::EncryptFile;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -43,12 +43,9 @@
|
||||
|
||||
#include "keylistjob.h"
|
||||
#include "listallkeysjob.h"
|
||||
#include "encryptjob.h"
|
||||
#include "decryptjob.h"
|
||||
#include "decryptverifyjob.h"
|
||||
#include "signjob.h"
|
||||
#include "signkeyjob.h"
|
||||
#include "signencryptjob.h"
|
||||
#include "verifydetachedjob.h"
|
||||
#include "verifyopaquejob.h"
|
||||
#include "keygenerationjob.h"
|
||||
@ -164,11 +161,8 @@ void QGpgME::Job::startNow()
|
||||
|
||||
make_job_subclass(KeyListJob)
|
||||
make_job_subclass(ListAllKeysJob)
|
||||
make_job_subclass(EncryptJob)
|
||||
make_job_subclass(DecryptJob)
|
||||
make_job_subclass(DecryptVerifyJob)
|
||||
make_job_subclass(SignJob)
|
||||
make_job_subclass(SignEncryptJob)
|
||||
make_job_subclass(SignKeyJob)
|
||||
make_job_subclass(VerifyDetachedJob)
|
||||
make_job_subclass(VerifyOpaqueJob)
|
||||
@ -202,11 +196,8 @@ make_job_subclass(SetPrimaryUserIDJob)
|
||||
|
||||
#include "keylistjob.moc"
|
||||
#include "listallkeysjob.moc"
|
||||
#include "encryptjob.moc"
|
||||
#include "decryptjob.moc"
|
||||
#include "decryptverifyjob.moc"
|
||||
#include "signjob.moc"
|
||||
#include "signencryptjob.moc"
|
||||
#include "signkeyjob.moc"
|
||||
#include "verifydetachedjob.moc"
|
||||
#include "verifyopaquejob.moc"
|
||||
|
@ -40,13 +40,13 @@
|
||||
|
||||
#include "qgpgmeencryptjob.h"
|
||||
|
||||
#include "encryptjob_p.h"
|
||||
|
||||
#include "dataprovider.h"
|
||||
#include "encryptjob_p.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "encryptionresult.h"
|
||||
#include "data.h"
|
||||
#include <context.h>
|
||||
#include <data.h>
|
||||
#include <encryptionresult.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QFileInfo>
|
||||
@ -72,11 +72,7 @@ public:
|
||||
~QGpgMEEncryptJobPrivate() 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
|
||||
{
|
||||
@ -168,6 +164,44 @@ static QGpgMEEncryptJob::result_type encrypt_qba(Context *ctx, const std::vector
|
||||
return encrypt(ctx, nullptr, recipients, buffer, std::shared_ptr<QIODevice>(), eflags, outputIsBsse64Encoded, inputEncoding, fileName);
|
||||
}
|
||||
|
||||
static QGpgMEEncryptJob::result_type encrypt_to_filename(Context *ctx,
|
||||
const std::vector<Key> &recipients,
|
||||
const QString &inputFilePath,
|
||||
const QString &outputFilePath,
|
||||
Context::EncryptionFlags flags)
|
||||
{
|
||||
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(EncryptionResult{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
|
||||
|
||||
flags = static_cast<Context::EncryptionFlags>(flags | Context::EncryptFile);
|
||||
const auto encryptionResult = ctx->encrypt(recipients, indata, outdata, flags);
|
||||
|
||||
if (!encryptionResult.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(encryptionResult, QByteArray{}, log, ae);
|
||||
}
|
||||
|
||||
Error QGpgMEEncryptJob::start(const std::vector<Key> &recipients, const QByteArray &plainText, bool alwaysTrust)
|
||||
{
|
||||
run(std::bind(&encrypt_qba, std::placeholders::_1, recipients, plainText,
|
||||
@ -213,4 +247,17 @@ void QGpgMEEncryptJob::resultHook(const result_type &tuple)
|
||||
mResult = std::get<0>(tuple);
|
||||
}
|
||||
|
||||
GpgME::Error QGpgMEEncryptJobPrivate::startIt()
|
||||
{
|
||||
if (m_inputFilePath.isEmpty() || m_outputFilePath.isEmpty()) {
|
||||
return Error::fromCode(GPG_ERR_INV_VALUE);
|
||||
}
|
||||
|
||||
q->run([=](Context *ctx) {
|
||||
return encrypt_to_filename(ctx, m_recipients, m_inputFilePath, m_outputFilePath, m_encryptionFlags);
|
||||
});
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
#include "qgpgmeencryptjob.moc"
|
||||
|
@ -40,14 +40,14 @@
|
||||
|
||||
#include "qgpgmesignencryptjob.h"
|
||||
|
||||
#include "signencryptjob_p.h"
|
||||
|
||||
#include "dataprovider.h"
|
||||
#include "signencryptjob_p.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "data.h"
|
||||
#include "key.h"
|
||||
#include "exception.h"
|
||||
#include <context.h>
|
||||
#include <data.h>
|
||||
#include <exception.h>
|
||||
#include <key.h>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QFileInfo>
|
||||
@ -73,11 +73,7 @@ public:
|
||||
~QGpgMESignEncryptJobPrivate() 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
|
||||
{
|
||||
@ -171,6 +167,60 @@ static QGpgMESignEncryptJob::result_type sign_encrypt_qba(Context *ctx, const st
|
||||
return sign_encrypt(ctx, nullptr, signers, recipients, buffer, std::shared_ptr<QIODevice>(), eflags, outputIsBsse64Encoded, fileName);
|
||||
}
|
||||
|
||||
static QGpgMESignEncryptJob::result_type sign_encrypt_to_filename(Context *ctx,
|
||||
const std::vector<Key> &signers,
|
||||
const std::vector<Key> &recipients,
|
||||
const QString &inputFilePath,
|
||||
const QString &outputFilePath,
|
||||
Context::EncryptionFlags flags)
|
||||
{
|
||||
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(SigningResult{Error::fromCode(GPG_ERR_EEXIST)},
|
||||
EncryptionResult{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
|
||||
|
||||
ctx->clearSigningKeys();
|
||||
for (const Key &signer : signers) {
|
||||
if (!signer.isNull()) {
|
||||
if (const Error err = ctx->addSigningKey(signer)) {
|
||||
return std::make_tuple(SigningResult{err}, EncryptionResult{}, QByteArray{}, QString{}, Error{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flags = static_cast<Context::EncryptionFlags>(flags | Context::EncryptFile);
|
||||
const auto results = ctx->signAndEncrypt(recipients, indata, outdata, flags);
|
||||
const auto &signingResult = results.first;
|
||||
const auto &encryptionResult = results.second;
|
||||
|
||||
if (!signingResult.error().code() && !encryptionResult.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(signingResult, encryptionResult, QByteArray{}, log, ae);
|
||||
}
|
||||
|
||||
Error QGpgMESignEncryptJob::start(const std::vector<Key> &signers, const std::vector<Key> &recipients, const QByteArray &plainText, bool alwaysTrust)
|
||||
{
|
||||
run(std::bind(&sign_encrypt_qba, std::placeholders::_1, signers, recipients, plainText, alwaysTrust ? Context::AlwaysTrust : Context::None, mOutputIsBase64Encoded, fileName()));
|
||||
@ -205,4 +255,18 @@ void QGpgMESignEncryptJob::resultHook(const result_type &tuple)
|
||||
{
|
||||
mResult = std::make_pair(std::get<0>(tuple), std::get<1>(tuple));
|
||||
}
|
||||
|
||||
GpgME::Error QGpgMESignEncryptJobPrivate::startIt()
|
||||
{
|
||||
if (m_inputFilePath.isEmpty() || m_outputFilePath.isEmpty()) {
|
||||
return Error::fromCode(GPG_ERR_INV_VALUE);
|
||||
}
|
||||
|
||||
q->run([=](Context *ctx) {
|
||||
return sign_encrypt_to_filename(ctx, m_signers, m_recipients, m_inputFilePath, m_outputFilePath, m_encryptionFlags);
|
||||
});
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
#include "qgpgmesignencryptjob.moc"
|
||||
|
@ -39,23 +39,52 @@
|
||||
#include "qgpgmesignjob.h"
|
||||
|
||||
#include "dataprovider.h"
|
||||
#include "signjob_p.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "context.h"
|
||||
#include "signingresult.h"
|
||||
#include "data.h"
|
||||
#include <context.h>
|
||||
#include <data.h>
|
||||
#include <signingresult.h>
|
||||
|
||||
#include <QBuffer>
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
using namespace QGpgME;
|
||||
using namespace GpgME;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
class QGpgMESignJobPrivate : public SignJobPrivate
|
||||
{
|
||||
QGpgMESignJob *q = nullptr;
|
||||
|
||||
public:
|
||||
QGpgMESignJobPrivate(QGpgMESignJob *qq)
|
||||
: q{qq}
|
||||
{
|
||||
}
|
||||
|
||||
~QGpgMESignJobPrivate() override = default;
|
||||
|
||||
private:
|
||||
GpgME::Error startIt() override;
|
||||
|
||||
void startNow() override
|
||||
{
|
||||
q->run();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
QGpgMESignJob::QGpgMESignJob(Context *context)
|
||||
: mixin_type(context),
|
||||
mOutputIsBase64Encoded(false)
|
||||
{
|
||||
setJobPrivate(this, std::unique_ptr<QGpgMESignJobPrivate>{new QGpgMESignJobPrivate{this}});
|
||||
lateInitialization();
|
||||
}
|
||||
|
||||
@ -137,6 +166,56 @@ static QGpgMESignJob::result_type sign_qba(Context *ctx,
|
||||
return sign(ctx, nullptr, signers, buffer, std::shared_ptr<QIODevice>(), mode, outputIsBsse64Encoded);
|
||||
}
|
||||
|
||||
static QGpgMESignJob::result_type sign_to_filename(Context *ctx,
|
||||
const std::vector<Key> &signers,
|
||||
const QString &inputFilePath,
|
||||
const QString &outputFilePath,
|
||||
SignatureMode flags)
|
||||
{
|
||||
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(SigningResult{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
|
||||
|
||||
ctx->clearSigningKeys();
|
||||
for (const Key &signer : signers) {
|
||||
if (!signer.isNull()) {
|
||||
if (const Error err = ctx->addSigningKey(signer)) {
|
||||
return std::make_tuple(SigningResult{err}, QByteArray{}, QString{}, Error{});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flags = static_cast<SignatureMode>(flags | SignFile);
|
||||
const auto signingResult = ctx->sign(indata, outdata, flags);
|
||||
|
||||
if (!signingResult.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(signingResult, QByteArray{}, log, ae);
|
||||
}
|
||||
|
||||
Error QGpgMESignJob::start(const std::vector<Key> &signers, const QByteArray &plainText, SignatureMode mode)
|
||||
{
|
||||
run(std::bind(&sign_qba, std::placeholders::_1, signers, plainText, mode, mOutputIsBase64Encoded));
|
||||
@ -161,4 +240,17 @@ void QGpgMESignJob::resultHook(const result_type &tuple)
|
||||
mResult = std::get<0>(tuple);
|
||||
}
|
||||
|
||||
GpgME::Error QGpgMESignJobPrivate::startIt()
|
||||
{
|
||||
if (m_inputFilePath.isEmpty() || m_outputFilePath.isEmpty()) {
|
||||
return Error::fromCode(GPG_ERR_INV_VALUE);
|
||||
}
|
||||
|
||||
q->run([=](Context *ctx) {
|
||||
return sign_to_filename(ctx, m_signers, m_inputFilePath, m_outputFilePath, m_signingFlags);
|
||||
});
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
#include "qgpgmesignjob.moc"
|
||||
|
@ -40,6 +40,13 @@
|
||||
|
||||
using namespace QGpgME;
|
||||
|
||||
SignEncryptJob::SignEncryptJob(QObject *parent)
|
||||
: Job{parent}
|
||||
{
|
||||
}
|
||||
|
||||
SignEncryptJob::~SignEncryptJob() = default;
|
||||
|
||||
void SignEncryptJob::setFileName(const QString &fileName)
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
@ -51,3 +58,65 @@ QString SignEncryptJob::fileName() const
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
return d->m_fileName;
|
||||
}
|
||||
|
||||
void SignEncryptJob::setSigners(const std::vector<GpgME::Key> &signers)
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
d->m_signers = signers;
|
||||
}
|
||||
|
||||
std::vector<GpgME::Key> SignEncryptJob::signers() const
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
return d->m_signers;
|
||||
}
|
||||
|
||||
void SignEncryptJob::setRecipients(const std::vector<GpgME::Key> &recipients)
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
d->m_recipients = recipients;
|
||||
}
|
||||
|
||||
std::vector<GpgME::Key> SignEncryptJob::recipients() const
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
return d->m_recipients;
|
||||
}
|
||||
|
||||
void SignEncryptJob::setInputFile(const QString &path)
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
d->m_inputFilePath = path;
|
||||
}
|
||||
|
||||
QString SignEncryptJob::inputFile() const
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
return d->m_inputFilePath;
|
||||
}
|
||||
|
||||
void SignEncryptJob::setOutputFile(const QString &path)
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
d->m_outputFilePath = path;
|
||||
}
|
||||
|
||||
QString SignEncryptJob::outputFile() const
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
return d->m_outputFilePath;
|
||||
}
|
||||
|
||||
void SignEncryptJob::setEncryptionFlags(GpgME::Context::EncryptionFlags flags)
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
d->m_encryptionFlags = static_cast<GpgME::Context::EncryptionFlags>(flags | GpgME::Context::EncryptFile);
|
||||
}
|
||||
|
||||
GpgME::Context::EncryptionFlags SignEncryptJob::encryptionFlags() const
|
||||
{
|
||||
auto d = jobPrivate<SignEncryptJobPrivate>(this);
|
||||
return d->m_encryptionFlags;
|
||||
}
|
||||
|
||||
#include "signencryptjob.moc"
|
||||
|
@ -76,6 +76,15 @@ namespace QGpgME
|
||||
SignEncryptJob 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 and, optionally, signers, recipients or flags.
|
||||
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 cipherText 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 SignEncryptJob will schedule it's
|
||||
own destruction by calling QObject::deleteLater().
|
||||
*/
|
||||
@ -85,11 +94,63 @@ class QGPGME_EXPORT SignEncryptJob : public Job
|
||||
protected:
|
||||
explicit SignEncryptJob(QObject *parent);
|
||||
public:
|
||||
~SignEncryptJob();
|
||||
~SignEncryptJob() override;
|
||||
|
||||
/**
|
||||
* Sets the file name to embed in the encryption result.
|
||||
*
|
||||
* This is only used if one of the start() functions is used.
|
||||
*/
|
||||
void setFileName(const QString &fileName);
|
||||
QString fileName() const;
|
||||
|
||||
/**
|
||||
* Sets the keys to use for signing.
|
||||
*
|
||||
* Used if the job is started with startIt().
|
||||
*/
|
||||
void setSigners(const std::vector<GpgME::Key> &signers);
|
||||
std::vector<GpgME::Key> signers() const;
|
||||
|
||||
/**
|
||||
* Sets the keys to use for encryption.
|
||||
*
|
||||
* Used if the job is started with startIt().
|
||||
*/
|
||||
void setRecipients(const std::vector<GpgME::Key> &recipients);
|
||||
std::vector<GpgME::Key> recipients() const;
|
||||
|
||||
/**
|
||||
* Sets the path of the file to encrypt.
|
||||
*
|
||||
* 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 encryption 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;
|
||||
|
||||
/**
|
||||
* Sets the flags to use for encryption.
|
||||
*
|
||||
* Defaults to \c EncryptFile.
|
||||
*
|
||||
* Used if the job is started with startIt(). The \c EncryptFile flag is
|
||||
* always assumed set.
|
||||
*/
|
||||
void setEncryptionFlags(GpgME::Context::EncryptionFlags flags);
|
||||
GpgME::Context::EncryptionFlags encryptionFlags() const;
|
||||
|
||||
/**
|
||||
Starts the combined signing and encrypting operation. \a signers
|
||||
is the list of keys to sign \a plainText with. \a recipients is
|
||||
|
@ -36,12 +36,22 @@
|
||||
|
||||
#include "job_p.h"
|
||||
|
||||
#include <key.h>
|
||||
|
||||
namespace QGpgME
|
||||
{
|
||||
|
||||
struct SignEncryptJobPrivate : public JobPrivate
|
||||
{
|
||||
// used by start() functions
|
||||
QString m_fileName;
|
||||
|
||||
// used by startIt()
|
||||
std::vector<GpgME::Key> m_signers;
|
||||
std::vector<GpgME::Key> m_recipients;
|
||||
QString m_inputFilePath;
|
||||
QString m_outputFilePath;
|
||||
GpgME::Context::EncryptionFlags m_encryptionFlags = GpgME::Context::EncryptFile;
|
||||
};
|
||||
|
||||
}
|
||||
|
98
lang/qt/src/signjob.cpp
Normal file
98
lang/qt/src/signjob.cpp
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
signjob.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 <dev@ingo-kloecker.de>
|
||||
|
||||
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 "signjob.h"
|
||||
#include "signjob_p.h"
|
||||
|
||||
using namespace QGpgME;
|
||||
|
||||
SignJob::SignJob(QObject *parent)
|
||||
: Job{parent}
|
||||
{
|
||||
}
|
||||
|
||||
SignJob::~SignJob() = default;
|
||||
|
||||
void SignJob::setSigners(const std::vector<GpgME::Key> &signers)
|
||||
{
|
||||
auto d = jobPrivate<SignJobPrivate>(this);
|
||||
d->m_signers = signers;
|
||||
}
|
||||
|
||||
std::vector<GpgME::Key> SignJob::signers() const
|
||||
{
|
||||
auto d = jobPrivate<SignJobPrivate>(this);
|
||||
return d->m_signers;
|
||||
}
|
||||
|
||||
void SignJob::setInputFile(const QString &path)
|
||||
{
|
||||
auto d = jobPrivate<SignJobPrivate>(this);
|
||||
d->m_inputFilePath = path;
|
||||
}
|
||||
|
||||
QString SignJob::inputFile() const
|
||||
{
|
||||
auto d = jobPrivate<SignJobPrivate>(this);
|
||||
return d->m_inputFilePath;
|
||||
}
|
||||
|
||||
void SignJob::setOutputFile(const QString &path)
|
||||
{
|
||||
auto d = jobPrivate<SignJobPrivate>(this);
|
||||
d->m_outputFilePath = path;
|
||||
}
|
||||
|
||||
QString SignJob::outputFile() const
|
||||
{
|
||||
auto d = jobPrivate<SignJobPrivate>(this);
|
||||
return d->m_outputFilePath;
|
||||
}
|
||||
|
||||
void SignJob::setSigningFlags(GpgME::SignatureMode flags)
|
||||
{
|
||||
auto d = jobPrivate<SignJobPrivate>(this);
|
||||
d->m_signingFlags = static_cast<GpgME::SignatureMode>(flags | GpgME::SignFile);
|
||||
}
|
||||
|
||||
GpgME::SignatureMode SignJob::signingFlags() const
|
||||
{
|
||||
auto d = jobPrivate<SignJobPrivate>(this);
|
||||
return d->m_signingFlags;
|
||||
}
|
||||
|
||||
#include "signjob.moc"
|
@ -70,6 +70,15 @@ namespace QGpgME
|
||||
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 and, optionally, signers or flags.
|
||||
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 signature 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 SignJob will schedule it's own
|
||||
destruction by calling QObject::deleteLater().
|
||||
*/
|
||||
@ -79,7 +88,46 @@ class QGPGME_EXPORT SignJob : public Job
|
||||
protected:
|
||||
explicit SignJob(QObject *parent);
|
||||
public:
|
||||
~SignJob();
|
||||
~SignJob() override;
|
||||
|
||||
/**
|
||||
* Sets the keys to use for signing.
|
||||
*
|
||||
* Used if the job is started with startIt().
|
||||
*/
|
||||
void setSigners(const std::vector<GpgME::Key> &signers);
|
||||
std::vector<GpgME::Key> signers() const;
|
||||
|
||||
/**
|
||||
* Sets the path of the file to sign.
|
||||
*
|
||||
* 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 signing 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;
|
||||
|
||||
/**
|
||||
* Sets the flags to use for signing.
|
||||
*
|
||||
* Defaults to \c SignFile.
|
||||
*
|
||||
* Used if the job is started with startIt(). The \c SignFile flag is
|
||||
* always assumed set.
|
||||
*/
|
||||
void setSigningFlags(GpgME::SignatureMode flags);
|
||||
GpgME::SignatureMode signingFlags() const;
|
||||
|
||||
/**
|
||||
Starts the signing operation. \a signers is the list of keys to
|
||||
|
55
lang/qt/src/signjob_p.h
Normal file
55
lang/qt/src/signjob_p.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
signjob_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 <dev@ingo-kloecker.de>
|
||||
|
||||
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_SIGNJOB_P_H__
|
||||
#define __QGPGME_SIGNJOB_P_H__
|
||||
|
||||
#include "job_p.h"
|
||||
|
||||
#include <key.h>
|
||||
|
||||
namespace QGpgME
|
||||
{
|
||||
|
||||
struct SignJobPrivate : public JobPrivate
|
||||
{
|
||||
// used by startIt()
|
||||
std::vector<GpgME::Key> m_signers;
|
||||
QString m_inputFilePath;
|
||||
QString m_outputFilePath;
|
||||
GpgME::SignatureMode m_signingFlags = GpgME::SignFile;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __QGPGME_SIGNJOB_P_H__
|
@ -91,12 +91,14 @@ t_revokekey_SOURCES = t-revokekey.cpp $(support_src)
|
||||
t_setprimaryuserid_SOURCES = t-setprimaryuserid.cpp $(support_src)
|
||||
run_decryptverifyarchivejob_SOURCES = run-decryptverifyarchivejob.cpp
|
||||
run_encryptarchivejob_SOURCES = run-encryptarchivejob.cpp
|
||||
run_encryptjob_SOURCES = run-encryptjob.cpp
|
||||
run_exportjob_SOURCES = run-exportjob.cpp
|
||||
run_importjob_SOURCES = run-importjob.cpp
|
||||
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
|
||||
run_receivekeysjob_SOURCES = run-receivekeysjob.cpp
|
||||
run_refreshkeysjob_SOURCES = run-refreshkeysjob.cpp
|
||||
run_signarchivejob_SOURCES = run-signarchivejob.cpp
|
||||
run_signjob_SOURCES = run-signjob.cpp
|
||||
run_wkdrefreshjob_SOURCES = run-wkdrefreshjob.cpp
|
||||
|
||||
nodist_t_keylist_SOURCES = $(moc_files)
|
||||
@ -112,8 +114,10 @@ noinst_PROGRAMS = \
|
||||
t-setprimaryuserid \
|
||||
run-decryptverifyarchivejob \
|
||||
run-encryptarchivejob \
|
||||
run-encryptjob \
|
||||
run-importjob run-exportjob run-receivekeysjob run-refreshkeysjob \
|
||||
run-signarchivejob \
|
||||
run-signjob \
|
||||
run-wkdrefreshjob
|
||||
|
||||
|
||||
|
198
lang/qt/tests/run-encryptjob.cpp
Normal file
198
lang/qt/tests/run-encryptjob.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
run-encryptjob.cpp
|
||||
|
||||
This file is part of QGpgME's test suite.
|
||||
Copyright (c) 2023 by g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
QGpgME is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
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 <protocol.h>
|
||||
#include <encryptjob.h>
|
||||
#include <signencryptjob.h>
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
|
||||
#include <context.h>
|
||||
#include <encryptionresult.h>
|
||||
#include <signingresult.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const QString &s)
|
||||
{
|
||||
return os << s.toLocal8Bit().constData();
|
||||
}
|
||||
|
||||
struct CommandLineOptions {
|
||||
bool armor = false;
|
||||
bool sign = false;
|
||||
QString inputFile;
|
||||
QString outputFile;
|
||||
std::chrono::seconds cancelTimeout{0};
|
||||
};
|
||||
|
||||
CommandLineOptions parseCommandLine(const QStringList &arguments)
|
||||
{
|
||||
CommandLineOptions options;
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Test program for EncryptJob and SignEncryptJob");
|
||||
parser.addHelpOption();
|
||||
parser.addOptions({
|
||||
{{"s", "sign"}, "Sign file before encryption."},
|
||||
{{"o", "output"}, "Write output to FILE.", "FILE"},
|
||||
{{"a", "armor"}, "Create ASCII armored output."},
|
||||
{"cancel-after", "Cancel the running job after SECONDS seconds.", "SECONDS"},
|
||||
});
|
||||
parser.addPositionalArgument("file", "File to encrypt", "FILE");
|
||||
|
||||
parser.process(arguments);
|
||||
|
||||
const auto args = parser.positionalArguments();
|
||||
if (args.size() != 1) {
|
||||
parser.showHelp(1);
|
||||
}
|
||||
|
||||
options.armor = parser.isSet("armor");
|
||||
options.sign = parser.isSet("sign");
|
||||
options.inputFile = args.front();
|
||||
options.outputFile = parser.value("output");
|
||||
if (parser.isSet("cancel-after")) {
|
||||
bool ok;
|
||||
options.cancelTimeout = std::chrono::seconds{parser.value("cancel-after").toInt(&ok)};
|
||||
if (!ok) {
|
||||
options.cancelTimeout = std::chrono::seconds{-1};
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GpgME::initializeLibrary();
|
||||
|
||||
QCoreApplication app{argc, argv};
|
||||
app.setApplicationName("run-encryptjob");
|
||||
|
||||
const auto options = parseCommandLine(app.arguments());
|
||||
if (options.cancelTimeout.count() < 0) {
|
||||
std::cerr << "Ignoring invalid timeout for cancel." << std::endl;
|
||||
}
|
||||
|
||||
std::shared_ptr<QFile> output;
|
||||
if (options.outputFile.isEmpty() || options.outputFile == QLatin1String{"-"}) {
|
||||
output.reset(new QFile);
|
||||
output->open(stdout, QIODevice::WriteOnly);
|
||||
} else {
|
||||
if (QFile::exists(options.outputFile)) {
|
||||
qCritical() << "File" << options.outputFile << "exists. Bailing out.";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<QFile> input;
|
||||
|
||||
if (options.sign) {
|
||||
auto job = QGpgME::openpgp()->signEncryptJob(options.armor);
|
||||
if (!job) {
|
||||
std::cerr << "Error: Could not create job" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
QObject::connect(job, &QGpgME::SignEncryptJob::result, &app, [](const GpgME::SigningResult &signingResult, const GpgME::EncryptionResult &encryptionResult, const QByteArray &, const QString &auditLog, const GpgME::Error &) {
|
||||
std::cerr << "Diagnostics: " << auditLog << std::endl;
|
||||
std::cerr << "Signing Result: " << signingResult << std::endl;
|
||||
std::cerr << "Encryption Result: " << encryptionResult << std::endl;
|
||||
qApp->quit();
|
||||
});
|
||||
if (options.cancelTimeout.count() > 0) {
|
||||
QTimer::singleShot(options.cancelTimeout, job, [job]() {
|
||||
std::cerr << "Canceling job" << std::endl;
|
||||
job->slotCancel();
|
||||
});
|
||||
}
|
||||
|
||||
GpgME::Error err;
|
||||
if (output) {
|
||||
input.reset(new QFile{options.inputFile});
|
||||
input->open(QIODevice::ReadOnly);
|
||||
job->start({}, {}, input, output, GpgME::Context::None);
|
||||
} else {
|
||||
job->setInputFile(options.inputFile);
|
||||
job->setOutputFile(options.outputFile);
|
||||
err = job->startIt();
|
||||
}
|
||||
if (err) {
|
||||
std::cerr << "Error: Starting the job failed: " << err.asString() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
auto job = QGpgME::openpgp()->encryptJob(options.armor);
|
||||
if (!job) {
|
||||
std::cerr << "Error: Could not create job" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
QObject::connect(job, &QGpgME::EncryptJob::result, &app, [](const GpgME::EncryptionResult &result, const QByteArray &, const QString &auditLog, const GpgME::Error &) {
|
||||
std::cerr << "Diagnostics: " << auditLog << std::endl;
|
||||
std::cerr << "Result: " << result << std::endl;
|
||||
qApp->quit();
|
||||
});
|
||||
if (options.cancelTimeout.count() > 0) {
|
||||
QTimer::singleShot(options.cancelTimeout, job, [job]() {
|
||||
std::cerr << "Canceling job" << std::endl;
|
||||
job->slotCancel();
|
||||
});
|
||||
}
|
||||
|
||||
GpgME::Error err;
|
||||
if (output) {
|
||||
input.reset(new QFile{options.inputFile});
|
||||
input->open(QIODevice::ReadOnly);
|
||||
job->start({}, input, output, GpgME::Context::None);
|
||||
} else {
|
||||
job->setInputFile(options.inputFile);
|
||||
job->setOutputFile(options.outputFile);
|
||||
err = job->startIt();
|
||||
}
|
||||
if (err) {
|
||||
std::cerr << "Error: Starting the job failed: " << err.asString() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
}
|
157
lang/qt/tests/run-signjob.cpp
Normal file
157
lang/qt/tests/run-signjob.cpp
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
run-signjob.cpp
|
||||
|
||||
This file is part of QGpgME's test suite.
|
||||
Copyright (c) 2023 by g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
QGpgME is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License,
|
||||
version 2, as published by the Free Software Foundation.
|
||||
|
||||
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 <protocol.h>
|
||||
#include <signjob.h>
|
||||
|
||||
#include <QCommandLineParser>
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
|
||||
#include <context.h>
|
||||
#include <signingresult.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const QString &s)
|
||||
{
|
||||
return os << s.toLocal8Bit().constData();
|
||||
}
|
||||
|
||||
struct CommandLineOptions {
|
||||
bool armor;
|
||||
QString inputFile;
|
||||
QString outputFile;
|
||||
std::chrono::seconds cancelTimeout{0};
|
||||
};
|
||||
|
||||
CommandLineOptions parseCommandLine(const QStringList &arguments)
|
||||
{
|
||||
CommandLineOptions options;
|
||||
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Test program for SignJob");
|
||||
parser.addHelpOption();
|
||||
parser.addOptions({
|
||||
{{"o", "output"}, "Write output to FILE.", "FILE"},
|
||||
{{"a", "armor"}, "Create ASCII armored output."},
|
||||
{"cancel-after", "Cancel the running job after SECONDS seconds.", "SECONDS"},
|
||||
});
|
||||
parser.addPositionalArgument("file", "File to sign", "FILE");
|
||||
|
||||
parser.process(arguments);
|
||||
|
||||
const auto args = parser.positionalArguments();
|
||||
if (args.size() != 1) {
|
||||
parser.showHelp(1);
|
||||
}
|
||||
|
||||
options.armor = parser.isSet("armor");
|
||||
options.inputFile = args.front();
|
||||
options.outputFile = parser.value("output");
|
||||
if (parser.isSet("cancel-after")) {
|
||||
bool ok;
|
||||
options.cancelTimeout = std::chrono::seconds{parser.value("cancel-after").toInt(&ok)};
|
||||
if (!ok) {
|
||||
options.cancelTimeout = std::chrono::seconds{-1};
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GpgME::initializeLibrary();
|
||||
|
||||
QCoreApplication app{argc, argv};
|
||||
app.setApplicationName("run-signjob");
|
||||
|
||||
const auto options = parseCommandLine(app.arguments());
|
||||
if (options.cancelTimeout.count() < 0) {
|
||||
std::cerr << "Ignoring invalid timeout for cancel." << std::endl;
|
||||
}
|
||||
|
||||
std::shared_ptr<QFile> output;
|
||||
if (options.outputFile.isEmpty() || options.outputFile == QLatin1String{"-"}) {
|
||||
output.reset(new QFile);
|
||||
output->open(stdout, QIODevice::WriteOnly);
|
||||
} else {
|
||||
if (QFile::exists(options.outputFile)) {
|
||||
qCritical() << "File" << options.outputFile << "exists. Bailing out.";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto job = QGpgME::openpgp()->signJob(options.armor);
|
||||
if (!job) {
|
||||
std::cerr << "Error: Could not create job" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
QObject::connect(job, &QGpgME::SignJob::result, &app, [](const GpgME::SigningResult &result, const QByteArray &, const QString &auditLog, const GpgME::Error &) {
|
||||
std::cerr << "Diagnostics: " << auditLog << std::endl;
|
||||
std::cerr << "Result: " << result << std::endl;
|
||||
qApp->quit();
|
||||
});
|
||||
if (options.cancelTimeout.count() > 0) {
|
||||
QTimer::singleShot(options.cancelTimeout, job, [job]() {
|
||||
std::cerr << "Canceling job" << std::endl;
|
||||
job->slotCancel();
|
||||
});
|
||||
}
|
||||
|
||||
std::shared_ptr<QFile> input;
|
||||
GpgME::Error err;
|
||||
if (output) {
|
||||
input.reset(new QFile{options.inputFile});
|
||||
input->open(QIODevice::ReadOnly);
|
||||
job->start({}, input, output, GpgME::NormalSignatureMode);
|
||||
} else {
|
||||
job->setInputFile(options.inputFile);
|
||||
job->setOutputFile(options.outputFile);
|
||||
err = job->startIt();
|
||||
}
|
||||
if (err) {
|
||||
std::cerr << "Error: Starting the job failed: " << err.asString() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
}
|
Loading…
Reference in New Issue
Block a user