From 63ffdb58e2021285bf07cc5643cbbf0312231927 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Vr=C3=A1til?= <daniel.vratil@kdab.com> Date: Tue, 28 Jun 2016 18:10:15 +0200 Subject: [PATCH 67/74] Fix accessing attachments in deeply nested extra nodes Certain message types, like opaque S/MIME-encrypted messages generate a deeper hierarchy of extra nodes. The path in URL must reflect this, so that we can find the correct parent node. --- messageviewer/viewer/nodehelper.cpp | 44 +++++++++++++++++++++++++++++-------- messageviewer/viewer/viewer_p.cpp | 31 ++++++++++++++------------ 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/messageviewer/viewer/nodehelper.cpp b/messageviewer/viewer/nodehelper.cpp index ddc184886f..5a15d8d503 100644 --- a/messageviewer/viewer/nodehelper.cpp +++ b/messageviewer/viewer/nodehelper.cpp @@ -664,20 +664,46 @@ void NodeHelper::setNodeDisplayedHidden( KMime::Content* node, bool displayedHid Used internally for robust indexing. */ -QString NodeHelper::persistentIndex( const KMime::Content * node ) const +QString NodeHelper::persistentIndex(const KMime::Content *node) const { - if ( !node ) + if (!node) { return QString(); + } QString indexStr = node->index().toString(); - const KMime::Content * const topLevel = node->topLevel(); - //if the node is an extra node, prepend the index of the extra node to the url - Q_FOREACH( const QList<KMime::Content*> & extraNodes, mExtraContents ) { - const int extraNodesSize( extraNodes.size() ); - for ( int i = 0; i < extraNodesSize; ++i ) - if ( topLevel == extraNodes.at(i) ) - return indexStr.prepend( QString::fromLatin1("%1:").arg(i) ); + if (indexStr.isEmpty()) { + Q_FOREACH (KMime::Content *realNode, mExtraContents.keys()) { + const auto &extraNodes = mExtraContents.value(realNode); + for (int i = 0; i < extraNodes.size(); i++) { + if (extraNodes[i] == node) { + indexStr = QString::fromLatin1("e%1").arg(i); + const QString parentIndex = persistentIndex(realNode); + if (!parentIndex.isEmpty()) { + indexStr = QString::fromLatin1("%1:%2").arg(parentIndex, indexStr); + } + return indexStr; + } + } + } + } else { + const KMime::Content *const topLevel = node->topLevel(); + //if the node is an extra node, prepend the index of the extra node to the url + Q_FOREACH (KMime::Content *realNode, mExtraContents.keys()) { + const QList<KMime::Content *> &extraNodes = extraContents(realNode); + for (int i = 0; i < extraNodes.size(); ++i) { + KMime::Content *const extraNode = extraNodes[i]; + if (topLevel == extraNode) { + indexStr.prepend(QString::fromLatin1("e%1:").arg(i)); + const QString parentIndex = persistentIndex(realNode); + if (!parentIndex.isEmpty()) { + indexStr = QString::fromLatin1("%1:%2").arg(parentIndex, indexStr); + } + return indexStr; + } + } + } } + return indexStr; } diff --git a/messageviewer/viewer/viewer_p.cpp b/messageviewer/viewer/viewer_p.cpp index 92937ef007..e1d3c5e318 100644 --- a/messageviewer/viewer/viewer_p.cpp +++ b/messageviewer/viewer/viewer_p.cpp @@ -303,21 +303,24 @@ KMime::Content * ViewerPrivate::nodeFromUrl( const KUrl & url ) return mMessage.get(); } if ( !url.isLocalFile() ) { - QString path = url.path(KUrl::RemoveTrailingSlash); - if ( path.contains(QLatin1Char(':')) ) { - //if the content was not found, it might be in an extra node. Get the index of the extra node (the first part of the url), - //and use the remaining part as a ContentIndex to find the node inside the extra node - int i = path.left( path.indexOf(QLatin1Char(':')) ).toInt(); - path = path.mid( path.indexOf(QLatin1Char(':')) + 1 ); - KMime::ContentIndex idx(path); - QList<KMime::Content*> extras = mNodeHelper->extraContents( mMessage.get() ); - if ( i >= 0 && i < extras.size() ) { - KMime::Content* c = extras[i]; - node = c->content( idx ); + QString urlPath = url.path(KUrl::RemoveTrailingSlash); + if (mMessage) { + KMime::Content *c = mMessage.get(); + const QStringList pathParts = urlPath.split(QLatin1Char(':'), QString::SkipEmptyParts); + for (int i = 0; i < pathParts.size(); ++i) { + const QString &path = pathParts[i]; + if (path.startsWith(QLatin1Char('e'))) { + const QList<KMime::Content*> &extraParts = mNodeHelper->extraContents(c); + const int idx = path.mid(1, -1).toInt(); + c = (idx < extraParts.size()) ? extraParts[idx] : 0; + } else { + c = c->content(KMime::ContentIndex(path)); + } + if (!c) { + break; + } } - } else { - if( mMessage ) - node= mMessage->content( KMime::ContentIndex( path ) ); + node = c; } } else { const QString path = url.toLocalFile(); -- 2.14.1