From 31bf3102fe8f8cdd3f1448f0f22f182d0c2820d2 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Tue, 23 May 2017 21:00:50 +0200 Subject: Moved MIME related stuff to a mime subdir --- framework/src/domain/mime/messageparser_new.cpp | 513 ++++++++++++++++++++++++ 1 file changed, 513 insertions(+) create mode 100644 framework/src/domain/mime/messageparser_new.cpp (limited to 'framework/src/domain/mime/messageparser_new.cpp') diff --git a/framework/src/domain/mime/messageparser_new.cpp b/framework/src/domain/mime/messageparser_new.cpp new file mode 100644 index 00000000..7e7dbfa6 --- /dev/null +++ b/framework/src/domain/mime/messageparser_new.cpp @@ -0,0 +1,513 @@ +/* + Copyright (c) 2016 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 "messageparser.h" +#include "mimetreeparser/interface.h" +#include "htmlutils.h" + +#include +#include + +Q_DECLARE_METATYPE(Part *) +Q_DECLARE_METATYPE(Content *) +Q_DECLARE_METATYPE(Signature *) +Q_DECLARE_METATYPE(Encryption *) + +class Entry; + +class NewModelPrivate +{ +public: + NewModelPrivate(NewModel *q_ptr, const std::shared_ptr &parser); + ~NewModelPrivate(); + + void createTree(); + + QSharedPointer getVar(const std::shared_ptr &sig); + QSharedPointer getVar(const std::shared_ptr &enc); + QSharedPointer getVar(const std::shared_ptr &part); + QSharedPointer getVar(Part *part); + QSharedPointer getVar(const std::shared_ptr &content); + QSharedPointer getVar(Content *content); + + int getPos(Signature *sig); + int getPos(Encryption *enc); + int getPos(Part *part); + int getPos(Content *content); + + NewModel *q; + QVector mParts; + std::unique_ptr mRoot; + + std::shared_ptr mParser; +private: + QMap, QSharedPointer> mSignatureMap; + QMap, QSharedPointer> mEncryptionMap; + QMap> mPartMap; + QMap> mCMap; +}; + +class Entry +{ +public: + Entry(NewModelPrivate *model) + : mParent(nullptr) + , mNewModelPrivate(model) + { + } + + ~Entry() + { + foreach(auto child, mChildren) { + delete child; + } + mChildren.clear(); + } + + void addChild(Entry *entry) + { + mChildren.append(entry); + entry->mParent = this; + } + + Entry *addSignatures(QVector signatures) + { + auto ret = this; + foreach(const auto &sig, signatures) { + auto entry = new Entry(mNewModelPrivate); + entry->mData = mNewModelPrivate->getVar(sig); + ret->addChild(entry); + ret = entry; + } + return ret; + } + + Entry *addEncryptions(QVector encryptions) + { + auto ret = this; + foreach(const auto &enc, encryptions) { + auto entry = new Entry(mNewModelPrivate); + entry->mData = mNewModelPrivate->getVar(enc); + ret->addChild(entry); + ret = entry; + } + return ret; + } + + Entry *addPart(Part *part) + { + auto entry = new Entry(mNewModelPrivate); + entry->mData = mNewModelPrivate->getVar(part); + addChild(entry); + + foreach(const auto &content, part->content()) { + auto _entry = entry; + _entry = _entry->addEncryptions(content->encryptions().mid(part->encryptions().size())); + _entry = _entry->addSignatures(content->signatures().mid(part->signatures().size())); + auto c = new Entry(mNewModelPrivate); + c->mData = mNewModelPrivate->getVar(content); + _entry->addChild(c); + } +// foreach(const auto &content, part->availableContents()) { +// foreach(const auto &contentPart, part->content(content)) { +// auto _entry = entry; +// _entry = _entry->addEncryptions(contentPart->encryptions().mid(part->encryptions().size())); +// _entry = _entry->addSignatures(contentPart->signatures().mid(part->signatures().size())); +// auto c = new Entry(mNewModelPrivate); +// c->mData = mNewModelPrivate->getVar(contentPart); +// _entry->addChild(c); +// } +// } + foreach(const auto &sp, part->subParts()) { + auto _entry = entry; + _entry = _entry->addEncryptions(sp->encryptions().mid(part->encryptions().size())); + _entry = _entry->addSignatures(sp->signatures().mid(part->signatures().size())); + _entry->addPart(sp.get()); + } + return entry; + } + + int pos() + { + if(!mParent) { + return -1; + } + int i=0; + foreach(const auto &child, mParent->mChildren) { + if (child == this) { + return i; + } + i++; + } + return -1; + } + + QSharedPointer mData; + + Entry *mParent; + QVector mChildren; + NewModelPrivate *mNewModelPrivate; +}; + + +NewModelPrivate::NewModelPrivate(NewModel *q_ptr, const std::shared_ptr &parser) + : q(q_ptr) + , mRoot(std::unique_ptr(new Entry(this))) + , mParser(parser) +{ + mParts = mParser->collectContentParts(); + createTree(); +} + +NewModelPrivate::~NewModelPrivate() +{ +} + +void NewModelPrivate::createTree() +{ + auto root = mRoot.get(); + auto parent = root; + Part *pPart = nullptr; + QVector signatures; + QVector encryptions; + foreach(const auto part, mParts) { + auto _parent = parent; + if (pPart != part->parent()) { + auto _parent = root; + _parent = _parent->addEncryptions(part->parent()->encryptions()); + _parent = _parent->addSignatures(part->parent()->signatures()); + signatures = part->parent()->signatures(); + encryptions = part->parent()->encryptions(); + parent = _parent; + pPart = part->parent(); + } + _parent = _parent->addEncryptions(part->encryptions().mid(encryptions.size())); + _parent = _parent->addSignatures(part->signatures().mid(signatures.size())); + _parent->addPart(part.get()); + } +} + +QSharedPointer NewModelPrivate::getVar(const std::shared_ptr &sig) +{ + if (!mSignatureMap.contains(sig)) { + auto var = new QVariant(); + var->setValue(sig.get()); + mSignatureMap.insert(sig, QSharedPointer(var)); + } + return mSignatureMap.value(sig); +} + +QSharedPointer NewModelPrivate::getVar(const std::shared_ptr &enc) +{ + if (!mEncryptionMap.contains(enc)) { + auto var = new QVariant(); + var->setValue(enc.get()); + mEncryptionMap.insert(enc, QSharedPointer(var)); + } + return mEncryptionMap.value(enc); +} + +QSharedPointer NewModelPrivate::getVar(const std::shared_ptr &part) +{ + return getVar(part.get()); +} + +QSharedPointer NewModelPrivate::getVar(Part *part) +{ + if (!mPartMap.contains(part)) { + auto var = new QVariant(); + var->setValue(part); + mPartMap.insert(part, QSharedPointer(var)); + } + return mPartMap.value(part); +} + +QSharedPointer NewModelPrivate::getVar(const std::shared_ptr &content) +{ + return getVar(content.get()); +} + +QSharedPointer NewModelPrivate::getVar(Content *content) +{ + if (!mCMap.contains(content)) { + auto var = new QVariant(); + var->setValue(content); + mCMap.insert(content, QSharedPointer(var)); + } + return mCMap.value(content); +} + +int NewModelPrivate::getPos(Signature *signature) +{ + const auto first = mParts.first(); + int i = 0; + foreach(const auto &sig, first->signatures()) { + if (sig.get() == signature) { + break; + } + i++; + } + return i; +} + +int NewModelPrivate::getPos(Encryption *encryption) +{ + const auto first = mParts.first(); + int i = 0; + foreach(const auto &enc, first->encryptions()) { + if (enc.get() == encryption) { + break; + } + i++; + } + return i; +} + +int NewModelPrivate::getPos(Part *part) +{ + int i = 0; + foreach(const auto &p, mParts) { + if (p.get() == part) { + break; + } + i++; + } + return i; +} + +int NewModelPrivate::getPos(Content *content) +{ + int i = 0; + foreach(const auto &c, content->parent()->content()) { + if (c.get() == content) { + break; + } + i++; + } + return i; +} + +NewModel::NewModel(std::shared_ptr parser) + : d(std::unique_ptr(new NewModelPrivate(this, parser))) +{ +} + +NewModel::~NewModel() +{ +} + +QHash NewModel::roleNames() const +{ + QHash roles; + roles[TypeRole] = "type"; + roles[ContentRole] = "content"; + roles[IsComplexHtmlContentRole] = "complexHtmlContent"; + roles[IsEmbededRole] = "embeded"; + roles[SecurityLevelRole] = "securityLevel"; + roles[EncryptionErrorType] = "errorType"; + roles[EncryptionErrorString] = "errorString"; + return roles; +} + +QModelIndex NewModel::index(int row, int column, const QModelIndex &parent) const +{ + if (row < 0 || column != 0) { + return QModelIndex(); + } + Entry *entry = d->mRoot.get(); + if (parent.isValid()) { + entry = static_cast(parent.internalPointer()); + } + + if (row < entry->mChildren.size()) { + return createIndex(row, column, entry->mChildren.at(row)); + } + return QModelIndex(); +} + +QVariant NewModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + switch (role) { + case Qt::DisplayRole: + return QString("root"); + case IsEmbededRole: + return false; + } + return QVariant(); + } + + if (index.internalPointer()) { + const auto entry = static_cast(index.internalPointer()); + const auto _data = entry->mData; + if (entry == d->mRoot.get()|| !_data) { + switch (role) { + case Qt::DisplayRole: + return QString("root"); + case IsEmbededRole: + return false; + } + return QVariant(); + } + if (_data->userType() == qMetaTypeId()) { + const auto signature = _data->value(); + int i = d->getPos(signature); + switch(role) { + case Qt::DisplayRole: + return QStringLiteral("Signature%1").arg(i); + case TypeRole: + return QStringLiteral("Signature"); + case SecurityLevelRole: + return QStringLiteral("RED"); + case IsEmbededRole: + return data(index.parent(), IsEmbededRole); + } + } else if (_data->userType() == qMetaTypeId()) { + const auto encryption = _data->value(); + int i = d->getPos(encryption); + switch(role) { + case Qt::DisplayRole: + return QStringLiteral("Encryption%1").arg(i); + case TypeRole: + return QStringLiteral("Encryption"); + case SecurityLevelRole: + return QStringLiteral("GREEN"); + case IsEmbededRole: + return data(index.parent(), IsEmbededRole); + case EncryptionErrorType: + { + switch(encryption->errorType()) { + case Encryption::NoError: + return QString(); + case Encryption::PassphraseError: + return QStringLiteral("PassphraseError"); + case Encryption::KeyMissing: + return QStringLiteral("KeyMissing"); + default: + return QStringLiteral("UnknownError"); + } + } + case EncryptionErrorString: + return encryption->errorString(); + } + } else if (_data->userType() == qMetaTypeId()) { + const auto part = _data->value(); + switch (role) { + case Qt::DisplayRole: + case TypeRole: + return QString::fromLatin1(part->type()); + case IsEmbededRole: + return data(index.parent(), IsEmbededRole); + } + } else if (_data->userType() == qMetaTypeId()) { + const auto content = _data->value(); + int i = d->getPos(content); + switch(role) { + case Qt::DisplayRole: + return QStringLiteral("Content%1").arg(i); + case TypeRole: + return QString::fromLatin1(content->type()); + case IsEmbededRole: + return data(index.parent(), IsEmbededRole); + case IsComplexHtmlContentRole: { + const auto contentType = data(index, TypeRole).toString(); + if (contentType == "HtmlContent") { + const auto text = content->encodedContent(); + if (text.contains("encodedContent(); + const auto contentType = data(index, TypeRole).toString(); + if (contentType == "HtmlContent") { + const auto rx = QRegExp("(src)\\s*=\\s*(\"|')(cid:[^\"']+)\\2"); + int pos = 0; + while ((pos = rx.indexIn(text, pos)) != -1) { + const auto link = QUrl(rx.cap(3).toUtf8()); + pos += rx.matchedLength(); + const auto repl = d->mParser->getPart(link); + if (!repl) { + continue; + } + const auto content = repl->content(); + if(content.size() < 1) { + continue; + } + const auto mailMime = content.first()->mailMime(); + const auto mimetype = mailMime->mimetype().name(); + if (mimetype.startsWith("image/")) { + const auto data = content.first()->content(); + text.replace(rx.cap(0), QString("src=\"data:%1;base64,%2\"").arg(mimetype, QString::fromLatin1(data.toBase64()))); + } + } + } else { //We assume plain + //We alwas do richtext (so we get highlighted links and stuff). + return HtmlUtils::linkify(Qt::convertFromPlainText(text)); + } + return text; + } + } + } + } + return QVariant(); +} + +QModelIndex NewModel::parent(const QModelIndex &index) const +{ + if (!index.internalPointer()) { + return QModelIndex(); + } + const auto entry = static_cast(index.internalPointer()); + if (entry->mParent && entry->mParent != d->mRoot.get()) { + return createIndex(entry->pos(), 0, entry->mParent); + } + return QModelIndex(); +} + +int NewModel::rowCount(const QModelIndex &parent) const +{ + if (!parent.isValid()) { + return d->mRoot->mChildren.size(); + } else { + if (!parent.internalPointer()) { + return 0; + } + const auto entry = static_cast(parent.internalPointer()); + return entry->mChildren.size(); + } + return 0; +} + +int NewModel::columnCount(const QModelIndex &parent) const +{ + return 1; +} -- cgit v1.2.3