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 }