Index: messageviewer/src/CMakeLists.txt =================================================================== --- messageviewer/src/CMakeLists.txt +++ messageviewer/src/CMakeLists.txt @@ -86,6 +86,7 @@ viewer/objecttreeemptysource.cpp viewer/objecttreeparser.cpp viewer/objecttreeviewersource.cpp + viewer/messagepart.cpp viewer/partnodebodypart.cpp viewer/pluginloaderbase.cpp viewer/viewer.cpp Index: messageviewer/src/viewer/messagepart.h =================================================================== --- /dev/null +++ messageviewer/src/viewer/messagepart.h @@ -0,0 +1,108 @@ +/* + Copyright (c) 2015 Sandro Knauß + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#ifndef _MESSAGEVIEWER_MESSAGEPART_H_ +#define _MESSAGEVIEWER_MESSAGEPART_H_ + +#include "objecttreeparser.h" + +#include + +class QTextCodec; + +namespace MessageViewer { +class HTMLBlock +{ +public: + HTMLBlock() + : entered(false) + { } + + virtual ~HTMLBlock() { } + +protected: + bool entered; +}; + +class CryptoBlock: public HTMLBlock +{ +public: + CryptoBlock(ObjectTreeParser *otp, + PartMetaData *block, + const Kleo::CryptoBackend::Protocol *cryptoProto, + const QString &fromAddress, + KMime::Content *node); + virtual ~CryptoBlock(); + +private: + void internalEnter(); + void internalExit(); + + ObjectTreeParser *mOtp; + PartMetaData *mMetaData; + const Kleo::CryptoBackend::Protocol *mCryptoProto; + QString mFromAddress; + KMime::Content *mNode; +}; + +class MessagePart +{ +public: + typedef QSharedPointer Ptr; + MessagePart(ObjectTreeParser *otp, + PartMetaData *block, + const QString &text); + + virtual QString text() const; + void setText(const QString &text); + virtual void html(bool decorate) const; + + PartMetaData *partMetaData() const; + +protected: + QString mText; + ObjectTreeParser *mOtp; + PartMetaData *mMetaData; +}; + +class CryptoMessagePart : public MessagePart +{ +public: + typedef QSharedPointer Ptr; + CryptoMessagePart(ObjectTreeParser *otp, + PartMetaData *block, + const QString &text, + const Kleo::CryptoBackend::Protocol *cryptoProto, + const QString &fromAddress, + KMime::Content *node); + + void startDecryption(const QByteArray &text, const QTextCodec *aCodec); + void startVerification(const QByteArray &text, const QTextCodec *aCodec); + void html(bool decorate) const Q_DECL_OVERRIDE; + +protected: + const Kleo::CryptoBackend::Protocol *mCryptoProto; + QString mFromAddress; + KMime::Content *mNode; + bool mDecryptMessage; + std::vector mSignatures; +}; + +} +#endif //_MESSAGEVIEWER_MESSAGEPART_H_ Index: messageviewer/src/viewer/messagepart.cpp =================================================================== --- /dev/null +++ messageviewer/src/viewer/messagepart.cpp @@ -0,0 +1,189 @@ +/* + Copyright (c) 2015 Sandro Knauß + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library 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 Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "messagepart.h" +#include "objecttreeparser.h" + +#include +#include +#include + +#include + +using namespace MessageViewer; + +//--------CryptoBlock------------------- +CryptoBlock::CryptoBlock(ObjectTreeParser *otp, + PartMetaData *block, + const Kleo::CryptoBackend::Protocol *cryptoProto, + const QString &fromAddress, + KMime::Content *node) + : HTMLBlock() + , mOtp(otp) + , mMetaData(block) + , mCryptoProto(cryptoProto) + , mFromAddress(fromAddress) + , mNode(node) +{ + internalEnter(); +} + +CryptoBlock::~CryptoBlock() +{ + internalExit(); +} + +void CryptoBlock::internalEnter() +{ + MessageViewer::HtmlWriter* writer = mOtp->htmlWriter(); + if (writer && !entered) { + entered = true; + writer->queue(mOtp->writeSigstatHeader(*mMetaData, mCryptoProto, mFromAddress, mNode)); + } +} + +void CryptoBlock::internalExit() +{ + if (!entered) { + return; + } + MessageViewer::HtmlWriter* writer = mOtp->htmlWriter(); + writer->queue(mOtp->writeSigstatFooter(*mMetaData)); + entered = false; +} + + +//------MessagePart----------------------- +MessagePart::MessagePart(ObjectTreeParser *otp, + PartMetaData *block, + const QString &text) +: mOtp(otp) +, mText(text) +, mMetaData(block) +{ + +} + +PartMetaData *MessagePart::partMetaData() const +{ + return mMetaData; +} + +QString MessagePart::text() const +{ + return mText; +} + +void MessagePart::setText(const QString &text) { + mText = text; +} + +void MessagePart::html(bool decorate) const +{ + MessageViewer::HtmlWriter* writer = mOtp->htmlWriter(); + + if (!writer) { + return; + } + + const CryptoBlock block(mOtp, mMetaData, 0, QString(), 0); + writer->queue(mOtp->quotedHTML(text(), decorate)); +} + +//-----CryptMessageBlock--------------------- + +CryptoMessagePart::CryptoMessagePart(ObjectTreeParser *otp, + PartMetaData *block, + const QString &text, + const Kleo::CryptoBackend::Protocol *cryptoProto, + const QString &fromAddress, + KMime::Content *node) + : MessagePart(otp, block, text) + , mCryptoProto(cryptoProto) + , mDecryptMessage(false) + , mFromAddress(fromAddress) + , mNode(node) +{ + +} + +void CryptoMessagePart::startDecryption(const QByteArray &text, const QTextCodec *aCodec) +{ + mDecryptMessage = true; + + KMime::Content *content = new KMime::Content; + content->setBody(text); + content->parse(); + + bool passphraseError; //write error + bool signatureFound; + bool actuallyEncrypted = true; + bool decryptionStarted; + + QByteArray decryptedData; + bool bOkDecrypt = mOtp->okDecryptMIME(*content, + decryptedData, + signatureFound, + mSignatures, + true, + passphraseError, + actuallyEncrypted, + decryptionStarted, + *mMetaData); + if (decryptionStarted) { + mMetaData->inProgress = true; + return; + } + mMetaData->isDecryptable = bOkDecrypt; + mMetaData->isEncrypted = actuallyEncrypted; + mMetaData->isSigned = signatureFound; + setText(aCodec->toUnicode(decryptedData)); + mOtp->sigStatusToMetaData(mSignatures, mCryptoProto, *mMetaData, GpgME::Key()); +} + +void CryptoMessagePart::startVerification(const QByteArray &text, const QTextCodec *aCodec) +{ + mMetaData->isEncrypted = false; + mMetaData->isDecryptable = false; + + QByteArray verifiedText; + if (mOtp->okVerify(text, mCryptoProto, *mMetaData, verifiedText, mSignatures, QByteArray(), mNode)) { + setText(aCodec->toUnicode(verifiedText)); + } + mOtp->sigStatusToMetaData(mSignatures, mCryptoProto, *mMetaData, GpgME::Key()); +} + +void CryptoMessagePart::html(bool decorate) const +{ + MessageViewer::HtmlWriter* writer = mOtp->htmlWriter(); + if (!writer) { + return; + } + + if (mMetaData->isEncrypted && !mDecryptMessage) { + mOtp->writeDeferredDecryptionBlock(); + } else if (mMetaData->inProgress) { + mOtp->writeDecryptionInProgressBlock(); + } else if (mMetaData->isEncrypted && !mMetaData->isDecryptable){ + const CryptoBlock block(mOtp, mMetaData, mCryptoProto, mFromAddress, mNode); + writer->queue(text()); //Do not quote ErrorText + } else { + MessagePart::html(decorate); + } +} Index: messageviewer/src/viewer/objecttreeparser.h =================================================================== --- messageviewer/src/viewer/objecttreeparser.h +++ messageviewer/src/viewer/objecttreeparser.h @@ -555,6 +555,9 @@ QString mExpandIcon; bool mDeleteNodeHelper; bool mPrinting; + + friend class MessagePart; + friend class CryptoMessagePart; }; } Index: messageviewer/src/viewer/objecttreeparser.cpp =================================================================== --- messageviewer/src/viewer/objecttreeparser.cpp +++ messageviewer/src/viewer/objecttreeparser.cpp @@ -40,6 +40,7 @@ #include "memento/verifyopaquebodypartmemento.h" #include "memento/cryptobodypartmemento.h" #include "memento/decryptverifybodypartmemento.h" +#include "messagepart.h" #include "objecttreesourceif.h" #include "messageviewer/autoqpointer.h" #include "viewer/viewer_p.h" @@ -2970,6 +2971,8 @@ bool updatePlainText = false; // If there are encrypted or signed parts inside the node // we need to update mPlainTextContent + QVector mpl; + if (!blocks.isEmpty()) { if (blocks.count() > 1 || blocks.at(0).type() != MessageViewer::NoPgpBlock) { @@ -2991,97 +2994,47 @@ bool fullySignedOrEncryptedTmp = true; Q_FOREACH (const Block &block, blocks) { - std::vector signatures; //write signature state - PartMetaData messagePart; - messagePart.isEncrypted = false; - messagePart.isSigned = false; - - QString text; + PartMetaData *messagePart = new PartMetaData; + messagePart->isEncrypted = false; + messagePart->isSigned = false; if (!fullySignedOrEncryptedTmp) { fullySignedOrEncrypted = false; } if (block.type() == NoPgpBlock && !block.text().trimmed().isEmpty()) { fullySignedOrEncryptedTmp = false; + mpl.append(MessagePart::Ptr(new MessagePart(this, messagePart, aCodec->toUnicode(block.text())))); } else if (block.type() == PgpMessageBlock) { updatePlainText = true; + CryptoMessagePart::Ptr mp(new CryptoMessagePart(this, messagePart, QString(), cryptoProtocol(), fromAddress, 0)); + mpl.append(mp); if (!mSource->decryptMessage()) { - writeDeferredDecryptionBlock(); continue; } - - KMime::Content *content = new KMime::Content; - content->setBody(block.text()); - content->parse(); - - bool passphraseError; //write error - - QByteArray decryptedData; - bool signatureFound; - bool actuallyEncrypted = true; - bool decryptionStarted; - bool bOkDecrypt = okDecryptMIME(*content, - decryptedData, - signatureFound, - signatures, - true, - passphraseError, - actuallyEncrypted, - decryptionStarted, - messagePart); - - if (decryptionStarted) { - writeDecryptionInProgressBlock(); + mp->startDecryption(block.text(), aCodec); + if (messagePart->inProgress) { continue; } - - messagePart.isDecryptable = bOkDecrypt; - messagePart.isEncrypted = actuallyEncrypted; - messagePart.isSigned = signatureFound; - - text = aCodec->toUnicode(decryptedData); - } else if (block.type() == ClearsignedBlock) { + CryptoMessagePart::Ptr mp(new CryptoMessagePart(this, messagePart, QString(), cryptoProtocol(), fromAddress, 0)); + mpl.append(mp); updatePlainText = true; - messagePart.isEncrypted = false; - messagePart.isDecryptable = false; - - QByteArray verifiedText; - if (okVerify(block.text(), cryptoProtocol(), messagePart, verifiedText, signatures, QByteArray(), 0)) { - text = aCodec->toUnicode(verifiedText); - } + mp->startVerification(block.text(), aCodec); + } else { + continue; } - if (!messagePart.isEncrypted && !messagePart.isSigned && !block.text().trimmed().isEmpty()) { - text = aCodec->toUnicode(block.text()); + if (!messagePart->isEncrypted && !messagePart->isSigned && !block.text().trimmed().isEmpty()) { + mpl.last()->setText(aCodec->toUnicode(block.text())); } - if (messagePart.isEncrypted) { + if (messagePart->isEncrypted) { inlineEncryptionState = KMMsgPartiallyEncrypted; } - if (messagePart.isSigned) { + if (messagePart->isSigned) { inlineSignatureState = KMMsgPartiallySigned; - sigStatusToMetaData(signatures, cryptoProtocol(), messagePart, GpgME::Key()); - } - - plainTextStr += text; - - if (htmlWriter()) { - if (messagePart.isEncrypted || messagePart.isSigned) { - htmlStr += writeSigstatHeader(messagePart, cryptoProtocol(), fromAddress); - } - - if (messagePart.isEncrypted && !messagePart.isDecryptable) { - htmlStr += text; //Do not quote ErrorText - } else if (!text.trimmed().isEmpty()) { - htmlStr += quotedHTML(text, decorate); - } - - if (messagePart.isEncrypted || messagePart.isSigned) { - htmlStr += writeSigstatFooter(messagePart); - } } } @@ -3096,13 +3049,21 @@ } if (htmlWriter()) { - htmlWriter()->queue(htmlStr); + foreach(const MessagePart::Ptr &mp, mpl) { + mp->html(decorate); + } } if (updatePlainText || mPlainTextContent.isEmpty()) { - mPlainTextContent = plainTextStr; + mPlainTextContent.clear(); + foreach(const MessagePart::Ptr &mp, mpl) { + mPlainTextContent += mp->text(); + } mPlainTextContentCharset = aCodec->name(); } + foreach(const MessagePart::Ptr &mp, mpl) { + delete mp->partMetaData(); + } } }