diff --git a/plugins/messageviewer/bodypartformatter/autotests/data/wks-confirmation-request-multipart-decrypted.mbox b/plugins/messageviewer/bodypartformatter/autotests/data/wks-confirmation-request-multipart-decrypted.mbox new file mode 100644 index 00000000..9b4f1c2a --- /dev/null +++ b/plugins/messageviewer/bodypartformatter/autotests/data/wks-confirmation-request-multipart-decrypted.mbox @@ -0,0 +1,25 @@ +From: key-submission@example.net +To: patrice.lumumba@example.net +Subject: Confirm your key publication +MIME-Version: 1.0 +Content-Type: multipart/mixed; + boundary="=-=01-wrzqued738dfx4x97u7y=-=" +Date: Wed, 05 Oct 2016 10:16:57 +0000 + +--=-=01-wrzqued738dfx4x97u7y=-= +Content-Type: text/plain +Content-Transfer-Encoding: 8bit + +body text you should not see in the result + +--=-=01-wrzqued738dfx4x97u7y=-= +Content-Type: application/vnd.gnupg.wks +Content-Transfer-Encoding: 8bit + +type: confirmation-request +sender: key-submission@example.net +address: patrice.lumumba@example.net +fingerprint: B21DEAB4F875FB3DA42F1D1D139563682A020D0A +nonce: f5pscz57zj6fk11wekk8gx4cmrb659a7 + +--=-=01-wrzqued738dfx4x97u7y=-=-- diff --git a/plugins/messageviewer/bodypartformatter/autotests/data/wks-confirmation-request-multipart-decrypted.mbox.html b/plugins/messageviewer/bodypartformatter/autotests/data/wks-confirmation-request-multipart-decrypted.mbox.html new file mode 100644 index 00000000..56eb6696 --- /dev/null +++ b/plugins/messageviewer/bodypartformatter/autotests/data/wks-confirmation-request-multipart-decrypted.mbox.html @@ -0,0 +1,43 @@ + + + + +
+ +
+ +
+
Register your OpenPGP key with your email provider.
+

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.

+
+ Register the key +
+
+

The email will be automatically deleted once you confirm the registration.

+
+
+ Show key details +
+
+
+
+ + diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwks.json b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwks.json index c099c6ed..8f480da8 100644 --- a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwks.json +++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwks.json @@ -1,10 +1,11 @@ { "formatter": [ { "mimetype": "application/pgp-keys" }, { "mimetype": "multipart/mixed" }, { "mimetype": "application/vnd.gnupg.wks" } ], "renderer": [ - { "type": "PgpKeyMessagePart" } + { "type": "PgpKeyMessagePart" }, + { "type": "GnuPGWKSMessagePart" } ] } diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.cpp b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.cpp index 89107935..52c25a88 100644 --- a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.cpp +++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.cpp @@ -1,148 +1,140 @@ /* Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company 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 #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include #include using namespace MimeTreeParser; using namespace MimeTreeParser::Interface; namespace { bool partHasMimeType(KMime::Content *part, const char *mt) { const auto ct = part->contentType(false); return ct && ct->isMimeType(mt); } } MessagePart::Ptr ApplicationGnuPGWKSFormatter::process(BodyPart &part) const { const auto ct = part.content()->contentType(false); if (ct && ct->isMimeType("multipart/mixed")) { const auto subParts = part.content()->contents(); if (subParts.size() == 2 && partHasMimeType(subParts[0], "text/plain") && partHasMimeType(subParts[1], "application/vnd.gnupg.wks")) { return MimeMessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), subParts.at(1), false)); } else { return MimeMessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), subParts.at(0), false)); } } - if (ct && ct->isMimeType("application/vnd.gnupg.wks")) - return BodyPartFormatter::process(part); + if (ct && ct->isMimeType("application/vnd.gnupg.wks")) { + const auto content = part.content()->decodedContent(); + if (content.startsWith("-----BEGIN PGP MESSAGE")) { + auto decrypt = QGpgME::openpgp()->decryptJob(); + QByteArray plainText; + auto result = decrypt->exec(part.content()->decodedContent(), plainText); + if (result.error()) { + qWarning() << "Decryption failed!" << result.error().asString(); + return {}; + } + part.content()->setBody(plainText); + } + return MessagePart::Ptr(new GnuPGWKSMessagePart(&part)); + } + return {}; } -BodyPartFormatter::Result ApplicationGnuPGWKSFormatter::format(BodyPart *part, MimeTreeParser::HtmlWriter *writer) const +bool ApplicationGnuPGWKSFormatter::render(const MimeTreeParser::MessagePartPtr& msgPart, MimeTreeParser::HtmlWriter* htmlWriter, MessageViewer::RenderContext* context) const { - if (!writer) { - return Ok; - } - - if (part->content()->contentType(false) && part->content()->contentType()->isMimeType("multipart/mixed")) { - auto formatters = part->source()->bodyPartFormatterFactory()->formattersForType(QStringLiteral("multipart/mixed")); - formatters.removeAll(this); - Q_ASSERT(!formatters.isEmpty()); // there *must* be a multipart/mixed handler - - return formatters.at(0)->format(part, writer); - } - - const auto content = part->content()->decodedContent(); - if (content.startsWith("-----BEGIN PGP MESSAGE")) { - auto decrypt = QGpgME::openpgp()->decryptJob(); - QByteArray plainText; - auto result = decrypt->exec(part->content()->decodedContent(), plainText); - if (result.error()) { - qWarning() << "Decryption failed!" << result.error().asString(); - return Failed; - } - part->content()->setBody(plainText); - } - - GnuPGWKSMessagePart mp(part); + Q_UNUSED(context); + auto mp = msgPart.dynamicCast(); + if (!mp) + return false; - const QByteArray propertyName = "_GnuPGWKS" + mp.fingerprint().toLatin1(); - const bool hasError = (part->nodeHelper()->property(propertyName).toString() == QLatin1String("error")); + const QByteArray propertyName = "_GnuPGWKS" + mp->fingerprint().toLatin1(); + const bool hasError = (mp->nodeHelper()->property(propertyName).toString() == QLatin1String("error")); if (hasError) { - part->nodeHelper()->setProperty(propertyName, QVariant()); + mp->nodeHelper()->setProperty(propertyName, QVariant()); } GrantleeTheme::Engine engine; engine.localizer()->setApplicationDomain(QByteArrayLiteral("messageviewer_application_gnupgwks_plugin")); engine.addTemplateLoader(QSharedPointer::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); + 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)))); + confirmQuery.addQueryItem(QStringLiteral("fpr"), mp->fingerprint()); + block.setProperty("confirmUrl", mp->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)))); + keyQuery.addQueryItem(QStringLiteral("fpr"), mp->fingerprint()); + block.setProperty("keyUrl", mp->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->write(tpl->render(&ctx)); - return Ok; + Grantlee::OutputStream s(htmlWriter->stream()); + tpl->render(&s, &ctx); + return true; } diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.h b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.h index c67f1715..69806700 100644 --- a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.h +++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksformatter.h @@ -1,48 +1,50 @@ /* Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company 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 #include class GnuPGWKSMessagePart; class GnuPGWKSMemento; -class ApplicationGnuPGWKSFormatter : public MimeTreeParser::Interface::BodyPartFormatter +class ApplicationGnuPGWKSFormatter + : public MimeTreeParser::Interface::BodyPartFormatter + , public MessageViewer::MessagePartRendererBase { public: ApplicationGnuPGWKSFormatter() = default; MimeTreeParser::MessagePartPtr process(MimeTreeParser::Interface::BodyPart &part) const override; - - MimeTreeParser::Interface::BodyPartFormatter::Result format(MimeTreeParser::Interface::BodyPart *part, MimeTreeParser::HtmlWriter *writer) const override; + bool render(const MimeTreeParser::MessagePartPtr &msgPart, MimeTreeParser::HtmlWriter *htmlWriter, MessageViewer::RenderContext *context) const 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 index 2cd48c3b..48ca20f0 100644 --- a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.cpp +++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.cpp @@ -1,96 +1,87 @@ /* Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company 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 #include GnuPGWKSMessagePart::GnuPGWKSMessagePart(MimeTreeParser::Interface::BodyPart *part) - : mPart(part) + : MimeTreeParser::MessagePart(part->objectTreeParser(), QString()) { - parseContent(mPart->content()); + setContent(part->content()); + parseContent(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 index 130f53bc..344ab505 100644 --- a/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.h +++ b/plugins/messageviewer/bodypartformatter/gnupgwks/gnupgwksmessagepart.h @@ -1,68 +1,68 @@ /* Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company 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 + #include namespace MimeTreeParser { namespace Interface { class BodyPart; } } namespace KMime { class Content; } -class GnuPGWKSMessagePart +class GnuPGWKSMessagePart : public MimeTreeParser::MessagePart { + Q_OBJECT 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 = nullptr; QString mSender; QString mAddress; QString mFingerprint; QString mNonce; ConfirmationType mType = UnknownType; }; #endif diff --git a/plugins/messageviewer/bodypartformatter/gnupgwks/plugin.cpp b/plugins/messageviewer/bodypartformatter/gnupgwks/plugin.cpp index 1eabda96..452cef0c 100644 --- a/plugins/messageviewer/bodypartformatter/gnupgwks/plugin.cpp +++ b/plugins/messageviewer/bodypartformatter/gnupgwks/plugin.cpp @@ -1,72 +1,72 @@ /* Copyright (c) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company 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_pgp_keys, - multipart_mixed, - application_vnd_gnupg_keys + application_vnd_gnupg_keys, + multipart_mixed }; } const MimeTreeParser::Interface::BodyPartFormatter *ApplicationGnuPGWKSPlugin::bodyPartFormatter(int idx) const { switch (idx) { case multipart_mixed: case application_vnd_gnupg_keys: return new ApplicationGnuPGWKSFormatter(); case application_pgp_keys: return new ApplicationPGPKeyFormatter(); default: return nullptr; } } MessageViewer::MessagePartRendererBase* ApplicationGnuPGWKSPlugin::renderer(int idx) { switch (idx) { case multipart_mixed: case application_vnd_gnupg_keys: - return nullptr; // TODO + return new ApplicationGnuPGWKSFormatter(); case application_pgp_keys: return new ApplicationPGPKeyFormatter(); default: return nullptr; } } const MessageViewer::Interface::BodyPartURLHandler *ApplicationGnuPGWKSPlugin::urlHandler(int idx) const { switch (idx) { case multipart_mixed: case application_vnd_gnupg_keys: return new ApplicationGnuPGWKSUrlHandler(); case application_pgp_keys: return new ApplicationPgpKeyUrlHandler(); default: return nullptr; } }