qt: Add job to add existing subkeys to other keys
* lang/qt/src/addexistingsubkeyjob.h, lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp, lang/qt/src/qgpgmeaddexistingsubkeyjob.h: New. * lang/qt/src/protocol.h (class Protocol): Add pure virtual member function addExistingSubkeyJob. * lang/qt/src/protocol_p.h (Protocol::addExistingSubkeyJob): Implement. * lang/qt/src/job.cpp, lang/qt/src/Makefile.am: Update accordingly. * lang/qt/tests/Makefile.am (the_tests, moc_files, noinst_PROGRAMS): Add new test. (t_addexistingsubkey_SOURCES): New. * lang/qt/tests/t-addexistingsubkey.cpp: New. * lang/qt/tests/t-support.h (VERIFY_OR_RETURN_VALUE, COMPARE_OR_RETURN_VALUE, VERIFY_OR_OBJECT, COMPARE_OR_OBJECT, VERIFY_OR_FALSE, COMPARE_OR_FALSE): New. * lang/qt/tests/t-support.h, lang/qt/tests/t-support.cpp (class QQGpgMETest): New member function importSecretKeys. -- The new job allows adding existing subkeys to other keys as with the "addkey" edit-key command of gpg. The added subkey will have the same expiration date (+/- 1 second) as the original subkey. GnuPG-bug-id: 5770
This commit is contained in:
parent
d308910cdf
commit
4d913a8aa5
4
NEWS
4
NEWS
@ -12,7 +12,7 @@ Noteworthy changes in version 1.16.1 (unreleased)
|
|||||||
* cpp,qt: Add support for export of secret keys and secret subkeys.
|
* cpp,qt: Add support for export of secret keys and secret subkeys.
|
||||||
[#5757]
|
[#5757]
|
||||||
|
|
||||||
* cpp: Support for adding existing subkeys to other keys. [#5770]
|
* cpp,qt: Support for adding existing subkeys to other keys. [#5770]
|
||||||
|
|
||||||
* qt: Extend ChangeExpiryJob to change expiration of primary key
|
* qt: Extend ChangeExpiryJob to change expiration of primary key
|
||||||
and of subkeys at the same time. [#4717]
|
and of subkeys at the same time. [#4717]
|
||||||
@ -35,6 +35,8 @@ Noteworthy changes in version 1.16.1 (unreleased)
|
|||||||
qt: ChangeExpiryJob::Options NEW.
|
qt: ChangeExpiryJob::Options NEW.
|
||||||
qt: ChangeExpiryJob::setOptions NEW.
|
qt: ChangeExpiryJob::setOptions NEW.
|
||||||
qt: ChangeExpiryJob::options NEW.
|
qt: ChangeExpiryJob::options NEW.
|
||||||
|
qt: AddExistingSubkeyJob NEW.
|
||||||
|
qt: Protocol::addExistingSubkeyJob NEW.
|
||||||
|
|
||||||
Noteworthy changes in version 1.16.0 (2021-06-24)
|
Noteworthy changes in version 1.16.0 (2021-06-24)
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
@ -27,6 +27,7 @@ qgpgme_sources = \
|
|||||||
dataprovider.cpp \
|
dataprovider.cpp \
|
||||||
debug.cpp \
|
debug.cpp \
|
||||||
job.cpp multideletejob.cpp qgpgmeadduseridjob.cpp \
|
job.cpp multideletejob.cpp qgpgmeadduseridjob.cpp \
|
||||||
|
qgpgmeaddexistingsubkeyjob.cpp \
|
||||||
qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \
|
qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \
|
||||||
qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \
|
qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \
|
||||||
qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \
|
qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \
|
||||||
@ -46,6 +47,7 @@ qgpgme_sources = \
|
|||||||
# If you add one here make sure that you also add one in camelcase
|
# If you add one here make sure that you also add one in camelcase
|
||||||
qgpgme_headers= \
|
qgpgme_headers= \
|
||||||
abstractimportjob.h \
|
abstractimportjob.h \
|
||||||
|
addexistingsubkeyjob.h \
|
||||||
adduseridjob.h \
|
adduseridjob.h \
|
||||||
changeexpiryjob.h \
|
changeexpiryjob.h \
|
||||||
changeownertrustjob.h \
|
changeownertrustjob.h \
|
||||||
@ -88,6 +90,7 @@ qgpgme_headers= \
|
|||||||
dn.h
|
dn.h
|
||||||
|
|
||||||
camelcase_headers= \
|
camelcase_headers= \
|
||||||
|
AddExistingSubkeyJob \
|
||||||
AddUserIDJob \
|
AddUserIDJob \
|
||||||
AbstractImportJob \
|
AbstractImportJob \
|
||||||
ChangeExpiryJob \
|
ChangeExpiryJob \
|
||||||
@ -133,6 +136,7 @@ private_qgpgme_headers = \
|
|||||||
qgpgme_export.h \
|
qgpgme_export.h \
|
||||||
protocol_p.h \
|
protocol_p.h \
|
||||||
job_p.h \
|
job_p.h \
|
||||||
|
qgpgmeaddexistingsubkeyjob.h \
|
||||||
qgpgmeadduseridjob.h \
|
qgpgmeadduseridjob.h \
|
||||||
qgpgmebackend.h \
|
qgpgmebackend.h \
|
||||||
qgpgmechangeexpiryjob.h \
|
qgpgmechangeexpiryjob.h \
|
||||||
@ -165,6 +169,7 @@ private_qgpgme_headers = \
|
|||||||
|
|
||||||
qgpgme_moc_sources = \
|
qgpgme_moc_sources = \
|
||||||
abstractimportjob.moc \
|
abstractimportjob.moc \
|
||||||
|
addexistingsubkeyjob.moc \
|
||||||
adduseridjob.moc \
|
adduseridjob.moc \
|
||||||
changeexpiryjob.moc \
|
changeexpiryjob.moc \
|
||||||
changeownertrustjob.moc \
|
changeownertrustjob.moc \
|
||||||
@ -183,6 +188,7 @@ qgpgme_moc_sources = \
|
|||||||
keylistjob.moc \
|
keylistjob.moc \
|
||||||
listallkeysjob.moc \
|
listallkeysjob.moc \
|
||||||
multideletejob.moc \
|
multideletejob.moc \
|
||||||
|
qgpgmeaddexistingsubkeyjob.moc \
|
||||||
qgpgmeadduseridjob.moc \
|
qgpgmeadduseridjob.moc \
|
||||||
qgpgmechangeexpiryjob.moc \
|
qgpgmechangeexpiryjob.moc \
|
||||||
qgpgmechangeownertrustjob.moc \
|
qgpgmechangeownertrustjob.moc \
|
||||||
|
79
lang/qt/src/addexistingsubkeyjob.h
Normal file
79
lang/qt/src/addexistingsubkeyjob.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
addexistingsubkeyjob.h
|
||||||
|
|
||||||
|
This file is part of qgpgme, the Qt API binding for gpgme
|
||||||
|
Copyright (c) 2022 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_ADDEXISTINGSUBKEYJOB_H__
|
||||||
|
#define __QGPGME_ADDEXISTINGSUBKEYJOB_H__
|
||||||
|
|
||||||
|
#include "job.h"
|
||||||
|
#include "qgpgme_export.h"
|
||||||
|
|
||||||
|
class QString;
|
||||||
|
|
||||||
|
namespace GpgME
|
||||||
|
{
|
||||||
|
class Error;
|
||||||
|
class Key;
|
||||||
|
class Subkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace QGpgME
|
||||||
|
{
|
||||||
|
|
||||||
|
class QGPGME_EXPORT AddExistingSubkeyJob : public Job
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
protected:
|
||||||
|
explicit AddExistingSubkeyJob(QObject *parent);
|
||||||
|
|
||||||
|
public:
|
||||||
|
~AddExistingSubkeyJob();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Starts the operation. \a key is the key to add the subkey \a subkey to.
|
||||||
|
|
||||||
|
The job deletes itself after it has completed the operation.
|
||||||
|
*/
|
||||||
|
virtual GpgME::Error start(const GpgME::Key &key, const GpgME::Subkey &subkey) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Runs the operation. \a key is the key to add the subkey \a subkey to.
|
||||||
|
*/
|
||||||
|
virtual GpgME::Error exec(const GpgME::Key &key, const GpgME::Subkey &subkey) = 0;
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
void result(const GpgME::Error &result, const QString &auditLogAsHtml = {}, const GpgME::Error &auditLogError = {});
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __QGPGME_ADDEXISTINGSUBKEYJOB_H__
|
@ -61,6 +61,7 @@
|
|||||||
#include "downloadjob.h"
|
#include "downloadjob.h"
|
||||||
#include "deletejob.h"
|
#include "deletejob.h"
|
||||||
#include "refreshkeysjob.h"
|
#include "refreshkeysjob.h"
|
||||||
|
#include "addexistingsubkeyjob.h"
|
||||||
#include "adduseridjob.h"
|
#include "adduseridjob.h"
|
||||||
#include "specialjob.h"
|
#include "specialjob.h"
|
||||||
#include "keyformailboxjob.h"
|
#include "keyformailboxjob.h"
|
||||||
@ -160,6 +161,7 @@ make_job_subclass(ChangePasswdJob)
|
|||||||
make_job_subclass(DownloadJob)
|
make_job_subclass(DownloadJob)
|
||||||
make_job_subclass(DeleteJob)
|
make_job_subclass(DeleteJob)
|
||||||
make_job_subclass(RefreshKeysJob)
|
make_job_subclass(RefreshKeysJob)
|
||||||
|
make_job_subclass(AddExistingSubkeyJob)
|
||||||
make_job_subclass(AddUserIDJob)
|
make_job_subclass(AddUserIDJob)
|
||||||
make_job_subclass(SpecialJob)
|
make_job_subclass(SpecialJob)
|
||||||
make_job_subclass(KeyForMailboxJob)
|
make_job_subclass(KeyForMailboxJob)
|
||||||
@ -194,6 +196,7 @@ make_job_subclass(GpgCardJob)
|
|||||||
#include "downloadjob.moc"
|
#include "downloadjob.moc"
|
||||||
#include "deletejob.moc"
|
#include "deletejob.moc"
|
||||||
#include "refreshkeysjob.moc"
|
#include "refreshkeysjob.moc"
|
||||||
|
#include "addexistingsubkeyjob.moc"
|
||||||
#include "adduseridjob.moc"
|
#include "adduseridjob.moc"
|
||||||
#include "specialjob.moc"
|
#include "specialjob.moc"
|
||||||
#include "keyformailboxjob.moc"
|
#include "keyformailboxjob.moc"
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "qgpgme_export.h"
|
#include "qgpgme_export.h"
|
||||||
|
|
||||||
namespace QGpgME {
|
namespace QGpgME {
|
||||||
|
class AddExistingSubkeyJob;
|
||||||
class CryptoConfig;
|
class CryptoConfig;
|
||||||
class KeyListJob;
|
class KeyListJob;
|
||||||
class ListAllKeysJob;
|
class ListAllKeysJob;
|
||||||
@ -138,6 +139,7 @@ public:
|
|||||||
virtual SignKeyJob *signKeyJob() const = 0;
|
virtual SignKeyJob *signKeyJob() const = 0;
|
||||||
virtual ChangePasswdJob *changePasswdJob() const = 0;
|
virtual ChangePasswdJob *changePasswdJob() const = 0;
|
||||||
virtual ChangeOwnerTrustJob *changeOwnerTrustJob() const = 0;
|
virtual ChangeOwnerTrustJob *changeOwnerTrustJob() const = 0;
|
||||||
|
virtual AddExistingSubkeyJob *addExistingSubkeyJob() const = 0;
|
||||||
virtual AddUserIDJob *addUserIDJob() const = 0;
|
virtual AddUserIDJob *addUserIDJob() const = 0;
|
||||||
virtual SpecialJob *specialJob(const char *type, const QMap<QString, QVariant> &args) const = 0;
|
virtual SpecialJob *specialJob(const char *type, const QMap<QString, QVariant> &args) const = 0;
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#include "qgpgmechangeexpiryjob.h"
|
#include "qgpgmechangeexpiryjob.h"
|
||||||
#include "qgpgmechangeownertrustjob.h"
|
#include "qgpgmechangeownertrustjob.h"
|
||||||
#include "qgpgmechangepasswdjob.h"
|
#include "qgpgmechangepasswdjob.h"
|
||||||
|
#include "qgpgmeaddexistingsubkeyjob.h"
|
||||||
#include "qgpgmeadduseridjob.h"
|
#include "qgpgmeadduseridjob.h"
|
||||||
#include "qgpgmekeyformailboxjob.h"
|
#include "qgpgmekeyformailboxjob.h"
|
||||||
#include "qgpgmewkdlookupjob.h"
|
#include "qgpgmewkdlookupjob.h"
|
||||||
@ -371,6 +372,19 @@ public:
|
|||||||
return new QGpgME::QGpgMEChangeOwnerTrustJob(context);
|
return new QGpgME::QGpgMEChangeOwnerTrustJob(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QGpgME:: AddExistingSubkeyJob *addExistingSubkeyJob() const override
|
||||||
|
{
|
||||||
|
if (mProtocol != GpgME::OpenPGP) {
|
||||||
|
return nullptr; // only supported by gpg
|
||||||
|
}
|
||||||
|
|
||||||
|
GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
|
||||||
|
if (!context) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return new QGpgME::QGpgMEAddExistingSubkeyJob{context};
|
||||||
|
}
|
||||||
|
|
||||||
QGpgME::AddUserIDJob *addUserIDJob() const Q_DECL_OVERRIDE
|
QGpgME::AddUserIDJob *addUserIDJob() const Q_DECL_OVERRIDE
|
||||||
{
|
{
|
||||||
if (mProtocol != GpgME::OpenPGP) {
|
if (mProtocol != GpgME::OpenPGP) {
|
||||||
|
96
lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp
Normal file
96
lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
qgpgmeaddexistingsubkeyjob.cpp
|
||||||
|
|
||||||
|
This file is part of qgpgme, the Qt API binding for gpgme
|
||||||
|
Copyright (c) 2022 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 "qgpgmeaddexistingsubkeyjob.h"
|
||||||
|
|
||||||
|
#include "dataprovider.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
|
#include "data.h"
|
||||||
|
#include "gpgaddexistingsubkeyeditinteractor.h"
|
||||||
|
#include "key.h"
|
||||||
|
|
||||||
|
#include <gpg-error.h>
|
||||||
|
|
||||||
|
using namespace QGpgME;
|
||||||
|
using namespace GpgME;
|
||||||
|
|
||||||
|
QGpgMEAddExistingSubkeyJob::QGpgMEAddExistingSubkeyJob(Context *context)
|
||||||
|
: mixin_type{context}
|
||||||
|
{
|
||||||
|
lateInitialization();
|
||||||
|
}
|
||||||
|
|
||||||
|
QGpgMEAddExistingSubkeyJob::~QGpgMEAddExistingSubkeyJob() = default;
|
||||||
|
|
||||||
|
static QGpgMEAddExistingSubkeyJob::result_type add_subkey(Context *ctx, const Key &key, const Subkey &subkey)
|
||||||
|
{
|
||||||
|
std::unique_ptr<GpgAddExistingSubkeyEditInteractor> interactor{new GpgAddExistingSubkeyEditInteractor{subkey.keyGrip()}};
|
||||||
|
|
||||||
|
if (!subkey.neverExpires()) {
|
||||||
|
const auto expiry = QDateTime::fromSecsSinceEpoch(subkey.expirationTime(), Qt::UTC).toString(u"yyyyMMdd'T'hhmmss").toStdString();
|
||||||
|
interactor->setExpiry(expiry);
|
||||||
|
}
|
||||||
|
|
||||||
|
QGpgME::QByteArrayDataProvider dp;
|
||||||
|
Data data(&dp);
|
||||||
|
assert(!data.isNull());
|
||||||
|
|
||||||
|
ctx->setFlag("extended-edit", "1");
|
||||||
|
|
||||||
|
const Error err = ctx->edit(key, std::unique_ptr<EditInteractor>(interactor.release()), data);
|
||||||
|
Error ae;
|
||||||
|
const QString log = _detail::audit_log_as_html(ctx, ae);
|
||||||
|
return std::make_tuple(err, log, ae);
|
||||||
|
}
|
||||||
|
|
||||||
|
Error QGpgMEAddExistingSubkeyJob::start(const GpgME::Key &key, const GpgME::Subkey &subkey)
|
||||||
|
{
|
||||||
|
run(std::bind(&add_subkey, std::placeholders::_1, key, subkey));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Error QGpgMEAddExistingSubkeyJob::exec(const GpgME::Key &key, const GpgME::Subkey &subkey)
|
||||||
|
{
|
||||||
|
const result_type r = add_subkey(context(), key, subkey);
|
||||||
|
resultHook(r);
|
||||||
|
return std::get<0>(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "qgpgmeaddexistingsubkeyjob.moc"
|
68
lang/qt/src/qgpgmeaddexistingsubkeyjob.h
Normal file
68
lang/qt/src/qgpgmeaddexistingsubkeyjob.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
qgpgmeaddexistingsubkeyjob.h
|
||||||
|
|
||||||
|
This file is part of qgpgme, the Qt API binding for gpgme
|
||||||
|
Copyright (c) 2022 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_QGPGMEADDEXISTINGSUBKEYJOB_H__
|
||||||
|
#define __QGPGME_QGPGMEADDEXISTINGSUBKEYJOB_H__
|
||||||
|
|
||||||
|
#include "threadedjobmixin.h"
|
||||||
|
#include "addexistingsubkeyjob.h"
|
||||||
|
|
||||||
|
namespace QGpgME
|
||||||
|
{
|
||||||
|
|
||||||
|
class QGpgMEAddExistingSubkeyJob
|
||||||
|
#ifdef Q_MOC_RUN
|
||||||
|
: public AddExistingSubkeyJob
|
||||||
|
#else
|
||||||
|
: public _detail::ThreadedJobMixin<AddExistingSubkeyJob>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
#ifdef Q_MOC_RUN
|
||||||
|
public Q_SLOTS:
|
||||||
|
void slotFinished();
|
||||||
|
#endif
|
||||||
|
public:
|
||||||
|
explicit QGpgMEAddExistingSubkeyJob(GpgME::Context *context);
|
||||||
|
~QGpgMEAddExistingSubkeyJob();
|
||||||
|
|
||||||
|
/* from AddExistingSubkeyJob */
|
||||||
|
GpgME::Error start(const GpgME::Key &key, const GpgME::Subkey &subkey) override;
|
||||||
|
|
||||||
|
/* from AddExistingSubkeyJob */
|
||||||
|
GpgME::Error exec(const GpgME::Key &key, const GpgME::Subkey &subkey) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __QGPGME_QGPGMEADDEXISTINGSUBKEYJOB_H__
|
@ -27,16 +27,19 @@ TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
|
|||||||
EXTRA_DIST = initial.test final.test
|
EXTRA_DIST = initial.test final.test
|
||||||
|
|
||||||
the_tests = \
|
the_tests = \
|
||||||
|
t-addexistingsubkey \
|
||||||
t-keylist t-keylocate t-ownertrust t-tofuinfo \
|
t-keylist t-keylocate t-ownertrust t-tofuinfo \
|
||||||
t-encrypt t-verify t-various t-config t-remarks t-trustsignatures \
|
t-encrypt t-verify t-various t-config t-remarks t-trustsignatures \
|
||||||
t-changeexpiryjob t-wkdlookup t-import
|
t-changeexpiryjob t-wkdlookup t-import
|
||||||
|
|
||||||
TESTS = initial.test $(the_tests) final.test
|
TESTS = initial.test $(the_tests) final.test
|
||||||
|
|
||||||
moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
|
moc_files = \
|
||||||
t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
|
t-addexistingsubkey.moc \
|
||||||
t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc \
|
t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
|
||||||
t-changeexpiryjob.moc t-wkdlookup.moc t-import.moc
|
t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
|
||||||
|
t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc \
|
||||||
|
t-changeexpiryjob.moc t-wkdlookup.moc t-import.moc
|
||||||
|
|
||||||
AM_LDFLAGS = -no-install
|
AM_LDFLAGS = -no-install
|
||||||
|
|
||||||
@ -52,6 +55,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
|
|||||||
|
|
||||||
support_src = t-support.h t-support.cpp
|
support_src = t-support.h t-support.cpp
|
||||||
|
|
||||||
|
t_addexistingsubkey_SOURCES = t-addexistingsubkey.cpp $(support_src)
|
||||||
t_keylist_SOURCES = t-keylist.cpp $(support_src)
|
t_keylist_SOURCES = t-keylist.cpp $(support_src)
|
||||||
t_keylocate_SOURCES = t-keylocate.cpp $(support_src)
|
t_keylocate_SOURCES = t-keylocate.cpp $(support_src)
|
||||||
t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src)
|
t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src)
|
||||||
@ -74,10 +78,12 @@ nodist_t_keylist_SOURCES = $(moc_files)
|
|||||||
|
|
||||||
BUILT_SOURCES = $(moc_files) pubring-stamp
|
BUILT_SOURCES = $(moc_files) pubring-stamp
|
||||||
|
|
||||||
noinst_PROGRAMS = t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
|
noinst_PROGRAMS = \
|
||||||
run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
|
t-addexistingsubkey \
|
||||||
t-trustsignatures t-changeexpiryjob t-wkdlookup t-import run-importjob \
|
t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
|
||||||
run-exportjob
|
run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
|
||||||
|
t-trustsignatures t-changeexpiryjob t-wkdlookup t-import run-importjob \
|
||||||
|
run-exportjob
|
||||||
|
|
||||||
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
|
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
|
||||||
gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \
|
gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \
|
||||||
|
260
lang/qt/tests/t-addexistingsubkey.cpp
Normal file
260
lang/qt/tests/t-addexistingsubkey.cpp
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
/* t-addexistingsubkey.cpp
|
||||||
|
|
||||||
|
This file is part of qgpgme, the Qt API binding for gpgme
|
||||||
|
Copyright (c) 2022 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 "t-support.h"
|
||||||
|
|
||||||
|
#include "addexistingsubkeyjob.h"
|
||||||
|
#include "protocol.h"
|
||||||
|
|
||||||
|
#include <QSignalSpy>
|
||||||
|
#include <QTest>
|
||||||
|
|
||||||
|
#include "context.h"
|
||||||
|
#include "data.h"
|
||||||
|
#include "engineinfo.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
using namespace QGpgME;
|
||||||
|
using namespace GpgME;
|
||||||
|
|
||||||
|
static const char *requiredVersion = "2.3.5";
|
||||||
|
|
||||||
|
/* Test keys
|
||||||
|
sec# ed25519 2022-01-13 [SC]
|
||||||
|
1CB8C6A0317AA83F44FE009932392C82B814C8E0
|
||||||
|
uid [ unknown] source-key@example.net
|
||||||
|
ssb cv25519 2022-01-13 [E]
|
||||||
|
ssb cv25519 2022-01-13 [E] [expires: 2100-01-01]
|
||||||
|
|
||||||
|
sec ed25519 2022-01-13 [SC]
|
||||||
|
C3C87F0A3920B01F9E4450EA2B79F21D4DD10BFC
|
||||||
|
uid [ unknown] target-key@example.net
|
||||||
|
ssb cv25519 2022-01-13 [E]
|
||||||
|
* generated with
|
||||||
|
export GNUPGHOME=$(mktemp -d)
|
||||||
|
gpg -K
|
||||||
|
gpg --batch --pinentry-mode loopback --passphrase abc --quick-gen-key source-key@example.net default default never
|
||||||
|
fpr=$(gpg -k --with-colons source-key@example.net | grep ^fpr | head -1 | cut -d ':' -f 10)
|
||||||
|
gpg --batch --pinentry-mode loopback --passphrase abc --quick-add-key ${fpr} default default 21000101T120000
|
||||||
|
gpg --batch --pinentry-mode loopback --passphrase abc --quick-gen-key target-key@example.net default default never
|
||||||
|
gpg -K
|
||||||
|
gpg --export-secret-subkeys --armor --batch --pinentry-mode loopback --passphrase abc --comment source-key@example.net source-key@example.net | sed 's/\(.*\)/ "\1\\n"/'
|
||||||
|
gpg --export-secret-keys --armor --batch --pinentry-mode loopback --passphrase abc --comment target-key@example.net target-key@example.net | sed 's/\(.*\)/ "\1\\n"/'
|
||||||
|
#rm -rf ${GNUPGHOME}
|
||||||
|
unset GNUPGHOME
|
||||||
|
*/
|
||||||
|
static const char *testKeyData =
|
||||||
|
"-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
|
||||||
|
"Comment: source-key@example.net\n"
|
||||||
|
"\n"
|
||||||
|
"lDsEYd/ujBYJKwYBBAHaRw8BAQdAwiZPINTcrpgmu6ZWSaPZlcRSd4nDuofVMhe7\n"
|
||||||
|
"c2XrFyT/AGUAR05VAbQWc291cmNlLWtleUBleGFtcGxlLm5ldIiUBBMWCgA8FiEE\n"
|
||||||
|
"HLjGoDF6qD9E/gCZMjksgrgUyOAFAmHf7owCGwMFCwkIBwIDIgIBBhUKCQgLAgQW\n"
|
||||||
|
"AgMBAh4HAheAAAoJEDI5LIK4FMjgupIA/Au2YEAT9dYdJd0eJCJerG5YAeoB+uBs\n"
|
||||||
|
"mBkgr6xXE0bIAP43b6u1Jtvf/Wm3BhRbLd5Tg67Ba4CIZ8ZLGng73FBoBpyLBGHf\n"
|
||||||
|
"7owSCisGAQQBl1UBBQEBB0Cpg8Qof/WShxROZZtmPnw24vTk0R8nIAF1CZJ0bG/C\n"
|
||||||
|
"SwMBCAf+BwMCtzxziVxQEor8w/VVzHp4/hVSCUyrpiX7Djf04cIMs2bFPduZLgxb\n"
|
||||||
|
"c1SXhlgiqU0YBNntbGGNdKjTP6FMbYWq1+NwQm6ZXtC76LPG7syM94h4BBgWCgAg\n"
|
||||||
|
"FiEEHLjGoDF6qD9E/gCZMjksgrgUyOAFAmHf7owCGwwACgkQMjksgrgUyOCI0wEA\n"
|
||||||
|
"+f56fkvDDUwMOMw7n4+GKpfJXpWhVL08ttccbBOa/9IA/2HYA/78ZaD8E5EyqAEK\n"
|
||||||
|
"Aj9Au+2oJu9V5qo92QEoqwYHnIsEYd/vgxIKKwYBBAGXVQEFAQEHQBa9FxJkm/9D\n"
|
||||||
|
"xABildkaYMrbJbu8BPk6uv9V8aLmv9FnAwEIB/4HAwIPhcbN8s6OzPz8/g78TrCh\n"
|
||||||
|
"xqQb2kygCEj+OQ4/XXU3lus2b5xS5h44LGt99Wisqx+wVPDXmPDJOaxjhHXDmJxd\n"
|
||||||
|
"/LplIEhykojSm3uUDxERiH4EGBYKACYWIQQcuMagMXqoP0T+AJkyOSyCuBTI4AUC\n"
|
||||||
|
"Yd/vgwIbDAUJkqcQPQAKCRAyOSyCuBTI4IUjAP9BTfOD+jy6lLmzNO9pquRSAxi/\n"
|
||||||
|
"PQuglGtpS0LQEJMEOwD+PFnsMe2EtQ+WVSDBeB7O0m61EXeY+RhpuhNtsNXVuwc=\n"
|
||||||
|
"=wIPU\n"
|
||||||
|
"-----END PGP PRIVATE KEY BLOCK-----\n"
|
||||||
|
"-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
|
||||||
|
"Comment: target-key@example.net\n"
|
||||||
|
"\n"
|
||||||
|
"lIYEYd/v/RYJKwYBBAHaRw8BAQdAKoILWXG3yaLb2EniNKQLUjwsrvy5vgAN299J\n"
|
||||||
|
"W5cFbrz+BwMC/uKbCq3sK5H8QVtEQ/IxGmjWNBpy6c8EDlOG4APi4o4VE+bEYD8w\n"
|
||||||
|
"J3Kk/lzSm6ZT5vC6DDASks797omjXD+J7zZ0vtTPvheYi/nsVz2UebQWdGFyZ2V0\n"
|
||||||
|
"LWtleUBleGFtcGxlLm5ldIiUBBMWCgA8FiEEw8h/CjkgsB+eRFDqK3nyHU3RC/wF\n"
|
||||||
|
"AmHf7/0CGwMFCwkIBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJECt58h1N0Qv8\n"
|
||||||
|
"rXcBAPxnkXqpp4IY3iTKV5XAdo7Uys7U/joUD73rj2XEvgI1AQDhKK4PLxPhf3ki\n"
|
||||||
|
"FKU0RA7itxzOH+F8bQ5BdYS49jDPCpyLBGHf7/0SCisGAQQBl1UBBQEBB0Dq9rwA\n"
|
||||||
|
"hAA2UFJShFsLFp7+g4uhWDfuDa3VjeIQRM+9QgMBCAf+BwMCMfCTl0LNqsn836t5\n"
|
||||||
|
"f2ZHBuMcNs4JWYmdLAIVaewEHq7zhOsX3iB+/yxwu9g2mXc4XUJ1iQzXLOYwgGov\n"
|
||||||
|
"8jIovrr01hDkSg4rvM9JKMWdd4h4BBgWCgAgFiEEw8h/CjkgsB+eRFDqK3nyHU3R\n"
|
||||||
|
"C/wFAmHf7/0CGwwACgkQK3nyHU3RC/xyfAEAqnMdSv6FTAwAWrYvJqJtSVoEhjMn\n"
|
||||||
|
"3c2qMsu34Bk86/MBAKHbLFmdyePvHaxKeO8CkQDoJzK8rYzw3RAmq/5JsQkL\n"
|
||||||
|
"=rOVf\n"
|
||||||
|
"-----END PGP PRIVATE KEY BLOCK-----\n";
|
||||||
|
|
||||||
|
class AddExistingSubkeyJobTest : public QGpgMETest
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
|
||||||
|
void initTestCase()
|
||||||
|
{
|
||||||
|
QGpgMETest::initTestCase();
|
||||||
|
|
||||||
|
// set up the test fixture for this test
|
||||||
|
qputenv("GNUPGHOME", mGnupgHomeTestFixture.path().toUtf8());
|
||||||
|
QVERIFY(importSecretKeys(testKeyData, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
|
||||||
|
QSKIP("gpg does not yet support adding an existing subkey to another key via the command API");
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up a copy of the test fixture for each test function
|
||||||
|
mGnupgHomeTestCopy.reset(new QTemporaryDir{});
|
||||||
|
QVERIFY(copyKeyrings(mGnupgHomeTestFixture.path(), mGnupgHomeTestCopy->path()));
|
||||||
|
qputenv("GNUPGHOME", mGnupgHomeTestCopy->path().toUtf8());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testAddExistingSubkeyAsync()
|
||||||
|
{
|
||||||
|
// Get the key the subkey should be added to
|
||||||
|
auto key = getTestKey("target-key@example.net");
|
||||||
|
QVERIFY(!key.isNull());
|
||||||
|
|
||||||
|
// Get the key with the subkey to add
|
||||||
|
auto sourceKey = getTestKey("source-key@example.net", 3);
|
||||||
|
QVERIFY(!sourceKey.isNull());
|
||||||
|
|
||||||
|
auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
|
||||||
|
hookUpPassphraseProvider(job.get());
|
||||||
|
|
||||||
|
Error result;
|
||||||
|
connect(job.get(), &AddExistingSubkeyJob::result,
|
||||||
|
job.get(), [this, &result](const Error &result_) {
|
||||||
|
result = result_;
|
||||||
|
Q_EMIT asyncDone();
|
||||||
|
});
|
||||||
|
QVERIFY(!job->start(key, sourceKey.subkey(1)));
|
||||||
|
job.release(); // after the job has been started it's on its own
|
||||||
|
|
||||||
|
QSignalSpy spy (this, SIGNAL(asyncDone()));
|
||||||
|
QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
|
||||||
|
|
||||||
|
QVERIFY(result.code() == GPG_ERR_NO_ERROR);
|
||||||
|
key.update();
|
||||||
|
QCOMPARE(key.numSubkeys(), 3u);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testAddExistingSubkeySync()
|
||||||
|
{
|
||||||
|
// Get the key the subkey should be added to
|
||||||
|
auto key = getTestKey("target-key@example.net");
|
||||||
|
QVERIFY(!key.isNull());
|
||||||
|
|
||||||
|
// Get the key with the subkey to add
|
||||||
|
auto sourceKey = getTestKey("source-key@example.net", 3);
|
||||||
|
QVERIFY(!sourceKey.isNull());
|
||||||
|
auto sourceSubkey = sourceKey.subkey(1);
|
||||||
|
QVERIFY(sourceSubkey.expirationTime() == 0);
|
||||||
|
|
||||||
|
auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
|
||||||
|
hookUpPassphraseProvider(job.get());
|
||||||
|
|
||||||
|
const auto result = job->exec(key, sourceSubkey);
|
||||||
|
|
||||||
|
QVERIFY(result.code() == GPG_ERR_NO_ERROR);
|
||||||
|
key.update();
|
||||||
|
QCOMPARE(key.numSubkeys(), 3u);
|
||||||
|
QCOMPARE(key.subkey(2).expirationTime(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testAddExistingSubkeyWithExpiration()
|
||||||
|
{
|
||||||
|
// Get the key the subkey should be added to
|
||||||
|
auto key = getTestKey("target-key@example.net");
|
||||||
|
QVERIFY(!key.isNull());
|
||||||
|
|
||||||
|
// Get the key with the subkey to add
|
||||||
|
auto sourceKey = getTestKey("source-key@example.net", 3);
|
||||||
|
QVERIFY(!sourceKey.isNull());
|
||||||
|
auto sourceSubkey = sourceKey.subkey(2);
|
||||||
|
QVERIFY(sourceSubkey.expirationTime() != 0);
|
||||||
|
|
||||||
|
auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
|
||||||
|
hookUpPassphraseProvider(job.get());
|
||||||
|
|
||||||
|
const auto result = job->exec(key, sourceSubkey);
|
||||||
|
|
||||||
|
QVERIFY(result.code() == GPG_ERR_NO_ERROR);
|
||||||
|
key.update();
|
||||||
|
QCOMPARE(key.numSubkeys(), 3u);
|
||||||
|
|
||||||
|
// allow 1 second different expiration because gpg calculates with
|
||||||
|
// expiration as difference to current time and takes current time
|
||||||
|
// several times
|
||||||
|
const auto allowedDeltaTSeconds = 1;
|
||||||
|
const auto expectedExpirationRange = std::make_pair(
|
||||||
|
sourceSubkey.expirationTime() - allowedDeltaTSeconds,
|
||||||
|
sourceSubkey.expirationTime() + allowedDeltaTSeconds);
|
||||||
|
const auto actualExpiration = key.subkey(2).expirationTime();
|
||||||
|
QVERIFY2(actualExpiration >= expectedExpirationRange.first,
|
||||||
|
("actual: " + std::to_string(actualExpiration) +
|
||||||
|
"; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
|
||||||
|
QVERIFY2(actualExpiration <= expectedExpirationRange.second,
|
||||||
|
("actual: " + std::to_string(actualExpiration) +
|
||||||
|
"; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Key getTestKey(const char *pattern, unsigned int expectedSubkeys = 2)
|
||||||
|
{
|
||||||
|
auto ctx = Context::create(OpenPGP);
|
||||||
|
VERIFY_OR_OBJECT(ctx);
|
||||||
|
|
||||||
|
Error err;
|
||||||
|
auto key = ctx->key(pattern, err, /*secret=*/true);
|
||||||
|
VERIFY_OR_OBJECT(!err);
|
||||||
|
VERIFY_OR_OBJECT(!key.isNull());
|
||||||
|
COMPARE_OR_OBJECT(key.numSubkeys(), expectedSubkeys);
|
||||||
|
for (unsigned int i = 0; i < key.numSubkeys(); ++i) {
|
||||||
|
VERIFY_OR_OBJECT(!key.subkey(i).isNull());
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTemporaryDir mGnupgHomeTestFixture;
|
||||||
|
std::unique_ptr<QTemporaryDir> mGnupgHomeTestCopy;
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(AddExistingSubkeyJobTest)
|
||||||
|
|
||||||
|
#include "t-addexistingsubkey.moc"
|
@ -36,7 +36,9 @@
|
|||||||
|
|
||||||
#include "t-support.h"
|
#include "t-support.h"
|
||||||
|
|
||||||
|
#include "importjob.h"
|
||||||
#include "job.h"
|
#include "job.h"
|
||||||
|
#include "protocol.h"
|
||||||
|
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
@ -44,9 +46,11 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
|
#include <QSignalSpy>
|
||||||
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "engineinfo.h"
|
#include "engineinfo.h"
|
||||||
|
#include "importresult.h"
|
||||||
|
|
||||||
using namespace GpgME;
|
using namespace GpgME;
|
||||||
using namespace QGpgME;
|
using namespace QGpgME;
|
||||||
@ -97,6 +101,30 @@ bool QGpgMETest::copyKeyrings(const QString &src, const QString &dest)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QGpgMETest::importSecretKeys(const char *keyData, int expectedKeys)
|
||||||
|
{
|
||||||
|
auto job = std::unique_ptr<ImportJob>{openpgp()->importJob()};
|
||||||
|
VERIFY_OR_FALSE(job);
|
||||||
|
hookUpPassphraseProvider(job.get());
|
||||||
|
|
||||||
|
ImportResult result;
|
||||||
|
connect(job.get(), &ImportJob::result,
|
||||||
|
this, [this, &result](const ImportResult &result_) {
|
||||||
|
result = result_;
|
||||||
|
Q_EMIT asyncDone();
|
||||||
|
});
|
||||||
|
VERIFY_OR_FALSE(!job->start(keyData));
|
||||||
|
job.release(); // after the job has been started it's on its own
|
||||||
|
|
||||||
|
QSignalSpy spy (this, SIGNAL(asyncDone()));
|
||||||
|
VERIFY_OR_FALSE(spy.wait(QSIGNALSPY_TIMEOUT));
|
||||||
|
VERIFY_OR_FALSE(!result.error());
|
||||||
|
VERIFY_OR_FALSE(!result.imports().empty());
|
||||||
|
COMPARE_OR_FALSE(result.numSecretKeysImported(), expectedKeys);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void QGpgMETest::hookUpPassphraseProvider(GpgME::Context *context)
|
void QGpgMETest::hookUpPassphraseProvider(GpgME::Context *context)
|
||||||
{
|
{
|
||||||
context->setPassphraseProvider(&mPassphraseProvider);
|
context->setPassphraseProvider(&mPassphraseProvider);
|
||||||
|
@ -48,6 +48,32 @@ namespace QGpgME
|
|||||||
class Job;
|
class Job;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// generic variant of QVERIFY returning \a returnValue on failure
|
||||||
|
#define VERIFY_OR_RETURN_VALUE(statement, returnValue) \
|
||||||
|
do {\
|
||||||
|
if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", __FILE__, __LINE__))\
|
||||||
|
return returnValue;\
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
/// generic variant of QCOMPARE returning \a returnValue on failure
|
||||||
|
#define COMPARE_OR_RETURN_VALUE(actual, expected, returnValue) \
|
||||||
|
do {\
|
||||||
|
if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__))\
|
||||||
|
return returnValue;\
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
/// variant of QVERIFY returning a default constructed object on failure
|
||||||
|
#define VERIFY_OR_OBJECT(statement) VERIFY_OR_RETURN_VALUE(statement, {})
|
||||||
|
|
||||||
|
/// variant of QCOMPARE returning a default constructed object on failure
|
||||||
|
#define COMPARE_OR_OBJECT(actual, expected) COMPARE_OR_RETURN_VALUE(actual, expected, {})
|
||||||
|
|
||||||
|
/// variant of QVERIFY returning \c false on failure
|
||||||
|
#define VERIFY_OR_FALSE(statement) VERIFY_OR_RETURN_VALUE(statement, false)
|
||||||
|
|
||||||
|
/// variant of QCOMPARE returning \c false on failure
|
||||||
|
#define COMPARE_OR_FALSE(actual, expected) COMPARE_OR_RETURN_VALUE(actual, expected, false)
|
||||||
|
|
||||||
namespace QTest
|
namespace QTest
|
||||||
{
|
{
|
||||||
template <>
|
template <>
|
||||||
@ -88,6 +114,8 @@ protected:
|
|||||||
|
|
||||||
bool copyKeyrings(const QString &from, const QString& to);
|
bool copyKeyrings(const QString &from, const QString& to);
|
||||||
|
|
||||||
|
bool importSecretKeys(const char *keyData, int expectedKeys = 1);
|
||||||
|
|
||||||
void hookUpPassphraseProvider(GpgME::Context *context);
|
void hookUpPassphraseProvider(GpgME::Context *context);
|
||||||
void hookUpPassphraseProvider(QGpgME::Job *job);
|
void hookUpPassphraseProvider(QGpgME::Job *job);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user