qt: Add WKSPublishJob

* lang/qt/src/Makefile.am: Add new files.
* lang/qt/src/job.cpp: Include moc / subclass stub.
* lang/qt/src/protocol.h: Add virtual for new job.
* lang/qt/src/protocol_p.h: Add job.
* lang/qt/src/wkspublishjob.h: Interface for WKSPublishJob.
* lang/qt/src/qgpgmewkspublishjob.cpp,
lang/qt/src/qgpgmewkspublishjob.h: New.

--
The Job was originally intended to be used with a SpawnEngine
Context but QProcess was a better fit for the job.

Usage is similar to the client tool. check, create, recieve.
This commit is contained in:
Andre Heinecke 2016-08-25 14:29:41 +02:00
parent de7b67f9b2
commit 94420b0577
7 changed files with 388 additions and 3 deletions

View File

@ -34,7 +34,7 @@ qgpgme_sources = \
qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \
qgpgmeverifyopaquejob.cpp threadedjobmixin.cpp \
qgpgmekeyformailboxjob.cpp gpgme_backend_debug.cpp \
defaultkeygenerationjob.cpp
defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp
# If you add one here make sure that you also add one in camelcase
qgpgme_headers= \
@ -68,7 +68,8 @@ qgpgme_headers= \
keylistjob.h \
listallkeysjob.h \
verifydetachedjob.h \
defaultkeygenerationjob.h
defaultkeygenerationjob.h \
wkspublishjob.h
camelcase_headers= \
AddUserIDJob \
@ -100,7 +101,8 @@ camelcase_headers= \
ListAllKeysJob \
VerifyDetachedJob \
KeyForMailboxJob \
DefaultKeyGenerationJob
DefaultKeyGenerationJob \
WKSPublishJob
private_qgpgme_headers = \
qgpgme_export.h \
@ -130,6 +132,7 @@ private_qgpgme_headers = \
qgpgmeverifydetachedjob.h \
qgpgmeverifyopaquejob.h \
qgpgmekeyformailboxjob.h \
qgpgmewkspublishjob.h \
specialjob.h \
threadedjobmixin.h
@ -175,6 +178,7 @@ qgpgme_moc_sources = \
qgpgmesignkeyjob.moc \
qgpgmeverifydetachedjob.moc \
qgpgmeverifyopaquejob.moc \
qgpgmewkspublishjob.moc \
refreshkeysjob.moc \
signencryptjob.moc \
signjob.moc \
@ -183,6 +187,7 @@ qgpgme_moc_sources = \
verifydetachedjob.moc \
verifyopaquejob.moc \
keyformailboxjob.moc \
wkspublishjob.moc \
qgpgmekeyformailboxjob.moc \
defaultkeygenerationjob.moc

View File

@ -56,6 +56,7 @@
#include "adduseridjob.h"
#include "specialjob.h"
#include "keyformailboxjob.h"
#include "wkspublishjob.h"
#include <QCoreApplication>
#include <QDebug>
@ -122,6 +123,7 @@ make_job_subclass(RefreshKeysJob)
make_job_subclass(AddUserIDJob)
make_job_subclass(SpecialJob)
make_job_subclass(KeyForMailboxJob)
make_job_subclass(WKSPublishJob)
#undef make_job_subclass
@ -151,3 +153,4 @@ make_job_subclass(KeyForMailboxJob)
#include "adduseridjob.moc"
#include "specialjob.moc"
#include "keyformailboxjob.moc"
#include "wkspublishjob.moc"

View File

@ -63,6 +63,7 @@ class ChangePasswdJob;
class AddUserIDJob;
class SpecialJob;
class KeyForMailboxJob;
class WKSPublishJob;
/** The main entry point for QGpgME Comes in OpenPGP and SMIME(CMS) flavors.
*
@ -148,6 +149,9 @@ public:
virtual KeyListJob *locateKeysJob() const = 0;
/** Find the best key to use for a mailbox. */
virtual KeyForMailboxJob *keyForMailboxJob() const = 0;
/** A Job for interacting with gnupg's wks tools. */
virtual WKSPublishJob *wksPublishJob() const = 0;
};
/** Obtain a reference to the OpenPGP Protocol.

View File

@ -57,6 +57,7 @@
#include "qgpgmechangepasswdjob.h"
#include "qgpgmeadduseridjob.h"
#include "qgpgmekeyformailboxjob.h"
#include "qgpgmewkspublishjob.h"
namespace
{
@ -387,6 +388,18 @@ public:
}
return new QGpgME::QGpgMEKeyForMailboxJob(context);
}
QGpgME::WKSPublishJob *wksPublishJob() const Q_DECL_OVERRIDE
{
if (mProtocol != GpgME::OpenPGP) {
return Q_NULLPTR;
}
auto context = GpgME::Context::createForEngine(GpgME::SpawnEngine);
if (!context) {
return Q_NULLPTR;
}
return new QGpgME::QGpgMEWKSPublishJob(context.release());
}
};
}

View File

@ -0,0 +1,189 @@
/* wkspublishjob.cpp
Copyright (c) 2016 Intevation GmbH
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.
*/
#include "qgpgmewkspublishjob.h"
#include "context.h"
#include "key.h"
#include "util.h"
#include <QFileInfo>
#include <QDir>
#include <QProcess>
/* Timeout for the WKS Processes will be 5 Minutes as
* they can involve pinentry questions. */
#define TIMEOUT_VALUE (5*60*1000)
using namespace QGpgME;
using namespace GpgME;
QGpgMEWKSPublishJob::QGpgMEWKSPublishJob(Context *context)
: mixin_type(context)
{
lateInitialization();
}
QGpgMEWKSPublishJob::~QGpgMEWKSPublishJob() {}
static QString getWKSClient()
{
auto libexecdir = QString::fromLocal8Bit(dirInfo("libexecdir"));
if (libexecdir.isEmpty()) {
return QString();
}
const QFileInfo fi(QDir(libexecdir).absoluteFilePath(QStringLiteral("gpg-wks-client")));
if (fi.exists() && fi.isExecutable()) {
return fi.absoluteFilePath();
}
return QString();
}
static QGpgMEWKSPublishJob::result_type check_worker(const QString &mail)
{
if (mail.isEmpty()) {
return std::make_tuple (Error(make_error(GPG_ERR_INV_ARG)),
QByteArray(), QByteArray(), QString(), Error());
}
const auto wksPath = getWKSClient();
if (wksPath.isEmpty()) {
return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
QByteArray(), QByteArray(), QString(), Error());
}
/* QProcess instead of engine_spawn because engine_spawn does not communicate
* the return value of the process and we are in qt anyway. */
QProcess proc;
proc.setProgram(wksPath);
proc.setArguments(QStringList() << QStringLiteral("--supported") << mail);
proc.start();
if (!proc.waitForStarted()) {
return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
QByteArray(), QByteArray(), QString(), Error());
}
if (!proc.waitForFinished(TIMEOUT_VALUE)) {
return std::make_tuple (Error(make_error(GPG_ERR_TIMEOUT)),
QByteArray(), QByteArray(), QString(), Error());
}
if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) {
return std::make_tuple (Error(), QByteArray(), QByteArray(), QString(), Error());
}
return std::make_tuple (Error(make_error(GPG_ERR_NOT_ENABLED)),
QByteArray(), QByteArray(), QString(), Error());
}
static QGpgMEWKSPublishJob::result_type create_worker(const char *fpr, const QString &mail)
{
if (mail.isEmpty() || !fpr) {
return std::make_tuple (Error(make_error(GPG_ERR_INV_ARG)),
QByteArray(), QByteArray(), QString(), Error());
}
const auto wksPath = getWKSClient();
if (wksPath.isEmpty()) {
return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
QByteArray(), QByteArray(), QString(), Error());
}
QProcess proc;
proc.setProgram(wksPath);
proc.setArguments(QStringList() << QStringLiteral("--create")
<< QLatin1String(fpr)
<< mail);
proc.start();
if (!proc.waitForStarted()) {
return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
QByteArray(), QByteArray(), QString(), Error());
}
if (!proc.waitForFinished(TIMEOUT_VALUE)) {
return std::make_tuple (Error(make_error(GPG_ERR_TIMEOUT)),
QByteArray(), QByteArray(), QString(), Error());
}
if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) {
return std::make_tuple (Error(), proc.readAllStandardOutput(),
proc.readAllStandardError(), QString(), Error());
}
return std::make_tuple (Error(make_error(GPG_ERR_GENERAL)),
proc.readAllStandardOutput(), proc.readAllStandardError(), QString(), Error());
}
static QGpgMEWKSPublishJob::result_type recieve_worker(const QByteArray &response)
{
if (response.isEmpty()) {
return std::make_tuple (Error(make_error(GPG_ERR_INV_ARG)),
QByteArray(), QByteArray(), QString(), Error());
}
const auto wksPath = getWKSClient();
if (wksPath.isEmpty()) {
return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
QByteArray(), QByteArray(), QString(), Error());
}
QProcess proc;
proc.setProgram(wksPath);
proc.setArguments(QStringList() << QStringLiteral("--receive"));
proc.start();
if (!proc.waitForStarted()) {
return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
QByteArray(), QByteArray(), QString(), Error());
}
proc.write(response);
proc.closeWriteChannel();
if (!proc.waitForFinished(TIMEOUT_VALUE)) {
return std::make_tuple (Error(make_error(GPG_ERR_TIMEOUT)),
QByteArray(), QByteArray(), QString(), Error());
}
if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) {
return std::make_tuple (Error(), proc.readAllStandardOutput(),
proc.readAllStandardError(), QString(), Error());
}
return std::make_tuple (Error(make_error(GPG_ERR_GENERAL)),
proc.readAllStandardOutput(), proc.readAllStandardError(), QString(), Error());
}
void QGpgMEWKSPublishJob::startCheck(const QString &mailbox)
{
run(std::bind(&check_worker, mailbox));
}
void QGpgMEWKSPublishJob::startCreate(const char *fpr, const QString &mailbox) {
run(std::bind(&create_worker, fpr, mailbox));
}
void QGpgMEWKSPublishJob::startRecieve(const QByteArray &response)
{
run(std::bind(&recieve_worker, response));
}
#include "qgpgmewkspublishjob.moc"

View File

@ -0,0 +1,70 @@
/* qgpgmewkspublishjob.h
Copyright (c) 2016 Intevation GmbH
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_QGPGMEWKSPUBLISHJOB_H
#define QGPGME_QGPGMEWKSPUBLISHJOB_H
#include "wkspublishjob.h"
#include "threadedjobmixin.h"
namespace GpgME
{
class Key;
} // namespace GpgME
namespace QGpgME {
/**
* Handles Web Key Service Publishing. Needs WKS tools installed and
* server support.
*/
class QGpgMEWKSPublishJob
#ifdef Q_MOC_RUN
: public WKSPublishJob
#else
: public _detail::ThreadedJobMixin<WKSPublishJob, std::tuple<GpgME::Error, QByteArray, QByteArray, QString, GpgME::Error> >
#endif
{
Q_OBJECT
#ifdef Q_MOC_RUN
public Q_SLOTS:
void slotFinished();
#endif
public:
explicit QGpgMEWKSPublishJob(GpgME::Context *context);
~QGpgMEWKSPublishJob();
void startCheck(const QString &mailbox) Q_DECL_OVERRIDE;
void startCreate(const char *fpr, const QString &mailbox) Q_DECL_OVERRIDE;
void startRecieve(const QByteArray &response) Q_DECL_OVERRIDE;
};
}
#endif

101
lang/qt/src/wkspublishjob.h Normal file
View File

@ -0,0 +1,101 @@
/* wkspublishjob.h
Copyright (c) 2016 Intevation GmbH
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_WKSPUBLISHJOB_H
#define QGPGME_WKSPUBLISHJOB_H
#include "job.h"
#include "qgpgme_export.h"
namespace GpgME
{
class Key;
} // namespace GpgME
namespace QGpgME {
/**
* Handles Web Key Service Publishing. Needs WKS tools installed and
* server support.
*
* Remember that after a result is emited the job is auto deleted
* so you can only use it for a single action.
*/
class QGPGME_EXPORT WKSPublishJob: public Job
{
Q_OBJECT
protected:
explicit WKSPublishJob(QObject *parent);
public:
~WKSPublishJob();
/** Start a check if WKS Publishing is supported. As this involves
* an HTTP Query it might take a while. Returns GPG_ERR_NOT_SUPPORED
* result if GnuPG is too old or the required tools are not installed.
*
* The error GPG_ERR_NOT_ENABLED indicates that wks-tools failed to
* detect a working wks service for this.
*
* @param the mailbox to check for.
**/
virtual void startCheck(const QString &mailbox) = 0;
/** Create a publish request.
* The returned Data from the result will contain
* the full Mail as returned by gpg-wks-client --create
*
* @param fpr the fingerprint of the key to create the request for.
* @param mailbox A simple mail address without a Name.
*/
virtual void startCreate(const char *fpr, const QString &mailbox) = 0;
/** Handle a submisson response. The returned Data will contain
* the full Mail as returned by gpg-wks-client --create
*
* @param response The response of the server.
**/
virtual void startRecieve(const QByteArray &response) = 0;
Q_SIGNALS:
/* Result of the operation returned Data and returned Error are
* the results from gpg-wks-client's stdout or stderr respectively.
*
* As usual auditLogAsHtml and auditLogError can be ignored.
**/
void result(const GpgME::Error &error, const QByteArray &returnedData,
const QByteArray &returnedError,
const QString &auditLogAsHtml = QString(),
const GpgME::Error &auditLogError = GpgME::Error());
};
}
#endif