Index: messageviewer/src/viewer/messagepart.h =================================================================== --- messageviewer/src/viewer/messagepart.h +++ messageviewer/src/viewer/messagepart.h @@ -164,6 +164,22 @@ const QString &mMsg; }; +// Make sure the whole content is relative, so that nothing is painted over the header +// if a malicious message uses absolute positioning. +// Also force word wrapping, which is useful for printing, see https://issues.kolab.org/issue3992. +class RootBlock : public HTMLBlock +{ +public: + RootBlock(MessageViewer::HtmlWriter *writer); + virtual ~RootBlock(); + +private: + void internalEnter(); + void internalExit(); + + HtmlWriter* mWriter; +}; + class MessagePart : public Interface::MessagePart { public: @@ -227,14 +243,18 @@ QString text() const Q_DECL_OVERRIDE; void html(bool decorate) Q_DECL_OVERRIDE; + void setRoot(bool root); + bool root() const; + void appendMessagePart(const Interface::MessagePart::Ptr &messagePart); const QVector &messageParts() const; void fix() const Q_DECL_OVERRIDE; void copyContentFrom() const Q_DECL_OVERRIDE; protected: + HTMLBlock::Ptr rootBlock() const; void htmlInternal(bool decorate); private: Index: messageviewer/src/viewer/messagepart.cpp =================================================================== --- messageviewer/src/viewer/messagepart.cpp +++ messageviewer/src/viewer/messagepart.cpp @@ -365,6 +365,38 @@ mWriter->queue(QStringLiteral("\n")); } +RootBlock::RootBlock(HtmlWriter* writer) + : mWriter(writer) +{ + internalEnter(); +} + +RootBlock::~RootBlock() +{ + internalExit(); +} + +void RootBlock::internalEnter() +{ + if (!mWriter || entered) { + return; + } + entered = true; + + mWriter->queue(QStringLiteral("
\n")); +} + +void RootBlock::internalExit() +{ + if (!entered) { + return; + } + + entered = false; + + mWriter->queue(QStringLiteral("
\n")); +} + //------MessagePart----------------------- MessagePart::MessagePart(ObjectTreeParser *otp, const QString &text) @@ -475,14 +507,33 @@ //-----MessagePartList---------------------- MessagePartList::MessagePartList(ObjectTreeParser* otp) : MessagePart(otp, QString()) + , mRoot(false) { } MessagePartList::~MessagePartList() { } +void MessagePartList::setRoot(bool root) +{ + mRoot = root; +} + +bool MessagePartList::root() const +{ + return mRoot; +} + +HTMLBlock::Ptr MessagePartList::rootBlock() const +{ + if (mOtp->htmlWriter() && root()) { + return HTMLBlock::Ptr(new RootBlock(mOtp->htmlWriter())); + } + return HTMLBlock::Ptr(); +} + void MessagePartList::appendMessagePart(const Interface::MessagePart::Ptr& messagePart) { mBlocks.append(messagePart); @@ -497,6 +548,7 @@ { MessageViewer::HtmlWriter *writer = mOtp->htmlWriter(); + const HTMLBlock::Ptr rBlock(rootBlock()); const HTMLBlock::Ptr aBlock(attachmentBlock()); htmlInternal(decorate); Index: messageviewer/src/viewer/objecttreeparser.cpp =================================================================== --- messageviewer/src/viewer/objecttreeparser.cpp +++ messageviewer/src/viewer/objecttreeparser.cpp @@ -316,15 +316,9 @@ mNodeHelper->setNodeUnprocessed(node, true); } - // Make sure the whole content is relative, so that nothing is painted over the header - // if a malicious message uses absolute positioning. - // Also force word wrapping, which is useful for printing, see https://issues.kolab.org/issue3992. - bool isRoot = node->isTopLevel(); - if (isRoot && htmlWriter()) { - htmlWriter()->queue(QStringLiteral("
\n")); - } - + const bool isRoot = node->isTopLevel(); MessagePartList::Ptr mpl(new MessagePartList(this)); + mpl->setRoot(isRoot); for (; node; node = MessageCore::NodeHelper::nextSibling(node)) { if (mNodeHelper->nodeProcessed(node)) { @@ -408,10 +402,6 @@ } } - - if (isRoot && htmlWriter()) { - htmlWriter()->queue(QStringLiteral("
\n")); - } return mpl; }