File indexing completed on 2024-06-16 05:00:15
0001 /* 0002 SPDX-FileCopyrightText: 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net 0003 SPDX-FileCopyrightText: 2009 Andras Mantia <andras@kdab.net> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #pragma once 0009 0010 #include "mimetreeparser_export.h" 0011 0012 #include "mimetreeparser/enums.h" 0013 #include "mimetreeparser/partmetadata.h" 0014 0015 #include <KMime/Headers> 0016 #include <KMime/Message> 0017 0018 #include <QList> 0019 #include <QMap> 0020 #include <QPointer> 0021 #include <QSet> 0022 0023 class QUrl; 0024 0025 namespace MimeTreeParser 0026 { 0027 class AttachmentTemporaryFilesDirs; 0028 class MessagePart; 0029 using MessagePartPtr = QSharedPointer<MessagePart>; 0030 namespace Interface 0031 { 0032 class BodyPartMemento; 0033 } 0034 } 0035 0036 namespace MimeTreeParser 0037 { 0038 /** 0039 * @author Andras Mantia <andras@kdab.net> 0040 */ 0041 class MIMETREEPARSER_EXPORT NodeHelper : public QObject 0042 { 0043 Q_OBJECT 0044 public: 0045 NodeHelper(); 0046 0047 ~NodeHelper() override; 0048 0049 void setNodeProcessed(KMime::Content *node, bool recurse); 0050 void setNodeUnprocessed(KMime::Content *node, bool recurse); 0051 [[nodiscard]] bool nodeProcessed(KMime::Content *node) const; 0052 void clear(); 0053 void forceCleanTempFiles(); 0054 0055 void setEncryptionState(const KMime::Content *node, const KMMsgEncryptionState state); 0056 [[nodiscard]] KMMsgEncryptionState encryptionState(const KMime::Content *node) const; 0057 0058 void setSignatureState(const KMime::Content *node, const KMMsgSignatureState state); 0059 [[nodiscard]] KMMsgSignatureState signatureState(const KMime::Content *node) const; 0060 0061 [[nodiscard]] KMMsgSignatureState overallSignatureState(KMime::Content *node) const; 0062 [[nodiscard]] KMMsgEncryptionState overallEncryptionState(KMime::Content *node) const; 0063 0064 void setPartMetaData(KMime::Content *node, const PartMetaData &metaData); 0065 [[nodiscard]] PartMetaData partMetaData(KMime::Content *node); 0066 0067 /** 0068 * Set the 'Content-Type' by mime-magic from the contents of the body. 0069 * If autoDecode is true the decoded body will be used for mime type 0070 * determination (this does not change the body itself). 0071 */ 0072 static void magicSetType(KMime::Content *node, bool autoDecode = true); 0073 0074 void clearOverrideHeaders(); 0075 void registerOverrideHeader(KMime::Content *message, MessagePartPtr); 0076 [[nodiscard]] bool hasMailHeader(const char *header, const KMime::Content *message) const; 0077 QList<MessagePartPtr> messagePartsOfMailHeader(const char *header, const KMime::Content *message) const; 0078 KMime::Headers::Base const *mailHeaderAsBase(const char *header, const KMime::Content *message) const; 0079 QSharedPointer<KMime::Headers::Generics::AddressList> mailHeaderAsAddressList(const char *header, const KMime::Content *message) const; 0080 QList<KMime::Headers::Base *> headers(const char *header, const KMime::Content *message); 0081 [[nodiscard]] QDateTime dateHeader(KMime::Content *message) const; 0082 0083 /** Attach an extra node to an existing node */ 0084 void attachExtraContent(KMime::Content *topLevelNode, KMime::Content *content); 0085 0086 void cleanExtraContent(KMime::Content *topLevelNode); 0087 0088 /** Get the extra nodes attached to the @param topLevelNode and all sub-nodes of @param topLevelNode */ 0089 [[nodiscard]] QList<KMime::Content *> extraContents(KMime::Content *topLevelNode) const; 0090 0091 /** Return a modified message (node tree) starting from @param topLevelNode that has the original nodes and the extra nodes. 0092 The caller has the responsibility to delete the new message. 0093 */ 0094 [[nodiscard]] KMime::Message *messageWithExtraContent(KMime::Content *topLevelNode); 0095 0096 /** Get a codec suitable for this message part */ 0097 QByteArray codecName(KMime::Content *node) const; 0098 0099 /** Set the charset the user selected for the message to display */ 0100 void setOverrideCodec(KMime::Content *node, const QByteArray &codec); 0101 0102 Interface::BodyPartMemento *bodyPartMemento(KMime::Content *node, const QByteArray &which) const; 0103 0104 void setBodyPartMemento(KMime::Content *node, const QByteArray &which, Interface::BodyPartMemento *memento); 0105 0106 // A flag to remember if the node was embedded. This is useful for attachment nodes, the reader 0107 // needs to know if they were displayed inline or not. 0108 [[nodiscard]] bool isNodeDisplayedEmbedded(KMime::Content *node) const; 0109 void setNodeDisplayedEmbedded(KMime::Content *node, bool displayedEmbedded); 0110 0111 // Same as above, but this time determines if the node was hidden or not 0112 [[nodiscard]] bool isNodeDisplayedHidden(KMime::Content *node) const; 0113 void setNodeDisplayedHidden(KMime::Content *node, bool displayedHidden); 0114 0115 /** 0116 * Writes the given message part to a temporary file and returns the 0117 * name of this file or QString() if writing failed. 0118 */ 0119 QString writeNodeToTempFile(KMime::Content *node); 0120 0121 [[nodiscard]] QString writeFileToTempFile(KMime::Content *node, const QString &filename); 0122 0123 /** 0124 * Returns the temporary file path and name where this node was saved, or an empty url 0125 * if it wasn't saved yet with writeNodeToTempFile() 0126 */ 0127 [[nodiscard]] QUrl tempFileUrlFromNode(const KMime::Content *node); 0128 0129 /** 0130 * Creates a temporary dir for saving attachments, etc. 0131 * Will be automatically deleted when another message is viewed. 0132 * @param param Optional part of the directory name. 0133 */ 0134 [[nodiscard]] QString createTempDir(const QString ¶m = QString()); 0135 0136 /** 0137 * Cleanup the attachment temp files 0138 */ 0139 void removeTempFiles(); 0140 0141 /** 0142 * Add a file to the list of managed temporary files 0143 */ 0144 void addTempFile(const QString &file); 0145 0146 // Get a href in the form attachment:<nodeId>?place=<place>, used by ObjectTreeParser and 0147 // UrlHandlerManager. 0148 [[nodiscard]] QString asHREF(const KMime::Content *node, const QString &place) const; 0149 KMime::Content *fromHREF(const KMime::Message::Ptr &mMessage, const QUrl &href) const; 0150 0151 // Overload which creates a URL without the query part. Used by MessagePart::makeLink. 0152 [[nodiscard]] QString asHREF(const KMime::Content *node) const; 0153 0154 /** 0155 * @return true if this node is a child or an encapsulated message 0156 */ 0157 [[nodiscard]] static bool isInEncapsulatedMessage(KMime::Content *node); 0158 0159 /** 0160 * Returns the charset for the given node. If no charset is specified 0161 * for the node, the defaultCharset() is returned. 0162 */ 0163 [[nodiscard]] static QByteArray charset(KMime::Content *node); 0164 0165 /** 0166 * Returns a usable filename for a node, that can be the filename from the 0167 * content disposition header, or if that one is empty, the name from the 0168 * content type header. 0169 */ 0170 [[nodiscard]] static QString fileName(const KMime::Content *node); 0171 0172 /** 0173 * Fixes an encoding received by a KDE function and returns the proper, 0174 * MIME-compliant encoding name instead. 0175 * @see encodingForName 0176 */ 0177 [[nodiscard]] static QString fixEncoding(const QString &encoding); // TODO(Andras) move to a utility class? 0178 0179 /** 0180 * Drop-in replacement for KCharsets::encodingForName(). The problem with 0181 * the KCharsets function is that it returns "human-readable" encoding names 0182 * like "ISO 8859-15" instead of valid encoding names like "ISO-8859-15". 0183 * This function fixes this by replacing whitespace with a hyphen. 0184 */ 0185 [[nodiscard]] static QString encodingForName(const QString &descriptiveName); // TODO(Andras) move to a utility class? 0186 0187 /** 0188 * Return a list of the supported encodings 0189 * @param usAscii if true, US-Ascii encoding will be prepended to the list. 0190 */ 0191 [[nodiscard]] static QStringList supportedEncodings(bool usAscii); // TODO(Andras) move to a utility class? 0192 0193 [[nodiscard]] QString fromAsString(KMime::Content *node) const; 0194 0195 KMime::Content *decryptedNodeForContent(KMime::Content *content) const; 0196 0197 /** 0198 * This function returns the unencrypted message that is based on @p originalMessage. 0199 * All encrypted MIME parts are removed and replaced by their decrypted plain-text versions. 0200 * Encrypted parts that are within signed parts are not replaced, since that would invalidate 0201 * the signature. 0202 * 0203 * This only works if the message was run through ObjectTreeParser::parseObjectTree() with the 0204 * current NodeHelper before, because parseObjectTree() actually decrypts the message and stores 0205 * the decrypted nodes by calling attachExtraContent(). 0206 * 0207 * @return the unencrypted message or an invalid pointer if the original message didn't contain 0208 * a part that needed to be modified. 0209 */ 0210 KMime::Message::Ptr unencryptedMessage(const KMime::Message::Ptr &originalMessage); 0211 0212 /** 0213 * Returns a list of attachments of attached extra content nodes. 0214 * This is mainly useful is order to get attachments of encrypted messages. 0215 * Note that this does not include attachments from the primary node tree. 0216 * @see KMime::Content::attachments(). 0217 */ 0218 [[nodiscard]] QList<KMime::Content *> attachmentsOfExtraContents() const; 0219 0220 [[nodiscard]] QString extractAttachmentIndex(const QString &path) const; 0221 Q_SIGNALS: 0222 void update(MimeTreeParser::UpdateMode); 0223 0224 private: 0225 Q_DISABLE_COPY(NodeHelper) 0226 bool unencryptedMessage_helper(KMime::Content *node, QByteArray &resultingData, bool addHeaders, int recursionLevel = 1); 0227 0228 MIMETREEPARSER_NO_EXPORT void mergeExtraNodes(KMime::Content *node); 0229 MIMETREEPARSER_NO_EXPORT void cleanFromExtraNodes(KMime::Content *node); 0230 0231 /** Creates a persistent index string that bridges the gap between the 0232 permanent nodes and the temporary ones. 0233 0234 Used internally for robust indexing. 0235 **/ 0236 [[nodiscard]] QString persistentIndex(const KMime::Content *node) const; 0237 0238 /** Translates the persistentIndex into a node back 0239 0240 node: any node of the actually message to what the persistentIndex is interpreded 0241 **/ 0242 KMime::Content *contentFromIndex(KMime::Content *node, const QString &persistentIndex) const; 0243 0244 private: 0245 QList<KMime::Content *> mProcessedNodes; 0246 QList<KMime::Content *> mNodesUnderProcess; 0247 QMap<const KMime::Content *, KMMsgEncryptionState> mEncryptionState; 0248 QMap<const KMime::Content *, KMMsgSignatureState> mSignatureState; 0249 QSet<KMime::Content *> mDisplayEmbeddedNodes; 0250 QSet<KMime::Content *> mDisplayHiddenNodes; 0251 QMap<KMime::Content *, QByteArray> mOverrideCodecs; 0252 QMap<QString, QMap<QByteArray, Interface::BodyPartMemento *>> mBodyPartMementoMap; 0253 QMap<KMime::Content *, PartMetaData> mPartMetaDatas; 0254 QMap<KMime::Message::Content *, QList<KMime::Content *>> mExtraContents; 0255 QPointer<AttachmentTemporaryFilesDirs> mAttachmentFilesDir; 0256 QMap<const KMime::Content *, QList<MessagePartPtr>> mHeaderOverwrite; 0257 QList<QPointer<AttachmentTemporaryFilesDirs>> mListAttachmentTemporaryDirs; 0258 friend class NodeHelperTest; 0259 }; 0260 }