From 595930d82b38a567dc6f0d699276b715b09fa109 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Wed, 25 Apr 2018 09:21:56 +0200 Subject: Fixed the case where we have plaintext inside the encrypted part. This is triggered when we have encrypted+signed inline parts. --- .../src/domain/mime/mimetreeparser/messagepart.cpp | 45 +++++++++++++--------- .../src/domain/mime/mimetreeparser/messagepart.h | 1 + .../mimetreeparser/tests/mimetreeparsertest.cpp | 15 ++++++++ 3 files changed, 42 insertions(+), 19 deletions(-) (limited to 'framework/src/domain/mime/mimetreeparser') diff --git a/framework/src/domain/mime/mimetreeparser/messagepart.cpp b/framework/src/domain/mime/mimetreeparser/messagepart.cpp index 17719ff8..9b677d86 100644 --- a/framework/src/domain/mime/mimetreeparser/messagepart.cpp +++ b/framework/src/domain/mime/mimetreeparser/messagepart.cpp @@ -261,6 +261,28 @@ void MessagePart::parseInternal(KMime::Content *node, bool onlyOneMimePart) } } +void MessagePart::parseInternal(const QByteArray &data) +{ + auto tempNode = new KMime::Content(); + + const auto lfData = KMime::CRLFtoLF(data); + //We have to deal with both bodies and full parts. In inline encrypted/signed parts we can have nested parts, + //or just plain-text, and both ends up here. setContent defaults to setting only the header, so we have to avoid this. + if (lfData.contains("\n\n")) { + tempNode->setContent(lfData); + } else { + tempNode->setBody(lfData); + } + tempNode->parse(); + bindLifetime(tempNode); + + if (!tempNode->head().isEmpty()) { + tempNode->contentDescription()->from7BitString("temporary node"); + } + + parseInternal(tempNode, false); +} + QString MessagePart::renderInternalText() const { QString text; @@ -392,7 +414,8 @@ void TextMessagePart::parseContent() const QString &fromAddress = mOtp->nodeHelper()->fromAsString(mNode); mSignatureState = KMMsgNotSigned; mEncryptionState = KMMsgNotEncrypted; - const auto blocks = prepareMessageForDecryption(mNode->decodedContent()); + auto body = mNode->decodedContent(); + const auto blocks = prepareMessageForDecryption(body); const auto cryptProto = GpgME::OpenPGP; @@ -880,15 +903,8 @@ void SignedMessagePart::setVerificationResult(const GpgME::VerificationResult &r mOtp->mNodeHelper->setPartMetaData(mNode, mMetaData); } if (!plainText.isEmpty() && parseText) { - auto tempNode = new KMime::Content(); - tempNode->setBody(plainText); - tempNode->parse(); - bindLifetime(tempNode); + parseInternal(plainText); - if (!tempNode->head().isEmpty()) { - tempNode->contentDescription()->from7BitString("signed data"); - } - parseInternal(tempNode, false); } } } @@ -1072,16 +1088,7 @@ void EncryptedMessagePart::startDecryption(KMime::Content *data) if (mNode && !mMetaData.isSigned) { mOtp->mNodeHelper->setPartMetaData(mNode, mMetaData); - auto tempNode = new KMime::Content(); - tempNode->setContent(KMime::CRLFtoLF(mDecryptedData.constData())); - tempNode->parse(); - bindLifetime(tempNode); - - if (!tempNode->head().isEmpty()) { - tempNode->contentDescription()->from7BitString("encrypted data"); - } - - parseInternal(tempNode, false); + parseInternal(mDecryptedData); } } diff --git a/framework/src/domain/mime/mimetreeparser/messagepart.h b/framework/src/domain/mime/mimetreeparser/messagepart.h index c039637a..8cd74717 100644 --- a/framework/src/domain/mime/mimetreeparser/messagepart.h +++ b/framework/src/domain/mime/mimetreeparser/messagepart.h @@ -125,6 +125,7 @@ public: protected: void parseInternal(KMime::Content *node, bool onlyOneMimePart); + void parseInternal(const QByteArray &data); QString renderInternalText() const; QString mText; diff --git a/framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp b/framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp index 90a07a7c..38857d58 100644 --- a/framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp +++ b/framework/src/domain/mime/mimetreeparser/tests/mimetreeparsertest.cpp @@ -386,6 +386,21 @@ private slots: QCOMPARE(part->encryptionState(), MimeTreeParser::KMMsgFullyEncrypted); QCOMPARE(otp.plainTextContent(), QString::fromUtf8("sdflskjsdf\n\n-- \nThis is a HTML signature.\n")); } + + void testOpenpgpMultipartEmbeddedSigned() + { + MimeTreeParser::ObjectTreeParser otp; + otp.parseObjectTree(readMailFromFile("openpgp-multipart-embedded-signed.mbox")); + otp.decryptParts(); + auto partList = otp.collectContentParts(); + QCOMPARE(partList.size(), 1); + auto part = partList[0].dynamicCast(); + QCOMPARE(part->encryptions().size(), 1); + QCOMPARE(part->signatures().size(), 1); + QCOMPARE(part->encryptionState(), MimeTreeParser::KMMsgFullyEncrypted); + QCOMPARE(part->signatureState(), MimeTreeParser::KMMsgFullySigned); + QCOMPARE(otp.plainTextContent(), QString::fromUtf8("test\n\n-- \nThis is a HTML signature.\n")); + } }; QTEST_GUILESS_MAIN(InterfaceTest) -- cgit v1.2.3