diff --git a/messageviewer/autotests/data/openpgp-encrypted-noData.mbox b/messageviewer/autotests/data/openpgp-encrypted-noData.mbox new file mode 100644 --- /dev/null +++ b/messageviewer/autotests/data/openpgp-encrypted-noData.mbox @@ -0,0 +1,17 @@ +From test@kolab.org Wed, 08 Sep 2010 17:02:52 +0200 +From: OpenPGP Test +To: test@kolab.org +Subject: OpenPGP encrypted +Date: Wed, 08 Sep 2010 17:02:52 +0200 +User-Agent: KMail/4.6 pre (Linux/2.6.34-rc2-2-default; KDE/4.5.60; x86_64; ; ) +MIME-Version: 1.0 +Content-Type: multipart/encrypted; boundary="nextPart1357031.ppLHckZtsp"; protocol="application/pgp-encrypted" +Content-Transfer-Encoding: 7Bit + +--nextPart1357031.ppLHckZtsp +Content-Type: application/pgp-encrypted +Content-Disposition: attachment + +Version: 1 + +--nextPart1357031.ppLHckZtsp-- diff --git a/messageviewer/autotests/data/openpgp-encrypted-noData.mbox.html b/messageviewer/autotests/data/openpgp-encrypted-noData.mbox.html new file mode 100644 --- /dev/null +++ b/messageviewer/autotests/data/openpgp-encrypted-noData.mbox.html @@ -0,0 +1,394 @@ + + + + + + <style> +div.header { + margin-bottom: 10pt ! important; +} + +table.textAtm { + margin-top: 10pt ! important; + margin-bottom: 10pt ! important; +} + +tr.textAtmH, +tr.textAtmB, +tr.rfc822B { + font-weight: normal ! important; +} + +tr.signInProgressH, +tr.rfc822H, +tr.encrH, +tr.signOkKeyOkH, +tr.signOkKeyBadH, +tr.signWarnH, +tr.signErrH { + font-weight: bold ! important; +} + +tr.textAtmH td, +tr.textAtmB td { + padding: 3px ! important; +} + +table.rfc822 { + width: 100% ! important; + border: solid 1px black ! important; + margin-top: 10pt ! important; + margin-bottom: 10pt ! important; +} + +table.textAtm, +table.encr, +table.signWarn, +table.signErr, +table.signOkKeyBad, +table.signOkKeyOk, +table.signInProgress, +div.fancy.header table { + width: 100% ! important; + border-width: 0px ! important; + line-height: normal; +} + +div.htmlWarn { + margin: 0px 5% ! important; + padding: 10px ! important; + text-align: left ! important; + line-height: normal; +} + +div.fancy.header > div { + font-weight: bold ! important; + padding: 4px ! important; + line-height: normal; +} + +div.fancy.header table { + padding: 2px ! important; + text-align: left ! important; + border-collapse: separate ! important; +} + +div.fancy.header table th { + font-family: "Sans Serif" ! important; + font-size: 0px ! important; + + padding: 0px ! important; + white-space: nowrap ! important; + border-spacing: 0px ! important; + text-align: left ! important; + vertical-align: top ! important; + background-color: #d6d2d0 ! important; + color: #221f1e ! important; + border: 1px ! important; +} + +div.fancy.header table td { + font-family: "Sans Serif" ! important; + font-size: 0px ! important; + + padding: 0px ! important; + border-spacing: 0px ! important; + text-align: left ! important; + vertical-align: top ! important; + width: 100% ! important; + background-color: #d6d2d0 ! important; + color: #221f1e ! important; + border: 1px ! important; +} + +div.fancy.header table a:hover { + background-color: transparent ! important; +} + +span.pimsmileytext { + position: absolute; + top: 0px; + left: 0px; + visibility: hidden; +} + +img.pimsmileyimg { +} + +div.quotelevelmark { + position: absolute; + margin-left:-10px; +} + +@media screen { + +body { + font-family: "Sans Serif" ! important; + font-size: 0px ! important; + color: #1f1c1b ! important; + background-color: #ffffff ! important; +} + +a { + color: #0057ae ! important; + text-decoration: none ! important; +} + +a.white { + color: white ! important; +} + +a.black { + color: black ! important; +} + +table.textAtm { background-color: #1f1c1b ! important; } + +tr.textAtmH { + background-color: #ffffff ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.textAtmB { + background-color: #ffffff ! important; +} + +table.signInProgress, +table.rfc822 { + background-color: #ffffff ! important; +} + +tr.signInProgressH, +tr.rfc822H { + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +table.encr { + background-color: #0069cc ! important; +} + +tr.encrH { + background-color: #0080ff ! important; + color: #ffffff ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.encrB { background-color: #e0f0ff ! important; } + +table.signOkKeyOk { + background-color: #33cc33 ! important; +} + +tr.signOkKeyOkH { + background-color: #40ff40 ! important; + color: #27ae60 ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.signOkKeyOkB { background-color: #e8ffe8 ! important; } + +table.signOkKeyBad { + background-color: #cccc33 ! important; +} + +tr.signOkKeyBadH { + background-color: #ffff40 ! important; + color: #f67400 ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.signOkKeyBadB { background-color: #ffffe8 ! important; } + +table.signWarn { + background-color: #cccc33 ! important; +} + +tr.signWarnH { + background-color: #ffff40 ! important; + color: #f67400 ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.signWarnB { background-color: #ffffe8 ! important; } + +table.signErr { + background-color: #cc0000 ! important; +} + +tr.signErrH { + background-color: #ff0000 ! important; + color: #da4453 ! important; + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +tr.signErrB { background-color: #ffe0e0 ! important; } + +div.htmlWarn { + border: 2px solid #ff4040 ! important; + line-height: normal; +} + +div.header { + font-family: "Sans Serif" ! important; + font-size: 0px ! important; +} + +div.fancy.header > div { + background-color: #43ace8 ! important; + color: #ffffff ! important; + border: solid #221f1e 1px ! important; + line-height: normal; +} + +div.fancy.header > div a[href] { color: #ffffff ! important; } + +div.fancy.header > div a[href]:hover { text-decoration: underline ! important; } + +div.fancy.header > div.spamheader { + background-color: #cdcdcd ! important; + border-top: 0px ! important; + padding: 3px ! important; + color: black ! important; + font-weight: bold ! important; + font-size: smaller ! important; +} + +div.fancy.header > table.outer { + background-color: #d6d2d0 ! important; + color: #221f1e ! important; + border-bottom: solid #221f1e 1px ! important; + border-left: solid #221f1e 1px ! important; + border-right: solid #221f1e 1px ! important; +} + +div.senderpic{ + padding: 0px ! important; + font-size:0.8em ! important; + border:1px solid #b3aba7 ! important; + background-color:#d6d2d0 ! important; +} + +div.senderstatus{ + text-align:center ! important; +} + +div.quotelevel1 { + color: #008000 ! important; + font-style: italic ! important; +} + +div.quotelevel2 { + color: #007000 ! important; + font-style: italic ! important; +} + +div.quotelevel3 { + color: #006000 ! important; + font-style: italic ! important; +} + +div.deepquotelevel1 { + color: #008000 ! important; + font-style: italic ! important; +} + +div.deepquotelevel2 { + color: #007000 ! important; + font-style: italic ! important; +} + +div.deepquotelevel3 { + color: #006000 ! important; + font-style: italic ! important; +} + +} +@media print { + +body { + font-family: "Sans Serif" ! important; + font-size: 9pt ! important; + color: #000000 ! important; + background-color: #ffffff ! important +} + +tr.textAtmH, +tr.signInProgressH, +tr.rfc822H, +tr.encrH, +tr.signOkKeyOkH, +tr.signOkKeyBadH, +tr.signWarnH, +tr.signErrH, +div.header { + font-family: "Sans Serif" ! important; + font-size: 9pt ! important; +} + +div.fancy.header > div { + background-color: #d6d2d0 ! important; + color: #221f1e ! important; + padding: 4px ! important; + border: solid #221f1e 1px ! important; + line-height: normal; +} + +div.fancy.header > div a[href] { color: #221f1e ! important; } + +div.fancy.header > table.outer{ + background-color: #d6d2d0 ! important; + color: #221f1e ! important; + border-bottom: solid #221f1e 1px ! important; + border-left: solid #221f1e 1px ! important; + border-right: solid #221f1e 1px ! important; +} + +div.spamheader { + display:none ! important; +} + +div.htmlWarn { + border: 2px solid #ffffff ! important; + line-height: normal; +} + +div.senderpic{ + font-size:0.8em ! important; + border:1px solid black ! important; + background-color:#d6d2d0 ! important; +} + +div.senderstatus{ + text-align:center ! important; +} + +div.noprint { + display:none ! important; +} + + +</style> + </head> + <body> + <div style="position: relative; word-wrap: break-word"> + <a name="att"/> + <div id="attachmentDiv"> + <a name="att1"/> + <div id="attachmentDiv1"> + <div> + <a href="attachment:1?place=body"><img src="file:" border="0" style="max-width: 100%" alt=""/>Unnamed</a> + </div> + <div/> + <br/> + </div> + </div> + </div> + </body> +</html> diff --git a/messageviewer/src/viewer/bodypartformatter.cpp b/messageviewer/src/viewer/bodypartformatter.cpp --- a/messageviewer/src/viewer/bodypartformatter.cpp +++ b/messageviewer/src/viewer/bodypartformatter.cpp @@ -181,6 +181,45 @@ return Failed; } +class MultiPartEncryptedBodyPartFormatter + : public MessageViewer::Interface::BodyPartFormatter +{ +public: + MessagePart::Ptr process(const Interface::BodyPart &part) const; + MessageViewer::Interface::BodyPartFormatter::Result format(Interface::BodyPart *, HtmlWriter *) const Q_DECL_OVERRIDE; + using MessageViewer::Interface::BodyPartFormatter::format; + static const MessageViewer::Interface::BodyPartFormatter *create(); +private: + static const MultiPartEncryptedBodyPartFormatter *self; +}; + +const MultiPartEncryptedBodyPartFormatter *MultiPartEncryptedBodyPartFormatter::self; + +const MessageViewer::Interface::BodyPartFormatter *MultiPartEncryptedBodyPartFormatter::create() +{ + if (!self) { + self = new MultiPartEncryptedBodyPartFormatter(); + } + return self; +} + +MessagePart::Ptr MultiPartEncryptedBodyPartFormatter::process(const Interface::BodyPart &part) const +{ + return part.objectTreeParser()->processMultiPartEncryptedSubtype(part.content(), *part.processResult()); +} + +MessageViewer::Interface::BodyPartFormatter::Result MultiPartEncryptedBodyPartFormatter::format(Interface::BodyPart *part, HtmlWriter *writer) const +{ + Q_UNUSED(writer) + MessagePart::Ptr mp = process(*part); + if (!mp.isNull()) { + mp->html(false); + return Ok; + } + + return Failed; +} + #define CREATE_BODY_PART_FORMATTER(subtype) \ class subtype##BodyPartFormatter \ : public MessageViewer::Interface::BodyPartFormatter \ @@ -213,15 +252,12 @@ CREATE_BODY_PART_FORMATTER(TextPlain) CREATE_BODY_PART_FORMATTER(TextHtml) -//CREATE_BODY_PART_FORMATTER(TextEnriched) CREATE_BODY_PART_FORMATTER(ApplicationPkcs7Mime) CREATE_BODY_PART_FORMATTER(ApplicationChiasmusText) -//CREATE_BODY_PART_FORMATTER(ApplicationPgp) CREATE_BODY_PART_FORMATTER(MultiPartMixed) CREATE_BODY_PART_FORMATTER(MultiPartAlternative) -CREATE_BODY_PART_FORMATTER(MultiPartEncrypted) typedef TextPlainBodyPartFormatter ApplicationPgpBodyPartFormatter; diff --git a/messageviewer/src/viewer/objecttreeparser.h b/messageviewer/src/viewer/objecttreeparser.h --- a/messageviewer/src/viewer/objecttreeparser.h +++ b/messageviewer/src/viewer/objecttreeparser.h @@ -414,7 +414,7 @@ bool processMultiPartDigestSubtype(KMime::Content *node, ProcessResult &result); bool processMultiPartParallelSubtype(KMime::Content *node, ProcessResult &result); MessagePart::Ptr processMultiPartSignedSubtype(KMime::Content *node, ProcessResult &result); - bool processMultiPartEncryptedSubtype(KMime::Content *node, ProcessResult &result); + MessagePart::Ptr processMultiPartEncryptedSubtype(KMime::Content *node, ProcessResult &result); bool processApplicationPkcs7MimeSubtype(KMime::Content *node, ProcessResult &result); bool processApplicationChiasmusTextSubtype(KMime::Content *node, ProcessResult &result); diff --git a/messageviewer/src/viewer/objecttreeparser.cpp b/messageviewer/src/viewer/objecttreeparser.cpp --- a/messageviewer/src/viewer/objecttreeparser.cpp +++ b/messageviewer/src/viewer/objecttreeparser.cpp @@ -1218,11 +1218,12 @@ return mp; } -bool ObjectTreeParser::processMultiPartEncryptedSubtype(KMime::Content *node, ProcessResult &result) +MessagePart::Ptr ObjectTreeParser::processMultiPartEncryptedSubtype(KMime::Content* node, ProcessResult& result) { KMime::Content *child = MessageCore::NodeHelper::firstChild(node); if (!child) { - return false; + Q_ASSERT(false); + return MessagePart::Ptr(); } const Kleo::CryptoBackend::Protocol *useThisCryptProto = 0; @@ -1245,36 +1246,31 @@ */ if (!data) { - standardChildHandling(child); - return true; + return MessagePart::Ptr(new MimeMessagePart(this, child, false)); } CryptoProtocolSaver cpws(this, useThisCryptProto); KMime::Content *dataChild = MessageCore::NodeHelper::firstChild(data); if (dataChild) { - standardChildHandling(dataChild); - return MessagePart::Ptr(); + Q_ASSERT(false); + return MessagePart::Ptr(new MimeMessagePart(this, dataChild, false)); } mNodeHelper->setEncryptionState(node, KMMsgFullyEncrypted); - - CryptoMessagePart mp(this, + CryptoMessagePart::Ptr mp(new CryptoMessagePart(this, data->decodedText(), Kleo::CryptoBackendFactory::instance()->openpgp(), - NodeHelper::fromAsString(data), node); + NodeHelper::fromAsString(data), node)); - PartMetaData *messagePart(mp.partMetaData()); + PartMetaData *messagePart(mp->partMetaData()); if (!mSource->decryptMessage()) { mNodeHelper->setNodeProcessed(data, false); // Set the data node to done to prevent it from being processed } else if (KMime::Content *newNode = mNodeHelper->decryptedNodeForContent(data)) { // if we already have a decrypted node for this encrypted node, don't do the decryption again - ObjectTreeParser otp(this); - otp.parseObjectTreeInternal(newNode); - copyContentFrom(&otp); - return true; + return MessagePart::Ptr(new MimeMessagePart(this, newNode, mShowOnlyOneMimePart)); } else { - mp.startDecryption(data); + mp->startDecryption(data); qCDebug(MESSAGEVIEWER_LOG) << "decrypted, signed?:" << messagePart->isSigned; @@ -1297,8 +1293,7 @@ } } } - mp.html(false); - return true; + return mp; } bool ObjectTreeParser::processApplicationPkcs7MimeSubtype(KMime::Content *node, ProcessResult &result)