File indexing completed on 2024-06-16 05:00:15
0001 /* 0002 SPDX-FileCopyrightText: 2015 Sandro Knauß <sknauss@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "mimetreeparser_export.h" 0010 0011 #include "mimetreeparser/bodypartformatter.h" 0012 #include "mimetreeparser/util.h" 0013 0014 #include <KMime/Message> 0015 0016 #include <gpgme++/decryptionresult.h> 0017 #include <gpgme++/importresult.h> 0018 #include <gpgme++/key.h> 0019 #include <gpgme++/verificationresult.h> 0020 0021 #include <QSharedPointer> 0022 #include <QString> 0023 0024 #include <memory> 0025 0026 namespace GpgME 0027 { 0028 class ImportResult; 0029 } 0030 0031 namespace QGpgME 0032 { 0033 class Protocol; 0034 } 0035 0036 namespace KMime 0037 { 0038 class Content; 0039 } 0040 0041 namespace Kleo 0042 { 0043 class KeyCache; 0044 } 0045 0046 namespace MimeTreeParser 0047 { 0048 class CompositeMemento; 0049 class CryptoBodyPartMemento; 0050 class MessagePartPrivate; 0051 namespace Interface 0052 { 0053 class ObjectTreeSource; 0054 } 0055 /** 0056 * @brief The MessagePart class 0057 */ 0058 class MIMETREEPARSER_EXPORT MessagePart : public QObject 0059 { 0060 Q_OBJECT 0061 Q_PROPERTY(QString plaintextContent READ plaintextContent) 0062 Q_PROPERTY(QString htmlContent READ htmlContent) 0063 Q_PROPERTY(bool isAttachment READ isAttachment) 0064 Q_PROPERTY(bool root READ isRoot) 0065 Q_PROPERTY(bool isHtml READ isHtml) 0066 Q_PROPERTY(bool isImage READ isImage CONSTANT) 0067 Q_PROPERTY(bool neverDisplayInline READ neverDisplayInline CONSTANT) 0068 Q_PROPERTY(QString attachmentIndex READ attachmentIndex CONSTANT) 0069 Q_PROPERTY(QString link READ attachmentLink CONSTANT) 0070 public: 0071 using Ptr = QSharedPointer<MessagePart>; 0072 MessagePart(ObjectTreeParser *otp, const QString &text); 0073 ~MessagePart() override; 0074 0075 void setParentPart(MessagePart *parentPart); 0076 [[nodiscard]] MessagePart *parentPart() const; 0077 0078 [[nodiscard]] virtual QString text() const; 0079 void setText(const QString &text); 0080 0081 [[nodiscard]] virtual QString plaintextContent() const; 0082 [[nodiscard]] virtual QString htmlContent() const; 0083 0084 /** The KMime::Content* node that's represented by this part. 0085 * Can be @c nullptr, e.g. for sub-parts of an inline signed body part. 0086 */ 0087 [[nodiscard]] KMime::Content *content() const; 0088 void setContent(KMime::Content *node); 0089 0090 /** The KMime::Content* node that's the source of this part. 0091 * This is not necessarily the same as content(), for example for 0092 * broken-up multipart nodes. 0093 */ 0094 [[nodiscard]] KMime::Content *attachmentContent() const; 0095 void setAttachmentContent(KMime::Content *node); 0096 [[nodiscard]] bool isAttachment() const; 0097 /** @see KMime::Content::index() */ 0098 [[nodiscard]] QString attachmentIndex() const; 0099 /** @see NodeHelper::asHREF */ 0100 [[nodiscard]] QString attachmentLink() const; 0101 0102 /** Returns a string representation of an URL that can be used 0103 * to invoke a BodyPartURLHandler for this body part. 0104 */ 0105 [[nodiscard]] QString makeLink(const QString &path) const; 0106 0107 void setIsRoot(bool root); 0108 [[nodiscard]] bool isRoot() const; 0109 0110 virtual bool isHtml() const; 0111 0112 [[nodiscard]] bool neverDisplayInline() const; 0113 void setNeverDisplayInline(bool displayInline); 0114 [[nodiscard]] bool isImage() const; 0115 void setIsImage(bool image); 0116 0117 PartMetaData *partMetaData() const; 0118 0119 Interface::BodyPartMemento *memento() const; 0120 void setMemento(Interface::BodyPartMemento *memento); 0121 0122 /* only a function that should be removed if the refactoring is over */ 0123 virtual void fix() const; 0124 0125 void appendSubPart(const MessagePart::Ptr &messagePart); 0126 const QList<MessagePart::Ptr> &subParts() const; 0127 [[nodiscard]] bool hasSubParts() const; 0128 void clearSubParts(); 0129 0130 Interface::ObjectTreeSource *source() const; 0131 NodeHelper *nodeHelper() const; 0132 0133 [[nodiscard]] virtual bool hasHeader(const char *headerType) const; 0134 virtual const KMime::Headers::Base *header(const char *headerType) const; 0135 virtual QList<KMime::Headers::Base *> headers(const char *headerType) const; 0136 0137 protected: 0138 void parseInternal(KMime::Content *node, bool onlyOneMimePart); 0139 [[nodiscard]] QString renderInternalText() const; 0140 0141 ObjectTreeParser *mOtp = nullptr; 0142 0143 private: 0144 std::unique_ptr<MessagePartPrivate> d; 0145 }; 0146 /** 0147 * @brief The MimeMessagePart class 0148 */ 0149 class MIMETREEPARSER_EXPORT MimeMessagePart : public MessagePart 0150 { 0151 Q_OBJECT 0152 public: 0153 using Ptr = QSharedPointer<MimeMessagePart>; 0154 MimeMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, bool onlyOneMimePart); 0155 ~MimeMessagePart() override; 0156 0157 [[nodiscard]] QString text() const override; 0158 0159 [[nodiscard]] QString plaintextContent() const override; 0160 [[nodiscard]] QString htmlContent() const override; 0161 0162 private: 0163 const bool mOnlyOneMimePart; 0164 }; 0165 /** 0166 * @brief The MessagePartList class 0167 */ 0168 class MIMETREEPARSER_EXPORT MessagePartList : public MessagePart 0169 { 0170 Q_OBJECT 0171 public: 0172 using Ptr = QSharedPointer<MessagePartList>; 0173 explicit MessagePartList(MimeTreeParser::ObjectTreeParser *otp); 0174 ~MessagePartList() override; 0175 0176 [[nodiscard]] QString text() const override; 0177 0178 [[nodiscard]] QString plaintextContent() const override; 0179 [[nodiscard]] QString htmlContent() const override; 0180 }; 0181 0182 enum IconType { NoIcon = 0, IconExternal, IconInline }; 0183 /** 0184 * @brief The TextMessagePart class 0185 */ 0186 class MIMETREEPARSER_EXPORT TextMessagePart : public MessagePartList 0187 { 0188 Q_OBJECT 0189 Q_PROPERTY(bool showLink READ showLink CONSTANT) 0190 Q_PROPERTY(bool isFirstTextPart READ isFirstTextPart CONSTANT) 0191 Q_PROPERTY(bool hasLabel READ hasLabel CONSTANT) 0192 Q_PROPERTY(QString label READ label CONSTANT) 0193 Q_PROPERTY(QString comment READ comment CONSTANT) 0194 public: 0195 using Ptr = QSharedPointer<TextMessagePart>; 0196 TextMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, bool decryptMessage); 0197 ~TextMessagePart() override; 0198 0199 KMMsgSignatureState signatureState() const; 0200 KMMsgEncryptionState encryptionState() const; 0201 0202 [[nodiscard]] bool decryptMessage() const; 0203 0204 [[nodiscard]] bool showLink() const; 0205 [[nodiscard]] bool isFirstTextPart() const; 0206 [[nodiscard]] bool hasLabel() const; 0207 0208 /** The attachment filename, or the closest approximation thereof we have. */ 0209 [[nodiscard]] QString label() const; 0210 /** A description of this attachment, if provided. */ 0211 [[nodiscard]] QString comment() const; 0212 /** Temporary file containing the part content. */ 0213 [[nodiscard]] QString temporaryFilePath() const; 0214 0215 private: 0216 MIMETREEPARSER_NO_EXPORT void parseContent(); 0217 0218 KMMsgSignatureState mSignatureState; 0219 KMMsgEncryptionState mEncryptionState; 0220 const bool mDecryptMessage; 0221 }; 0222 /** 0223 * @brief The AttachmentMessagePart class 0224 */ 0225 class MIMETREEPARSER_EXPORT AttachmentMessagePart : public TextMessagePart 0226 { 0227 Q_OBJECT 0228 public: 0229 using Ptr = QSharedPointer<AttachmentMessagePart>; 0230 AttachmentMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, bool decryptMessage); 0231 ~AttachmentMessagePart() override; 0232 }; 0233 /** 0234 * @brief The HtmlMessagePart class 0235 */ 0236 class MIMETREEPARSER_EXPORT HtmlMessagePart : public MessagePart 0237 { 0238 Q_OBJECT 0239 public: 0240 using Ptr = QSharedPointer<HtmlMessagePart>; 0241 HtmlMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, MimeTreeParser::Interface::ObjectTreeSource *source); 0242 ~HtmlMessagePart() override; 0243 0244 [[nodiscard]] QString text() const override; 0245 [[nodiscard]] QString plaintextContent() const override; 0246 0247 void fix() const override; 0248 [[nodiscard]] bool isHtml() const override; 0249 0250 [[nodiscard]] QString bodyHtml() const; 0251 0252 private: 0253 QString mBodyHTML; 0254 QByteArray mCharset; 0255 }; 0256 /** 0257 * @brief The AlternativeMessagePart class 0258 */ 0259 class MIMETREEPARSER_EXPORT AlternativeMessagePart : public MessagePart 0260 { 0261 Q_OBJECT 0262 public: 0263 using Ptr = QSharedPointer<AlternativeMessagePart>; 0264 AlternativeMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, Util::HtmlMode preferredMode); 0265 ~AlternativeMessagePart() override; 0266 0267 [[nodiscard]] QString text() const override; 0268 0269 [[nodiscard]] Util::HtmlMode preferredMode() const; 0270 void setPreferredMode(Util::HtmlMode preferredMode); 0271 0272 [[nodiscard]] bool isHtml() const override; 0273 0274 [[nodiscard]] QString plaintextContent() const override; 0275 [[nodiscard]] QString htmlContent() const override; 0276 0277 [[nodiscard]] QList<Util::HtmlMode> availableModes(); 0278 0279 void fix() const override; 0280 0281 const QMap<Util::HtmlMode, MimeMessagePart::Ptr> &childParts() const; 0282 0283 private: 0284 Util::HtmlMode mPreferredMode; 0285 0286 QMap<Util::HtmlMode, KMime::Content *> mChildNodes; 0287 QMap<Util::HtmlMode, MimeMessagePart::Ptr> mChildParts; 0288 }; 0289 /** 0290 * @brief The CertMessagePart class 0291 */ 0292 class MIMETREEPARSER_EXPORT CertMessagePart : public MessagePart 0293 { 0294 Q_OBJECT 0295 public: 0296 using Ptr = QSharedPointer<CertMessagePart>; 0297 CertMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, const QGpgME::Protocol *cryptoProto, bool autoImport); 0298 ~CertMessagePart() override; 0299 0300 [[nodiscard]] QString text() const override; 0301 0302 const GpgME::ImportResult &importResult() const; 0303 0304 private: 0305 bool mAutoImport; 0306 GpgME::ImportResult mImportResult; 0307 const QGpgME::Protocol *mCryptoProto; 0308 }; 0309 /** 0310 * @brief The EncapsulatedRfc822MessagePart class 0311 */ 0312 class MIMETREEPARSER_EXPORT EncapsulatedRfc822MessagePart : public MessagePart 0313 { 0314 Q_OBJECT 0315 public: 0316 using Ptr = QSharedPointer<EncapsulatedRfc822MessagePart>; 0317 EncapsulatedRfc822MessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, const KMime::Message::Ptr &message); 0318 ~EncapsulatedRfc822MessagePart() override; 0319 0320 [[nodiscard]] QString text() const override; 0321 0322 void fix() const override; 0323 0324 const KMime::Message::Ptr message() const; 0325 0326 private: 0327 const KMime::Message::Ptr mMessage; 0328 }; 0329 /** 0330 * @brief The EncryptedMessagePart class 0331 */ 0332 class MIMETREEPARSER_EXPORT EncryptedMessagePart : public MessagePart 0333 { 0334 Q_OBJECT 0335 Q_PROPERTY(bool decryptMessage READ decryptMessage WRITE setDecryptMessage) 0336 Q_PROPERTY(bool isEncrypted READ isEncrypted) 0337 Q_PROPERTY(bool isNoSecKey READ isNoSecKey) 0338 Q_PROPERTY(bool passphraseError READ passphraseError) 0339 public: 0340 using Ptr = QSharedPointer<EncryptedMessagePart>; 0341 EncryptedMessagePart(ObjectTreeParser *otp, const QString &text, const QGpgME::Protocol *cryptoProto, const QString &fromAddress, KMime::Content *node); 0342 0343 ~EncryptedMessagePart() override; 0344 0345 [[nodiscard]] QString text() const override; 0346 0347 void setDecryptMessage(bool decrypt); 0348 [[nodiscard]] bool decryptMessage() const; 0349 0350 void setIsEncrypted(bool encrypted); 0351 [[nodiscard]] bool isEncrypted() const; 0352 0353 [[nodiscard]] bool isDecryptable() const; 0354 0355 [[nodiscard]] bool isNoSecKey() const; 0356 [[nodiscard]] bool passphraseError() const; 0357 0358 void startDecryption(const QByteArray &text, QByteArrayView aCodec); 0359 void startDecryption(KMime::Content *data = nullptr); 0360 0361 void setMementoName(const QByteArray &name); 0362 [[nodiscard]] QByteArray mementoName() const; 0363 0364 [[nodiscard]] QString plaintextContent() const override; 0365 [[nodiscard]] QString htmlContent() const override; 0366 0367 const QGpgME::Protocol *cryptoProto() const; 0368 [[nodiscard]] QString fromAddress() const; 0369 0370 const std::vector<std::pair<GpgME::DecryptionResult::Recipient, GpgME::Key>> &decryptRecipients() const; 0371 0372 [[nodiscard]] bool hasHeader(const char *headerType) const override; 0373 const KMime::Headers::Base *header(const char *headerType) const override; 0374 QList<KMime::Headers::Base *> headers(const char *headerType) const override; 0375 0376 QByteArray mDecryptedData; 0377 0378 private: 0379 /** Handles the decryption of a given content 0380 * returns true if the decryption was successful 0381 * if used in async mode, check if mMetaData.inPogress is true, it initiates a running decryption process. 0382 */ 0383 [[nodiscard]] bool okDecryptMIME(KMime::Content &data); 0384 0385 protected: 0386 bool mPassphraseError; 0387 bool mNoSecKey; 0388 bool mDecryptMessage; 0389 const QGpgME::Protocol *mCryptoProto; 0390 QString mFromAddress; 0391 QByteArray mVerifiedText; 0392 QByteArray mMementoName; 0393 std::vector<std::pair<GpgME::DecryptionResult::Recipient, GpgME::Key>> mDecryptRecipients; 0394 std::shared_ptr<const Kleo::KeyCache> mKeyCache; 0395 0396 friend class EncryptedBodyPartFormatter; 0397 }; 0398 /** 0399 * @brief The SignedMessagePart class 0400 */ 0401 class MIMETREEPARSER_EXPORT SignedMessagePart : public MessagePart 0402 { 0403 Q_OBJECT 0404 Q_PROPERTY(bool isSigned READ isSigned) 0405 public: 0406 using Ptr = QSharedPointer<SignedMessagePart>; 0407 SignedMessagePart(ObjectTreeParser *otp, const QString &text, const QGpgME::Protocol *cryptoProto, const QString &fromAddress, KMime::Content *node); 0408 0409 ~SignedMessagePart() override; 0410 0411 void setIsSigned(bool isSigned); 0412 [[nodiscard]] bool isSigned() const; 0413 0414 void startVerification(const QByteArray &text, QByteArrayView aCodec); 0415 void startVerificationDetached(const QByteArray &text, KMime::Content *textNode, const QByteArray &signature); 0416 0417 void setMementoName(const QByteArray &name); 0418 [[nodiscard]] QByteArray mementoName() const; 0419 0420 QByteArray mDecryptedData; 0421 std::vector<GpgME::Signature> mSignatures; 0422 0423 [[nodiscard]] QString plaintextContent() const override; 0424 [[nodiscard]] QString htmlContent() const override; 0425 0426 const QGpgME::Protocol *cryptoProto() const; 0427 [[nodiscard]] QString fromAddress() const; 0428 0429 [[nodiscard]] bool hasHeader(const char *headerType) const override; 0430 const KMime::Headers::Base *header(const char *headerType) const override; 0431 QList<KMime::Headers::Base *> headers(const char *headerType) const override; 0432 0433 private: 0434 /** Handles the verification of data 0435 * If signature is empty it is handled as inline signature otherwise as detached signature mode. 0436 * Returns true if the verification was successful and the block is signed. 0437 * If used in async mode, check if mMetaData.inProgress is true, it initiates a running verification process. 0438 */ 0439 [[nodiscard]] bool okVerify(const QByteArray &data, const QByteArray &signature, KMime::Content *textNode); 0440 0441 MIMETREEPARSER_NO_EXPORT void sigStatusToMetaData(); 0442 0443 void setVerificationResult(const CompositeMemento *m, KMime::Content *textNode); 0444 0445 protected: 0446 const QGpgME::Protocol *mCryptoProto; 0447 QString mFromAddress; 0448 QByteArray mVerifiedText; 0449 QByteArray mMementoName; 0450 std::shared_ptr<const Kleo::KeyCache> mKeyCache; 0451 0452 friend EncryptedMessagePart; 0453 }; 0454 }