messageviewer
#include <objecttreeparser.h>
Public Member Functions | |
ObjectTreeParser (ObjectTreeSourceIf *source, NodeHelper *nodeHelper=0, const Kleo::CryptoBackend::Protocol *protocol=0, bool showOneMimePart=false, bool keepEncryptions=false, bool includeSignatures=true, const AttachmentStrategy *attachmentStrategy=0) | |
ObjectTreeParser (const ObjectTreeParser *topLevelParser, bool showOneMimePart=false, bool keepEncryptions=false, bool includeSignatures=true, const AttachmentStrategy *attachmentStrategy=0) | |
virtual | ~ObjectTreeParser () |
bool | allowAsync () const |
const AttachmentStrategy * | attachmentStrategy () const |
QString | convertedHtmlContent () const |
QString | convertedTextContent () const |
const Kleo::CryptoBackend::Protocol * | cryptoProtocol () const |
CSSHelper * | cssHelper () const |
bool | decryptChiasmus (const QByteArray &data, QByteArray &bodyDecoded, QString &errorText) |
bool | hasPendingAsyncJobs () const |
QString | htmlContent () const |
QByteArray | htmlContentCharset () const |
HtmlWriter * | htmlWriter () const |
bool | includeSignatures () const |
bool | isMailmanMessage (KMime::Content *curNode) |
bool | keepEncryptions () const |
NodeHelper * | nodeHelper () const |
void | parseObjectTree (KMime::Content *node) |
QString | plainTextContent () const |
QByteArray | plainTextContentCharset () const |
bool | processApplicationChiasmusTextSubtype (KMime::Content *node, ProcessResult &result) |
bool | processApplicationOctetStreamSubtype (KMime::Content *node, ProcessResult &result) |
bool | processApplicationPkcs7MimeSubtype (KMime::Content *node, ProcessResult &result) |
bool | processMessageRfc822Subtype (KMime::Content *node, ProcessResult &result) |
bool | processMultiPartAlternativeSubtype (KMime::Content *node, ProcessResult &result) |
bool | processMultiPartDigestSubtype (KMime::Content *node, ProcessResult &result) |
bool | processMultiPartEncryptedSubtype (KMime::Content *node, ProcessResult &result) |
bool | processMultiPartMixedSubtype (KMime::Content *node, ProcessResult &result) |
bool | processMultiPartParallelSubtype (KMime::Content *node, ProcessResult &result) |
bool | processMultiPartSignedSubtype (KMime::Content *node, ProcessResult &result) |
bool | processTextHtmlSubtype (KMime::Content *node, ProcessResult &result) |
bool | processTextPlainSubtype (KMime::Content *node, ProcessResult &result) |
KDE_DEPRECATED QByteArray | rawDecryptedBody () const |
void | setAllowAsync (bool allow) |
void | setCryptoProtocol (const Kleo::CryptoBackend::Protocol *protocol) |
void | setIncludeSignatures (bool include) |
void | setKeepEncryptions (bool keep) |
void | setPrinting (bool printing) |
void | setShowOnlyOneMimePart (bool show) |
void | setShowRawToltecMail (bool showRawToltecMail) |
bool | showOnlyOneMimePart () const |
bool | showRawToltecMail () const |
QString | sigStatusToString (const Kleo::CryptoBackend::Protocol *cryptProto, int status_code, GpgME::Signature::Summary summary, int &frameColor, bool &showKeyInfos) |
void | writeAttachmentMarkFooter () |
void | writeAttachmentMarkHeader (KMime::Content *node) |
void | writeBodyStr (const QByteArray &bodyString, const QTextCodec *aCodec, const QString &fromAddress, KMMsgSignatureState &inlineSignatureState, KMMsgEncryptionState &inlineEncryptionState, bool decorate) |
void | writeBodyStr (const QByteArray &bodyString, const QTextCodec *aCodec, const QString &fromAddress) |
void | writeBodyString (const QByteArray &bodyString, const QString &fromAddress, const QTextCodec *codec, ProcessResult &result, bool decorate) |
void | writePartIcon (KMime::Content *msgPart, bool inlineImage=false) |
QString | writeSigstatFooter (PartMetaData &part) |
QString | writeSigstatHeader (PartMetaData &part, const Kleo::CryptoBackend::Protocol *cryptProto, const QString &fromAddress, KMime::Content *node=0) |
Static Public Member Functions | |
static QString | defaultToltecReplacementText () |
static KMime::Content * | findType (KMime::Content *content, const QByteArray &mimeType, bool deep, bool wide) |
static KMime::Content * | findType (KMime::Content *content, const QByteArray &mediaType, const QByteArray &subType, bool deep, bool wide) |
static KMime::Content * | findTypeNot (KMime::Content *content, const QByteArray &mediaType, const QByteArray &subType, bool deep=true, bool wide=true) |
Detailed Description
Parses messages and generates HTML display code out of them.
- Introduction
First, have a look at the documentation in Mainpage.dox and at the documentation of ViewerPrivate to understand the broader picture.
Just a note on the terminology: 'Node' refers to a MIME part here, which in KMime is a KMime::Content.
- Basics
The ObjectTreeParser basically has two modes: Generating the HTML code for the Viewer, or only extracting the plainTextContent() for situations where only the message text is needed, for example when inline forwarding a message. The mode depends on the ObjectTreeSourceIf passed to the constructor: If ObjectTreeSourceIf::htmlWriter() is not 0, then the HTML code generation mode is used.
Basically, all the ObjectTreeParser does is going through the tree of MIME parts and operating on those nodes. Operating here means creating the HTML code for the node or extracting the textual content from it. This process is started with parseObjectTree(), where we loop over the subnodes of the current root node. For each of those subnodes, we try to find a BodyPartFormatter that can handle the type of the node. This can either be an internal function, such as processMultiPartAlternativeSubtype() or processTextHtmlSubtype(), or it can be an external plugin. More on external plugins later. When no matching formatter is found, defaultHandling() is called for that node.
- Multipart Nodes
Those nodes that are of type multipart have subnodes. If one of those children needs to be processed normally, the processMultipartXXX() functions call stdChildHandling() for the node that should be handled normally. stdChildHandling() creates its own ObjectTreeParser, which is a clone of the current ObjectTreeParser, and processes the node. stdChildHandling() is not called for all children of the multipart node, for example processMultiPartAlternativeSubtype() only calls it on one of the children, as the other one doesn't need to be displayed. Similary, processMultiPartSignedSubtype() doesn't call stdChildHandling() for the signature node, only for the signed node.
- Processed and Unprocessed Nodes
When a BodyPartFormatter has finished processing a node, it is processed. Nodes are set to being not processed at the beginning of parseObjectTree(). The processed state of a node is saved in a list in NodeHelper, see NodeHelper::setNodeProcessed(), NodeHelper::nodeProcessed() and the other related helper functions.
It is the responsibility of the BodyPartFormatter to correctly call setNodeProcessed() and the related functions. This is important so that processing the same node twice can be prevented. The check that prevents duplicate processing is in parseObjectTree().
An example where duplicate processing would happen if we didn't check for it is in stdChildHandling(), which is for example called from processMultiPartAlternativeSubtype(). Let's say the setting is to prefer HTML over plain text. In this case, processMultiPartAlternativeSubtype() would call stdChildHandling() on the HTML node, which would create a new ObjectTreeParser and call parseObjectTree() on it. parseObjectTree() processes the node and all its siblings, and one of the siblings is the plain text node, which shouldn't be processed! Therefore processMultiPartAlternativeSubtype() sets the plain text node as been processed already.
- Plain Text Output
Various nodes have plain text that should be displayed. This plain text is usually processed though writeBodyString() first. That method checks if the provided text is an inline PGP text and decrypts it if necessary. It also pushes the text through quotedHTML(), which does a number of things like coloring quoted lines or detecting links and creating real link tags for them.
- Modifying the Message
The ObjectTreeParser does not only parse its message, in some circumstances it also modifies it before displaying. This is for example the case when displaying a decrypted message: The original message only contains a binary blob of crypto data, and processMultiPartEncryptedSubtype() decrypts that blob. After decryption, the current node is replaced with the decrypted node, which happens in insertAndParseNewChildNode().
- Crypto Operations
For signature and decryption handling, there are functions which help with generating the HTML code for the signature header and footer. These are writeDeferredDecryptionBlock(), writeSigstatFooter() and writeSigstatHeader(). As the name writeDeferredDecryptionBlock() suggests, a setting can cause the message to not be decrypted unless the user clicks a link. Whether the message should be decrypted or not can be controlled by ObjectTreeSourceIf::decryptMessage(). When the user clicks the decryption link, the URLHandler for 'kmail:' URLs sets that variable to true and triggers an update of the Viewer, which will cause parseObjectTree() to be called again.
- Async Crypto Operations
The above case describes decryption the message in place. However, decryption and also verifying of the signature can take a long time, so synchronous decryption and verifing would cause the Viewer to block. Therefore it is possible to run these operations in async mode, see allowAsync(). In the first run of the async mode, all the ObjectTreeParser does is starting the decrypt or the verify job, and informing the user that the operation is in progress with writeDecryptionInProgressBlock() or with writeSigstatHeader(). Then, it creates and associates a BodyPartMemento with the current node, for example a VerifyDetachedBodyPartMemento. Each node can have multiple mementos associated with it, which are differeniated by name.
NodeHelper::setBodyPartMemento() and NodeHelper::bodyPartMemento() provide means to store and retrieve these mementos. A memento is basically a thin wrapper around the crypto job, it stores the job pointer, the job input data and the job result. Mementos can be used for any async situation, not just for crypto jobs, but I'll describe crypto jobs here.
So in the first run of decrypting or verifying a message, the BodyPartFormatter only starts the crypto job, creates the BodyPartMemento and writes the HTML code that tells the user that the operation is in progress. parseObjectTree() thus finishes without waiting for anything, and the message is displayed.
At some point, the crypto jobs then finish, which will cause slotResult() of the BodyPartMemento to be called. slotResult() then saves the result to some member variable and calls BodyPartMemento::notify(), which in the end will trigger an update of the Viewer. That update will, in ViewerPrivate::parseMsg(), create a new ObjectTreeParser and call parseObjectTree() on it. This is where the second run begins.
The functions that deal with decrypting of verifying, like processMultiPartSignedSubtype() or processMultiPartEncryptedSubtype() will look if they find a BodyPartMemento that is associated with the current node. Now it finds that memento, since it was created in the first run. It checks if the memento's job has finished, and if so, the result can be written out (either the decrypted data or the verified signature).
When dealing with encrypted nodes, new nodes are created with the decrypted data. It is important to note that the original MIME tree is never modified, and remains the same as the original one. The method createAndParseTempNode is called with the newly decrypted data, and it generates a new temporary node to store the decrypted data. When these nodes are created, it is important to keep track of them as otherwise some mementos that are added to the newly created temporary nodes will be constantly regenerated. As the regeneration triggers a viewer update when complete, it results in an infinite refresh loop. The function NodeHelper::linkAsPermanentDecrypted will create a link between the newly created node and the original parent. Conversely, the function NodeHelper::attachExtraContent will create a link in the other direction, from the parent node to the newly created temporary node.
When generating some mementos for nodes that may be temporary nodes (for example, contact photo mementos), the function NodeHelper::setBodyPartMementoForPermanentParent is used. This will save the given body part memento for the closest found permanent parent node, rather than the transient node itself. Then when checking for the existence of a certain memento in a node, NodeHelper::findPermanentParentBodyPartMemento will check to see if any parent of the given temporary node is a permanent (encrypted) node that has been used to generate the asked-for node.
To conclude: For async operations, parseObjectTree() is called twice: The first call starts the crypto operation and creates the BodyPartMemento, the second calls sees that the BodyPartMemento is there and can use its result for writing out the HTML.
- PartMetaData and ProcessResult
For crypto operations, the class PartMetaData is used a lot, mainly to pass around info about the crypto state of a node. A PartMetaData can also be associated with a node by using NodeHelper::setPartMetaData(). The only user of that however is MessageAnalyzer::processPart() of the Nepomuk E-Mail Feeder, which also uses the ObjectTreeParser to analyze the message.
You'll notice that a ProcessResult is passed to each formatter. The formatter is supposed to modify the ProcessResult to tell the callers something about the state of the nodes that were processed. One example for its use is to tell the caller about the crypto state of the node.
- BodyPartFormatter Plugins
As mentioned way earlier, BodyPartFormatter can either be plugins or be internal. bodypartformatter.cpp contains some trickery so that the processXXX() methods of the ObjectTreeParser are called from a BodyPartFormatter associated with them, see the CREATE_BODY_PART_FORMATTER macro.
The BodyPartFormatter code is work in progress, it was supposed to be refactored, but that has not yet happened at the time of writing. Therefore the code can seem a bit chaotic.
External plugins are loaded with loadPlugins() in bodypartformatterfactory.cpp. External plugins can only use the classes in the interfaces/ directory, they include BodyPart, BodyPartMemento, BodyPartFormatterPlugin, BodyPartFormatter, BodyPartURLHandler, HtmlWriter and URLHandler. Therefore external plugins have powerful capabilities, which are needed for example in the iCal formatter or in the vCard formatter.
- Special HTML tags
As also mentioned in the documentation of ViewerPrivate, the ObjectTreeParser writes out special links that are only understood by the viewer, for example 'kmail:' URLs or 'attachment:' URLs. Also, some special HTML tags are created, which the Viewer later uses for post-processing. For example a div with the id 'attachmentInjectionPoint', or a div with the id 'attachmentDiv', which is used to mark an attachment in the body with a yellow border when the user clicks the attachment in the header. Finally, parseObjectTree() creates an anchor with the id 'att%1', which is used in the Viewer to scroll to the attachment.
Definition at line 287 of file objecttreeparser.h.
Constructor & Destructor Documentation
|
explicit |
Definition at line 168 of file objecttreeparser.cpp.
|
explicit |
Definition at line 149 of file objecttreeparser.cpp.
|
virtual |
Definition at line 220 of file objecttreeparser.cpp.
Member Function Documentation
|
inline |
Definition at line 310 of file objecttreeparser.h.
|
inline |
Definition at line 398 of file objecttreeparser.h.
QString ObjectTreeParser::convertedHtmlContent | ( | ) | const |
Returns a HTML version of the plain text mail.
If the HTML content is already available, it returns the HTML content as it is.
Definition at line 3542 of file objecttreeparser.cpp.
QString ObjectTreeParser::convertedTextContent | ( | ) | const |
Returns a plain text version of the content, which is either plainTextContent() if that exists, or htmlContent() converted to plain text otherwise.
Definition at line 3525 of file objecttreeparser.cpp.
|
inline |
Definition at line 370 of file objecttreeparser.h.
|
inline |
Definition at line 404 of file objecttreeparser.h.
bool ObjectTreeParser::decryptChiasmus | ( | const QByteArray & | data, |
QByteArray & | bodyDecoded, | ||
QString & | errorText | ||
) |
Definition at line 2070 of file objecttreeparser.cpp.
|
static |
Default text for processToltecMail(), which is used in messageviewer.kcfg, therefore it needs to be static here.
Definition at line 1478 of file objecttreeparser.cpp.
|
static |
Definition at line 3474 of file objecttreeparser.cpp.
|
static |
Definition at line 3490 of file objecttreeparser.cpp.
|
static |
Definition at line 3508 of file objecttreeparser.cpp.
|
inline |
Definition at line 312 of file objecttreeparser.h.
|
inline |
Similar to plainTextContent(), but returns the HTML source of the first text/html MIME part.
Not to be consfused with the HTML code that the message viewer widget displays, that HTML is written out by htmlWriter() and a totally different pair of shoes.
Definition at line 345 of file objecttreeparser.h.
|
inline |
Definition at line 365 of file objecttreeparser.h.
|
inline |
Definition at line 402 of file objecttreeparser.h.
|
inline |
Definition at line 384 of file objecttreeparser.h.
bool ObjectTreeParser::isMailmanMessage | ( | KMime::Content * | curNode | ) |
Definition at line 1283 of file objecttreeparser.cpp.
|
inline |
Definition at line 379 of file objecttreeparser.h.
|
inline |
Definition at line 406 of file objecttreeparser.h.
void ObjectTreeParser::parseObjectTree | ( | KMime::Content * | node | ) |
Parse beginning at a given node and recursively parsing the children of that node and it's next sibling.
Definition at line 268 of file objecttreeparser.cpp.
|
inline |
The text of the message, ie.
what would appear in the composer's text editor if this was edited or replied to. This is usually the content of the first text/plain MIME part.
Definition at line 337 of file objecttreeparser.h.
|
inline |
The original charset of MIME part the plain text was extracted from.
If there were more than one text/plain MIME parts in the mail, the this is the charset of the last MIME part processed.
Definition at line 364 of file objecttreeparser.h.
bool ObjectTreeParser::processApplicationChiasmusTextSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 2147 of file objecttreeparser.cpp.
bool ObjectTreeParser::processApplicationOctetStreamSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1829 of file objecttreeparser.cpp.
bool ObjectTreeParser::processApplicationPkcs7MimeSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1911 of file objecttreeparser.cpp.
bool ObjectTreeParser::processMessageRfc822Subtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1779 of file objecttreeparser.cpp.
bool ObjectTreeParser::processMultiPartAlternativeSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1511 of file objecttreeparser.cpp.
bool ObjectTreeParser::processMultiPartDigestSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1569 of file objecttreeparser.cpp.
bool ObjectTreeParser::processMultiPartEncryptedSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1631 of file objecttreeparser.cpp.
bool ObjectTreeParser::processMultiPartMixedSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1496 of file objecttreeparser.cpp.
bool ObjectTreeParser::processMultiPartParallelSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1573 of file objecttreeparser.cpp.
bool ObjectTreeParser::processMultiPartSignedSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1577 of file objecttreeparser.cpp.
bool ObjectTreeParser::processTextHtmlSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1212 of file objecttreeparser.cpp.
bool ObjectTreeParser::processTextPlainSubtype | ( | KMime::Content * | node, |
ProcessResult & | result | ||
) |
Definition at line 1407 of file objecttreeparser.cpp.
|
inline |
The origin and purpose of this function is unknown, the ancient wisdom about it got lost during the centuries.
Historicans believe that the intent of the function is to return the raw body of the mail, i.e. no charset decoding has been done yet. Sometimes CTE decoding has been done, sometimes not. For encrypted parts, this returns the content of the decrypted part. For a mail with multiple MIME parts, the results are conecated together. Not all parts are included in this.
Although conecating multiple undecoded body parts with potentially different CTEs together might not seem to make any sense in these modern times, it is assumed that initially this function performed quite well, but the ancient scrolls got damaged with the ravages of time and were re-written multiple times.
Do not use. Use plainTextContent() and htmlContent() instead.
Definition at line 330 of file objecttreeparser.h.
|
inline |
Definition at line 309 of file objecttreeparser.h.
|
inline |
Definition at line 367 of file objecttreeparser.h.
|
inline |
Definition at line 385 of file objecttreeparser.h.
|
inline |
Definition at line 380 of file objecttreeparser.h.
void ObjectTreeParser::setPrinting | ( | bool | printing | ) |
Definition at line 274 of file objecttreeparser.cpp.
|
inline |
Definition at line 375 of file objecttreeparser.h.
|
inline |
Definition at line 391 of file objecttreeparser.h.
|
inline |
Definition at line 374 of file objecttreeparser.h.
|
inline |
Definition at line 392 of file objecttreeparser.h.
QString ObjectTreeParser::sigStatusToString | ( | const Kleo::CryptoBackend::Protocol * | cryptProto, |
int | status_code, | ||
GpgME::Signature::Summary | summary, | ||
int & | frameColor, | ||
bool & | showKeyInfos | ||
) |
Definition at line 2245 of file objecttreeparser.cpp.
void ObjectTreeParser::writeAttachmentMarkFooter | ( | ) |
Definition at line 2938 of file objecttreeparser.cpp.
void ObjectTreeParser::writeAttachmentMarkHeader | ( | KMime::Content * | node | ) |
Definition at line 2928 of file objecttreeparser.cpp.
void ObjectTreeParser::writeBodyStr | ( | const QByteArray & | bodyString, |
const QTextCodec * | aCodec, | ||
const QString & | fromAddress, | ||
KMMsgSignatureState & | inlineSignatureState, | ||
KMMsgEncryptionState & | inlineEncryptionState, | ||
bool | decorate | ||
) |
Definition at line 2958 of file objecttreeparser.cpp.
void ObjectTreeParser::writeBodyStr | ( | const QByteArray & | bodyString, |
const QTextCodec * | aCodec, | ||
const QString & | fromAddress | ||
) |
Definition at line 2949 of file objecttreeparser.cpp.
void ObjectTreeParser::writeBodyString | ( | const QByteArray & | bodyString, |
const QString & | fromAddress, | ||
const QTextCodec * | codec, | ||
ProcessResult & | result, | ||
bool | decorate | ||
) |
Definition at line 2185 of file objecttreeparser.cpp.
void ObjectTreeParser::writePartIcon | ( | KMime::Content * | msgPart, |
bool | inlineImage = false |
||
) |
Definition at line 2200 of file objecttreeparser.cpp.
QString ObjectTreeParser::writeSigstatFooter | ( | PartMetaData & | part | ) |
Definition at line 2896 of file objecttreeparser.cpp.
QString ObjectTreeParser::writeSigstatHeader | ( | PartMetaData & | part, |
const Kleo::CryptoBackend::Protocol * | cryptProto, | ||
const QString & | fromAddress, | ||
KMime::Content * | node = 0 |
||
) |
Definition at line 2501 of file objecttreeparser.cpp.
The documentation for this class was generated from the following files:
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:32:46 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.