summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Vrátil <dvratil@kde.org>2016-11-03 10:39:45 (GMT)
committerDaniel Vrátil <dvratil@kde.org>2016-11-09 17:26:37 (GMT)
commit91b894103cc5104af8e624748f0da4d7011fdbe4 (patch)
tree0bb31f05025b52e702752613d2bfcf60087b3f97
parent99555bfd80b39c6106757029e9c9a9a3040f4d0c (diff)
Introduce GnuPG WKS and PGP keys formatter plugins
This adds two new body part formatter plugins for messageviewer: one for application/pgp-keys and one for application/vnd.gnupg.wks mimetypes. The application/pgp-keys formatter simply prints a message saying that this part is an OpenPGP key and explains what a key is, and has buttons to display key details and to import the key to user's keychain or open the key in Kleopatra. The application/vnd.gnupg.wks formatter handles WKS Publishing Comfirmation request messages. Those are automated emails sent by WKS server when user request key publishing. The formatter explains what this email is, why it was received and has a 'Register the key' button which, when clicked, generates a response email for the server and deletes the email. The response is also deleted. Differential Revision: https://phabricator.kde.org/D3140
-rw-r--r--CMakeLists.txt1
-rw-r--r--kdepim-addons.categories1
-rw-r--r--plugins/messageviewer/bodypartformatter/CMakeLists.txt1
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/CMakeLists.txt37
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/Messages.sh4
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/application_gnupgwks.desktop8
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.cpp100
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.h50
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.cpp98
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.h69
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksurlhandler.cpp190
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksurlhandler.h52
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyformatter.cpp133
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyformatter.h43
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymemento.cpp105
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymemento.h68
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymessagepart.cpp132
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymessagepart.h73
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyurlhandler.cpp90
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyurlhandler.h48
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/plugin.cpp88
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/plugin.h37
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/templates.qrc7
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/templates/gnupgwksmessagepart.html52
-rw-r--r--plugins/messageviewer/bodypartformatter/gnupgwks/templates/pgpkeymessagepart.html54
25 files changed, 1541 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b725224..c1d944e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -93,6 +93,7 @@ find_package(KF5Akonadi ${AKONADI_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5AkonadiCalendar ${AKONADICALENDAR_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5Gravatar ${GRAVATAR_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5PimTextEdit ${KPIMTEXTEDIT_LIB_VERSION} CONFIG REQUIRED)
+find_package(KF5IdentityManagement ${KIDENTITYMANAGEMENT_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5Tnef ${KTNEF_LIB_VERSION} CONFIG REQUIRED)
diff --git a/kdepim-addons.categories b/kdepim-addons.categories
index 83b3aaa..a8443c1 100644
--- a/kdepim-addons.categories
+++ b/kdepim-addons.categories
@@ -21,3 +21,4 @@ org.kde.pim.kmail_confirmaddressplugin kdepim-addons (Confirm Address plugin)
org.kde.pim.kmail_checkbeforesend kdepim-addons (Check Before Send plugin)
org.kde.pim.kmail_automaticaddcontactsplugin kdepim-addons (Automatic add contacts plugin)
org.kde.pim.kaddressbook_importexportgmx kdepim-addons (KAddressbook import export gmx plugin)
+org.kde.pim.gnupgwks kdepim-addons (OpenPGP and GnuPG WKS body part formatter plugin)
diff --git a/plugins/messageviewer/bodypartformatter/CMakeLists.txt b/plugins/messageviewer/bodypartformatter/CMakeLists.txt
index f2281c3..ca561b1 100644
--- a/plugins/messageviewer/bodypartformatter/CMakeLists.txt
+++ b/plugins/messageviewer/bodypartformatter/CMakeLists.txt
@@ -4,3 +4,4 @@ add_subdirectory(ms-tnef)
add_subdirectory(vcard)
add_subdirectory(xdiff)
add_subdirectory(calendar)
+add_subdirectory(gnupgwks)
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/CMakeLists.txt b/plugins/messageviewer/bodypartformatter/gnupgwks/CMakeLists.txt
new file mode 100644
index 0000000..c2461f3
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/CMakeLists.txt
@@ -0,0 +1,37 @@
+add_definitions(-DTRANSLATION_DOMAIN=\"messageviewer_application_gnupgwks_plugin\")
+
+set(messageviewer_bodypartformatter_application_gnupgwks_SRCS
+ plugin.cpp
+ gnupgwksformatter.cpp
+ gnupgwksurlhandler.cpp
+ gnupgwksmessagepart.cpp
+ pgpkeyformatter.cpp
+ pgpkeymemento.cpp
+ pgpkeymessagepart.cpp
+ pgpkeyurlhandler.cpp
+)
+
+qt5_add_resources(messageviewer_bodypartformatter_application_gnupgwks_SRCS templates.qrc)
+
+ecm_qt_declare_logging_category(messageviewer_bodypartformatter_application_gnupgwks_SRCS
+ HEADER gnupgwks_debug.h
+ IDENTIFIER GNUPGWKS_LOG
+ CATEGORY_NAME org.kde.pim.gnupgwks)
+
+add_library(messageviewer_bodypartformatter_application_gnupgwks MODULE ${messageviewer_bodypartformatter_application_gnupgwks_SRCS})
+
+target_link_libraries(messageviewer_bodypartformatter_application_gnupgwks
+ Qt5::Core
+ KF5::MessageCore
+ KF5::MessageViewer
+ KF5::MailTransport
+ KF5::GrantleeTheme
+ KF5::I18n
+ KF5::Mime
+ KF5::IdentityManagement
+ Grantlee5::Templates
+ Gpgmepp
+)
+install(TARGETS messageviewer_bodypartformatter_application_gnupgwks DESTINATION ${KDE_INSTALL_PLUGINDIR})
+
+install(FILES application_gnupgwks.desktop DESTINATION ${KDE_INSTALL_DATADIR}/messageviewer/plugins/bodypartformatter)
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/Messages.sh b/plugins/messageviewer/bodypartformatter/gnupgwks/Messages.sh
new file mode 100644
index 0000000..d280f54
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/Messages.sh
@@ -0,0 +1,4 @@
+#! /bin/sh
+$EXTRACT_GRANTLEE_TEMPLATE_STRINGS `find templates -name \*.html` >> html.cpp
+$XGETTEXT html.cpp *.cpp -o $podir/messageviewer_application_gnupgwks_plugin.pot
+rm -f html.cpp
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/application_gnupgwks.desktop b/plugins/messageviewer/bodypartformatter/gnupgwks/application_gnupgwks.desktop
new file mode 100644
index 0000000..470f721
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/application_gnupgwks.desktop
@@ -0,0 +1,8 @@
+[Misc]
+Name=PGP and GnuPG WKS formatter
+Comment=A bodypart formatter plugin for OpenPGP Keys and GnuPG WKS messages
+
+[Plugin]
+Type=application/vnd.gnupg.wks
+X-KDE-Library=messageviewer_bodypartformatter_application_gnupgwks
+
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.cpp b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.cpp
new file mode 100644
index 0000000..dc417a2
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.cpp
@@ -0,0 +1,100 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "gnupgwksformatter.h"
+#include "gnupgwksmessagepart.h"
+
+#include <QObject>
+#include <QVariant>
+#include <QPalette>
+#include <QUrl>
+
+#include <MimeTreeParser/BodyPart>
+#include <MimeTreeParser/HtmlWriter>
+#include <MimeTreeParser/NodeHelper>
+#include <MessageCore/MessageCoreUtil>
+#include <MessageViewer/Viewer>
+
+#include <GrantleeTheme/GrantleeThemeEngine>
+#include <GrantleeTheme/GrantleeKi18nLocalizer>
+#include <GrantleeTheme/QtResourceTemplateLoader>
+#include <grantlee/context.h>
+#include <grantlee/template.h>
+
+using namespace MimeTreeParser::Interface;
+
+BodyPartFormatter::Result ApplicationGnuPGWKSFormatter::format(BodyPart* part, MimeTreeParser::HtmlWriter *writer) const
+{
+ return format(part, writer, Q_NULLPTR);
+}
+
+BodyPartFormatter::Result ApplicationGnuPGWKSFormatter::format(BodyPart* part, MimeTreeParser::HtmlWriter *writer,
+ QObject *) const
+{
+ if (!writer) {
+ return Ok;
+ }
+
+ GnuPGWKSMessagePart mp(part);
+
+ const QByteArray propertyName = "_GnuPGWKS" + mp.fingerprint().toLatin1();
+ const bool hasError = (part->nodeHelper()->property(propertyName).toString() == QLatin1String("error"));
+ if (hasError) {
+ part->nodeHelper()->setProperty(propertyName, QVariant());
+ }
+
+ GrantleeTheme::Engine engine;
+ engine.localizer()->setApplicationDomain(QByteArrayLiteral("messageviewer_application_gnupgwks_plugin"));
+ engine.addTemplateLoader(QSharedPointer<GrantleeTheme::QtResourceTemplateLoader>::create());
+
+ Grantlee::Template tpl = engine.loadByName(QStringLiteral(":/gnupgwksmessagepart.html"));
+ Grantlee::Context ctx;
+ ctx.setLocalizer(engine.localizer());
+
+ QObject block;
+
+ const auto baseUrl = QStringLiteral("gnupgwks?%1");
+ block.setProperty("isRequest", mp.confirmationType() == GnuPGWKSMessagePart::ConfirmationRequest);
+ block.setProperty("isResponse", mp.confirmationType() == GnuPGWKSMessagePart::ConfirmationResponse);
+ QUrlQuery confirmQuery;
+ confirmQuery.addQueryItem(QStringLiteral("action"), QStringLiteral("confirm"));
+ confirmQuery.addQueryItem(QStringLiteral("fpr"), mp.fingerprint());
+ block.setProperty("confirmUrl", mp.part()->makeLink(baseUrl.arg(confirmQuery.toString(QUrl::FullyDecoded))));
+ QUrlQuery keyQuery;
+ keyQuery.addQueryItem(QStringLiteral("action"), QStringLiteral("show"));
+ keyQuery.addQueryItem(QStringLiteral("fpr"), mp.fingerprint());
+ block.setProperty("keyUrl", mp.part()->makeLink(baseUrl.arg(keyQuery.toString(QUrl::FullyDecoded))));
+ block.setProperty("hasError", hasError);
+ ctx.insert(QStringLiteral("block"), &block);
+
+ QObject style;
+ QPalette p;
+ p.setCurrentColorGroup(QPalette::Normal);
+ style.setProperty("buttonBg", p.color(QPalette::Button).name());
+ style.setProperty("buttonBorder", p.shadow().color().name());
+ p.setCurrentColorGroup(QPalette::Active);
+ style.setProperty("buttonBorderHl", p.shadow().color().name());
+ p.setCurrentColorGroup(QPalette::Normal);
+ style.setProperty("buttonFg", p.color(QPalette::ButtonText).name());
+ style.setProperty("errorFg", MessageCore::ColorUtil::self()->pgpSignedBadTextColor().name());
+ ctx.insert(QStringLiteral("style"), &style);
+
+ writer->queue(tpl->render(&ctx));
+ return Ok;
+}
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.h b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.h
new file mode 100644
index 0000000..c265d61
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.h
@@ -0,0 +1,50 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef GNUPGWKSFORMATTER_H_
+#define GNUPGWKSFORMATTER_H_
+
+#include <MimeTreeParser/BodyPartFormatter>
+
+class GnuPGWKSMessagePart;
+class GnuPGWKSMemento;
+
+class ApplicationGnuPGWKSFormatter : public MimeTreeParser::Interface::BodyPartFormatter
+{
+public:
+ ApplicationGnuPGWKSFormatter() = default;
+
+ MimeTreeParser::Interface::BodyPartFormatter::Result format(MimeTreeParser::Interface::BodyPart *part,
+ MimeTreeParser::HtmlWriter *writer) const Q_DECL_OVERRIDE;
+ MimeTreeParser::Interface::BodyPartFormatter::Result format(MimeTreeParser::Interface::BodyPart *part,
+ MimeTreeParser::HtmlWriter *writer,
+ QObject *asyncResultObserver) const Q_DECL_OVERRIDE;
+
+private:
+ enum WKSStatus {
+ CheckingPublishing,
+ NotPublished,
+ Published
+ };
+
+ QString render(const GnuPGWKSMessagePart &mp, WKSStatus status) const;
+ WKSStatus runMemento(GnuPGWKSMemento *memento, const GnuPGWKSMessagePart &mp, bool async) const;
+};
+
+#endif
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.cpp b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.cpp
new file mode 100644
index 0000000..2c503f9
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.cpp
@@ -0,0 +1,98 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "gnupgwksmessagepart.h"
+
+#include <MimeTreeParser/BodyPart>
+#include <KMime/Content>
+
+
+GnuPGWKSMessagePart::GnuPGWKSMessagePart(MimeTreeParser::Interface::BodyPart *part)
+ : mPart(part)
+ , mType(UnknownType)
+{
+ parseContent(part->content());
+}
+
+GnuPGWKSMessagePart::ConfirmationType GnuPGWKSMessagePart::confirmationType() const
+{
+ return mType;
+}
+
+QString GnuPGWKSMessagePart::address() const
+{
+ return mAddress;
+}
+
+QString GnuPGWKSMessagePart::sender() const
+{
+ return mSender;
+}
+
+QString GnuPGWKSMessagePart::fingerprint() const
+{
+ return mFingerprint;
+}
+
+QString GnuPGWKSMessagePart::nonce() const
+{
+ return mNonce;
+}
+
+KMime::Content *GnuPGWKSMessagePart::node() const
+{
+ return mPart->content();
+}
+
+MimeTreeParser::Interface::BodyPart *GnuPGWKSMessagePart::part() const
+{
+ return mPart;
+}
+
+GnuPGWKSMessagePart::ConfirmationType GnuPGWKSMessagePart::stringToType(const QStringRef &str)
+{
+ if (str == QLatin1String("confirmation-request")) {
+ return ConfirmationRequest;
+ } else if (str == QLatin1String("confirmation-response")) {
+ return ConfirmationResponse;
+ } else {
+ return UnknownType;
+ }
+}
+
+void GnuPGWKSMessagePart::parseContent(KMime::Content *node)
+{
+ const auto text = QString::fromUtf8(node->decodedContent());
+ const auto lines = text.split(QLatin1Char('\n'), QString::SkipEmptyParts);
+ // https://tools.ietf.org/id/draft-koch-openpgp-webkey-service-02.txt
+ // sections 4.3 and 4.4
+ for (const auto &line : lines) {
+ if (line.startsWith(QLatin1String("type:"))) {
+ mType = stringToType(line.midRef(sizeof("type:") - 1).trimmed());
+ } else if (line.startsWith(QLatin1String("sender:"))) {
+ mSender = line.midRef(sizeof("sender:") - 1).trimmed().toString();
+ } else if (line.startsWith(QLatin1String("address:"))) {
+ mAddress = line.midRef(sizeof("address:") - 1).trimmed().toString();
+ } else if (line.startsWith(QLatin1String("fingerprint:"))) {
+ mFingerprint = line.midRef(sizeof("fingerprint:") - 1).trimmed().toString();
+ } else if (line.startsWith(QLatin1String("nonce:"))) {
+ mNonce = line.midRef(sizeof("nonce:") - 1).trimmed().toString();
+ }
+ }
+}
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.h b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.h
new file mode 100644
index 0000000..4376e2a
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.h
@@ -0,0 +1,69 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef GNUPGWKSMESSAGEPART_H_
+#define GNUPGWKSMESSAGEPART_H_
+
+#include <QString>
+
+namespace MimeTreeParser {
+namespace Interface {
+class BodyPart;
+class ObjectTreeSource;
+}
+}
+
+namespace KMime {
+class Content;
+}
+
+class GnuPGWKSMessagePart
+{
+public:
+ enum ConfirmationType {
+ UnknownType,
+ ConfirmationRequest,
+ ConfirmationResponse
+ };
+
+ GnuPGWKSMessagePart(MimeTreeParser::Interface::BodyPart *part);
+
+ virtual ~GnuPGWKSMessagePart() = default;
+
+ ConfirmationType confirmationType() const;
+ QString sender() const;
+ QString address() const;
+ QString fingerprint() const;
+ QString nonce() const;
+ KMime::Content *node() const;
+ MimeTreeParser::Interface::BodyPart *part() const;
+
+protected:
+ void parseContent(KMime::Content *node);
+ ConfirmationType stringToType(const QStringRef &str);
+
+ MimeTreeParser::Interface::BodyPart *mPart;
+ QString mSender;
+ QString mAddress;
+ QString mFingerprint;
+ QString mNonce;
+ ConfirmationType mType;
+};
+
+#endif
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksurlhandler.cpp b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksurlhandler.cpp
new file mode 100644
index 0000000..0ce0c6f
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksurlhandler.cpp
@@ -0,0 +1,190 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "gnupgwksurlhandler.h"
+#include "gnupgwksmessagepart.h"
+#include "gnupgwks_debug.h"
+
+#include <QString>
+#include <QUrlQuery>
+#include <QProcess>
+
+#include <MimeTreeParser/BodyPart>
+#include <MimeTreeParser/NodeHelper>
+#include <MessageViewer/Viewer>
+
+#include <QGpgME/Protocol>
+#include <QGpgME/WKSPublishJob>
+
+#include <MailTransport/Transport>
+#include <MailTransport/TransportManager>
+#include <MailTransport/MessageQueueJob>
+
+#include <KIdentityManagement/IdentityManager>
+#include <KIdentityManagement/Identity>
+
+#include <KMime/Message>
+#include <KMime/Util>
+
+#include <AkonadiCore/ItemDeleteJob>
+
+#include <KLocalizedString>
+
+using namespace MimeTreeParser::Interface;
+
+bool ApplicationGnuPGWKSUrlHandler::handleContextMenuRequest(BodyPart *,
+ const QString &,
+ const QPoint &) const
+{
+ return false;
+}
+
+bool ApplicationGnuPGWKSUrlHandler::handleClick(MessageViewer::Viewer *viewerInstance,
+ BodyPart *part, const QString &path) const
+{
+ Q_UNUSED(viewerInstance);
+
+ if (!path.startsWith(QLatin1String("gnupgwks?"))) {
+ return false;
+ }
+
+ const QUrlQuery q(path.mid(sizeof("gnupgwks?") - 1));
+ if (q.queryItemValue(QStringLiteral("action")) == QLatin1String("show")) {
+ QProcess::startDetached(QStringLiteral("kleopatra"),
+ { QStringLiteral("--query"), q.queryItemValue(QStringLiteral("fpr")) });
+ return true;
+ } else if (q.queryItemValue(QStringLiteral("action")) == QLatin1String("confirm")) {
+ GnuPGWKSMessagePart mp(part);
+ if (!sendConfirmation(viewerInstance, mp)) {
+ part->nodeHelper()->setProperty("__GnuPGWKS" + mp.fingerprint().toLatin1(), QStringLiteral("error"));
+ }
+ return true;
+ }
+
+ return false;
+}
+
+QString ApplicationGnuPGWKSUrlHandler::statusBarMessage(BodyPart* part, const QString &path) const
+{
+ Q_UNUSED(part);
+
+ if (!path.startsWith(QLatin1String("gnupgwks?"))) {
+ return QString();
+ }
+
+ const QUrlQuery q(path.mid(sizeof("gnupgwks?") - 1));
+ if (q.queryItemValue(QStringLiteral("action")) == QLatin1String("show")) {
+ return i18n("Display key details");
+ } else if (q.queryItemValue(QStringLiteral("action")) == QLatin1String("confirm")) {
+ return i18n("Publish the key");
+ }
+ return QString();
+}
+
+
+QByteArray ApplicationGnuPGWKSUrlHandler::createConfirmation(const KMime::Message::Ptr &msg) const
+{
+ auto job = QGpgME::openpgp()->wksPublishJob();
+ QEventLoop el;
+ QByteArray result;
+ QObject::connect(job, &QGpgME::WKSPublishJob::result,
+ [&el, &result](const GpgME::Error &, const QByteArray &returnedData,
+ const QByteArray &returnedError)
+ {
+ if (returnedData.isEmpty()) {
+ qCWarning(GNUPGWKS_LOG) << "GPG:" << returnedError;
+ }
+ result = returnedData;
+ el.quit();
+ });
+ job->startReceive(msg->encodedContent());
+ el.exec();
+
+ return result;
+}
+
+
+bool ApplicationGnuPGWKSUrlHandler::sendConfirmation(MessageViewer::Viewer *viewerInstance,
+ const GnuPGWKSMessagePart &mp) const
+{
+
+
+ const QByteArray data = createConfirmation(viewerInstance->message());
+ if (data.isEmpty()) {
+ return false;
+ }
+
+ auto msg = KMime::Message::Ptr::create();
+ msg->setContent(KMime::CRLFtoLF(data));
+ msg->parse();
+
+ // Find identity
+ const auto identity = KIdentityManagement::IdentityManager::self()->identityForAddress(mp.address());
+ const bool nullIdentity = (identity == KIdentityManagement::Identity::null());
+ if (!nullIdentity) {
+ KMime::Headers::Generic *x_header = new KMime::Headers::Generic("X-KMail-Identity");
+ x_header->from7BitString(QByteArray::number(identity.uoid()));
+ msg->setHeader(x_header);
+ }
+
+ // Find transport set in the identity, fallback to default transport
+ auto transportMgr = MailTransport::TransportManager::self();
+ const bool identityHasTransport = !identity.transport().isEmpty();
+ int transportId = -1;
+ if (!nullIdentity && identityHasTransport) {
+ transportId = identity.transport().toInt();
+ } else {
+ transportId = transportMgr->defaultTransportId();
+ }
+ // No transport exists, ask user to create one
+ if (transportId == -1) {
+ if (!transportMgr->showTransportCreationDialog(0, MailTransport::TransportManager::IfNoTransportExists)) {
+ return false;
+ }
+ transportId = transportMgr->defaultTransportId();
+ }
+ auto header = new KMime::Headers::Generic("X-KMail-Transport");
+ header->fromUnicodeString(QString::number(transportId), "utf-8");
+ msg->setHeader(header);
+
+ // Build the message
+ msg->assemble();
+
+ // Move to outbox
+ auto transport = transportMgr->transportById(transportId);
+ auto job = new MailTransport::MessageQueueJob;
+ job->addressAttribute().setTo({ msg->to(false)->asUnicodeString() });
+ job->transportAttribute().setTransportId(transport->id());
+ job->addressAttribute().setFrom(msg->from(false)->asUnicodeString());
+ job->sentBehaviourAttribute().setSentBehaviour(MailTransport::SentBehaviourAttribute::Delete);
+ job->sentBehaviourAttribute().setSendSilently(true);
+ job->setMessage(msg);
+
+ // Send
+ if (!job->exec()) {
+ qCWarning(GNUPGWKS_LOG) << "Error queuing message in output:" << job->errorText();
+ return false;
+ }
+
+ // Delete the original request
+ // Don't use viewerInstance->deleteMessage(), which triggers Move To Trash,
+ // we want to get rid of the message for good.
+ new Akonadi::ItemDeleteJob(viewerInstance->messageItem());
+ return true;
+}
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksurlhandler.h b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksurlhandler.h
new file mode 100644
index 0000000..abbd30a
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksurlhandler.h
@@ -0,0 +1,52 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef GNUPGWKSURLHANDLER_H_
+#define GNUPGWKSURLHANDLER_H_
+
+#include <QtGlobal>
+#include <MessageViewer/BodyPartURLHandler>
+
+#include <KMime/Message>
+
+class GnuPGWKSMessagePart;
+
+class ApplicationGnuPGWKSUrlHandler : public MimeTreeParser::Interface::BodyPartURLHandler
+{
+public:
+ ApplicationGnuPGWKSUrlHandler() = default;
+
+ bool handleClick(MessageViewer::Viewer *viewerInstance,
+ MimeTreeParser::Interface::BodyPart *part,
+ const QString &path) const Q_DECL_OVERRIDE;
+ bool handleContextMenuRequest(MimeTreeParser::Interface::BodyPart *part,
+ const QString &path,
+ const QPoint &p) const Q_DECL_OVERRIDE;
+ QString statusBarMessage(MimeTreeParser::Interface::BodyPart *part,
+ const QString &path) const Q_DECL_OVERRIDE;
+
+private:
+ bool sendConfirmation(MessageViewer::Viewer *viewerInstance,
+ const GnuPGWKSMessagePart &mp) const;
+
+ QByteArray createConfirmation(const KMime::Message::Ptr &msg) const;
+};
+
+
+#endif
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyformatter.cpp b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyformatter.cpp
new file mode 100644
index 0000000..3b969dd
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyformatter.cpp
@@ -0,0 +1,133 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "pgpkeyformatter.h"
+#include "pgpkeymessagepart.h"
+#include "pgpkeymemento.h"
+
+#include <QUrl>
+#include <QApplication>
+#include <QPalette>
+
+#include <MimeTreeParser/HtmlWriter>
+#include <MimeTreeParser/MessagePart>
+
+#include <GrantleeTheme/GrantleeThemeEngine>
+#include <GrantleeTheme/QtResourceTemplateLoader>
+#include <GrantleeTheme/GrantleeKi18nLocalizer>
+
+#include <KLocalizedString>
+
+using namespace MimeTreeParser::Interface;
+
+BodyPartFormatter::Result ApplicationPGPKeyFormatter::format(BodyPart *part,
+ MimeTreeParser::HtmlWriter *writer) const
+{
+ return format(part, writer, Q_NULLPTR);
+}
+
+BodyPartFormatter::Result ApplicationPGPKeyFormatter::format(BodyPart *part,
+ MimeTreeParser::HtmlWriter *writer,
+ QObject *asyncResultObserver) const
+{
+ if (!writer) {
+ return Ok;
+ }
+
+ PgpKeyMemento *m = dynamic_cast<PgpKeyMemento *>(part->memento());
+ PgpKeyMessagePart mp(part);
+
+ if (!m) {
+ auto memento = new PgpKeyMemento();
+ if (asyncResultObserver) {
+ QObject::connect(memento, SIGNAL(update(MimeTreeParser::UpdateMode)),
+ asyncResultObserver, SLOT(update(MimeTreeParser::UpdateMode)));
+ memento->start(mp.fingerprint());
+ } else {
+ memento->exec(mp.fingerprint());
+ m = memento;
+ }
+ part->setBodyPartMemento(memento);
+ } else if (m->isRunning()) {
+ m = Q_NULLPTR;
+ }
+
+ if (m) {
+ Q_ASSERT(!m->isRunning());
+
+ mp.setError(m->error());
+ mp.setKey(m->key());
+ }
+
+ writer->queue(render(mp));
+ return Ok;
+}
+
+QString ApplicationPGPKeyFormatter::render(const PgpKeyMessagePart &mp) const
+{
+ GrantleeTheme::Engine engine;
+ engine.localizer()->setApplicationDomain(QByteArrayLiteral("messageviewer_application_gnupgwks_plugin"));
+ engine.addTemplateLoader(QSharedPointer<GrantleeTheme::QtResourceTemplateLoader>::create());
+
+ Grantlee::Template tpl = engine.loadByName(QStringLiteral(":/pgpkeymessagepart.html"));
+ Grantlee::Context ctx;
+ ctx.setLocalizer(engine.localizer());
+
+ QObject block;
+
+ block.setProperty("showKeyDetails", mp.source()->showSignatureDetails());
+ block.setProperty("error", mp.error());
+ block.setProperty("importUrl", mp.part()->makeLink(QStringLiteral("pgpkey?action=import")));
+ const auto key = mp.key();
+ if (key.isNull()) {
+ block.setProperty("uid", mp.userID());
+ block.setProperty("fingerprint", mp.fingerprint());
+ block.setProperty("created", mp.keyDate().toString(Qt::SystemLocaleDate));
+ } else {
+ const auto uid = key.userID(0);
+ block.setProperty("hasKey", true);
+ if (uid.email() && *uid.email() && uid.name() && *uid.name()) {
+ block.setProperty("uid", QStringLiteral("%1 <%2>").arg(QString::fromUtf8(uid.name()),
+ QString::fromUtf8(uid.email())));
+ } else if (uid.name() && *uid.name()) {
+ block.setProperty("uid", QString::fromUtf8(uid.name()));
+ } else if (uid.email() && *uid.email()) {
+ block.setProperty("uid", QString::fromUtf8(uid.email()));
+ } else {
+ block.setProperty("uid", i18n("Unknown identity"));
+ }
+ block.setProperty("created", QDateTime::fromTime_t(key.subkey(0).creationTime()).toString(Qt::SystemLocaleDate));
+ block.setProperty("fingerprint", QString::fromLatin1(key.primaryFingerprint()));
+ block.setProperty("keyUrl", QStringLiteral("kmail:showCertificate#GpgME ### gpgme ### %1").arg(QString::fromLatin1(key.keyID())));
+ }
+
+ QObject style;
+ const auto bgColor = QApplication::palette().color(QPalette::Base);
+ if (bgColor.value() < 128) { // HSV value (brightness): 0 = darkest, 255 = brightest
+ style.setProperty("borderColor", QColor(Qt::white).name());
+ style.setProperty("frameTextColor", QColor(Qt::black).name());
+ } else {
+ style.setProperty("borderColor", QColor(Qt::black).name());
+ style.setProperty("frameTextColor", QColor(Qt::white).name());
+ }
+
+ ctx.insert(QStringLiteral("block"), &block);
+ ctx.insert(QStringLiteral("style"), &style);
+ return tpl->render(&ctx);
+}
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyformatter.h b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyformatter.h
new file mode 100644
index 0000000..4abeb8b
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyformatter.h
@@ -0,0 +1,43 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef PGPKEYFORMATTER_H_
+#define PGPKEYFORMATTER_H_
+
+#include <MimeTreeParser/BodyPartFormatter>
+
+class PgpKeyMessagePart;
+
+class ApplicationPGPKeyFormatter : public MimeTreeParser::Interface::BodyPartFormatter
+{
+public:
+ ApplicationPGPKeyFormatter() = default;
+
+ MimeTreeParser::Interface::BodyPartFormatter::Result format(MimeTreeParser::Interface::BodyPart *part,
+ MimeTreeParser::HtmlWriter *writer) const Q_DECL_OVERRIDE;
+ MimeTreeParser::Interface::BodyPartFormatter::Result format(MimeTreeParser::Interface::BodyPart *part,
+ MimeTreeParser::HtmlWriter *writer,
+ QObject *asyncResultObserver) const Q_DECL_OVERRIDE;
+
+private:
+ QString render(const PgpKeyMessagePart &mp) const;
+};
+
+#endif
+
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymemento.cpp b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymemento.cpp
new file mode 100644
index 0000000..d6d1d2e
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymemento.cpp
@@ -0,0 +1,105 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "pgpkeymemento.h"
+
+#include <QGpgME/Protocol>
+#include <QGpgME/KeyListJob>
+#include <gpgme++/keylistresult.h>
+
+PgpKeyMemento::PgpKeyMemento()
+ : QObject(Q_NULLPTR)
+ , MimeTreeParser::Interface::BodyPartMemento()
+ , mIsRunning(false)
+{
+}
+
+PgpKeyMemento::~PgpKeyMemento()
+{
+}
+
+void PgpKeyMemento::detach()
+{
+ disconnect(this, SIGNAL(update(MimeTreeParser::UpdateMode)), 0, 0);
+}
+
+void PgpKeyMemento::notify()
+{
+ Q_EMIT update(MimeTreeParser::Force);
+}
+
+bool PgpKeyMemento::isRunning() const
+{
+ return mIsRunning;
+}
+
+void PgpKeyMemento::setRunning(bool running)
+{
+ mIsRunning = running;
+}
+
+GpgME::Key PgpKeyMemento::key() const
+{
+ return mKey;
+}
+
+QString PgpKeyMemento::error() const
+{
+ return mError;
+}
+
+bool PgpKeyMemento::start(const QString &fingerprint)
+{
+ auto job = QGpgME::openpgp()->keyListJob(false, false, true);
+ connect(job, &QGpgME::KeyListJob::nextKey,
+ this, &PgpKeyMemento::onKeyReceived);
+ connect(job, &QGpgME::KeyListJob::result,
+ this, &PgpKeyMemento::onListJobFinished);
+ job->start({ fingerprint });
+
+ setRunning(true);
+ return true;
+}
+
+void PgpKeyMemento::exec(const QString &fingerprint)
+{
+ auto job = QGpgME::openpgp()->keyListJob(false, false, true);
+ std::vector<GpgME::Key> outKeys;
+ auto result = job->exec({ fingerprint }, false, outKeys);
+ if (result.error()) {
+ mError = QString::fromStdString(result.error().asString());
+ } else if (!outKeys.empty()) {
+ mKey = outKeys[0];
+ }
+}
+
+void PgpKeyMemento::onKeyReceived(const GpgME::Key &key)
+{
+ mKey = key;
+}
+
+void PgpKeyMemento::onListJobFinished(const GpgME::KeyListResult &result)
+{
+ if (result.error()) {
+ mError = QString::fromStdString(result.error().asString());
+ }
+
+ setRunning(false);
+ notify();
+}
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymemento.h b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymemento.h
new file mode 100644
index 0000000..fc64c05
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymemento.h
@@ -0,0 +1,68 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef PGPKEYMEMENTO_H_
+#define PGPKEYMEMENTO_H_
+
+#include <QObject>
+#include <MimeTreeParser/BodyPart>
+#include <MimeTreeParser/Enums>
+
+#include <gpgme++/key.h>
+
+namespace GpgME {
+class KeyListResult;
+}
+
+class PgpKeyMemento : public QObject
+ , public MimeTreeParser::Interface::BodyPartMemento
+{
+ Q_OBJECT
+public:
+ explicit PgpKeyMemento();
+ ~PgpKeyMemento();
+
+ bool isRunning() const;
+ void setRunning(bool running);
+
+ GpgME::Key key() const;
+ QString error() const;
+
+ bool start(const QString &fingerprint);
+ void exec(const QString &fingerprint);
+
+ void detach() Q_DECL_OVERRIDE;
+
+Q_SIGNALS:
+ void update(MimeTreeParser::UpdateMode update);
+
+private:
+ void notify();
+
+private Q_SLOTS:
+ void onKeyReceived(const GpgME::Key &key);
+ void onListJobFinished(const GpgME::KeyListResult &result);
+
+private:
+ GpgME::Key mKey;
+ QString mError;
+ bool mIsRunning;
+};
+
+#endif
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymessagepart.cpp b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymessagepart.cpp
new file mode 100644
index 0000000..427c0c3
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymessagepart.cpp
@@ -0,0 +1,132 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "pgpkeymessagepart.h"
+
+#include <QProcess>
+
+#include <MimeTreeParser/BodyPart>
+#include <KMime/Content>
+
+PgpKeyMessagePart::PgpKeyMessagePart(MimeTreeParser::Interface::BodyPart *part)
+ : mPart(part)
+{
+ parseContent(mPart->content());
+}
+
+QDateTime PgpKeyMessagePart::keyDate() const
+{
+ return mKeyDate;
+}
+
+QString PgpKeyMessagePart::keyID() const
+{
+ return mKeyID;
+}
+
+QString PgpKeyMessagePart::userID() const
+{
+ return mUserID;
+}
+
+QString PgpKeyMessagePart::fingerprint() const
+{
+ return mFingerprint;
+}
+
+GpgME::Key PgpKeyMessagePart::key() const
+{
+ return mKey;
+}
+
+void PgpKeyMessagePart::setKey(const GpgME::Key &key)
+{
+ mKey = key;
+}
+
+QString PgpKeyMessagePart::error() const
+{
+ return mError;
+}
+
+void PgpKeyMessagePart::setError(const QString &error)
+{
+ mError = error;
+}
+
+QByteArray PgpKeyMessagePart::rawKey() const
+{
+ return mPart->content()->decodedContent();
+}
+
+MimeTreeParser::Interface::ObjectTreeSource *PgpKeyMessagePart::source() const
+{
+ return mPart->source();
+}
+
+MimeTreeParser::Interface::BodyPart *PgpKeyMessagePart::part() const
+{
+ return mPart;
+}
+
+
+void PgpKeyMessagePart::parseContent(KMime::Content *node)
+{
+ QProcess p;
+ p.start(QStringLiteral("gpg"), { QStringLiteral("--with-colons"),
+ QStringLiteral("--fixed-list-mode"),
+ QStringLiteral("--with-fingerprint") });
+ p.waitForStarted();
+ p.write(node->decodedContent());
+ p.closeWriteChannel();
+ p.waitForReadyRead();
+ const QByteArray result = p.readAllStandardOutput();
+ p.waitForFinished();
+
+ const auto lines = result.split('\n');
+ for (const auto &line : lines) {
+ const auto cols = line.split(':');
+ if (cols.isEmpty()) {
+ continue;
+ }
+
+ const int size = cols.size();
+
+ // "pub" line can appear multiple times, but we are only interested in
+ // the first one
+ if (cols[0] == "pub" && mKeyID.isEmpty()) {
+ if (size > 4) {
+ mKeyID = QString::fromUtf8(cols[4]);
+ }
+ // gpg1: "pub" contains UID
+ if (size > 9) {
+ mUserID = QString::fromUtf8(cols[9]);
+ }
+ if (size > 6) {
+ mKeyDate = QDateTime::fromTime_t(cols[5].toUInt());
+ }
+ // gpg2: UID is on a separate line
+ } else if (cols[0] == "uid" && size > 9 && mUserID.isEmpty()) {
+ mUserID = QString::fromUtf8(cols[9]);
+ } else if (cols[0] == "fpr" && size > 9 && mFingerprint.isEmpty()) {
+ mFingerprint = QString::fromLatin1(cols[9]);
+ }
+ }
+}
+
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymessagepart.h b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymessagepart.h
new file mode 100644
index 0000000..1252d86
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeymessagepart.h
@@ -0,0 +1,73 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef PGPKEYMESSAGEPART_H_
+#define PGPKEYMESSAGEPART_H_
+
+#include <QDateTime>
+#include <QString>
+
+#include <gpgme++/key.h>
+
+namespace MimeTreeParser {
+namespace Interface {
+class BodyPart;
+class ObjectTreeSource;
+}
+}
+namespace KMime {
+class Content;
+}
+
+class PgpKeyMessagePart
+{
+public:
+ PgpKeyMessagePart(MimeTreeParser::Interface::BodyPart *part);
+
+ virtual ~PgpKeyMessagePart() = default;
+
+ QDateTime keyDate() const;
+ QString userID() const;
+ QString keyID() const;
+ QString fingerprint() const;
+
+ QString error() const;
+ void setError(const QString &error);
+
+ void setKey(const GpgME::Key &key);
+ GpgME::Key key() const;
+
+ QByteArray rawKey() const;
+
+ MimeTreeParser::Interface::ObjectTreeSource *source() const;
+ MimeTreeParser::Interface::BodyPart *part() const;
+
+protected:
+ void parseContent(KMime::Content *node);
+
+ MimeTreeParser::Interface::BodyPart *mPart;
+ QDateTime mKeyDate;
+ QString mUserID;
+ QString mKeyID;
+ QString mFingerprint;
+ QString mError;
+ GpgME::Key mKey;
+};
+
+#endif
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyurlhandler.cpp b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyurlhandler.cpp
new file mode 100644
index 0000000..bbd2f80
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyurlhandler.cpp
@@ -0,0 +1,90 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "pgpkeyurlhandler.h"
+
+#include <QString>
+#include <QUrlQuery>
+#include <QProcess>
+
+#include <KLocalizedString>
+
+#include <MimeTreeParser/NodeHelper>
+#include <MimeTreeParser/BodyPart>
+#include <MessageViewer/Viewer>
+
+#include <QGpgME/Protocol>
+#include <QGpgME/ImportJob>
+#include <gpgme++/importresult.h>
+#include <gpgme++/error.h>
+
+#include <KMessageBox>
+
+using namespace MimeTreeParser::Interface;
+
+QUrlQuery ApplicationPgpKeyUrlHandler::decodePath(const QString &path) const
+{
+ if (!path.startsWith(QLatin1String("pgpkey?"))) {
+ return QUrlQuery();
+ }
+
+ return QUrlQuery(path.mid(sizeof("pgpkey?") - 1));
+}
+
+
+
+bool ApplicationPgpKeyUrlHandler::handleContextMenuRequest(BodyPart *, const QString &, const QPoint &) const
+{
+ return false;
+}
+
+QString ApplicationPgpKeyUrlHandler::statusBarMessage(BodyPart *part, const QString &path) const
+{
+ const QUrlQuery q = decodePath(path);
+ if (q.queryItemValue(QStringLiteral("action")) == QLatin1String("import")) {
+ return i18n("Import the key");
+ }
+
+ return QString();
+}
+
+bool ApplicationPgpKeyUrlHandler::handleClick(MessageViewer::Viewer *v,
+ BodyPart *part, const QString &path) const
+{
+ const QUrlQuery q = decodePath(path);
+ if (q.queryItemValue(QStringLiteral("action")) == QLatin1String("import")) {
+ auto job = QGpgME::openpgp()->importJob();
+ auto res = job->exec(part->content()->decodedContent());
+ if (res.error()) {
+ KMessageBox::detailedError(v,
+ i18n("An error occured while importing the key."),
+ QString::fromUtf8(res.error().asString()),
+ i18n("Import error"));
+ } else {
+ KMessageBox::information(v,
+ i18n("The key has been succesfully imported."),
+ i18n("Import finished"));
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyurlhandler.h b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyurlhandler.h
new file mode 100644
index 0000000..c798741
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/pgpkeyurlhandler.h
@@ -0,0 +1,48 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef PGPKEYURLHANDLER_H
+#define PGPKEYURLHANDLER_H
+
+#include <QtGlobal>
+#include <MessageViewer/BodyPartURLHandler>
+
+class QUrlQuery;
+
+class ApplicationPgpKeyUrlHandler : public MimeTreeParser::Interface::BodyPartURLHandler
+{
+public:
+ ApplicationPgpKeyUrlHandler() = default;
+
+ bool handleClick(MessageViewer::Viewer *viewerInstance,
+ MimeTreeParser::Interface::BodyPart *part,
+ const QString &path) const Q_DECL_OVERRIDE;
+ bool handleContextMenuRequest(MimeTreeParser::Interface::BodyPart *part,
+ const QString &path,
+ const QPoint &p) const Q_DECL_OVERRIDE;
+ QString statusBarMessage(MimeTreeParser::Interface::BodyPart *part,
+ const QString &path) const Q_DECL_OVERRIDE;
+
+private:
+ QUrlQuery decodePath(const QString &path) const;
+};
+
+
+#endif
+
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/plugin.cpp b/plugins/messageviewer/bodypartformatter/gnupgwks/plugin.cpp
new file mode 100644
index 0000000..8735ca1
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/plugin.cpp
@@ -0,0 +1,88 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "plugin.h"
+
+#include "gnupgwksformatter.h"
+#include "gnupgwksurlhandler.h"
+#include "pgpkeyformatter.h"
+#include "pgpkeyurlhandler.h"
+
+namespace {
+enum Index {
+ application_vnd_gnupg_keys,
+ application_pgp_keys
+};
+}
+
+const char *ApplicationGnuPGWKSPlugin::type(int idx) const
+{
+ switch (idx) {
+ case application_vnd_gnupg_keys:
+ case application_pgp_keys:
+ return "application";
+ default:
+ return Q_NULLPTR;
+ }
+}
+
+const char *ApplicationGnuPGWKSPlugin::subtype(int idx) const
+{
+ switch (idx) {
+ case application_vnd_gnupg_keys:
+ return "vnd.gnupg.wks";
+ case application_pgp_keys:
+ return "pgp-keys";
+ default:
+ return Q_NULLPTR;
+ }
+}
+
+
+const MimeTreeParser::Interface::BodyPartFormatter *ApplicationGnuPGWKSPlugin::bodyPartFormatter(int idx) const
+{
+ switch (idx) {
+ case application_vnd_gnupg_keys:
+ return new ApplicationGnuPGWKSFormatter();
+ case application_pgp_keys:
+ return new ApplicationPGPKeyFormatter();
+ default:
+ return Q_NULLPTR;
+ }
+}
+
+const MimeTreeParser::Interface::BodyPartURLHandler *ApplicationGnuPGWKSPlugin::urlHandler(int idx) const
+{
+ switch (idx) {
+ case application_vnd_gnupg_keys:
+ return new ApplicationGnuPGWKSUrlHandler();
+ case application_pgp_keys:
+ return new ApplicationPgpKeyUrlHandler();
+ default:
+ return Q_NULLPTR;
+ }
+}
+
+
+extern "C"
+Q_DECL_EXPORT MimeTreeParser::Interface::BodyPartFormatterPlugin *
+messageviewer_bodypartformatter_application_gnupgwks_create_bodypart_formatter_plugin()
+{
+ return new ApplicationGnuPGWKSPlugin();
+}
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/plugin.h b/plugins/messageviewer/bodypartformatter/gnupgwks/plugin.h
new file mode 100644
index 0000000..b0bf21b
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/plugin.h
@@ -0,0 +1,37 @@
+/*
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library 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 Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef GNUPGWKSPLUGIN_H
+#define GNUPGWKSPLUGIN_H
+
+#include <MimeTreeParser/BodyPartFormatter>
+
+class ApplicationGnuPGWKSPlugin : public MimeTreeParser::Interface::BodyPartFormatterPlugin
+{
+public:
+ ApplicationGnuPGWKSPlugin() = default;
+
+ const MimeTreeParser::Interface::BodyPartFormatter *bodyPartFormatter(int idx) const Q_DECL_OVERRIDE;
+ const char *subtype(int idx) const Q_DECL_OVERRIDE;
+ const char *type(int idx) const Q_DECL_OVERRIDE;
+ const MimeTreeParser::Interface::BodyPartURLHandler *urlHandler(int idx) const Q_DECL_OVERRIDE;
+};
+
+
+#endif
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/templates.qrc b/plugins/messageviewer/bodypartformatter/gnupgwks/templates.qrc
new file mode 100644
index 0000000..b908dac
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/templates.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file alias="pgpkeymessagepart.html">templates/pgpkeymessagepart.html</file>
+ <file alias="gnupgwksmessagepart.html">templates/gnupgwksmessagepart.html</file>
+ </qresource>
+</RCC>
+
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/templates/gnupgwksmessagepart.html b/plugins/messageviewer/bodypartformatter/gnupgwks/templates/gnupgwksmessagepart.html
new file mode 100644
index 0000000..9614dca
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/templates/gnupgwksmessagepart.html
@@ -0,0 +1,52 @@
+<style type="text/css">
+.gnupgwksbutton {
+ display: inline-block !important;
+ font-weight: bold !important;
+ padding: 4px 8px !important;
+ margin-bottom: 4px !important;
+ border: 1px solid {{ style.buttonBorder }} !important;
+ border-radius: 3px !important;
+ background: {{ style.buttonBg }} !important;
+ vertical-align: middle !important;
+}
+.gnupgwksbutton:hover{
+ border-color: {{ style.buttonBorderHl }} !important;
+}
+.gnupgwksbutton a.button {
+ color: {{ style.buttonFg }} !important;
+}
+.gnupgwkserror {
+ color: {{ style.errorFg }};
+}
+</style>
+
+<div style="padding: 5pt">
+{% if block.isRequest %}
+ <div style="font-size: large; text-align: center; padding-bottom: 20pt;">
+ {% i18n "Register your OpenPGP key with your email provider. " %}
+ </div>
+ <p>{% i18n "When you register your key with your email provider other people will then be able to retrieve the key and send you encrypted emails and verify authenticity of emails you send them." %}</p>
+ <div style="text-align: center; padding-bottom: 20pt;">
+ {% if block.hasError %}
+ <p style="gnupgwkserror">{% i18n "An error occured while publishing the key. Please try again later." %}</p>
+ {% else %}
+ <a class="gnupgwksbutton" href="{{ block.confirmUrl }}">{% i18n "Register the key" %}</a>
+ <br><br>
+ <p>{% i18n "The email will be automatically deleted once you confirm the registration." %}</p>
+ {% endif %}
+ <br></br>
+ <a href="{{ block.keyUrl }}">{% i18n "Show key details" %}</a>
+ </div>
+{% elif block.isResponse %}
+ <div style="font-size: large; text-align: center; padding-bottom: 20pt;">
+ {% i18n "This is an automatically generated email. The purpose of this email is to regisdter your OpenPGP key with your email provider." %}
+ </div>
+ <div styl="text-align: center; padding-bottom: 20pt;">
+ <p>{% i18n "Your OpenPGP key will be published on your email provider's key server. Other users will be able to retrieve the key and send you encrypted emails and verify authenticity of emails you send them." %}</p>
+ <br/>
+ <br/>
+ <a href="{{ block.keyUrl }}">{% i18n "Show key details" %}</a>
+ </div>
+{% endif %}
+</div>
+
diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/templates/pgpkeymessagepart.html b/plugins/messageviewer/bodypartformatter/gnupgwks/templates/pgpkeymessagepart.html
new file mode 100644
index 0000000..244e6ce
--- /dev/null
+++ b/plugins/messageviewer/bodypartformatter/gnupgwks/templates/pgpkeymessagepart.html
@@ -0,0 +1,54 @@
+<style type="text/css">
+table.key {
+ width: 100%;
+ border: 1px solid {{ style.borderColor }};
+}
+table .keyH {
+ background-color: {{ style.borderColor }};
+ color: {{ style.frameTextColor }};
+}
+table .keyB {
+}
+</style>
+<table cellspacing="0" cellpadding="2" class="key">
+<tr class="keyH"><td>{% i18n "OpenPGP Key" %}</td></tr>
+<tr class="keyb"><td>
+ <div style="padding: 10pt;">
+ <p>
+ {% i18n "This is an OpenPGP key, which can be used to sign or encrypt emails." %}
+ </p>
+
+ {% if block.showKeyDetails %}
+ {% if block.hasKey %}
+ <table border="0" cellspacing="1" cellpadding="1">
+ <tr>
+ <td><b>{% i18n "Owner:" %}&nbsp;</b></td><td>{{ block.uid }}</td>
+ </tr>
+ {% if block.created %}
+ <tr>
+ <td><b>{% i18n "Created:" %}&nbsp;</td><td>{{ block.created }}</td>
+ </tr>
+ {% endif %}
+ {% if block.fingerprint %}
+ <tr>
+ <td><b>{% i18n "Fingerprint:" %}&nbsp;</td><td>{{ block.fingerprint }}</td>
+ </tr>
+ {% endif %}
+ </table>
+ <a href="kmail:hideSignatureDetails">{% i18n "Hide key details" %}</a>
+ {% if block.keyUrl %}
+ | <a href="{{ block.keyUrl }}">{% i18n "Open in Kleopatra" %}</a>
+ {% endif %}
+ {% elif block.error %}
+ <p class="error">{% i18n "Error while loading key: %1" key.error %}</p>
+ {% else %}
+ <p>{% i18n "Loading key details..." %}</p>
+ {% endif %}
+ {% else %}
+ <a href="kmail:showSignatureDetails">{% i18n "Show key details ..." %}</a>
+ {% endif %}
+ | <a href="{{ block.importUrl }}">{% i18n "Import key" %}</a>
+ </div>
+</td></tr>
+<tr class="keyH"><td>&nbsp;</td></tr>
+</table>