Index: messageviewer/src/CMakeLists.txt =================================================================== --- messageviewer/src/CMakeLists.txt +++ messageviewer/src/CMakeLists.txt @@ -161,6 +161,7 @@ set(libmessageviewer_htmlwriter_SRCS htmlwriter/filehtmlwriter.cpp + htmlwriter/queuehtmlwriter.cpp htmlwriter/teehtmlwriter.cpp htmlwriter/webkitparthtmlwriter.cpp ) Index: messageviewer/src/htmlwriter/queuehtmlwriter.h =================================================================== --- /dev/null +++ messageviewer/src/htmlwriter/queuehtmlwriter.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- + queuehtmlwriter.h + + Copyright (c) 2015 Sandro Knauß + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + KMail is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __MESSAGEVIEWER_QUEUEHTMLWRITER_H__ +#define __MESSAGEVIEWER_QUEUEHTMLWRITER_H__ + +#include "messageviewer_export.h" +#include "interfaces/htmlwriter.h" + +#include +#include + +class QString; +class QByteArray; + +namespace MessageViewer +{ + +class MESSAGEVIEWER_EXPORT QueueHtmlWriter : public HtmlWriter +{ +public: + explicit QueueHtmlWriter( MessageViewer::HtmlWriter* base ); + virtual ~QueueHtmlWriter(); + + void begin(const QString &cssDefs) Q_DECL_OVERRIDE; + void end() Q_DECL_OVERRIDE; + void reset() Q_DECL_OVERRIDE; + void write(const QString &str) Q_DECL_OVERRIDE; + void queue(const QString &str) Q_DECL_OVERRIDE; + void flush() Q_DECL_OVERRIDE; + void embedPart(const QByteArray &contentId, const QString &url) Q_DECL_OVERRIDE; + void extraHead(const QString &str) Q_DECL_OVERRIDE; + + void reply(); + +private: + HtmlWriter *mBase; + QVector mQueue; +}; + +} // namespace MessageViewer + +#endif // __MESSAGEVIEWER_QUEUEHTMLWRITER_H__ Index: messageviewer/src/htmlwriter/queuehtmlwriter.cpp =================================================================== --- /dev/null +++ messageviewer/src/htmlwriter/queuehtmlwriter.cpp @@ -0,0 +1,114 @@ +/* -*- c++ -*- + queuehtmlwriter.h + + Copyright (c) 2015 Sandro Knauß + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + KMail is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "queuehtmlwriter.h" + +#include "messageviewer_debug.h" + +#include +#include + +using namespace MessageViewer; + +QueueHtmlWriter::QueueHtmlWriter(HtmlWriter *base) + : HtmlWriter() + , mBase(base) +{ +} + +QueueHtmlWriter::~QueueHtmlWriter() +{ +} + +void QueueHtmlWriter::begin(const QString &css) +{ + mQueue.append(QVariantList() << QByteArray("begin") << css); +} + +void QueueHtmlWriter::end() +{ + mQueue.append(QVariantList() << QByteArray("end")); +} + +void QueueHtmlWriter::reset() +{ + mQueue.append(QVariantList() << QByteArray("reset")); +} + +void QueueHtmlWriter::write(const QString &str) +{ + mQueue.append(QVariantList() << QByteArray("write") << str); +} + +void QueueHtmlWriter::queue(const QString &str) +{ + mQueue.append(QVariantList() << QByteArray("queue") << str); +} + +void QueueHtmlWriter::flush() +{ + mQueue.append(QVariantList() << QByteArray("flush")); +} + +void QueueHtmlWriter::reply() +{ + foreach(auto entry, mQueue) + { + const QByteArray name(entry.first().toByteArray()); + + if (name == QByteArray("begin")) { + mBase->begin(entry[1].toString()); + } else if (name == QByteArray("end")) { + mBase->end(); + } else if (name == QByteArray("reset")) { + mBase->reset(); + } else if (name == QByteArray("write")) { + mBase->write(entry[1].toString()); + } else if (name == QByteArray("queue")) { + mBase->queue(entry[1].toString()); + } else if (name == QByteArray("flush")) { + mBase->flush(); + } else if (name == QByteArray("embedPart")) { + mBase->embedPart(entry[1].toByteArray(), entry[2].toString()); + } else if (name == QByteArray("extraHead")) { + mBase->extraHead(entry[1].toString()); + } + } +} + +void QueueHtmlWriter::embedPart(const QByteArray &contentId, const QString &url) +{ + mQueue.append(QVariantList() << QByteArray("embedPart") << contentId << url); +} +void QueueHtmlWriter::extraHead(const QString &extra) +{ + mQueue.append(QVariantList() << QByteArray("extraHead") << extra); +} \ No newline at end of file Index: messageviewer/src/viewer/messagepart.h =================================================================== --- messageviewer/src/viewer/messagepart.h +++ messageviewer/src/viewer/messagepart.h @@ -73,6 +73,8 @@ PartMetaData *block, const QString &text); + virtual ~MessagePart() {} + virtual QString text() const; void setText(const QString &text); virtual void html(bool decorate) const; @@ -96,6 +98,8 @@ const QString &fromAddress, KMime::Content *node); + virtual ~CryptoMessagePart(); + void startDecryption(const QByteArray &text, const QTextCodec *aCodec); void startDecryption(KMime::Content *data = 0); void startVerification(const QByteArray &text, const QTextCodec *aCodec); @@ -112,12 +116,13 @@ void writeDeferredDecryptionBlock() const; protected: + ObjectTreeParser *mSubOtp; const Kleo::CryptoBackend::Protocol *mCryptoProto; QString mFromAddress; - KMime::Content *mNode, *mTextNode; + KMime::Content *mNode; bool mDecryptMessage; QByteArray mVerifiedText; }; } #endif //_MESSAGEVIEWER_MESSAGEPART_H_ \ No newline at end of file Index: messageviewer/src/viewer/messagepart.cpp =================================================================== --- messageviewer/src/viewer/messagepart.cpp +++ messageviewer/src/viewer/messagepart.cpp @@ -21,6 +21,7 @@ #include "objecttreeparser.h" #include +#include #include #include #include @@ -128,11 +129,11 @@ const QString &fromAddress, KMime::Content *node) : MessagePart(otp, block, text) + , mSubOtp(0) , mCryptoProto(cryptoProto) , mDecryptMessage(false) , mFromAddress(fromAddress) , mNode(node) - , mTextNode(0) { mMetaData->technicalProblem = (mCryptoProto == 0); mMetaData->isSigned = false; @@ -144,6 +145,16 @@ mMetaData->status_code = GPGME_SIG_STAT_NONE; } +CryptoMessagePart::~CryptoMessagePart() +{ + if (mSubOtp) { + delete mSubOtp->mHtmlWriter; + delete mSubOtp; + mSubOtp = 0; + } +} + + void CryptoMessagePart::startDecryption(const QByteArray &text, const QTextCodec *aCodec) { mDecryptMessage = true; @@ -203,6 +214,24 @@ if (mNode) { mOtp->mNodeHelper->setPartMetaData(mNode, *mMetaData); + + if (mDecryptMessage) { + auto tempNode = new KMime::Content(); + tempNode->setContent(KMime::CRLFtoLF(mDecryptedData.constData())); + tempNode->parse(); + + if (!tempNode->head().isEmpty()) { + tempNode->contentDescription()->from7BitString("encrypted data"); + } + mOtp->mNodeHelper->attachExtraContent(mNode, tempNode); + + mSubOtp = new ObjectTreeParser(mOtp, true); + mSubOtp->setAllowAsync(mOtp->allowAsync()); + if (mOtp->htmlWriter()) { + mSubOtp->mHtmlWriter = new QueueHtmlWriter(mOtp->htmlWriter()); + } + mSubOtp->parseObjectTreeInternal(tempNode); + } } } @@ -230,8 +259,25 @@ if (mNode) { if (textNode && !signature.isEmpty()) { - mTextNode = textNode; mVerifiedText = text; + } else if (!mVerifiedText.isEmpty()) { + textNode = new KMime::Content(); + textNode->setContent(KMime::CRLFtoLF(mVerifiedText.constData())); + textNode->parse(); + + if (!textNode->head().isEmpty()) { + textNode->contentDescription()->from7BitString("opaque signed data"); + } + mOtp->mNodeHelper->attachExtraContent(mNode, textNode); + } + + if (!mVerifiedText.isEmpty() && textNode) { + mSubOtp = new ObjectTreeParser(mOtp, true); + mSubOtp->setAllowAsync(mOtp->allowAsync()); + if (mOtp->htmlWriter()) { + mSubOtp->mHtmlWriter = new QueueHtmlWriter(mOtp->htmlWriter()); + } + mSubOtp->parseObjectTreeInternal(textNode); } } @@ -265,28 +311,20 @@ bool hideErrors = false; MessageViewer::HtmlWriter* writer = mOtp->htmlWriter(); - if (!writer) { - if (mNode && (mDecryptMessage || !mVerifiedText.isEmpty())) { - //TODO: Bad hack, we need the TempNodeParsing anycase - // but till we not make sure that the nodeparsing also creates html directly we need to have this hack. - if (!mVerifiedText.isEmpty() && mTextNode) { - auto otp = new ObjectTreeParser(mOtp, true); - otp->setAllowAsync(mOtp->allowAsync()); - otp->parseObjectTreeInternal(mTextNode); - mOtp->copyContentFrom(otp); - } else if (!mVerifiedText.isEmpty()) { - mOtp->createAndParseTempNode(mNode, mVerifiedText.constData(), "opaque signed data"); - } else { - mOtp->createAndParseTempNode(mNode, mDecryptedData.constData(), "encrypted node"); - } - } - return; + + //TODO: still the following part should not be here + if (mSubOtp) { + mOtp->copyContentFrom(mSubOtp); } if (mMetaData->isEncrypted && !mDecryptMessage) { mMetaData->isDecryptable = true; } + if (!writer) { + return; + } + if (mMetaData->isEncrypted && !mDecryptMessage) { const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); writeDeferredDecryptionBlock(); @@ -313,18 +351,11 @@ } } else if (mNode) { const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); - if (!mVerifiedText.isEmpty() && mTextNode) { - auto otp = new ObjectTreeParser(mOtp, true); - otp->setAllowAsync(mOtp->allowAsync()); - otp->parseObjectTreeInternal(mTextNode); - mOtp->copyContentFrom(otp); - } else if (!mVerifiedText.isEmpty()) { - mOtp->createAndParseTempNode(mNode, mVerifiedText.constData(), "opaque signed data"); - } else { - mOtp->createAndParseTempNode(mNode, mDecryptedData.constData(), "encrypted node"); + if (mSubOtp) { + static_cast(mSubOtp->htmlWriter())->reply(); } } else { MessagePart::html(decorate); } } } \ No newline at end of file Index: messageviewer/src/viewer/objecttreeparser.h =================================================================== --- messageviewer/src/viewer/objecttreeparser.h +++ messageviewer/src/viewer/objecttreeparser.h @@ -511,6 +511,7 @@ private: ObjectTreeSourceIf *mSource; NodeHelper *mNodeHelper; + HtmlWriter *mHtmlWriter; QByteArray mPlainTextContentCharset; QByteArray mHtmlContentCharset; QString mPlainTextContent; Index: messageviewer/src/viewer/objecttreeparser.cpp =================================================================== --- messageviewer/src/viewer/objecttreeparser.cpp +++ messageviewer/src/viewer/objecttreeparser.cpp @@ -150,6 +150,7 @@ bool includeSignatures, const AttachmentStrategy *strategy) : mSource(topLevelParser->mSource), + mHtmlWriter(topLevelParser->mHtmlWriter), mNodeHelper(topLevelParser->mNodeHelper), mTopLevelContent(topLevelParser->mTopLevelContent), mCryptoProtocol(topLevelParser->mCryptoProtocol), @@ -171,6 +172,7 @@ bool includeSignatures, const AttachmentStrategy *strategy) : mSource(source), + mHtmlWriter(0), mNodeHelper(nodeHelper), mTopLevelContent(0), mCryptoProtocol(protocol), @@ -202,6 +204,7 @@ ObjectTreeParser::ObjectTreeParser(const ObjectTreeParser &other) : mSource(other.mSource), + mHtmlWriter(other.mHtmlWriter), mNodeHelper(other.nodeHelper()), //TODO(Andras) hm, review what happens if mDeleteNodeHelper was true in the source mTopLevelContent(other.mTopLevelContent), mCryptoProtocol(other.cryptoProtocol()), @@ -3189,6 +3192,9 @@ HtmlWriter *ObjectTreeParser::htmlWriter() const { + if (mHtmlWriter) { + return mHtmlWriter; + } return mSource->htmlWriter(); }