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> 22 #include <QGpgME/ImportJob> 23 #include <QGpgME/KeyListJob> 24 #include <QGpgME/Protocol> 25 #include <QGpgME/VerifyDetachedJob> 26 #include <QGpgME/VerifyOpaqueJob> 28 #include <gpgme++/key.h> 29 #include <gpgme++/keylistresult.h> 32 #include <KLocalizedString> 42 class MessagePartPrivate
50 PartMetaData mMetaData;
52 bool mIsImage =
false;
53 bool mNeverDisplayInline =
false;
59 , d(new MessagePartPrivate)
64 MessagePart::~MessagePart() =
default;
68 return d->mParentPart;
71 void MessagePart::setParentPart(
MessagePart *parentPart)
73 d->mParentPart = parentPart;
76 QString MessagePart::htmlContent()
const 81 QString MessagePart::plaintextContent()
const 86 PartMetaData *MessagePart::partMetaData()
const 93 return nodeHelper()->bodyPartMemento(content(),
"__plugin__");
98 nodeHelper()->setBodyPartMemento(content(),
"__plugin__", memento);
113 return d->mAttachmentNode;
118 d->mAttachmentNode = node;
121 bool MessagePart::isAttachment()
const 123 return d->mAttachmentNode;
126 QString MessagePart::attachmentIndex()
const 128 return attachmentContent()->index().toString();
133 return mOtp->nodeHelper()->asHREF(content(), QStringLiteral(
"body"));
139 static int serial = 0;
143 return QStringLiteral(
"x-kmail:/bodypart/%1/%2/%3")
148 void MessagePart::setIsRoot(
bool root)
153 bool MessagePart::isRoot()
const 158 QString MessagePart::text()
const 163 void MessagePart::setText(
const QString &text)
168 bool MessagePart::isHtml()
const 176 return mOtp->mSource;
182 return mOtp->nodeHelper();
185 void MessagePart::parseInternal(
KMime::Content *node,
bool onlyOneMimePart)
187 auto subMessagePart = mOtp->parseObjectTreeInternal(node, onlyOneMimePart);
188 d->mRoot = subMessagePart->isRoot();
190 for (
const auto &part : subParts) {
195 QString MessagePart::renderInternalText()
const 198 const auto subPartsLst = subParts();
199 for (
const auto &mp : subPartsLst) {
205 void MessagePart::fix()
const 207 const auto subPartsLst = subParts();
208 for (
const auto &mp : subPartsLst) {
218 messagePart->setParentPart(
this);
219 d->mBlocks.append(messagePart);
227 bool MessagePart::hasSubParts()
const 232 void MessagePart::clearSubParts()
237 bool MessagePart::neverDisplayInline()
const 239 return d->mNeverDisplayInline;
242 void MessagePart::setNeverDisplayInline(
bool displayInline)
244 d->mNeverDisplayInline = displayInline;
247 bool MessagePart::isImage()
const 252 void MessagePart::setIsImage(
bool image)
257 bool MessagePart::hasHeader(
const char *headerType)
const 281 MessagePartList::~MessagePartList()
285 QString MessagePartList::text()
const 287 return renderInternalText();
290 QString MessagePartList::plaintextContent()
const 295 QString MessagePartList::htmlContent()
const 304 , mDecryptMessage(decryptMessage)
307 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
316 TextMessagePart::~TextMessagePart()
320 bool TextMessagePart::decryptMessage()
const 322 return mDecryptMessage;
325 void TextMessagePart::parseContent()
327 const auto aCodec = mOtp->codecFor(content());
328 const QString &fromAddress = mOtp->nodeHelper()->fromAsString(content());
329 mSignatureState = KMMsgNotSigned;
330 mEncryptionState = KMMsgNotEncrypted;
331 const auto blocks = prepareMessageForDecryption(content()->decodedContent());
333 const auto cryptProto = QGpgME::openpgp();
335 if (!blocks.isEmpty()) {
343 bool fullySignedOrEncrypted =
true;
344 bool fullySignedOrEncryptedTmp =
true;
347 for (
const auto &block : blocks) {
349 if (!fullySignedOrEncryptedTmp) {
350 fullySignedOrEncrypted =
false;
353 if (block.type() == NoPgpBlock && !block.text().trimmed().isEmpty()) {
354 fullySignedOrEncryptedTmp =
false;
356 }
else if (block.type() == PgpMessageBlock) {
358 mp->setDecryptMessage(decryptMessage());
359 mp->setIsEncrypted(
true);
360 mp->setMementoName(mp->mementoName() +
"-" + nodeHelper()->asHREF(content(),
QString::number(blockIndex)).toLocal8Bit());
362 if (!decryptMessage()) {
365 mp->startDecryption(block.text(), aCodec);
366 if (mp->partMetaData()->inProgress) {
369 }
else if (block.type() == ClearsignedBlock) {
371 mp->setMementoName(mp->mementoName() +
"-" + nodeHelper()->asHREF(content(),
QString::number(blockIndex)).toLocal8Bit());
373 mp->startVerification(block.text(), aCodec);
379 const PartMetaData *messagePart(mp->partMetaData());
381 if (!messagePart->isEncrypted && !messagePart->isSigned && !block.text().trimmed().isEmpty()) {
382 mp->setText(aCodec->toUnicode(block.text()));
385 if (messagePart->isEncrypted) {
386 mEncryptionState = KMMsgPartiallyEncrypted;
389 if (messagePart->isSigned) {
390 mSignatureState = KMMsgPartiallySigned;
395 if (fullySignedOrEncrypted) {
396 if (mSignatureState == KMMsgPartiallySigned) {
397 mSignatureState = KMMsgFullySigned;
399 if (mEncryptionState == KMMsgPartiallyEncrypted) {
400 mEncryptionState = KMMsgFullyEncrypted;
406 KMMsgEncryptionState TextMessagePart::encryptionState()
const 408 return mEncryptionState;
411 KMMsgSignatureState TextMessagePart::signatureState()
const 413 return mSignatureState;
416 bool TextMessagePart::showLink()
const 418 return !temporaryFilePath().isEmpty();
421 bool TextMessagePart::isFirstTextPart()
const 423 return content()->topLevel()->textContent() == content();
426 bool TextMessagePart::hasLabel()
const 428 return !NodeHelper::fileName(content()).isEmpty();
431 QString TextMessagePart::label()
const 433 const QString name = content()->contentType()->name();
434 QString label = name.
isEmpty() ? NodeHelper::fileName(content()) : name;
436 label =
i18nc(
"display name for an unnamed attachment",
"Unnamed");
441 QString TextMessagePart::comment()
const 443 const QString comment = content()->contentDescription()->asUnicodeString();
444 if (comment == label()) {
450 QString TextMessagePart::temporaryFilePath()
const 452 return nodeHelper()->writeNodeToTempFile(content());
462 AttachmentMessagePart::~AttachmentMessagePart()
473 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
479 mBodyHTML = mOtp->codecFor(node)->toUnicode(partBody);
480 mCharset = NodeHelper::charset(node);
483 HtmlMessagePart::~HtmlMessagePart()
487 void HtmlMessagePart::fix()
const 489 mOtp->mHtmlContent += mBodyHTML;
490 mOtp->mHtmlContentCharset = mCharset;
493 QString HtmlMessagePart::text()
const 498 QString MimeTreeParser::HtmlMessagePart::plaintextContent()
const 503 bool HtmlMessagePart::isHtml()
const 508 QString HtmlMessagePart::bodyHtml()
const 517 , mOnlyOneMimePart(onlyOneMimePart)
520 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
525 parseInternal(node, mOnlyOneMimePart);
528 MimeMessagePart::~MimeMessagePart()
532 QString MimeMessagePart::text()
const 534 return renderInternalText();
537 QString MimeMessagePart::plaintextContent()
const 542 QString MimeMessagePart::htmlContent()
const 551 , mPreferredMode(preferredMode)
554 KMime::Content *dataIcal = findTypeInDirectChilds(node,
"text/calendar");
555 KMime::Content *dataHtml = findTypeInDirectChilds(node,
"text/html");
556 KMime::Content *dataText = findTypeInDirectChilds(node,
"text/plain");
563 dataHtml = findTypeInDirectChilds(node,
"multipart/related");
571 dataHtml = findTypeInDirectChilds(node,
"multipart/mixed");
576 mChildNodes[Util::MultipartIcal] = dataIcal;
580 mChildNodes[Util::MultipartPlain] = dataText;
584 mChildNodes[Util::MultipartHtml] = dataHtml;
587 if (mChildNodes.isEmpty()) {
588 qCWarning(MIMETREEPARSER_LOG) <<
"no valid nodes";
599 AlternativeMessagePart::~AlternativeMessagePart()
605 return mPreferredMode;
608 void AlternativeMessagePart::setPreferredMode(
Util::HtmlMode preferredMode)
610 mPreferredMode = preferredMode;
615 return mChildParts.keys();
618 QString AlternativeMessagePart::text()
const 620 if (mChildParts.contains(Util::MultipartPlain)) {
621 return mChildParts[Util::MultipartPlain]->text();
626 void AlternativeMessagePart::fix()
const 628 if (mChildParts.contains(Util::MultipartPlain)) {
629 mChildParts[Util::MultipartPlain]->fix();
632 const auto mode = preferredMode();
633 if (mode != Util::MultipartPlain && mChildParts.contains(mode)) {
634 mChildParts[mode]->fix();
643 bool AlternativeMessagePart::isHtml()
const 645 return mChildParts.
contains(Util::MultipartHtml);
648 QString AlternativeMessagePart::plaintextContent()
const 653 QString AlternativeMessagePart::htmlContent()
const 655 if (mChildParts.contains(Util::MultipartHtml)) {
656 return mChildParts[Util::MultipartHtml]->text();
658 return plaintextContent();
666 , mAutoImport(autoImport)
667 , mCryptoProto(cryptoProto)
670 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
681 QGpgME::ImportJob *
import = mCryptoProto->importJob();
683 mImportResult = executor.exec(
import, certData);
686 CertMessagePart::~CertMessagePart()
690 QString CertMessagePart::text()
const 695 const GpgME::ImportResult &CertMessagePart::importResult()
const 697 return mImportResult;
703 const QGpgME::Protocol *cryptoProto,
707 , mCryptoProto(cryptoProto)
708 , mFromAddress(fromAddress)
709 , mMementoName(
"verification")
712 partMetaData()->technicalProblem = (mCryptoProto ==
nullptr);
713 partMetaData()->isSigned =
true;
714 partMetaData()->isGoodSignature =
false;
715 partMetaData()->keyTrust = GpgME::Signature::Unknown;
716 partMetaData()->status =
i18n(
"Wrong Crypto Plug-In.");
717 partMetaData()->status_code = GPGME_SIG_STAT_NONE;
720 SignedMessagePart::~SignedMessagePart()
724 void SignedMessagePart::setIsSigned(
bool isSigned)
726 partMetaData()->isSigned = isSigned;
729 bool SignedMessagePart::isSigned()
const 731 return partMetaData()->isSigned;
734 QByteArray SignedMessagePart::mementoName()
const 739 void SignedMessagePart::setMementoName(
const QByteArray &name)
748 partMetaData()->isSigned =
false;
749 partMetaData()->technicalProblem = (mCryptoProto ==
nullptr);
750 partMetaData()->keyTrust = GpgME::Signature::Unknown;
751 partMetaData()->status =
i18n(
"Wrong Crypto Plug-In.");
752 partMetaData()->status_code = GPGME_SIG_STAT_NONE;
754 const QByteArray _mementoName = mementoName();
756 auto *m =
dynamic_cast<CryptoBodyPartMemento *
>(nodeHelper->bodyPartMemento(content(), _mementoName));
757 Q_ASSERT(!m || mCryptoProto);
759 if (!m && mCryptoProto) {
761 QGpgME::VerifyDetachedJob *job = mCryptoProto->verifyDetachedJob();
763 m =
new VerifyDetachedBodyPartMemento(job, mCryptoProto->keyListJob(), signature, data);
766 QGpgME::VerifyOpaqueJob *job = mCryptoProto->verifyOpaqueJob();
768 m =
new VerifyOpaqueBodyPartMemento(job, mCryptoProto->keyListJob(), data);
772 if (mOtp->allowAsync()) {
773 QObject::connect(m, &CryptoBodyPartMemento::update, nodeHelper, &NodeHelper::update);
775 partMetaData()->inProgress =
true;
776 mOtp->mHasPendingAsyncJobs =
true;
781 nodeHelper->setBodyPartMemento(content(), _mementoName, m);
783 }
else if (m && m->isRunning()) {
784 partMetaData()->inProgress =
true;
785 mOtp->mHasPendingAsyncJobs =
true;
787 partMetaData()->inProgress =
false;
788 mOtp->mHasPendingAsyncJobs =
false;
791 if (m && !partMetaData()->inProgress) {
793 mVerifiedText = data;
795 setVerificationResult(m, textNode);
798 if (!m && !partMetaData()->inProgress) {
803 cryptPlugLibName = mCryptoProto->name();
804 cryptPlugDisplayName = mCryptoProto->displayName();
808 if (cryptPlugDisplayName.
isEmpty()) {
809 errorMsg =
i18n(
"No appropriate crypto plug-in was found.");
811 errorMsg =
i18nc(
"%1 is either 'OpenPGP' or 'S/MIME'",
"No %1 plug-in was found.", cryptPlugDisplayName);
814 errorMsg =
i18n(
"Crypto plug-in \"%1\" cannot verify signatures.", cryptPlugLibName);
816 partMetaData()->errorText =
i18n(
817 "The message is signed, but the " 818 "validity of the signature cannot be " 824 return partMetaData()->isSigned;
827 static int signatureToStatus(
const GpgME::Signature &sig)
829 switch (sig.status().code()) {
830 case GPG_ERR_NO_ERROR:
831 return GPGME_SIG_STAT_GOOD;
832 case GPG_ERR_BAD_SIGNATURE:
833 return GPGME_SIG_STAT_BAD;
834 case GPG_ERR_NO_PUBKEY:
835 return GPGME_SIG_STAT_NOKEY;
836 case GPG_ERR_NO_DATA:
837 return GPGME_SIG_STAT_NOSIG;
838 case GPG_ERR_SIG_EXPIRED:
839 return GPGME_SIG_STAT_GOOD_EXP;
840 case GPG_ERR_KEY_EXPIRED:
841 return GPGME_SIG_STAT_GOOD_EXPKEY;
843 return GPGME_SIG_STAT_ERROR;
847 QString prettifyDN(
const char *uid)
849 return QGpgME::DN(uid).prettyDN();
852 void SignedMessagePart::sigStatusToMetaData()
855 if (partMetaData()->isSigned) {
856 GpgME::Signature signature = mSignatures.
front();
857 partMetaData()->status_code = signatureToStatus(signature);
858 partMetaData()->isGoodSignature = partMetaData()->status_code & GPGME_SIG_STAT_GOOD;
860 partMetaData()->sigSummary = signature.summary();
862 if (partMetaData()->isGoodSignature && !key.keyID()) {
865 QGpgME::KeyListJob *job = mCryptoProto->keyListJob(
false,
false,
false);
867 qCDebug(MIMETREEPARSER_LOG) <<
"The Crypto backend does not support listing keys. ";
869 std::vector<GpgME::Key> found_keys;
873 qCDebug(MIMETREEPARSER_LOG) <<
"Error while searching key for Fingerprint: " << signature.fingerprint();
875 if (found_keys.size() > 1) {
877 qCDebug(MIMETREEPARSER_LOG) <<
"Oops: Found more then one Key for Fingerprint: " << signature.fingerprint();
879 if (found_keys.size() != 1) {
881 qCDebug(MIMETREEPARSER_LOG) <<
"Oops: Found no Key for Fingerprint: " << signature.fingerprint();
890 partMetaData()->keyId = key.keyID();
892 if (partMetaData()->keyId.isEmpty()) {
893 partMetaData()->keyId = signature.fingerprint();
895 partMetaData()->keyTrust = signature.validity();
896 if (key.numUserIDs() > 0 && key.userID(0).id()) {
897 partMetaData()->signer = prettifyDN(key.userID(0).id());
899 for (uint iMail = 0; iMail < key.numUserIDs(); ++iMail) {
902 if (key.userID(iMail).email()) {
907 email = email.
mid(1, email.
length() - 2);
910 partMetaData()->signerMailAddresses.
append(email);
915 if (signature.creationTime()) {
916 partMetaData()->creationTime.setSecsSinceEpoch(signature.creationTime());
918 partMetaData()->creationTime =
QDateTime();
920 if (partMetaData()->signer.isEmpty()) {
921 if (key.numUserIDs() > 0 && key.userID(0).name()) {
922 partMetaData()->signer = prettifyDN(key.userID(0).name());
924 if (!partMetaData()->signerMailAddresses.empty()) {
925 if (partMetaData()->signer.isEmpty()) {
926 partMetaData()->signer = partMetaData()->signerMailAddresses.
front();
937 startVerificationDetached(text,
nullptr,
QByteArray());
939 if (!content() && partMetaData()->isSigned) {
940 setText(aCodec->
toUnicode(mVerifiedText));
946 partMetaData()->isEncrypted =
false;
947 partMetaData()->isDecryptable =
false;
950 parseInternal(textNode,
false);
953 if (!okVerify(text, signature, textNode)) {
954 partMetaData()->creationTime =
QDateTime();
958 void SignedMessagePart::setVerificationResult(
const CryptoBodyPartMemento *m,
KMime::Content *textNode)
961 const auto vm =
dynamic_cast<const VerifyDetachedBodyPartMemento *
>(m);
963 mSignatures = vm->verifyResult().signatures();
967 const auto vm =
dynamic_cast<const VerifyOpaqueBodyPartMemento *
>(m);
969 mVerifiedText = vm->plainText();
970 mSignatures = vm->verifyResult().signatures();
974 const auto vm =
dynamic_cast<const DecryptVerifyBodyPartMemento *
>(m);
976 mVerifiedText = vm->plainText();
977 mSignatures = vm->verifyResult().signatures();
980 partMetaData()->auditLogError = m->auditLogError();
981 partMetaData()->auditLog = m->auditLogAsHtml();
982 partMetaData()->isSigned = !mSignatures.empty();
984 if (partMetaData()->isSigned) {
985 sigStatusToMetaData();
987 mOtp->nodeHelper()->setSignatureState(content(), KMMsgFullySigned);
989 mOtp->nodeHelper()->setPartMetaData(content(), *partMetaData());
991 if (!mVerifiedText.isEmpty()) {
993 tempNode->setContent(KMime::CRLFtoLF(mVerifiedText.constData()));
996 if (!tempNode->head().isEmpty()) {
997 tempNode->contentDescription()->from7BitString(
"signed data");
999 mOtp->nodeHelper()->attachExtraContent(content(), tempNode);
1001 parseInternal(tempNode,
false);
1008 QString SignedMessagePart::plaintextContent()
const 1011 return MessagePart::text();
1017 QString SignedMessagePart::htmlContent()
const 1020 return MessagePart::text();
1026 const QGpgME::Protocol *SignedMessagePart::cryptoProto()
const 1028 return mCryptoProto;
1031 QString SignedMessagePart::fromAddress()
const 1033 return mFromAddress;
1036 bool SignedMessagePart::hasHeader(
const char *headerType)
const 1039 return content()->hasHeader(headerType);
1044 const KMime::Headers::Base *MimeTreeParser::SignedMessagePart::header(
const char *headerType)
const 1047 return content()->headerByType(headerType);
1055 return content()->headersByType(headerType);
1063 const QGpgME::Protocol *cryptoProto,
1067 , mPassphraseError(
false)
1069 , mDecryptMessage(
false)
1070 , mCryptoProto(cryptoProto)
1071 , mFromAddress(fromAddress)
1072 , mMementoName(
"decryptverify")
1075 partMetaData()->technicalProblem = (mCryptoProto ==
nullptr);
1076 partMetaData()->isSigned =
false;
1077 partMetaData()->isGoodSignature =
false;
1078 partMetaData()->isEncrypted =
false;
1079 partMetaData()->isDecryptable =
false;
1080 partMetaData()->keyTrust = GpgME::Signature::Unknown;
1081 partMetaData()->status =
i18n(
"Wrong Crypto Plug-In.");
1082 partMetaData()->status_code = GPGME_SIG_STAT_NONE;
1085 EncryptedMessagePart::~EncryptedMessagePart()
1089 void EncryptedMessagePart::setDecryptMessage(
bool decrypt)
1091 mDecryptMessage = decrypt;
1094 bool EncryptedMessagePart::decryptMessage()
const 1096 return mDecryptMessage;
1099 void EncryptedMessagePart::setIsEncrypted(
bool encrypted)
1101 partMetaData()->isEncrypted = encrypted;
1104 bool EncryptedMessagePart::isEncrypted()
const 1106 return partMetaData()->isEncrypted;
1109 bool EncryptedMessagePart::isDecryptable()
const 1111 return partMetaData()->isDecryptable;
1114 bool EncryptedMessagePart::isNoSecKey()
const 1119 bool EncryptedMessagePart::passphraseError()
const 1121 return mPassphraseError;
1124 QByteArray EncryptedMessagePart::mementoName()
const 1126 return mMementoName;
1129 void EncryptedMessagePart::setMementoName(
const QByteArray &name)
1131 mMementoName = name;
1140 startDecryption(content);
1142 if (!partMetaData()->inProgress && partMetaData()->isDecryptable) {
1143 if (hasSubParts()) {
1144 auto _mp = (subParts()[0]).dynamicCast<SignedMessagePart>();
1146 _mp->setText(aCodec->
toUnicode(mDecryptedData));
1148 setText(aCodec->
toUnicode(mDecryptedData));
1151 setText(aCodec->
toUnicode(mDecryptedData));
1159 mPassphraseError =
false;
1160 partMetaData()->inProgress =
false;
1161 partMetaData()->errorText.clear();
1162 partMetaData()->auditLogError = GpgME::Error();
1163 partMetaData()->auditLog.clear();
1164 bool bDecryptionOk =
false;
1165 bool cannotDecrypt =
false;
1168 Q_ASSERT(decryptMessage());
1170 const QByteArray _mementoName = mementoName();
1172 const DecryptVerifyBodyPartMemento *m =
dynamic_cast<DecryptVerifyBodyPartMemento *
>(nodeHelper->bodyPartMemento(&data, _mementoName));
1174 Q_ASSERT(!m || mCryptoProto);
1176 if (!m && mCryptoProto) {
1177 QGpgME::DecryptVerifyJob *job = mCryptoProto->decryptVerifyJob();
1179 cannotDecrypt =
true;
1182 auto newM =
new DecryptVerifyBodyPartMemento(job, ciphertext);
1183 if (mOtp->allowAsync()) {
1184 QObject::connect(newM, &CryptoBodyPartMemento::update, nodeHelper, &NodeHelper::update);
1185 if (newM->start()) {
1186 partMetaData()->inProgress =
true;
1187 mOtp->mHasPendingAsyncJobs =
true;
1195 nodeHelper->setBodyPartMemento(&data, _mementoName, newM);
1197 }
else if (m && m->isRunning()) {
1198 partMetaData()->inProgress =
true;
1199 mOtp->mHasPendingAsyncJobs =
true;
1204 const QByteArray &plainText = m->plainText();
1205 const GpgME::DecryptionResult &decryptResult = m->decryptResult();
1206 const GpgME::VerificationResult &verifyResult = m->verifyResult();
1207 partMetaData()->isSigned = verifyResult.signatures().
size() > 0;
1209 if (partMetaData()->isSigned) {
1211 subPart->setVerificationResult(m,
nullptr);
1212 appendSubPart(subPart);
1215 mDecryptRecipients.clear();
1216 bDecryptionOk = !decryptResult.error();
1222 for (
const auto &recipient : decryptResult.recipients()) {
1223 if (!recipient.status()) {
1224 bDecryptionOk =
true;
1227 QGpgME::KeyListJob *job = mCryptoProto->keyListJob(
false,
false,
false);
1229 qCDebug(MIMETREEPARSER_LOG) <<
"The Crypto backend does not support listing keys. ";
1231 std::vector<GpgME::Key> found_keys;
1235 qCDebug(MIMETREEPARSER_LOG) <<
"Error while searching key for Fingerprint: " << recipient.keyID();
1237 if (found_keys.size() > 1) {
1239 qCDebug(MIMETREEPARSER_LOG) <<
"Oops: Found more then one Key for Fingerprint: " << recipient.keyID();
1241 if (found_keys.size() != 1) {
1243 qCDebug(MIMETREEPARSER_LOG) <<
"Oops: Found no Key for Fingerprint: " << recipient.keyID();
1245 key = found_keys[0];
1248 mDecryptRecipients.push_back(std::make_pair(recipient, key));
1251 if (!bDecryptionOk && partMetaData()->isSigned) {
1253 partMetaData()->isEncrypted =
false;
1254 bDecryptionOk =
true;
1255 mDecryptedData = plainText;
1257 mPassphraseError = decryptResult.error().isCanceled() || decryptResult.error().code() == GPG_ERR_NO_SECKEY;
1258 partMetaData()->isEncrypted = bDecryptionOk || decryptResult.error().code() != GPG_ERR_NO_DATA;
1260 if (decryptResult.error().isCanceled()) {
1261 setDecryptMessage(
false);
1265 if (partMetaData()->isEncrypted && decryptResult.numRecipients() > 0) {
1266 partMetaData()->keyId = decryptResult.recipient(0).keyID();
1269 if (bDecryptionOk) {
1270 mDecryptedData = plainText;
1273 const auto decryRecipients = decryptResult.recipients();
1274 for (
const GpgME::DecryptionResult::Recipient &recipient : decryRecipients) {
1275 mNoSecKey &= (recipient.status().code() == GPG_ERR_NO_SECKEY);
1277 if (!mPassphraseError && !mNoSecKey) {
1278 mPassphraseError =
true;
1284 if (!bDecryptionOk) {
1287 cryptPlugLibName = mCryptoProto->name();
1290 if (!mCryptoProto) {
1291 partMetaData()->errorText =
i18n(
"No appropriate crypto plug-in was found.");
1292 }
else if (cannotDecrypt) {
1293 partMetaData()->errorText =
i18n(
"Crypto plug-in \"%1\" cannot decrypt messages.", cryptPlugLibName);
1294 }
else if (!passphraseError()) {
1295 partMetaData()->errorText =
i18n(
"Crypto plug-in \"%1\" could not decrypt the data.", cryptPlugLibName) +
QLatin1String(
"<br />")
1296 +
i18n(
"Error: %1", partMetaData()->errorText);
1299 return bDecryptionOk;
1304 if (!content() && !data) {
1312 partMetaData()->isEncrypted =
true;
1314 bool bOkDecrypt = okDecryptMIME(*data);
1316 if (partMetaData()->inProgress) {
1319 partMetaData()->isDecryptable = bOkDecrypt;
1321 if (!partMetaData()->isDecryptable) {
1325 if (partMetaData()->isEncrypted && !decryptMessage()) {
1326 partMetaData()->isDecryptable =
true;
1329 if (content() && !partMetaData()->isSigned) {
1330 mOtp->nodeHelper()->setPartMetaData(content(), *partMetaData());
1332 if (decryptMessage()) {
1334 tempNode->setContent(KMime::CRLFtoLF(mDecryptedData.constData()));
1337 if (!tempNode->head().isEmpty()) {
1338 tempNode->contentDescription()->from7BitString(
"encrypted data");
1340 mOtp->nodeHelper()->attachExtraContent(content(), tempNode);
1342 parseInternal(tempNode,
false);
1347 QString EncryptedMessagePart::plaintextContent()
const 1350 return MessagePart::text();
1356 QString EncryptedMessagePart::htmlContent()
const 1359 return MessagePart::text();
1365 QString EncryptedMessagePart::text()
const 1367 if (hasSubParts()) {
1368 auto _mp = (subParts()[0]).dynamicCast<SignedMessagePart>();
1372 return MessagePart::text();
1375 return MessagePart::text();
1379 const QGpgME::Protocol *EncryptedMessagePart::cryptoProto()
const 1381 return mCryptoProto;
1384 QString EncryptedMessagePart::fromAddress()
const 1386 return mFromAddress;
1389 const std::vector<std::pair<GpgME::DecryptionResult::Recipient, GpgME::Key>> &EncryptedMessagePart::decryptRecipients()
const 1391 return mDecryptRecipients;
1394 bool EncryptedMessagePart::hasHeader(
const char *headerType)
const 1396 const auto extraContent = mOtp->nodeHelper()->decryptedNodeForContent(content());
1398 return nodeHelper()->hasMailHeader(headerType, extraContent);
1405 const auto extraContent = mOtp->nodeHelper()->decryptedNodeForContent(content());
1407 return nodeHelper()->mailHeaderAsBase(headerType, extraContent);
1414 const auto extraContent = mOtp->nodeHelper()->decryptedNodeForContent(content());
1416 return nodeHelper()->headers(headerType, extraContent);
1426 partMetaData()->isEncrypted =
false;
1427 partMetaData()->isSigned =
false;
1428 partMetaData()->isEncapsulatedRfc822Message =
true;
1430 mOtp->nodeHelper()->setNodeDisplayedEmbedded(node,
true);
1431 mOtp->nodeHelper()->setPartMetaData(node, *partMetaData());
1434 qCWarning(MIMETREEPARSER_LOG) <<
"Node is of type message/rfc822 but doesn't have a message!";
1440 mOtp->nodeHelper()->writeNodeToTempFile(message.
data());
1442 parseInternal(message.
data(),
false);
1445 EncapsulatedRfc822MessagePart::~EncapsulatedRfc822MessagePart()
1449 QString EncapsulatedRfc822MessagePart::text()
const 1451 return renderInternalText();
1454 void EncapsulatedRfc822MessagePart::fix()
const
QString & append(QChar ch)
bool contains(const Key &key) const const
HtmlMode
Describes the type of the displayed message.
QChar front() const const
bool isEmpty() const const
QString number(int n, int base)
QString fromLocal8Bit(const char *str, int size)
QByteArray decodedContent()
QString fromUtf8(const char *str, int size)
QMapIterator::Item next()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
bool isEmpty() const const
void setBody(const QByteArray &body)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
The EncryptedMessagePart class.
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
const Key & key() const const
const T & value() const const
The MimeMessagePart class.
QString i18n(const char *text, const TYPE &arg...)
The MessagePartList class.
QString mid(int position, int n) const const
Interface for object tree sources.
interface of classes that implement status for BodyPartFormatters.
bool isEmpty() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QByteArray toPercentEncoding(const QString &input, const QByteArray &exclude, const QByteArray &include)
QLatin1Char front() const const
Parses messages and generates HTML display code out of them.
QString fromLatin1(const char *str, int size)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QSharedPointer< X > staticCast() const const
The SignedMessagePart class.
Helper class for synchronous execution of Kleo crypto jobs.
The TextMessagePart class.
QString toUnicode(const QByteArray &a) const const
bool hasNext() const const