7 #include "messagepart.h"
8 #include "cryptohelper.h"
9 #include "job/qgpgmejobexecutor.h"
10 #include "memento/cryptobodypartmemento.h"
11 #include "memento/decryptverifybodypartmemento.h"
12 #include "memento/verifydetachedbodypartmemento.h"
13 #include "memento/verifyopaquebodypartmemento.h"
14 #include "mimetreeparser_debug.h"
15 #include "objecttreeparser.h"
17 #include "bodyformatter/utils.h"
19 #include <KMime/Content>
20 #include <Libkleo/Compliance>
21 #include <Libkleo/KeyCache>
24 #include <QGpgME/ImportJob>
25 #include <QGpgME/Protocol>
26 #include <QGpgME/VerifyDetachedJob>
27 #include <QGpgME/VerifyOpaqueJob>
29 #include <gpgme++/key.h>
30 #include <gpgme++/keylistresult.h>
33 #include <KLocalizedString>
38 using namespace MimeTreeParser;
41 namespace MimeTreeParser
43 class MessagePartPrivate
51 PartMetaData mMetaData;
53 bool mIsImage =
false;
54 bool mNeverDisplayInline =
false;
60 , d(new MessagePartPrivate)
65 MessagePart::~MessagePart() =
default;
69 return d->mParentPart;
72 void MessagePart::setParentPart(
MessagePart *parentPart)
74 d->mParentPart = parentPart;
77 QString MessagePart::htmlContent()
const
82 QString MessagePart::plaintextContent()
const
87 PartMetaData *MessagePart::partMetaData()
const
94 return nodeHelper()->bodyPartMemento(content(),
"__plugin__");
99 nodeHelper()->setBodyPartMemento(content(),
"__plugin__", memento);
114 return d->mAttachmentNode;
119 d->mAttachmentNode = node;
122 bool MessagePart::isAttachment()
const
124 return d->mAttachmentNode;
127 QString MessagePart::attachmentIndex()
const
129 return attachmentContent()->index().toString();
134 return mOtp->nodeHelper()->asHREF(content(), QStringLiteral(
"body"));
140 static int serial = 0;
144 return QStringLiteral(
"x-kmail:/bodypart/%1/%2/%3")
149 void MessagePart::setIsRoot(
bool root)
154 bool MessagePart::isRoot()
const
159 QString MessagePart::text()
const
164 void MessagePart::setText(
const QString &text)
169 bool MessagePart::isHtml()
const
177 return mOtp->mSource;
183 return mOtp->nodeHelper();
186 void MessagePart::parseInternal(
KMime::Content *node,
bool onlyOneMimePart)
188 auto subMessagePart = mOtp->parseObjectTreeInternal(node, onlyOneMimePart);
189 d->mRoot = subMessagePart->isRoot();
191 for (
const auto &part : subParts) {
196 QString MessagePart::renderInternalText()
const
199 const auto subPartsLst = subParts();
200 for (
const auto &mp : subPartsLst) {
206 void MessagePart::fix()
const
208 const auto subPartsLst = subParts();
209 for (
const auto &mp : subPartsLst) {
219 messagePart->setParentPart(
this);
220 d->mBlocks.append(messagePart);
228 bool MessagePart::hasSubParts()
const
233 void MessagePart::clearSubParts()
238 bool MessagePart::neverDisplayInline()
const
240 return d->mNeverDisplayInline;
243 void MessagePart::setNeverDisplayInline(
bool displayInline)
245 d->mNeverDisplayInline = displayInline;
248 bool MessagePart::isImage()
const
253 void MessagePart::setIsImage(
bool image)
258 bool MessagePart::hasHeader(
const char *headerType)
const
282 MessagePartList::~MessagePartList() =
default;
284 QString MessagePartList::text()
const
286 return renderInternalText();
289 QString MessagePartList::plaintextContent()
const
294 QString MessagePartList::htmlContent()
const
303 , mDecryptMessage(decryptMessage)
306 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
315 TextMessagePart::~TextMessagePart() =
default;
317 bool TextMessagePart::decryptMessage()
const
319 return mDecryptMessage;
322 void TextMessagePart::parseContent()
324 const auto aCodec = mOtp->codecFor(
content());
325 const QString &fromAddress = mOtp->nodeHelper()->fromAsString(
content());
326 mSignatureState = KMMsgNotSigned;
327 mEncryptionState = KMMsgNotEncrypted;
328 const auto blocks = prepareMessageForDecryption(
content()->decodedContent());
330 const auto cryptProto = QGpgME::openpgp();
332 if (!blocks.isEmpty()) {
340 bool fullySignedOrEncrypted =
true;
341 bool fullySignedOrEncryptedTmp =
true;
344 for (
const auto &block : blocks) {
346 if (!fullySignedOrEncryptedTmp) {
347 fullySignedOrEncrypted =
false;
350 if (block.type() == NoPgpBlock && !block.text().trimmed().isEmpty()) {
351 fullySignedOrEncryptedTmp =
false;
353 }
else if (block.type() == PgpMessageBlock) {
355 mp->setDecryptMessage(decryptMessage());
356 mp->setIsEncrypted(
true);
357 mp->setMementoName(mp->mementoName() +
"-" + nodeHelper()->asHREF(
content(),
QString::number(blockIndex)).toLocal8Bit());
359 if (!decryptMessage()) {
362 mp->startDecryption(block.text(), aCodec);
363 if (mp->partMetaData()->inProgress) {
366 }
else if (block.type() == ClearsignedBlock) {
368 mp->setMementoName(mp->mementoName() +
"-" + nodeHelper()->asHREF(
content(),
QString::number(blockIndex)).toLocal8Bit());
370 mp->startVerification(block.text(), aCodec);
376 const PartMetaData *messagePart(mp->partMetaData());
378 if (!messagePart->isEncrypted && !messagePart->isSigned && !block.text().trimmed().isEmpty()) {
379 mp->setText(aCodec->toUnicode(block.text()));
382 if (messagePart->isEncrypted) {
383 mEncryptionState = KMMsgPartiallyEncrypted;
386 if (messagePart->isSigned) {
387 mSignatureState = KMMsgPartiallySigned;
392 if (fullySignedOrEncrypted) {
393 if (mSignatureState == KMMsgPartiallySigned) {
394 mSignatureState = KMMsgFullySigned;
396 if (mEncryptionState == KMMsgPartiallyEncrypted) {
397 mEncryptionState = KMMsgFullyEncrypted;
403 KMMsgEncryptionState TextMessagePart::encryptionState()
const
405 return mEncryptionState;
408 KMMsgSignatureState TextMessagePart::signatureState()
const
410 return mSignatureState;
413 bool TextMessagePart::showLink()
const
418 bool TextMessagePart::isFirstTextPart()
const
423 bool TextMessagePart::hasLabel()
const
428 QString TextMessagePart::label()
const
433 label =
i18nc(
"display name for an unnamed attachment",
"Unnamed");
438 QString TextMessagePart::comment()
const
441 if (comment ==
label()) {
459 AttachmentMessagePart::~AttachmentMessagePart() =
default;
468 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
474 mBodyHTML = mOtp->codecFor(node)->
toUnicode(partBody);
478 HtmlMessagePart::~HtmlMessagePart() =
default;
480 void HtmlMessagePart::fix()
const
482 mOtp->mHtmlContent += mBodyHTML;
483 mOtp->mHtmlContentCharset = mCharset;
486 QString HtmlMessagePart::text()
const
491 QString MimeTreeParser::HtmlMessagePart::plaintextContent()
const
496 bool HtmlMessagePart::isHtml()
const
501 QString HtmlMessagePart::bodyHtml()
const
510 , mOnlyOneMimePart(onlyOneMimePart)
513 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
518 parseInternal(node, mOnlyOneMimePart);
521 MimeMessagePart::~MimeMessagePart() =
default;
523 QString MimeMessagePart::text()
const
525 return renderInternalText();
528 QString MimeMessagePart::plaintextContent()
const
533 QString MimeMessagePart::htmlContent()
const
542 , mPreferredMode(preferredMode)
545 KMime::Content *dataIcal = findTypeInDirectChilds(node,
"text/calendar");
546 KMime::Content *dataHtml = findTypeInDirectChilds(node,
"text/html");
547 KMime::Content *dataText = findTypeInDirectChilds(node,
"text/plain");
554 dataHtml = findTypeInDirectChilds(node,
"multipart/related");
562 dataHtml = findTypeInDirectChilds(node,
"multipart/mixed");
578 if (mChildNodes.isEmpty()) {
579 qCWarning(MIMETREEPARSER_LOG) <<
"no valid nodes";
584 while (i.hasNext()) {
590 AlternativeMessagePart::~AlternativeMessagePart() =
default;
594 return mPreferredMode;
597 void AlternativeMessagePart::setPreferredMode(
Util::HtmlMode preferredMode)
599 mPreferredMode = preferredMode;
604 return mChildParts.keys();
607 QString AlternativeMessagePart::text()
const
615 void AlternativeMessagePart::fix()
const
621 const auto mode = preferredMode();
623 mChildParts[mode]->fix();
632 bool AlternativeMessagePart::isHtml()
const
637 QString AlternativeMessagePart::plaintextContent()
const
642 QString AlternativeMessagePart::htmlContent()
const
647 return plaintextContent();
655 , mAutoImport(autoImport)
656 , mCryptoProto(cryptoProto)
659 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
670 QGpgME::ImportJob *
import = mCryptoProto->importJob();
672 mImportResult = executor.exec(
import, certData);
675 CertMessagePart::~CertMessagePart() =
default;
677 QString CertMessagePart::text()
const
682 const GpgME::ImportResult &CertMessagePart::importResult()
const
684 return mImportResult;
690 const QGpgME::Protocol *cryptoProto,
694 , mCryptoProto(cryptoProto)
695 , mFromAddress(fromAddress)
696 , mMementoName(
"verification")
699 partMetaData()->technicalProblem = (mCryptoProto ==
nullptr);
700 partMetaData()->isSigned =
true;
701 partMetaData()->isGoodSignature =
false;
702 partMetaData()->keyTrust = GpgME::Signature::Unknown;
703 partMetaData()->status =
i18n(
"Wrong Crypto Plug-In.");
704 partMetaData()->status_code = GPGME_SIG_STAT_NONE;
707 SignedMessagePart::~SignedMessagePart() =
default;
709 void SignedMessagePart::setIsSigned(
bool isSigned)
711 partMetaData()->isSigned = isSigned;
714 bool SignedMessagePart::isSigned()
const
716 return partMetaData()->isSigned;
719 QByteArray SignedMessagePart::mementoName()
const
724 void SignedMessagePart::setMementoName(
const QByteArray &name)
733 partMetaData()->isSigned =
false;
734 partMetaData()->technicalProblem = (mCryptoProto ==
nullptr);
735 partMetaData()->keyTrust = GpgME::Signature::Unknown;
736 partMetaData()->status =
i18n(
"Wrong Crypto Plug-In.");
737 partMetaData()->status_code = GPGME_SIG_STAT_NONE;
739 const QByteArray _mementoName = mementoName();
741 auto m =
dynamic_cast<CryptoBodyPartMemento *
>(nodeHelper->bodyPartMemento(
content(), _mementoName));
742 Q_ASSERT(!m || mCryptoProto);
744 if (!m && mCryptoProto) {
746 QGpgME::VerifyDetachedJob *job = mCryptoProto->verifyDetachedJob();
748 m =
new VerifyDetachedBodyPartMemento(job, mCryptoProto->keyListJob(), signature, data);
751 QGpgME::VerifyOpaqueJob *job = mCryptoProto->verifyOpaqueJob();
753 m =
new VerifyOpaqueBodyPartMemento(job, mCryptoProto->keyListJob(), data);
757 if (mOtp->allowAsync()) {
758 QObject::connect(m, &CryptoBodyPartMemento::update, nodeHelper, &NodeHelper::update);
760 partMetaData()->inProgress =
true;
761 mOtp->mHasPendingAsyncJobs =
true;
766 nodeHelper->setBodyPartMemento(
content(), _mementoName, m);
768 }
else if (m && m->isRunning()) {
769 partMetaData()->inProgress =
true;
770 mOtp->mHasPendingAsyncJobs =
true;
772 partMetaData()->inProgress =
false;
773 mOtp->mHasPendingAsyncJobs =
false;
776 if (m && !partMetaData()->inProgress) {
778 mVerifiedText = data;
780 setVerificationResult(m, textNode);
783 if (!m && !partMetaData()->inProgress) {
788 cryptPlugLibName = mCryptoProto->name();
789 cryptPlugDisplayName = mCryptoProto->displayName();
793 if (cryptPlugDisplayName.
isEmpty()) {
794 errorMsg =
i18n(
"No appropriate crypto plug-in was found.");
796 errorMsg =
i18nc(
"%1 is either 'OpenPGP' or 'S/MIME'",
"No %1 plug-in was found.", cryptPlugDisplayName);
799 errorMsg =
i18n(
"Crypto plug-in \"%1\" cannot verify signatures.", cryptPlugLibName);
801 partMetaData()->errorText =
i18n(
802 "The message is signed, but the "
803 "validity of the signature cannot be "
809 return partMetaData()->isSigned;
812 static int signatureToStatus(
const GpgME::Signature &sig)
814 switch (sig.status().code()) {
815 case GPG_ERR_NO_ERROR:
816 return GPGME_SIG_STAT_GOOD;
817 case GPG_ERR_BAD_SIGNATURE:
818 return GPGME_SIG_STAT_BAD;
819 case GPG_ERR_NO_PUBKEY:
820 return GPGME_SIG_STAT_NOKEY;
821 case GPG_ERR_NO_DATA:
822 return GPGME_SIG_STAT_NOSIG;
823 case GPG_ERR_SIG_EXPIRED:
824 return GPGME_SIG_STAT_GOOD_EXP;
825 case GPG_ERR_KEY_EXPIRED:
826 return GPGME_SIG_STAT_GOOD_EXPKEY;
828 return GPGME_SIG_STAT_ERROR;
832 QString prettifyDN(
const char *uid)
834 return QGpgME::DN(uid).prettyDN();
837 void SignedMessagePart::sigStatusToMetaData()
840 if (partMetaData()->isSigned) {
841 GpgME::Signature signature = mSignatures.front();
842 partMetaData()->status_code = signatureToStatus(signature);
843 partMetaData()->isGoodSignature = partMetaData()->status_code & GPGME_SIG_STAT_GOOD;
845 partMetaData()->sigSummary = signature.summary();
847 if (partMetaData()->isGoodSignature && !key.keyID()) {
850 key = Kleo::KeyCache::instance()->findByFingerprint(signature.fingerprint());
852 qCDebug(MIMETREEPARSER_LOG) <<
"Found no Key for Fingerprint" << signature.fingerprint();
857 partMetaData()->keyId = key.keyID();
859 if (partMetaData()->keyId.isEmpty()) {
860 partMetaData()->keyId = signature.fingerprint();
862 partMetaData()->keyTrust = signature.validity();
863 if (key.numUserIDs() > 0 && key.userID(0).id()) {
864 partMetaData()->signer = prettifyDN(key.userID(0).id());
866 for (
const auto &uid : key.userIDs()) {
872 partMetaData()->signerMailAddresses.append(email);
877 if (signature.creationTime()) {
878 partMetaData()->creationTime.setSecsSinceEpoch(signature.creationTime());
880 partMetaData()->creationTime =
QDateTime();
882 if (partMetaData()->signer.isEmpty()) {
883 if (key.numUserIDs() > 0 && key.userID(0).name()) {
884 partMetaData()->signer = prettifyDN(key.userID(0).name());
886 if (!partMetaData()->signerMailAddresses.empty()) {
887 if (partMetaData()->signer.isEmpty()) {
888 partMetaData()->signer = partMetaData()->signerMailAddresses.front();
894 if (Kleo::DeVSCompliance::isCompliant()) {
895 partMetaData()->isCompliant = signature.isDeVs();
896 partMetaData()->compliance = Kleo::DeVSCompliance::name(signature.isDeVs());
898 partMetaData()->isCompliant =
true;
905 startVerificationDetached(text,
nullptr,
QByteArray());
907 if (!
content() && partMetaData()->isSigned) {
908 setText(aCodec->
toUnicode(mVerifiedText));
914 partMetaData()->isEncrypted =
false;
915 partMetaData()->isDecryptable =
false;
918 parseInternal(textNode,
false);
921 if (!okVerify(text, signature, textNode)) {
922 partMetaData()->creationTime =
QDateTime();
926 void SignedMessagePart::setVerificationResult(
const CryptoBodyPartMemento *m,
KMime::Content *textNode)
929 const auto vm =
dynamic_cast<const VerifyDetachedBodyPartMemento *
>(m);
931 mSignatures = vm->verifyResult().signatures();
935 const auto vm =
dynamic_cast<const VerifyOpaqueBodyPartMemento *
>(m);
937 mVerifiedText = vm->plainText();
938 mSignatures = vm->verifyResult().signatures();
942 const auto vm =
dynamic_cast<const DecryptVerifyBodyPartMemento *
>(m);
944 mVerifiedText = vm->plainText();
945 mSignatures = vm->verifyResult().signatures();
948 partMetaData()->auditLogError = m->auditLogError();
949 partMetaData()->auditLog = m->auditLogAsHtml();
950 partMetaData()->isSigned = !mSignatures.empty();
952 if (partMetaData()->isSigned) {
953 sigStatusToMetaData();
955 mOtp->nodeHelper()->setSignatureState(
content(), KMMsgFullySigned);
957 mOtp->nodeHelper()->setPartMetaData(
content(), *partMetaData());
959 if (!mVerifiedText.
isEmpty()) {
961 tempNode->setContent(KMime::CRLFtoLF(mVerifiedText.
constData()));
964 if (!tempNode->head().isEmpty()) {
965 tempNode->contentDescription()->from7BitString(
"signed data");
969 parseInternal(tempNode,
false);
976 QString SignedMessagePart::plaintextContent()
const
979 return MessagePart::text();
985 QString SignedMessagePart::htmlContent()
const
988 return MessagePart::text();
994 const QGpgME::Protocol *SignedMessagePart::cryptoProto()
const
999 QString SignedMessagePart::fromAddress()
const
1001 return mFromAddress;
1004 bool SignedMessagePart::hasHeader(
const char *headerType)
const
1012 const KMime::Headers::Base *MimeTreeParser::SignedMessagePart::header(
const char *headerType)
const
1015 return content()->headerByType(headerType);
1031 const QGpgME::Protocol *cryptoProto,
1035 , mPassphraseError(false)
1037 , mDecryptMessage(false)
1038 , mCryptoProto(cryptoProto)
1039 , mFromAddress(fromAddress)
1040 , mMementoName(
"decryptverify")
1043 partMetaData()->technicalProblem = (mCryptoProto ==
nullptr);
1044 partMetaData()->isSigned =
false;
1045 partMetaData()->isGoodSignature =
false;
1046 partMetaData()->isEncrypted =
false;
1047 partMetaData()->isDecryptable =
false;
1048 partMetaData()->keyTrust = GpgME::Signature::Unknown;
1049 partMetaData()->status =
i18n(
"Wrong Crypto Plug-In.");
1050 partMetaData()->status_code = GPGME_SIG_STAT_NONE;
1053 EncryptedMessagePart::~EncryptedMessagePart() =
default;
1055 void EncryptedMessagePart::setDecryptMessage(
bool decrypt)
1057 mDecryptMessage = decrypt;
1060 bool EncryptedMessagePart::decryptMessage()
const
1062 return mDecryptMessage;
1065 void EncryptedMessagePart::setIsEncrypted(
bool encrypted)
1067 partMetaData()->isEncrypted = encrypted;
1070 bool EncryptedMessagePart::isEncrypted()
const
1072 return partMetaData()->isEncrypted;
1075 bool EncryptedMessagePart::isDecryptable()
const
1077 return partMetaData()->isDecryptable;
1080 bool EncryptedMessagePart::isNoSecKey()
const
1085 bool EncryptedMessagePart::passphraseError()
const
1087 return mPassphraseError;
1090 QByteArray EncryptedMessagePart::mementoName()
const
1092 return mMementoName;
1095 void EncryptedMessagePart::setMementoName(
const QByteArray &name)
1097 mMementoName =
name;
1108 if (!partMetaData()->inProgress && partMetaData()->isDecryptable) {
1109 if (hasSubParts()) {
1110 auto _mp = (subParts()[0]).dynamicCast<SignedMessagePart>();
1112 _mp->setText(aCodec->
toUnicode(mDecryptedData));
1114 setText(aCodec->
toUnicode(mDecryptedData));
1117 setText(aCodec->
toUnicode(mDecryptedData));
1125 mPassphraseError =
false;
1126 partMetaData()->inProgress =
false;
1127 partMetaData()->errorText.clear();
1128 partMetaData()->auditLogError = GpgME::Error();
1129 partMetaData()->auditLog.clear();
1130 bool bDecryptionOk =
false;
1131 bool cannotDecrypt =
false;
1134 Q_ASSERT(decryptMessage());
1136 const QByteArray _mementoName = mementoName();
1138 const DecryptVerifyBodyPartMemento *m =
dynamic_cast<DecryptVerifyBodyPartMemento *
>(nodeHelper->bodyPartMemento(&data, _mementoName));
1140 Q_ASSERT(!m || mCryptoProto);
1142 if (!m && mCryptoProto) {
1143 QGpgME::DecryptVerifyJob *job = mCryptoProto->decryptVerifyJob();
1145 cannotDecrypt =
true;
1148 auto newM =
new DecryptVerifyBodyPartMemento(job, ciphertext);
1149 if (mOtp->allowAsync()) {
1150 QObject::connect(newM, &CryptoBodyPartMemento::update, nodeHelper, &NodeHelper::update);
1151 if (newM->start()) {
1152 partMetaData()->inProgress =
true;
1153 mOtp->mHasPendingAsyncJobs =
true;
1161 nodeHelper->setBodyPartMemento(&data, _mementoName, newM);
1163 }
else if (m && m->isRunning()) {
1164 partMetaData()->inProgress =
true;
1165 mOtp->mHasPendingAsyncJobs =
true;
1170 const QByteArray &plainText = m->plainText();
1171 const GpgME::DecryptionResult &decryptResult = m->decryptResult();
1172 const GpgME::VerificationResult &verifyResult = m->verifyResult();
1173 partMetaData()->isSigned = verifyResult.signatures().size() > 0;
1175 if (partMetaData()->isSigned) {
1177 subPart->setVerificationResult(m,
nullptr);
1178 appendSubPart(subPart);
1181 mDecryptRecipients.clear();
1182 bDecryptionOk = !decryptResult.error();
1188 for (
const auto &recipient : decryptResult.recipients()) {
1189 if (!recipient.status()) {
1190 bDecryptionOk =
true;
1193 key = Kleo::KeyCache::instance()->findByKeyIDOrFingerprint(recipient.keyID());
1195 auto ret = Kleo::KeyCache::instance()->findSubkeysByKeyID({recipient.keyID()});
1196 if (ret.size() == 1) {
1197 key = ret.front().parent();
1200 qCDebug(MIMETREEPARSER_LOG) <<
"Found no Key for KeyID " << recipient.keyID();
1203 mDecryptRecipients.emplace_back(recipient, key);
1206 if (!bDecryptionOk && partMetaData()->isSigned) {
1208 partMetaData()->isEncrypted =
false;
1209 bDecryptionOk =
true;
1210 mDecryptedData = plainText;
1212 mPassphraseError = decryptResult.error().isCanceled() || decryptResult.error().code() == GPG_ERR_NO_SECKEY;
1213 partMetaData()->isEncrypted = bDecryptionOk || decryptResult.error().code() != GPG_ERR_NO_DATA;
1215 if (decryptResult.error().isCanceled()) {
1216 setDecryptMessage(
false);
1220 if (Kleo::DeVSCompliance::isCompliant()) {
1221 partMetaData()->isCompliant = decryptResult.isDeVs();
1222 partMetaData()->compliance = Kleo::DeVSCompliance::name(decryptResult.isDeVs());
1224 partMetaData()->isCompliant =
true;
1226 if (partMetaData()->isEncrypted && decryptResult.numRecipients() > 0) {
1227 partMetaData()->keyId = decryptResult.recipient(0).keyID();
1230 if (bDecryptionOk) {
1231 mDecryptedData = plainText;
1234 const auto decryRecipients = decryptResult.recipients();
1235 for (
const GpgME::DecryptionResult::Recipient &recipient : decryRecipients) {
1236 mNoSecKey &= (recipient.status().code() == GPG_ERR_NO_SECKEY);
1238 if (!mPassphraseError && !mNoSecKey) {
1239 mPassphraseError =
true;
1245 if (!bDecryptionOk) {
1248 cryptPlugLibName = mCryptoProto->name();
1251 if (!mCryptoProto) {
1252 partMetaData()->errorText =
i18n(
"No appropriate crypto plug-in was found.");
1253 }
else if (cannotDecrypt) {
1254 partMetaData()->errorText =
i18n(
"Crypto plug-in \"%1\" cannot decrypt messages.", cryptPlugLibName);
1255 }
else if (!passphraseError()) {
1256 partMetaData()->errorText =
i18n(
"Crypto plug-in \"%1\" could not decrypt the data.", cryptPlugLibName) +
QLatin1String(
"<br />")
1257 +
i18n(
"Error: %1", partMetaData()->errorText);
1260 return bDecryptionOk;
1273 partMetaData()->isEncrypted =
true;
1275 bool bOkDecrypt = okDecryptMIME(*data);
1277 if (partMetaData()->inProgress) {
1280 partMetaData()->isDecryptable = bOkDecrypt;
1282 if (!partMetaData()->isDecryptable) {
1286 if (partMetaData()->isEncrypted && !decryptMessage()) {
1287 partMetaData()->isDecryptable =
true;
1290 if (
content() && !partMetaData()->isSigned) {
1291 mOtp->nodeHelper()->setPartMetaData(
content(), *partMetaData());
1293 if (decryptMessage()) {
1295 tempNode->setContent(KMime::CRLFtoLF(mDecryptedData.
constData()));
1298 if (!tempNode->head().isEmpty()) {
1299 tempNode->contentDescription()->from7BitString(
"encrypted data");
1303 parseInternal(tempNode,
false);
1308 QString EncryptedMessagePart::plaintextContent()
const
1311 return MessagePart::text();
1317 QString EncryptedMessagePart::htmlContent()
const
1320 return MessagePart::text();
1326 QString EncryptedMessagePart::text()
const
1328 if (hasSubParts()) {
1329 auto _mp = (subParts()[0]).dynamicCast<SignedMessagePart>();
1333 return MessagePart::text();
1336 return MessagePart::text();
1340 const QGpgME::Protocol *EncryptedMessagePart::cryptoProto()
const
1342 return mCryptoProto;
1345 QString EncryptedMessagePart::fromAddress()
const
1347 return mFromAddress;
1350 const std::vector<std::pair<GpgME::DecryptionResult::Recipient, GpgME::Key>> &EncryptedMessagePart::decryptRecipients()
const
1352 return mDecryptRecipients;
1355 bool EncryptedMessagePart::hasHeader(
const char *headerType)
const
1357 const auto extraContent = mOtp->nodeHelper()->decryptedNodeForContent(
content());
1359 return nodeHelper()->hasMailHeader(headerType, extraContent);
1366 const auto extraContent = mOtp->nodeHelper()->decryptedNodeForContent(
content());
1368 return nodeHelper()->mailHeaderAsBase(headerType, extraContent);
1375 const auto extraContent = mOtp->nodeHelper()->decryptedNodeForContent(
content());
1377 return nodeHelper()->headers(headerType, extraContent);
1387 partMetaData()->isEncrypted =
false;
1388 partMetaData()->isSigned =
false;
1389 partMetaData()->isEncapsulatedRfc822Message =
true;
1391 mOtp->nodeHelper()->setNodeDisplayedEmbedded(node,
true);
1392 mOtp->nodeHelper()->setPartMetaData(node, *partMetaData());
1395 qCWarning(MIMETREEPARSER_LOG) <<
"Node is of type message/rfc822 but doesn't have a message!";
1406 EncapsulatedRfc822MessagePart::~EncapsulatedRfc822MessagePart() =
default;
1408 QString EncapsulatedRfc822MessagePart::text()
const
1410 return renderInternalText();
1413 void EncapsulatedRfc822MessagePart::fix()
const