diff --git a/messageviewer/src/CMakeLists.txt b/messageviewer/src/CMakeLists.txt index 05c5bd83..60387e62 100644 --- a/messageviewer/src/CMakeLists.txt +++ b/messageviewer/src/CMakeLists.txt @@ -1,421 +1,420 @@ add_definitions( -DQT_NO_CAST_FROM_ASCII ) add_definitions( -DQT_NO_CAST_TO_ASCII ) add_definitions(-DTRANSLATION_DOMAIN=\"libmessageviewer\") # KCFG files: # The main messageviewer.kcfg is configured by CMake and put in the build directory. if(KDEPIM_ENTERPRISE_BUILD) set(LEGACY_MANGLE_FROM_TO_HEADERS true) set(LEGACY_BODY_INVITES true) set(EXCHANGE_COMPATIBLE_INVITATIONS true) else() set(LEGACY_MANGLE_FROM_TO_HEADERS false) set(LEGACY_BODY_INVITES false) set(EXCHANGE_COMPATIBLE_INVITATIONS false) endif() configure_file(settings/messageviewer.kcfg.cmake ${CMAKE_CURRENT_BINARY_DIR}/messageviewer.kcfg) include(CheckIncludeFiles) find_package(Inotify) set_package_properties(Inotify PROPERTIES PURPOSE "Filesystem alteration notifications using inotify") if(Inotify_FOUND) set(HAVE_SYS_INOTIFY_H 1) else() set(HAVE_SYS_INOTIFY_H 0) endif() configure_file(config-messageviewer.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-messageviewer.h) # target_include_directories does not handle empty include paths include_directories(${GPGME_INCLUDES}) if(BUILD_TESTING) add_subdirectory(scamdetection/autotests) add_subdirectory(scamdetection/tests) add_subdirectory(viewerplugins/tests/) add_subdirectory(htmlwriter/autotests) add_subdirectory(viewer/webengine/tests) add_subdirectory(messagepartthemes/default/autotests) add_subdirectory(viewer/webengine/autotests) endif() add_subdirectory(pics) add_subdirectory(kconf_update) add_subdirectory(about) add_subdirectory(messageviewerheaderplugins) if(DEBUG_SIGNATURE) add_definitions(-DDEBUG_SIGNATURE) endif() set(libmessageviewer_mailviewer_SRCS viewer/webengine/mailwebengineview.cpp viewer/webengine/mailwebenginepage.cpp viewer/webengine/loadexternalreferencesurlinterceptor/loadexternalreferencesurlinterceptor.cpp viewer/webengine/cidreferencesurlinterceptor/cidreferencesurlinterceptor.cpp viewer/webengine/blockexternalresourcesurlinterceptor/blockexternalresourcesurlinterceptor.cpp viewer/webengine/mailwebenginescript.cpp ) set(libmessageviewer_viewer_SRCS viewer/bodypartformatterfactory.cpp viewer/bodypartformatterfactorysingleton.cpp viewer/csshelper.cpp viewer/csshelperbase.cpp viewer/editorwatcher.cpp viewer/objecttreeemptysource.cpp viewer/objecttreeviewersource.cpp viewer/viewer.cpp viewer/viewer_p.cpp viewer/messagedisplayformatattribute.cpp viewer/urlhandlermanager.cpp viewer/mimeparttree/mimeparttreeview.cpp viewer/mimeparttree/mimetreemodel.cpp ) set(libmessageviewer_widgets_SRCS widgets/attachmentdialog.cpp widgets/configurewidget.cpp widgets/printingsettings.cpp widgets/htmlstatusbar.cpp widgets/vcardviewer.cpp widgets/invitationsettings.cpp widgets/openattachmentfolderwidget.cpp widgets/mailsourceviewtextbrowserwidget.cpp widgets/submittedformwarningwidget.cpp ) set(libmessageviewer_widgets_webengine_SRCS widgets/mailsourcewebengineviewer.cpp ) set(libmessageviewer_header_SRCS header/contactdisplaymessagememento.cpp header/headerstrategy.cpp header/richheaderstrategy.cpp header/headerstyle.cpp header/grantleeheaderstyle.cpp header/plainheaderstyle.cpp header/headerstyle_util.cpp header/grantleeheaderformatter.cpp header/grantleeheaderteststyle.cpp header/kxface.cpp header/headerstyleplugin.cpp header/headerstylepluginmanager.cpp header/headerstyleinterface.cpp header/headerstylemenumanager.cpp ) set(libmessageviewer_scamdetection_SRCS scamdetection/scamdetectionwarningwidget.cpp scamdetection/scamdetectiondetailsdialog.cpp scamdetection/scamattribute.cpp scamdetection/scamcheckshorturl.cpp scamdetection/scamexpandurljob.cpp scamdetection/scamcheckshorturlmanager.cpp ) set(libmessageviewer_scamdetection_webengine_SRCS scamdetection/scamdetectionwebengine.cpp ) set(libmessageviewer_findbar_SRCS findbar/findbarsourceview.cpp ) set(libmessageviewer_utils_SRCS utils/iconnamecache.cpp utils/markmessagereadhandler.cpp utils/messageviewerutil.cpp utils/mimetype.cpp ) set(libmessageviewer_htmlwriter_webengine_SRCS htmlwriter/webengineparthtmlwriter.cpp htmlwriter/webengineembedpart.cpp ) set(libmessageviewer_antispam_SRCS antispam/spamheaderanalyzer.cpp antispam/antispamconfig.cpp ) set(libmessageviewer_job_SRCS job/attachmenteditjob.cpp job/modifymessagedisplayformatjob.cpp ) set(libmessageviewer_viewerplugins_SRCS viewerplugins/viewerpluginmanager.cpp viewerplugins/viewerplugin.cpp viewerplugins/viewerplugininterface.cpp viewerplugins/viewerplugintoolmanager.cpp ) set(libmessageviewer_messagepartthemes_default_SRCS messagepartthemes/default/converthtmltoplaintext.cpp messagepartthemes/default/defaultrenderer.cpp messagepartthemes/default/htmlblock.cpp messagepartthemes/default/messagepartrenderermanager.cpp - messagepartthemes/default/partrendered.cpp messagepartthemes/default/plugins/attachmentmessagepartrenderer.cpp messagepartthemes/default/plugins/messagepartrenderer.cpp messagepartthemes/default/plugins/textmessagepartrenderer.cpp messagepartthemes/default/plugins/quotehtml.cpp messagepartthemes/default/messagepartrenderbase.cpp messagepartthemes/default/messagepartrendererfactory.cpp ) set(libmessageviewer_SRCS ${libmessageviewer_messagepartthemes_default_SRCS} ${libmessageviewer_htmlwriter_webengine_SRCS} ${libmessageviewer_messagepartthemes_SRCS} ${libmessageviewer_scamdetection_webengine_SRCS} ${libmessageviewer_widgets_webengine_SRCS} ${libmessageviewer_viewer_SRCS} ${libmessageviewer_widgets_SRCS} ${libmessageviewer_header_SRCS} ${libmessageviewer_scamdetection_SRCS} ${libmessageviewer_findbar_SRCS} ${libmessageviewer_utils_SRCS} ${libmessageviewer_antispam_SRCS} ${libmessageviewer_job_SRCS} ${libmessageviewer_viewerplugins_SRCS} settings/messageviewersettings.cpp ${libmessageviewer_mailviewer_SRCS} ) qt5_add_resources(libmessageviewer_SRCS messagepartthemes.qrc) ecm_qt_declare_logging_category(libmessageviewer_SRCS HEADER messageviewer_debug.h IDENTIFIER MESSAGEVIEWER_LOG CATEGORY_NAME org.kde.pim.messageviewer) kconfig_add_kcfg_files(libmessageviewer_SRCS settings/globalsettings_messageviewer.kcfgc ) ki18n_wrap_ui(libmessageviewer_SRCS ui/settings.ui ui/invitationsettings.ui ui/printingsettings.ui ) add_library(KF5MessageViewer ${libmessageviewer_SRCS}) generate_export_header(KF5MessageViewer BASE_NAME messageviewer) add_library(KF5::MessageViewer ALIAS KF5MessageViewer) target_include_directories(KF5MessageViewer INTERFACE "$") target_link_libraries(KF5MessageViewer PUBLIC KF5::MessageCore KF5::PimCommon KF5::AkonadiCore KF5::AkonadiMime KF5::Contacts KF5::Libkleo KF5::MimeTreeParser PRIVATE KF5::SyntaxHighlighting KF5::ItemViews Qt5::Network KF5::WebEngineViewer KF5::LibkdepimAkonadi KF5::GrantleeTheme KF5::KaddressbookGrantlee Grantlee5::Templates KF5::MailTransportAkonadi KF5::Mime KF5::Mbox KF5::PimTextEdit KF5::Gravatar KF5::IconThemes KF5::I18n KF5::KIOFileWidgets KF5::KIOWidgets KF5::WindowSystem KF5::XmlGui Grantlee5::TextDocument Grantlee5::Templates Qt5::PrintSupport QGpgme ) set_target_properties(KF5MessageViewer PROPERTIES VERSION ${MESSAGEVIEWER_VERSION_STRING} SOVERSION ${MESSAGEVIEWER_SOVERSION} EXPORT_NAME MessageViewer ) install(TARGETS KF5MessageViewer EXPORT KF5MessageViewerTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS} ${LIBRARY_NAMELINK} ) ecm_generate_headers(MessageViewer_Camelcasewebengine_HEADERS HEADER_NAMES MailWebEnginePage MailWebEngineView REQUIRED_HEADERS MessageViewer_webengine_HEADERS PREFIX MessageViewer RELATIVE viewer/webengine ) ecm_generate_headers(MessageViewer_Camelcasescam_HEADERS HEADER_NAMES ScamExpandUrlJob ScamCheckShortUrlManager ScamCheckShortUrl REQUIRED_HEADERS MessageViewer_scam_HEADERS PREFIX MessageViewer RELATIVE scamdetection ) ecm_generate_headers(MessageViewer_Camelcaseviewer_HEADERS HEADER_NAMES Viewer CSSHelperBase CSSHelper ObjectTreeEmptySource EditorWatcher Stl_Util BodyPartFormatterFactory REQUIRED_HEADERS MessageViewer_viewer_HEADERS PREFIX MessageViewer RELATIVE viewer ) ecm_generate_headers(MessageViewer_Camelcasewidgets_HEADERS HEADER_NAMES InvitationSettings PrintingSettings ConfigureWidget REQUIRED_HEADERS MessageViewer_widgets_HEADERS PREFIX MessageViewer RELATIVE widgets ) ecm_generate_headers(MessageViewer_Camelcaseutils_HEADERS HEADER_NAMES IconNameCache MarkMessageReadHandler MessageViewerUtil MimeType REQUIRED_HEADERS MessageViewer_utils_HEADERS PREFIX MessageViewer RELATIVE utils ) ecm_generate_headers(MessageViewer_Camelcaseantispam_HEADERS HEADER_NAMES SpamHeaderAnalyzer REQUIRED_HEADERS MessageViewer_antispam_HEADERS PREFIX MessageViewer RELATIVE antispam ) ecm_generate_headers(MessageViewer_Camelcaseinterfaces_HEADERS HEADER_NAMES BodyPartURLHandler URLHandler REQUIRED_HEADERS MessageViewer_interfaces_HEADERS PREFIX MessageViewer RELATIVE interfaces ) ecm_generate_headers(MessageViewer_Camelcasesettings_HEADERS HEADER_NAMES MessageViewerSettings REQUIRED_HEADERS MessageViewer_settings_HEADERS PREFIX MessageViewer RELATIVE settings ) ecm_generate_headers(MessageViewer_Camelcaseheader_HEADERS HEADER_NAMES HeaderStrategy GrantleeHeaderTestStyle GrantleeHeaderStyle HeaderStyle KXFace HeaderStyle_Util HeaderStylePlugin HeaderStyleInterface PlainHeaderStyle RichHeaderStrategy HeaderStylePluginManager HeaderStyleMenuManager REQUIRED_HEADERS MessageViewer_header_HEADERS PREFIX MessageViewer RELATIVE header ) ecm_generate_headers(MessageViewer_Camelcaseviewerplugin_HEADERS HEADER_NAMES ViewerPluginManager ViewerPlugin ViewerPluginInterface ViewerPluginToolManager REQUIRED_HEADERS MessageViewer_viewerplugin_HEADERS PREFIX MessageViewer RELATIVE viewerplugins ) ecm_generate_pri_file(BASE_NAME MessageViewer LIB_NAME KF5MessageViewer DEPS "PimCommon MessageCore AkonadiCore AkonadiMime Contacts Libkleo MimeTreeParser" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/MessageViewer ) install(FILES ${MessageViewer_Camelcasewebengine_HEADERS} ${MessageViewer_Camelcaseheader_HEADERS} ${MessageViewer_Camelcaseviewerplugin_HEADERS} ${MessageViewer_Camelcasesettings_HEADERS} ${MessageViewer_Camelcaseutils_HEADERS} ${MessageViewer_Camelcaseinterfaces_HEADERS} ${MessageViewer_Camelcaseviewer_HEADERS} ${MessageViewer_Camelcasewidgets_HEADERS} ${MessageViewer_Camelcaseantispam_HEADERS} ${MessageViewer_Camelfindbar_HEADERS} ${MessageViewer_Camelcasescam_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/MessageViewer COMPONENT Devel ) install(FILES ${MessageViewer_webengine_HEADERS} ${MessageViewer_scam_HEADERS} ${MessageViewer_viewerplugin_HEADERS} ${MessageViewer_settings_HEADERS} ${MessageViewer_header_HEADERS} ${MessageViewer_utils_HEADERS} ${MessageViewer_interfaces_HEADERS} ${MessageViewer_HEADERS} ${MessageViewer_viewer_HEADERS} ${MessageViewer_widgets_HEADERS} ${MessageViewer_antispam_HEADERS} ${MessageViewer_findbar_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/messageviewer_export.h ${CMAKE_CURRENT_BINARY_DIR}/globalsettings_messageviewer.h ${CMAKE_CURRENT_BINARY_DIR}/messageviewer_debug.h ${CMAKE_CURRENT_BINARY_DIR}/config-messageviewer.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/messageviewer COMPONENT Devel ) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) install(FILES header/data/messageviewer_header_themes.knsrc DESTINATION ${KDE_INSTALL_CONFDIR} ) install(FILES notify/messageviewer.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFY5RCDIR} ) install(FILES scamdetection/data/longurlServices.json DESTINATION ${KDE_INSTALL_DATADIR}/messageviewer ) diff --git a/messageviewer/src/messagepartthemes/default/defaultrenderer.cpp b/messageviewer/src/messagepartthemes/default/defaultrenderer.cpp index f8225190..ba9c4f48 100644 --- a/messageviewer/src/messagepartthemes/default/defaultrenderer.cpp +++ b/messageviewer/src/messagepartthemes/default/defaultrenderer.cpp @@ -1,962 +1,942 @@ /* 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 "defaultrenderer.h" #include "defaultrenderer_p.h" #include "messageviewer_debug.h" #include "cachehtmlwriter.h" #include "converthtmltoplaintext.h" #include "messagepartrendererbase.h" #include "messagepartrendererfactory.h" #include "htmlblock.h" -#include "partrendered.h" #include "utils/iconnamecache.h" #include "utils/mimetype.h" #include "viewer/csshelperbase.h" #include "messagepartrenderermanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace MimeTreeParser; using namespace MessageViewer; Q_DECLARE_METATYPE(GpgME::DecryptionResult::Recipient) Q_DECLARE_METATYPE(const QGpgME::Protocol *) static const int SIG_FRAME_COL_UNDEF = 99; #define SIG_FRAME_COL_RED -1 #define SIG_FRAME_COL_YELLOW 0 #define SIG_FRAME_COL_GREEN 1 QString sigStatusToString(const QGpgME::Protocol *cryptProto, int status_code, GpgME::Signature::Summary summary, int &frameColor, bool &showKeyInfos) { // note: At the moment frameColor and showKeyInfos are // used for CMS only but not for PGP signatures // pending(khz): Implement usage of these for PGP sigs as well. showKeyInfos = true; QString result; if (cryptProto) { if (cryptProto == QGpgME::openpgp()) { // process enum according to it's definition to be read in // GNU Privacy Guard CVS repository /gpgme/gpgme/gpgme.h switch (status_code) { case 0: // GPGME_SIG_STAT_NONE result = i18n("Error: Signature not verified"); break; case 1: // GPGME_SIG_STAT_GOOD result = i18n("Good signature"); break; case 2: // GPGME_SIG_STAT_BAD result = i18n("Bad signature"); break; case 3: // GPGME_SIG_STAT_NOKEY result = i18n("No public key to verify the signature"); break; case 4: // GPGME_SIG_STAT_NOSIG result = i18n("No signature found"); break; case 5: // GPGME_SIG_STAT_ERROR result = i18n("Error verifying the signature"); break; case 6: // GPGME_SIG_STAT_DIFF result = i18n("Different results for signatures"); break; /* PENDING(khz) Verify exact meaning of the following values: case 7: // GPGME_SIG_STAT_GOOD_EXP return i18n("Signature certificate is expired"); break; case 8: // GPGME_SIG_STAT_GOOD_EXPKEY return i18n("One of the certificate's keys is expired"); break; */ default: result.clear(); // do *not* return a default text here ! break; } } else if (cryptProto == QGpgME::smime()) { // process status bits according to SigStatus_... // definitions in kdenetwork/libkdenetwork/cryptplug.h if (summary == GpgME::Signature::None) { result = i18n("No status information available."); frameColor = SIG_FRAME_COL_YELLOW; showKeyInfos = false; return result; } if (summary & GpgME::Signature::Valid) { result = i18n("Good signature."); // Note: // Here we are work differently than KMail did before! // // The GOOD case ( == sig matching and the complete // certificate chain was verified and is valid today ) // by definition does *not* show any key // information but just states that things are OK. // (khz, according to LinuxTag 2002 meeting) frameColor = SIG_FRAME_COL_GREEN; showKeyInfos = false; return result; } // we are still there? OK, let's test the different cases: // we assume green, test for yellow or red (in this order!) frameColor = SIG_FRAME_COL_GREEN; QString result2; if (summary & GpgME::Signature::KeyExpired) { // still is green! result2 = i18n("One key has expired."); } if (summary & GpgME::Signature::SigExpired) { // and still is green! result2 += i18n("The signature has expired."); } // test for yellow: if (summary & GpgME::Signature::KeyMissing) { result2 += i18n("Unable to verify: key missing."); // if the signature certificate is missing // we cannot show information on it showKeyInfos = false; frameColor = SIG_FRAME_COL_YELLOW; } if (summary & GpgME::Signature::CrlMissing) { result2 += i18n("CRL not available."); frameColor = SIG_FRAME_COL_YELLOW; } if (summary & GpgME::Signature::CrlTooOld) { result2 += i18n("Available CRL is too old."); frameColor = SIG_FRAME_COL_YELLOW; } if (summary & GpgME::Signature::BadPolicy) { result2 += i18n("A policy was not met."); frameColor = SIG_FRAME_COL_YELLOW; } if (summary & GpgME::Signature::SysError) { result2 += i18n("A system error occurred."); // if a system error occurred // we cannot trust any information // that was given back by the plug-in showKeyInfos = false; frameColor = SIG_FRAME_COL_YELLOW; } // test for red: if (summary & GpgME::Signature::KeyRevoked) { // this is red! result2 += i18n("One key has been revoked."); frameColor = SIG_FRAME_COL_RED; } if (summary & GpgME::Signature::Red) { if (result2.isEmpty()) { // Note: // Here we are work differently than KMail did before! // // The BAD case ( == sig *not* matching ) // by definition does *not* show any key // information but just states that things are BAD. // // The reason for this: In this case ALL information // might be falsificated, we can NOT trust the data // in the body NOT the signature - so we don't show // any key/signature information at all! // (khz, according to LinuxTag 2002 meeting) showKeyInfos = false; } frameColor = SIG_FRAME_COL_RED; } else { result.clear(); } if (SIG_FRAME_COL_GREEN == frameColor) { result = i18n("Good signature."); } else if (SIG_FRAME_COL_RED == frameColor) { result = i18n("Bad signature."); } else { result.clear(); } if (!result2.isEmpty()) { if (!result.isEmpty()) { result.append(QLatin1String("
")); } result.append(result2); } } /* // add i18n support for 3rd party plug-ins here: else if ( cryptPlug->libName().contains( "yetanotherpluginname", Qt::CaseInsensitive )) { } */ } return result; } /** Checks whether @p str contains external references. To be precise, we only check whether @p str contains 'xxx="http[s]:' where xxx is not href. Obfuscated external references are ignored on purpose. */ bool containsExternalReferences(const QString &str, const QString &extraHead) { const bool hasBaseInHeader = extraHead.contains(QStringLiteral( "= 0 || httpsPos >= 0) { // pos = index of next occurrence of "http: or "https: whichever comes first int pos = (httpPos < httpsPos) ? ((httpPos >= 0) ? httpPos : httpsPos) : ((httpsPos >= 0) ? httpsPos : httpPos); // look backwards for "href" if (pos > 5) { int hrefPos = str.lastIndexOf(QLatin1String("href"), pos - 5, Qt::CaseInsensitive); // if no 'href' is found or the distance between 'href' and '"http[s]:' // is larger than 7 (7 is the distance in 'href = "http[s]:') then // we assume that we have found an external reference if ((hrefPos == -1) || (pos - hrefPos > 7)) { // HTML messages created by KMail itself for now contain the following: // // Make sure not to show an external references warning for this string int dtdPos = str.indexOf(QLatin1String( "http://www.w3.org/TR/html4/loose.dtd"), pos + 1); if (dtdPos != (pos + 1)) { return true; } } } // find next occurrence of "http: or "https: if (pos == httpPos) { httpPos = str.indexOf(QLatin1String("\"http:"), httpPos + 6, Qt::CaseInsensitive); } else { httpsPos = str.indexOf(QLatin1String("\"https:"), httpsPos + 7, Qt::CaseInsensitive); } } return false; } // FIXME this used to go through the full webkit parser to extract the body and head blocks // until we have that back, at least attempt to fix some of the damage // yes, "parsing" HTML with regexps is very very wrong, but it's still better than not filtering // this at all... QString processHtml(const QString &htmlSource, QString &extraHead) { auto s = htmlSource.trimmed(); s = s.replace(QRegExp(QStringLiteral("^]*>"), Qt::CaseInsensitive), QString()).trimmed(); s = s.replace(QRegExp(QStringLiteral("^]*>"), Qt::CaseInsensitive), QString()).trimmed(); // head s = s.replace(QRegExp(QStringLiteral("^"), Qt::CaseInsensitive), QString()).trimmed(); if (s.startsWith(QLatin1String("", Qt::CaseInsensitive))) { const auto idx = s.indexOf(QLatin1String(""), Qt::CaseInsensitive); if (idx < 0) { return htmlSource; } extraHead = s.mid(6, idx - 6); s = s.mid(idx + 7).trimmed(); } // body s = s.replace(QRegExp(QStringLiteral("]*>"), Qt::CaseInsensitive), QString()).trimmed(); s = s.replace(QRegExp(QStringLiteral("$"), Qt::CaseInsensitive), QString()).trimmed(); s = s.replace(QRegExp(QStringLiteral("$"), Qt::CaseInsensitive), QString()).trimmed(); return s; } DefaultRendererPrivate::DefaultRendererPrivate(const MessagePart::Ptr &msgPart, CSSHelperBase *cssHelper, HtmlWriter *writer, const MessagePartRendererFactory *rendererFactory) : mMsgPart(msgPart) , mOldWriter(writer) , mCSSHelper(cssHelper) , mRendererFactory(rendererFactory) { mHtml = renderFactory(mMsgPart, nullptr); } DefaultRendererPrivate::~DefaultRendererPrivate() { } QString DefaultRendererPrivate::alignText() { return QApplication::isRightToLeft() ? QStringLiteral("rtl") : QStringLiteral("ltr"); } CSSHelperBase *DefaultRendererPrivate::cssHelper() const { return mCSSHelper; } Interface::ObjectTreeSource *DefaultRendererPrivate::source() const { return mMsgPart->source(); } void DefaultRendererPrivate::renderSubParts(const MessagePart::Ptr &msgPart, HtmlWriter *htmlWriter) { foreach (const auto &m, msgPart->subParts()) htmlWriter->write(renderFactory(m, htmlWriter)); } void DefaultRendererPrivate::render(const MessagePartList::Ptr &mp, HtmlWriter *htmlWriter) { HTMLBlock::Ptr rBlock; HTMLBlock::Ptr aBlock; if (mp->isRoot()) { rBlock = HTMLBlock::Ptr(new RootBlock(htmlWriter)); } if (mp->isAttachment()) { aBlock = HTMLBlock::Ptr(new AttachmentMarkBlock(htmlWriter, mp->attachmentContent())); } renderSubParts(mp, htmlWriter); } void DefaultRendererPrivate::render(const MimeMessagePart::Ptr &mp, HtmlWriter *htmlWriter) { HTMLBlock::Ptr aBlock; HTMLBlock::Ptr rBlock; if (mp->isAttachment()) { aBlock = HTMLBlock::Ptr(new AttachmentMarkBlock(htmlWriter, mp->attachmentContent())); } if (mp->isRoot()) { rBlock = HTMLBlock::Ptr(new RootBlock(htmlWriter)); } renderSubParts(mp, htmlWriter); } void DefaultRendererPrivate::render(const EncapsulatedRfc822MessagePart::Ptr &mp, HtmlWriter *htmlWriter) { if (!mp->hasSubParts()) { return; } Grantlee::Template t = MessageViewer::MessagePartRendererManager::self()->loadByName(QStringLiteral( ":/encapsulatedrfc822messagepart.html")); Grantlee::Context c = MessageViewer::MessagePartRendererManager::self()->createContext(); QObject block; c.insert(QStringLiteral("block"), &block); block.setProperty("dir", alignText()); block.setProperty("link", mp->mOtp->nodeHelper()->asHREF(mp->mMessage.data(), QStringLiteral("body"))); c.insert(QStringLiteral("msgHeader"), mp->source()->createMessageHeader(mp->mMessage.data())); { auto _htmlWriter = QSharedPointer(new CacheHtmlWriter(htmlWriter)); renderSubParts(mp, _htmlWriter.data()); c.insert(QStringLiteral("content"), _htmlWriter->html()); } HTMLBlock::Ptr aBlock; if (mp->isAttachment()) { aBlock = HTMLBlock::Ptr(new AttachmentMarkBlock(htmlWriter, mp->attachmentContent())); } Grantlee::OutputStream s(htmlWriter->stream()); t->render(&s, &c); } void DefaultRendererPrivate::render(const HtmlMessagePart::Ptr &mp, HtmlWriter *htmlWriter) { Grantlee::Template t = MessageViewer::MessagePartRendererManager::self()->loadByName(QStringLiteral( ":/htmlmessagepart.html")); Grantlee::Context c = MessageViewer::MessagePartRendererManager::self()->createContext(); QObject block; c.insert(QStringLiteral("block"), &block); auto preferredMode = mp->source()->preferredMode(); bool isHtmlPreferred = (preferredMode == Util::Html) || (preferredMode == Util::MultipartHtml); const bool isPrinting = mp->source()->isPrinting(); block.setProperty("htmlMail", isHtmlPreferred); block.setProperty("loadExternal", mp->source()->htmlLoadExternal()); block.setProperty("isPrinting", isPrinting); { QString extraHead; //laurent: FIXME port to async method webengine QString bodyText = processHtml(mp->mBodyHTML, extraHead); if (isHtmlPreferred) { mp->mOtp->nodeHelper()->setNodeDisplayedEmbedded(mp->content(), true); htmlWriter->extraHead(extraHead); } block.setProperty("containsExternalReferences", containsExternalReferences(bodyText, extraHead)); c.insert(QStringLiteral("content"), bodyText); } { ConvertHtmlToPlainText convert; convert.setHtmlString(mp->mBodyHTML); QString plaintext = convert.generatePlainText(); plaintext.replace(QLatin1Char('\n'), QStringLiteral("
")); c.insert(QStringLiteral("plaintext"), plaintext); } mp->source()->setHtmlMode(Util::Html, QList() << Util::Html); HTMLBlock::Ptr aBlock; if (mp->isAttachment()) { aBlock = HTMLBlock::Ptr(new AttachmentMarkBlock(htmlWriter, mp->attachmentContent())); } Grantlee::OutputStream s(htmlWriter->stream()); t->render(&s, &c); } void DefaultRendererPrivate::renderEncrypted(const EncryptedMessagePart::Ptr &mp, HtmlWriter *htmlWriter) { KMime::Content *node = mp->content(); const auto metaData = *mp->partMetaData(); Grantlee::Template t = MessageViewer::MessagePartRendererManager::self()->loadByName(QStringLiteral( ":/encryptedmessagepart.html")); Grantlee::Context c = MessageViewer::MessagePartRendererManager::self()->createContext(); QObject block; if (node || mp->hasSubParts()) { auto _htmlWriter = QSharedPointer(new CacheHtmlWriter(mOldWriter)); { HTMLBlock::Ptr rBlock; if (node && mp->isRoot()) { rBlock = HTMLBlock::Ptr(new RootBlock(_htmlWriter.data())); } renderSubParts(mp, _htmlWriter.data()); } c.insert(QStringLiteral("content"), _htmlWriter->html()); } else if (!metaData.inProgress) { - auto part = renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp); - if (part) { - c.insert(QStringLiteral("content"), part->html()); + CacheHtmlWriter nestedWriter(htmlWriter); + if (renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp, &nestedWriter)) { + c.insert(QStringLiteral("content"), nestedWriter.html()); } else { c.insert(QStringLiteral("content"), QString()); } } c.insert(QStringLiteral("cryptoProto"), QVariant::fromValue(mp->mCryptoProto)); if (mp->mDecryptRecipients.size() > 0) { c.insert(QStringLiteral("decryptedRecipients"), QVariant::fromValue(mp->mDecryptRecipients)); } c.insert(QStringLiteral("block"), &block); block.setProperty("dir", alignText()); block.setProperty("inProgress", metaData.inProgress); block.setProperty("isDecrypted", mp->decryptMessage()); block.setProperty("isDecryptable", metaData.isDecryptable); block.setProperty("decryptIcon", QUrl::fromLocalFile(IconNameCache::instance()->iconPath(QStringLiteral( "document-decrypt"), KIconLoader::Small)).url()); block.setProperty("errorText", metaData.errorText); block.setProperty("noSecKey", mp->mNoSecKey); block.setProperty("iconSize", MessageViewer::MessagePartRendererManager::self()->iconCurrentSize()); Grantlee::OutputStream s(htmlWriter->stream()); t->render(&s, &c); } void DefaultRendererPrivate::renderSigned(const SignedMessagePart::Ptr &mp, HtmlWriter *htmlWriter) { KMime::Content *node = mp->content(); const auto metaData = *mp->partMetaData(); auto cryptoProto = mp->mCryptoProto; const bool isSMIME = cryptoProto && (cryptoProto == QGpgME::smime()); Grantlee::Template t = MessageViewer::MessagePartRendererManager::self()->loadByName(QStringLiteral( ":/signedmessagepart.html")); Grantlee::Context c = MessageViewer::MessagePartRendererManager::self()->createContext(); QObject block; if (node) { auto _htmlWriter = QSharedPointer(new CacheHtmlWriter(htmlWriter)); { HTMLBlock::Ptr rBlock; if (mp->isRoot()) { rBlock = HTMLBlock::Ptr(new RootBlock(_htmlWriter.data())); } renderSubParts(mp, _htmlWriter.data()); } c.insert(QStringLiteral("content"), _htmlWriter->html()); } else if (!metaData.inProgress) { - auto part = renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp); - if (part) { - c.insert(QStringLiteral("content"), part->html()); + CacheHtmlWriter nestedWriter(htmlWriter); + if (renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp, &nestedWriter)) { + c.insert(QStringLiteral("content"), nestedWriter.html()); } else { c.insert(QStringLiteral("content"), QString()); } } c.insert(QStringLiteral("cryptoProto"), QVariant::fromValue(cryptoProto)); c.insert(QStringLiteral("block"), &block); block.setProperty("dir", alignText()); block.setProperty("inProgress", metaData.inProgress); block.setProperty("errorText", metaData.errorText); block.setProperty("detailHeader", mp->source()->showSignatureDetails()); block.setProperty("printing", false); block.setProperty("addr", metaData.signerMailAddresses.join(QLatin1Char(','))); block.setProperty("technicalProblem", metaData.technicalProblem); block.setProperty("keyId", metaData.keyId); if (metaData.creationTime.isValid()) { //should be handled inside grantlee but currently not possible see: https://bugs.kde.org/363475 block.setProperty("creationTime", QLocale().toString(metaData.creationTime, QLocale::ShortFormat)); } block.setProperty("isGoodSignature", metaData.isGoodSignature); block.setProperty("isSMIME", isSMIME); if (metaData.keyTrust == GpgME::Signature::Unknown) { block.setProperty("keyTrust", QStringLiteral("unknown")); } else if (metaData.keyTrust == GpgME::Signature::Marginal) { block.setProperty("keyTrust", QStringLiteral("marginal")); } else if (metaData.keyTrust == GpgME::Signature::Full) { block.setProperty("keyTrust", QStringLiteral("full")); } else if (metaData.keyTrust == GpgME::Signature::Ultimate) { block.setProperty("keyTrust", QStringLiteral("ultimate")); } else { block.setProperty("keyTrust", QStringLiteral("untrusted")); } QString startKeyHREF; { QString keyWithWithoutURL; if (cryptoProto) { startKeyHREF = QStringLiteral("") .arg(cryptoProto->displayName(), cryptoProto->name(), QString::fromLatin1(metaData.keyId)); keyWithWithoutURL = QStringLiteral("%1%2").arg(startKeyHREF, QString::fromLatin1(QByteArray(QByteArrayLiteral( "0x") + metaData.keyId))); } else { keyWithWithoutURL = QStringLiteral("0x") + QString::fromUtf8(metaData.keyId); } block.setProperty("keyWithWithoutURL", keyWithWithoutURL); } bool onlyShowKeyURL = false; bool showKeyInfos = false; bool cannotCheckSignature = true; QString signer = metaData.signer; QString statusStr; QString mClass; QString greenCaseWarning; if (metaData.inProgress) { mClass = QStringLiteral("signInProgress"); } else { const QStringList &blockAddrs(metaData.signerMailAddresses); // note: At the moment frameColor and showKeyInfos are // used for CMS only but not for PGP signatures // pending(khz): Implement usage of these for PGP sigs as well. int frameColor = SIG_FRAME_COL_UNDEF; statusStr = sigStatusToString(cryptoProto, metaData.status_code, metaData.sigSummary, frameColor, showKeyInfos); // if needed fallback to english status text // that was reported by the plugin if (statusStr.isEmpty()) { statusStr = metaData.status; } if (metaData.technicalProblem) { frameColor = SIG_FRAME_COL_YELLOW; } switch (frameColor) { case SIG_FRAME_COL_RED: cannotCheckSignature = false; break; case SIG_FRAME_COL_YELLOW: cannotCheckSignature = true; break; case SIG_FRAME_COL_GREEN: cannotCheckSignature = false; break; } // temporary hack: always show key information! showKeyInfos = true; if (isSMIME && (SIG_FRAME_COL_UNDEF != frameColor)) { switch (frameColor) { case SIG_FRAME_COL_RED: mClass = QStringLiteral("signErr"); onlyShowKeyURL = true; break; case SIG_FRAME_COL_YELLOW: if (metaData.technicalProblem) { mClass = QStringLiteral("signWarn"); } else { mClass = QStringLiteral("signOkKeyBad"); } break; case SIG_FRAME_COL_GREEN: mClass = QStringLiteral("signOkKeyOk"); // extra hint for green case // that email addresses in DN do not match fromAddress QString msgFrom(KEmailAddress::extractEmailAddress(mp->mFromAddress)); QString certificate; if (metaData.keyId.isEmpty()) { certificate = i18n("certificate"); } else { certificate = startKeyHREF + i18n("certificate") + QStringLiteral(""); } if (!blockAddrs.empty()) { if (!blockAddrs.contains(msgFrom, Qt::CaseInsensitive)) { greenCaseWarning = QStringLiteral("") +i18nc("Start of warning message.", "Warning:") +QStringLiteral(" ") +i18n( "Sender's mail address is not stored in the %1 used for signing.", certificate) +QStringLiteral("
") +i18n("sender: ") +msgFrom +QStringLiteral("
") +i18n("stored: "); // We cannot use Qt's join() function here but // have to join the addresses manually to // extract the mail addresses (without '<''>') // before including it into our string: bool bStart = true; QStringList::ConstIterator end(blockAddrs.constEnd()); for (QStringList::ConstIterator it = blockAddrs.constBegin(); it != end; ++it) { if (!bStart) { greenCaseWarning.append(QStringLiteral(",
   ")); } bStart = false; greenCaseWarning.append(KEmailAddress::extractEmailAddress(*it)); } } } else { greenCaseWarning = QStringLiteral("") +i18nc("Start of warning message.", "Warning:") +QStringLiteral(" ") +i18n("No mail address is stored in the %1 used for signing, " "so we cannot compare it to the sender's address %2.", certificate, msgFrom); } break; } if (showKeyInfos && !cannotCheckSignature) { if (metaData.signer.isEmpty()) { signer.clear(); } else { if (!blockAddrs.empty()) { const QUrl address = KEmailAddress::encodeMailtoUrl(blockAddrs.first()); signer = QStringLiteral("%2").arg(QLatin1String(QUrl :: toPercentEncoding( address . path())), signer); } } } } else { if (metaData.signer.isEmpty() || metaData.technicalProblem) { mClass = QStringLiteral("signWarn"); } else { // HTMLize the signer's user id and create mailto: link signer = MessageCore::StringUtil::quoteHtmlChars(signer, true); signer = QStringLiteral("%1").arg(signer); if (metaData.isGoodSignature) { if (metaData.keyTrust < GpgME::Signature::Marginal) { mClass = QStringLiteral("signOkKeyBad"); } else { mClass = QStringLiteral("signOkKeyOk"); } } else { mClass = QStringLiteral("signErr"); } } } } block.setProperty("onlyShowKeyURL", onlyShowKeyURL); block.setProperty("showKeyInfos", showKeyInfos); block.setProperty("cannotCheckSignature", cannotCheckSignature); block.setProperty("signer", signer); block.setProperty("statusStr", statusStr); block.setProperty("signClass", mClass); block.setProperty("greenCaseWarning", greenCaseWarning); Grantlee::OutputStream s(htmlWriter->stream()); t->render(&s, &c); } void DefaultRendererPrivate::render(const SignedMessagePart::Ptr &mp, HtmlWriter *htmlWriter) { const auto metaData = *mp->partMetaData(); if (metaData.isSigned || metaData.inProgress) { HTMLBlock::Ptr aBlock; if (mp->isAttachment()) { aBlock = HTMLBlock::Ptr(new AttachmentMarkBlock(htmlWriter, mp->attachmentContent())); } renderSigned(mp, htmlWriter); return; } HTMLBlock::Ptr aBlock; if (mp->isAttachment()) { aBlock = HTMLBlock::Ptr(new AttachmentMarkBlock(htmlWriter, mp->attachmentContent())); } if (mp->hasSubParts()) { renderSubParts(mp, htmlWriter); } else if (!metaData.inProgress) { - auto part = renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp); - if (part) { - htmlWriter->write(part->html()); - } + renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp, htmlWriter); } } void DefaultRendererPrivate::render(const EncryptedMessagePart::Ptr &mp, HtmlWriter *htmlWriter) { const auto metaData = *mp->partMetaData(); if (metaData.isEncrypted || metaData.inProgress) { HTMLBlock::Ptr aBlock; if (mp->isAttachment()) { aBlock = HTMLBlock::Ptr(new AttachmentMarkBlock(htmlWriter, mp->attachmentContent())); } renderEncrypted(mp, htmlWriter); return; } HTMLBlock::Ptr aBlock; if (mp->isAttachment()) { aBlock = HTMLBlock::Ptr(new AttachmentMarkBlock(htmlWriter, mp->attachmentContent())); } if (mp->hasSubParts()) { renderSubParts(mp, htmlWriter); } else if (!metaData.inProgress) { - auto part = renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp); - if (part) { - htmlWriter->write(part->html()); - } + renderWithFactory(QStringLiteral("MimeTreeParser::MessagePart"), mp, htmlWriter); } } void DefaultRendererPrivate::render(const AlternativeMessagePart::Ptr &mp, HtmlWriter *htmlWriter) { HTMLBlock::Ptr aBlock; if (mp->isAttachment()) { aBlock = HTMLBlock::Ptr(new AttachmentMarkBlock(htmlWriter, mp->attachmentContent())); } auto mode = mp->preferredMode(); if (mode == MimeTreeParser::Util::MultipartPlain && mp->text().trimmed().isEmpty()) { foreach (const auto m, mp->availableModes()) { if (m != MimeTreeParser::Util::MultipartPlain) { mode = m; break; } } } MimeMessagePart::Ptr part(mp->mChildParts.first()); if (mp->mChildParts.contains(mode)) { part = mp->mChildParts[mode]; } render(part, htmlWriter); } void DefaultRendererPrivate::render(const CertMessagePart::Ptr &mp, HtmlWriter *htmlWriter) { const GpgME::ImportResult &importResult(mp->mImportResult); Grantlee::Template t = MessageViewer::MessagePartRendererManager::self()->loadByName(QStringLiteral( ":/certmessagepart.html")); Grantlee::Context c = MessageViewer::MessagePartRendererManager::self()->createContext(); QObject block; c.insert(QStringLiteral("block"), &block); block.setProperty("importError", QString::fromLocal8Bit(importResult.error().asString())); block.setProperty("nImp", importResult.numImported()); block.setProperty("nUnc", importResult.numUnchanged()); block.setProperty("nSKImp", importResult.numSecretKeysImported()); block.setProperty("nSKUnc", importResult.numSecretKeysUnchanged()); QVariantList keylist; const auto imports = importResult.imports(); auto end(imports.end()); for (auto it = imports.begin(); it != end; ++it) { QObject *key(new QObject(mp.data())); key->setProperty("error", QString::fromLocal8Bit((*it).error().asString())); key->setProperty("status", (*it).status()); key->setProperty("fingerprint", QLatin1String((*it).fingerprint())); keylist << QVariant::fromValue(key); } HTMLBlock::Ptr aBlock; if (mp->isAttachment()) { aBlock = HTMLBlock::Ptr(new AttachmentMarkBlock(htmlWriter, mp->attachmentContent())); } Grantlee::OutputStream s(htmlWriter->stream()); t->render(&s, &c); } -QSharedPointer DefaultRendererPrivate::renderWithFactory(QString className, const MessagePart::Ptr &msgPart) +bool DefaultRendererPrivate::renderWithFactory(const QString &className, const MessagePart::Ptr &msgPart, HtmlWriter *htmlWriter) { - if (mRendererFactory) { - const auto registry = mRendererFactory->typeRegistry(className); - - if (registry.size() > 0) { - const auto plugin = registry.at(0); - return plugin->render(this, msgPart); - } - } - - return QSharedPointer(); + if (!mRendererFactory) + return false; + const auto registry = mRendererFactory->typeRegistry(className); + if (registry.empty()) + return false; + + const auto plugin = registry.at(0); + return plugin->render(this, msgPart, htmlWriter); } QString DefaultRendererPrivate::renderFactory(const MessagePart::Ptr &msgPart, HtmlWriter *_htmlWriter) { + auto htmlWriter = QSharedPointer(new CacheHtmlWriter(mOldWriter)); const QString className = QString::fromUtf8(msgPart->metaObject()->className()); - const auto rendered = renderWithFactory(className, msgPart); - if (rendered) { - const auto parts = rendered->embededParts(); - foreach (auto key, parts.keys()) { - _htmlWriter->embedPart(key, parts.value(key)); - } - - foreach (auto entry, rendered->extraHeader()) { - _htmlWriter->extraHead(entry); - } + if (renderWithFactory(className, msgPart, htmlWriter.data())) + return htmlWriter->html(); - return rendered->html(); - } - - auto htmlWriter = QSharedPointer(new CacheHtmlWriter(mOldWriter)); if (className == QStringLiteral("MimeTreeParser::MessagePartList")) { auto mp = msgPart.dynamicCast(); if (mp) { render(mp, htmlWriter.data()); } } else if (className == QStringLiteral("MimeTreeParser::MimeMessagePart")) { auto mp = msgPart.dynamicCast(); if (mp) { render(mp, htmlWriter.data()); } } else if (className == QStringLiteral("MimeTreeParser::EncapsulatedRfc822MessagePart")) { auto mp = msgPart.dynamicCast(); if (mp) { render(mp, htmlWriter.data()); } } else if (className == QStringLiteral("MimeTreeParser::HtmlMessagePart")) { auto mp = msgPart.dynamicCast(); if (mp) { render(mp, htmlWriter.data()); } } else if (className == QStringLiteral("MimeTreeParser::SignedMessagePart")) { auto mp = msgPart.dynamicCast(); if (mp) { render(mp, htmlWriter.data()); } } else if (className == QStringLiteral("MimeTreeParser::EncryptedMessagePart")) { auto mp = msgPart.dynamicCast(); if (mp) { render(mp, htmlWriter.data()); } } else if (className == QStringLiteral("MimeTreeParser::AlternativeMessagePart")) { auto mp = msgPart.dynamicCast(); if (mp) { render(mp, htmlWriter.data()); } } else if (className == QStringLiteral("MimeTreeParser::CertMessagePart")) { auto mp = msgPart.dynamicCast(); if (mp) { render(mp, htmlWriter.data()); } } else if (auto mp = msgPart.dynamicCast()) { return mp->formatOutput(); } else { qCWarning(MESSAGEVIEWER_LOG) << "We got a unkonwn classname, using default behaviour for " << className; } return htmlWriter->html(); } DefaultRenderer::DefaultRenderer(const MimeTreeParser::MessagePart::Ptr &msgPart, CSSHelperBase *cssHelper, MimeTreeParser::HtmlWriter *writer) : d(new MimeTreeParser::DefaultRendererPrivate(msgPart, cssHelper, writer, MessagePartRendererFactory::instance())) { } DefaultRenderer::~DefaultRenderer() { delete d; } QString DefaultRenderer::html() const { return d->mHtml; } diff --git a/messageviewer/src/messagepartthemes/default/defaultrenderer_p.h b/messageviewer/src/messagepartthemes/default/defaultrenderer_p.h index 4699a607..8b9ac368 100644 --- a/messageviewer/src/messagepartthemes/default/defaultrenderer_p.h +++ b/messageviewer/src/messagepartthemes/default/defaultrenderer_p.h @@ -1,72 +1,72 @@ /* 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. */ #ifndef __MESSAGEVIEWER_DEFAULTRENDERER_P_H__ #define __MESSAGEVIEWER_DEFAULTRENDERER_P_H__ #include "defaultrenderer.h" #include using namespace MimeTreeParser; using namespace MessageViewer; class PartRendered; namespace MessageViewer { class MessagePartRendererFactory; class CSSHelperBase; class HtmlWriter; } namespace MimeTreeParser { class DefaultRendererPrivate { public: DefaultRendererPrivate(const MessagePart::Ptr &msgPart, CSSHelperBase *cssHelper, HtmlWriter *writer, const MessagePartRendererFactory *rendererFactory); ~DefaultRendererPrivate(); QString alignText(); CSSHelperBase *cssHelper() const; Interface::ObjectTreeSource *source() const; void renderSubParts(const MessagePart::Ptr &msgPart, HtmlWriter *htmlWriter); void render(const MessagePartList::Ptr &mp, HtmlWriter *htmlWriter); void render(const MimeMessagePart::Ptr &mp, HtmlWriter *htmlWriter); void render(const EncapsulatedRfc822MessagePart::Ptr &mp, HtmlWriter *htmlWriter); void render(const HtmlMessagePart::Ptr &mp, HtmlWriter *htmlWriter); void renderEncrypted(const EncryptedMessagePart::Ptr &mp, HtmlWriter *htmlWriter); void renderSigned(const SignedMessagePart::Ptr &mp, HtmlWriter *htmlWriter); void render(const SignedMessagePart::Ptr &mp, HtmlWriter *htmlWriter); void render(const EncryptedMessagePart::Ptr &mp, HtmlWriter *htmlWriter); void render(const AlternativeMessagePart::Ptr &mp, HtmlWriter *htmlWriter); void render(const CertMessagePart::Ptr &mp, HtmlWriter *htmlWriter); - QSharedPointer renderWithFactory(QString className, const MessagePart::Ptr &msgPart); + bool renderWithFactory(const QString &className, const MessagePart::Ptr &msgPart, HtmlWriter *writer); QString renderFactory(const MessagePart::Ptr &msgPart, HtmlWriter *htmlWriter); QString mHtml; MessagePart::Ptr mMsgPart; HtmlWriter *mOldWriter = nullptr; CSSHelperBase *mCSSHelper = nullptr; const MessageViewer::MessagePartRendererFactory *mRendererFactory = nullptr; }; } #endif diff --git a/messageviewer/src/messagepartthemes/default/messagepartrendererbase.h b/messageviewer/src/messagepartthemes/default/messagepartrendererbase.h index c7a589b0..49b22ba1 100644 --- a/messageviewer/src/messagepartthemes/default/messagepartrendererbase.h +++ b/messageviewer/src/messagepartthemes/default/messagepartrendererbase.h @@ -1,56 +1,55 @@ /* Copyright (c) 2017 Sandro Knauß KMail 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_MESSAGEPARTRENDERERBASE_H__ #define __MESSAGEVIEWER_MESSAGEPARTRENDERERBASE_H__ #include "messageviewer_export.h" #include #include #include namespace MimeTreeParser { class DefaultRendererPrivate; +class HtmlWriter; class MessagePart; typedef QSharedPointer MessagePartPtr; } -class PartRendered; - class MessagePartRendererBase { public: MessagePartRendererBase(); virtual ~MessagePartRendererBase(); - virtual QSharedPointer render(MimeTreeParser::DefaultRendererPrivate *, const MimeTreeParser::MessagePartPtr &) + virtual bool render(MimeTreeParser::DefaultRendererPrivate *, const MimeTreeParser::MessagePartPtr &, MimeTreeParser::HtmlWriter *htmlWriter) const = 0; }; #endif diff --git a/messageviewer/src/messagepartthemes/default/partrendered.cpp b/messageviewer/src/messagepartthemes/default/partrendered.cpp deleted file mode 100644 index ec1a05ab..00000000 --- a/messageviewer/src/messagepartthemes/default/partrendered.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - Copyright (c) 2017 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 "partrendered.h" - -#include "defaultrenderer.h" -#include "defaultrenderer_p.h" -#include "htmlblock.h" - -#include "messagepartrenderermanager.h" - -#include -#include - -#include - -#include -#include - -#include - -using namespace MessageViewer; - -PartRendered::PartRendered() -{ -} - -PartRendered::~PartRendered() -{ -} - -inline QString PartRendered::alignText() -{ - return QApplication::isRightToLeft() ? QStringLiteral("rtl") : QStringLiteral("ltr"); -} - -QVector > PartRendered::renderSubParts( - MimeTreeParser::MessagePart::Ptr mp) -{ - QVector > ret; - foreach (const auto &_m, mp->subParts()) { - CacheHtmlWriter cacheWriter; - DefaultRenderer::Ptr renderer = mp->source()->messagePartTheme(_m); - cacheWriter.write(renderer->html()); - ret.append(QSharedPointer(new WrapperPartRendered(&cacheWriter))); - } - return ret; -} - -EmptyPartRendered::EmptyPartRendered() -{ -} - -EmptyPartRendered::~EmptyPartRendered() -{ -} - -QString EmptyPartRendered::extraHeader() -{ - return QString(); -} - -QString EmptyPartRendered::html() -{ - return QString(); -} - -QMap EmptyPartRendered::embededParts() -{ - return QMap(); -} - -WrapperPartRendered::WrapperPartRendered(CacheHtmlWriter *htmlWriter) - : PartRendered() -{ - mHtml = htmlWriter->html(); - mHead = htmlWriter->head; - mEmbeded = htmlWriter->embedParts; -} - -WrapperPartRendered::~WrapperPartRendered() -{ -} - -QString WrapperPartRendered::html() -{ - return mHtml; -} - -QString WrapperPartRendered::extraHeader() -{ - return mHead; -} - -QMap WrapperPartRendered::embededParts() -{ - return mEmbeded; -} - -HtmlOnlyPartRendered::HtmlOnlyPartRendered(MimeTreeParser::MessagePart::Ptr mp, const QString &html) - : mHtml(html) -{ - mShowAttachmentBlock = mp->isAttachment(); - mAttachmentNode = mp->attachmentContent(); -} - -HtmlOnlyPartRendered::~HtmlOnlyPartRendered() -{ -} - -QMap HtmlOnlyPartRendered::embededParts() -{ - return QMap(); -} - -QString HtmlOnlyPartRendered::extraHeader() -{ - return QString(); -} - -QString HtmlOnlyPartRendered::html() -{ - MimeTreeParser::AttachmentMarkBlock block(nullptr, mAttachmentNode); - - QString ret; - if (mShowAttachmentBlock) { - ret += block.enter(); - } - - ret += mHtml; - ret += block.exit(); - - return ret; -} - -TextPartRendered::TextPartRendered(MimeTreeParser::TextMessagePart::Ptr mp) - : mShowAttachmentBlock(false) - , mAttachmentNode(nullptr) -{ - auto node = mp->content(); - auto nodeHelper = mp->mOtp->nodeHelper(); - - if (mp->isHidden()) { - return; - } - - Grantlee::Template t; - Grantlee::Context c = MessageViewer::MessagePartRendererManager::self()->createContext(); - QObject block; - c.insert(QStringLiteral("block"), &block); - - block.setProperty("showTextFrame", mp->showTextFrame()); - block.setProperty("label", - MessageCore::StringUtil::quoteHtmlChars(MimeTreeParser::NodeHelper::fileName( - node), true)); - block.setProperty("comment", - MessageCore::StringUtil::quoteHtmlChars(node->contentDescription()-> - asUnicodeString(), true)); - block.setProperty("link", nodeHelper->asHREF(node, QStringLiteral("body"))); - block.setProperty("showLink", mp->showLink()); - block.setProperty("dir", alignText()); - - t - = MessageViewer::MessagePartRendererManager::self()->loadByName(QStringLiteral( - ":/textmessagepart.html")); - mSubList = renderSubParts(mp); - QString content; - foreach (auto part, mSubList) { - content += part->html(); - } - c.insert(QStringLiteral("content"), content); - - mShowAttachmentBlock = mp->isAttachment(); - mHtml = t->render(&c); - mAttachmentNode = mp->attachmentContent(); -} - -TextPartRendered::~TextPartRendered() -{ -} - -QMap TextPartRendered::embededParts() -{ - QMap ret; - foreach (auto part, mSubList) { - //ret += part->embededParts(); - } - return ret; -} - -QString TextPartRendered::extraHeader() -{ - QString ret; - foreach (auto part, mSubList) { - ret += part->extraHeader(); - } - return ret; -} - -QString TextPartRendered::html() -{ - MimeTreeParser::AttachmentMarkBlock block(nullptr, mAttachmentNode); - - QString ret; - if (mShowAttachmentBlock) { - ret += block.enter(); - } - - ret += mHtml; - ret += block.exit(); - - return ret; -} diff --git a/messageviewer/src/messagepartthemes/default/partrendered.h b/messageviewer/src/messagepartthemes/default/partrendered.h deleted file mode 100644 index 0d75adcd..00000000 --- a/messageviewer/src/messagepartthemes/default/partrendered.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - Copyright (c) 2017 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_PARTRENDERED_H__ -#define __MESSAGEVIEWER_PARTRENDERED_H__ - -#include "cachehtmlwriter.h" - -#include -#include -#include -#include - -namespace MimeTreeParser { -class MessagePart; -typedef QSharedPointer MessagePartPtr; -class TextMessagePart; -typedef QSharedPointer TextMessagePartPtr; -class DefaultRendererPrivate; -} - -namespace KMime { -class Content; -} - -class PartRendered -{ -public: - PartRendered(); - virtual ~PartRendered(); - - inline QString alignText(); - virtual QString html() = 0; - virtual QMap embededParts() = 0; - virtual QString extraHeader() = 0; - -protected: - QVector > renderSubParts(MimeTreeParser::MessagePartPtr mp); -}; -class EmptyPartRendered : public PartRendered -{ -public: - EmptyPartRendered(); - virtual ~EmptyPartRendered(); - - QString html() override; - QMap embededParts() override; - QString extraHeader() override; -}; - -class WrapperPartRendered : public PartRendered -{ -public: - WrapperPartRendered(MessageViewer::CacheHtmlWriter*); - virtual ~WrapperPartRendered(); - - QString html() override; - QMap embededParts() override; - QString extraHeader() override; - -private: - QString mHtml; - QString mHead; - QMap mEmbeded; -}; - -class HtmlOnlyPartRendered : public PartRendered -{ -public: - HtmlOnlyPartRendered(MimeTreeParser::MessagePartPtr part, const QString &html); - virtual ~HtmlOnlyPartRendered(); - - QString html() override; - QMap embededParts() override; - QString extraHeader() override; - -protected: - void setHtml(const QString &html); - -private: - QString mHtml; - bool mShowAttachmentBlock; - KMime::Content *mAttachmentNode = nullptr; -}; - -class TextPartRendered : public PartRendered -{ -public: - TextPartRendered(MimeTreeParser::TextMessagePartPtr part); - virtual ~TextPartRendered(); - - QString html() override; - QMap embededParts() override; - QString extraHeader() override; - -private: - QString mHtml; - QVector > mSubList; - bool mShowAttachmentBlock; - KMime::Content *mAttachmentNode = nullptr; -}; - -#endif diff --git a/messageviewer/src/messagepartthemes/default/plugins/attachmentmessagepartrenderer.cpp b/messageviewer/src/messagepartthemes/default/plugins/attachmentmessagepartrenderer.cpp index 2b43813e..e4b5229d 100644 --- a/messageviewer/src/messagepartthemes/default/plugins/attachmentmessagepartrenderer.cpp +++ b/messageviewer/src/messagepartthemes/default/plugins/attachmentmessagepartrenderer.cpp @@ -1,114 +1,121 @@ /* 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 "attachmentmessagepartrenderer.h" #include "quotehtml.h" #include "utils/mimetype.h" -#include "../partrendered.h" +#include "../htmlblock.h" #include "../defaultrenderer_p.h" #include "../messagepartrenderermanager.h" #include +#include #include #include #include AttachmentMessagePartRenderer::AttachmentMessagePartRenderer() { } AttachmentMessagePartRenderer::~AttachmentMessagePartRenderer() { } -QSharedPointer AttachmentMessagePartRenderer::render(DefaultRendererPrivate *drp, const MimeTreeParser::MessagePartPtr &msgPart) -const +bool AttachmentMessagePartRenderer::render(MimeTreeParser::DefaultRendererPrivate* drp, const MimeTreeParser::MessagePartPtr& msgPart, MimeTreeParser::HtmlWriter* htmlWriter) const { auto mp = msgPart.dynamicCast(); if (!mp) { - return QSharedPointer(); + return false; } KMime::Content *node = mp->content(); NodeHelper *nodeHelper = mp->mOtp->nodeHelper(); if (mp->isHidden()) { - return QSharedPointer(new EmptyPartRendered()); + return true; } const auto tmpAsIcon = mp->asIcon(); if (tmpAsIcon == MimeTreeParser::NoIcon) { - return drp->renderWithFactory(QStringLiteral("MimeTreeParser::TextMessagePart"), mp); + return drp->renderWithFactory(QStringLiteral("MimeTreeParser::TextMessagePart"), mp, htmlWriter); } Grantlee::Template t = MessageViewer::MessagePartRendererManager::self()->loadByName(QStringLiteral( ":/asiconpart.html")); Grantlee::Context c = MessageViewer::MessagePartRendererManager::self()->createContext(); QObject block; c.insert(QStringLiteral("block"), &block); block.setProperty("showTextFrame", mp->showTextFrame()); block.setProperty("label", MessageCore::StringUtil::quoteHtmlChars(NodeHelper::fileName(node), true)); block.setProperty("comment", MessageCore::StringUtil::quoteHtmlChars(node->contentDescription()-> asUnicodeString(), true)); block.setProperty("link", nodeHelper->asHREF(node, QStringLiteral("body"))); block.setProperty("showLink", mp->showLink()); block.setProperty("dir", drp->alignText()); block.setProperty("iconSize", MessageViewer::MessagePartRendererManager::self()->iconCurrentSize()); block.setProperty("inline", (tmpAsIcon == MimeTreeParser::IconInline)); QString iconPath; if (tmpAsIcon == MimeTreeParser::IconInline) { iconPath = nodeHelper->writeNodeToTempFile(node); } else { iconPath = MessageViewer::Util::iconPathForContent(node, KIconLoader::Desktop); if (iconPath.right(14) == QLatin1String("mime_empty.png")) { nodeHelper->magicSetType(node); iconPath = MessageViewer::Util::iconPathForContent(node, KIconLoader::Desktop); } } block.setProperty("iconPath", QUrl::fromLocalFile(iconPath).url()); const QString name = node->contentType()->name(); QString label = name.isEmpty() ? NodeHelper::fileName(node) : name; QString comment = node->contentDescription()->asUnicodeString(); if (label.isEmpty()) { label = i18nc("display name for an unnamed attachment", "Unnamed"); } label = MessageCore::StringUtil::quoteHtmlChars(label, true); comment = MessageCore::StringUtil::quoteHtmlChars(comment, true); if (label == comment) { comment.clear(); } block.setProperty("label", label); block.setProperty("comment", comment); - const auto html = t->render(&c); - return QSharedPointer(new HtmlOnlyPartRendered(mp, html)); + MimeTreeParser::AttachmentMarkBlock attBlock(nullptr, mp->attachmentContent()); + if (mp->isAttachment()) + htmlWriter->write(attBlock.enter()); + + Grantlee::OutputStream s(htmlWriter->stream()); + t->render(&s, &c); + htmlWriter->write(attBlock.exit()); + + return true; } diff --git a/messageviewer/src/messagepartthemes/default/plugins/attachmentmessagepartrenderer.h b/messageviewer/src/messagepartthemes/default/plugins/attachmentmessagepartrenderer.h index f88a23f2..759b7871 100644 --- a/messageviewer/src/messagepartthemes/default/plugins/attachmentmessagepartrenderer.h +++ b/messageviewer/src/messagepartthemes/default/plugins/attachmentmessagepartrenderer.h @@ -1,36 +1,35 @@ /* 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. */ #ifndef __MESSAGEVIEWER_DEFAULTRENDERER_ATTACHMENTMESSAGEPARTRENDERER_H__ #define __MESSAGEVIEWER_DEFAULTRENDERER_ATTACHMENTMESSAGEPARTRENDERER_H__ #include "../messagepartrendererbase.h" #include class AttachmentMessagePartRenderer : public MessagePartRendererBase { public: AttachmentMessagePartRenderer(); virtual ~AttachmentMessagePartRenderer(); - QSharedPointer render(MimeTreeParser::DefaultRendererPrivate *drp, const MimeTreeParser::MessagePartPtr &msgPart) - const override; + bool render(MimeTreeParser::DefaultRendererPrivate *drp, const MimeTreeParser::MessagePartPtr &msgPart, MimeTreeParser::HtmlWriter *htmlWriter) const override; }; #endif diff --git a/messageviewer/src/messagepartthemes/default/plugins/messagepartrenderer.cpp b/messageviewer/src/messagepartthemes/default/plugins/messagepartrenderer.cpp index df72ea9f..e03c5d49 100644 --- a/messageviewer/src/messagepartthemes/default/plugins/messagepartrenderer.cpp +++ b/messageviewer/src/messagepartthemes/default/plugins/messagepartrenderer.cpp @@ -1,41 +1,47 @@ /* 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 "messagepartrenderer.h" #include "quotehtml.h" -#include "../partrendered.h" +#include "../htmlblock.h" #include "../defaultrenderer_p.h" +#include + MessagePartRenderer::MessagePartRenderer() { } MessagePartRenderer::~MessagePartRenderer() { } -QSharedPointer MessagePartRenderer::render( - MimeTreeParser::DefaultRendererPrivate *drp, const MimeTreeParser::MessagePartPtr &msgPart) const +bool MessagePartRenderer::render(MimeTreeParser::DefaultRendererPrivate *drp, const MimeTreeParser::MessagePartPtr &msgPart, MimeTreeParser::HtmlWriter *htmlWriter) const { - return QSharedPointer(new HtmlOnlyPartRendered(msgPart, quotedHTML(msgPart->text(), - msgPart->source(), - drp->cssHelper()))); + MimeTreeParser::AttachmentMarkBlock block(nullptr, msgPart->attachmentContent()); + if (msgPart->isAttachment()) { + htmlWriter->write(block.enter()); + } + + htmlWriter->write(quotedHTML(msgPart->text(), msgPart->source(), drp->cssHelper())); + htmlWriter->write(block.exit()); + return true; } diff --git a/messageviewer/src/messagepartthemes/default/plugins/messagepartrenderer.h b/messageviewer/src/messagepartthemes/default/plugins/messagepartrenderer.h index 6c15b1b3..1acb475a 100644 --- a/messageviewer/src/messagepartthemes/default/plugins/messagepartrenderer.h +++ b/messageviewer/src/messagepartthemes/default/plugins/messagepartrenderer.h @@ -1,36 +1,35 @@ /* 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. */ #ifndef __MESSAGEVIEWER_DEFAULTRENDERER_MESSAGEPARTRENDERER_H__ #define __MESSAGEVIEWER_DEFAULTRENDERER_MESSAGEPARTRENDERER_H__ #include "../messagepartrendererbase.h" #include class MessagePartRenderer : public MessagePartRendererBase { public: MessagePartRenderer(); virtual ~MessagePartRenderer(); - QSharedPointer render(MimeTreeParser::DefaultRendererPrivate *drp, const MimeTreeParser::MessagePartPtr &msgPart) - const override; + bool render(MimeTreeParser::DefaultRendererPrivate *drp, const MimeTreeParser::MessagePartPtr &msgPart, MimeTreeParser::HtmlWriter *htmlWriter) const override; }; #endif diff --git a/messageviewer/src/messagepartthemes/default/plugins/textmessagepartrenderer.cpp b/messageviewer/src/messagepartthemes/default/plugins/textmessagepartrenderer.cpp index 23ae2055..0dbde4de 100644 --- a/messageviewer/src/messagepartthemes/default/plugins/textmessagepartrenderer.cpp +++ b/messageviewer/src/messagepartthemes/default/plugins/textmessagepartrenderer.cpp @@ -1,43 +1,95 @@ /* 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 "textmessagepartrenderer.h" #include "quotehtml.h" -#include "../partrendered.h" #include "../defaultrenderer_p.h" +#include "../htmlblock.h" +#include "../messagepartrenderermanager.h" + +#include +#include + +#include +#include + +#include TextMessagePartRenderer::TextMessagePartRenderer() { } TextMessagePartRenderer::~TextMessagePartRenderer() { } -QSharedPointer TextMessagePartRenderer::render(DefaultRendererPrivate *drp, const MimeTreeParser::MessagePartPtr &msgPart) -const +static QString alignText() +{ + return QApplication::isRightToLeft() ? QStringLiteral("rtl") : QStringLiteral("ltr"); +} + +bool TextMessagePartRenderer::render(MimeTreeParser::DefaultRendererPrivate* drp, const MimeTreeParser::MessagePartPtr& msgPart, MimeTreeParser::HtmlWriter* htmlWriter) const { auto mp = msgPart.dynamicCast(); - if (mp) { - return QSharedPointer(new TextPartRendered(mp)); + if (!mp) + return false; + + auto node = mp->content(); + auto nodeHelper = mp->mOtp->nodeHelper(); + if (mp->isHidden()) { + return true; } - return QSharedPointer(); + + Grantlee::Template t; + Grantlee::Context c = MessageViewer::MessagePartRendererManager::self()->createContext(); + QObject block; + c.insert(QStringLiteral("block"), &block); + + block.setProperty("showTextFrame", mp->showTextFrame()); + block.setProperty("label", + MessageCore::StringUtil::quoteHtmlChars(MimeTreeParser::NodeHelper::fileName( + node), true)); + block.setProperty("comment", + MessageCore::StringUtil::quoteHtmlChars(node->contentDescription()-> + asUnicodeString(), true)); + block.setProperty("link", nodeHelper->asHREF(node, QStringLiteral("body"))); + block.setProperty("showLink", mp->showLink()); + block.setProperty("dir", alignText()); + + t = MessageViewer::MessagePartRendererManager::self()->loadByName(QStringLiteral( + ":/textmessagepart.html")); + + QString content; + foreach (const auto &_m, mp->subParts()) { + DefaultRenderer::Ptr renderer = mp->source()->messagePartTheme(_m); + content += renderer->html(); + } + c.insert(QStringLiteral("content"), content); + + MimeTreeParser::AttachmentMarkBlock attBlock(nullptr, mp->attachmentContent()); + if (mp->isAttachment()) + htmlWriter->write(attBlock.enter()); + + Grantlee::OutputStream s(htmlWriter->stream()); + t->render(&s, &c); + htmlWriter->write(attBlock.exit()); + return true; } diff --git a/messageviewer/src/messagepartthemes/default/plugins/textmessagepartrenderer.h b/messageviewer/src/messagepartthemes/default/plugins/textmessagepartrenderer.h index 4c65a51f..651d69dc 100644 --- a/messageviewer/src/messagepartthemes/default/plugins/textmessagepartrenderer.h +++ b/messageviewer/src/messagepartthemes/default/plugins/textmessagepartrenderer.h @@ -1,36 +1,35 @@ /* 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. */ #ifndef __MESSAGEVIEWER_DEFAULTRENDERER_TEXTMESSAGEPARTRENDERER_H__ #define __MESSAGEVIEWER_DEFAULTRENDERER_TEXTMESSAGEPARTRENDERER_H__ #include "../messagepartrendererbase.h" #include class TextMessagePartRenderer : public MessagePartRendererBase { public: TextMessagePartRenderer(); virtual ~TextMessagePartRenderer(); - QSharedPointer render(MimeTreeParser::DefaultRendererPrivate *drp, const MimeTreeParser::MessagePartPtr &msgPart) - const override; + bool render(MimeTreeParser::DefaultRendererPrivate* drp, const MimeTreeParser::MessagePartPtr& msgPart, MimeTreeParser::HtmlWriter *htmlWriter) const override; }; #endif diff --git a/mimetreeparser/src/viewer/messagepart.h b/mimetreeparser/src/viewer/messagepart.h index b9a38f4f..0767b5f2 100644 --- a/mimetreeparser/src/viewer/messagepart.h +++ b/mimetreeparser/src/viewer/messagepart.h @@ -1,416 +1,416 @@ /* 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 __MIMETREEPARSER_MESSAGEPART_H__ #define __MIMETREEPARSER_MESSAGEPART_H__ #include "mimetreeparser_export.h" #include "mimetreeparser/bodypartformatter.h" #include "mimetreeparser/util.h" #include #include #include #include #include #include #include class QTextCodec; -class TextPartRendered; +class TextMessagePartRenderer; class AttachmentMessagePartRenderer; namespace GpgME { class ImportResult; } namespace QGpgME { class Protocol; } namespace KMime { class Content; } namespace MimeTreeParser { class ObjectTreeParser; class HtmlWriter; class CryptoBodyPartMemento; class MessagePartPrivate; class MultiPartAlternativeBodyPartFormatter; namespace Interface { class ObjectTreeSource; } class MIMETREEPARSER_EXPORT MessagePart : public QObject { Q_OBJECT Q_PROPERTY(QString plaintextContent READ plaintextContent) Q_PROPERTY(QString htmlContent READ htmlContent) Q_PROPERTY(bool attachment READ isAttachment) Q_PROPERTY(bool root READ isRoot) Q_PROPERTY(bool isHtml READ isHtml) Q_PROPERTY(bool isHidden READ isHidden) public: typedef QSharedPointer Ptr; MessagePart(ObjectTreeParser *otp, const QString &text); ~MessagePart(); void setParentPart(MessagePart *parentPart); MessagePart *parentPart() const; virtual QString text() const; void setText(const QString &text); virtual QString plaintextContent() const; virtual QString htmlContent() const; /** The KMime::Content* node that's represented by this part. * Can be @c nullptr, e.g. for sub-parts of an inline signed body part. */ KMime::Content *content() const; void setContent(KMime::Content *node); /** The KMime::Content* node that's the source of this part. * This is not necessarily the same as content(), for example for * broken-up multipart nodes. */ KMime::Content *attachmentContent() const; void setAttachmentContent(KMime::Content *node); bool isAttachment() const; void setIsRoot(bool root); bool isRoot() const; virtual bool isHtml() const; virtual bool isHidden() const; PartMetaData *partMetaData() const; /* only a function that should be removed if the refactoring is over */ virtual void fix() const; void appendSubPart(const MessagePart::Ptr &messagePart); const QVector &subParts() const; bool hasSubParts() const; Interface::ObjectTreeSource *source() const; protected: void parseInternal(KMime::Content *node, bool onlyOneMimePart); QString renderInternalText() const; ObjectTreeParser *mOtp = nullptr; private: std::unique_ptr d; }; // TODO remove once all plugins are ported away from BPF::format() class MIMETREEPARSER_DEPRECATED_EXPORT LegacyPluginMessagePart : public MessagePart { Q_OBJECT public: LegacyPluginMessagePart(MimeTreeParser::ObjectTreeParser *otp); ~LegacyPluginMessagePart(); HtmlWriter *htmlWriter() const; QString formatOutput() const; private: std::unique_ptr m_htmlWriter; }; class MIMETREEPARSER_EXPORT MimeMessagePart : public MessagePart { Q_OBJECT public: typedef QSharedPointer Ptr; MimeMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, bool onlyOneMimePart); virtual ~MimeMessagePart(); QString text() const override; QString plaintextContent() const override; QString htmlContent() const override; private: bool mOnlyOneMimePart; friend class AlternativeMessagePart; }; class MIMETREEPARSER_EXPORT MessagePartList : public MessagePart { Q_OBJECT public: typedef QSharedPointer Ptr; MessagePartList(MimeTreeParser::ObjectTreeParser *otp); virtual ~MessagePartList(); QString text() const override; QString plaintextContent() const override; QString htmlContent() const override; }; enum IconType { NoIcon = 0, IconExternal, IconInline }; class MIMETREEPARSER_EXPORT TextMessagePart : public MessagePartList { Q_OBJECT public: typedef QSharedPointer Ptr; TextMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, bool drawFrame, bool showLink, bool decryptMessage); virtual ~TextMessagePart(); KMMsgSignatureState signatureState() const; KMMsgEncryptionState encryptionState() const; bool decryptMessage() const; bool isHidden() const override; bool showLink() const; bool showTextFrame() const; private: void parseContent(); KMMsgSignatureState mSignatureState; KMMsgEncryptionState mEncryptionState; bool mDrawFrame; bool mShowLink; bool mDecryptMessage; bool mIsHidden; - friend class ::TextPartRendered; + friend class ::TextMessagePartRenderer; friend class ::AttachmentMessagePartRenderer; friend class ObjectTreeParser; }; class MIMETREEPARSER_EXPORT AttachmentMessagePart : public TextMessagePart { Q_OBJECT public: typedef QSharedPointer Ptr; AttachmentMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, bool drawFrame, bool showLink, bool decryptMessage); virtual ~AttachmentMessagePart(); IconType asIcon() const; bool neverDisplayInline() const; void setNeverDisplayInline(bool displayInline); bool isImage() const; void setIsImage(bool image); bool isHidden() const override; private: bool mIsImage; bool mNeverDisplayInline; }; class MIMETREEPARSER_EXPORT HtmlMessagePart : public MessagePart { Q_OBJECT public: typedef QSharedPointer Ptr; HtmlMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, MimeTreeParser::Interface::ObjectTreeSource *source); virtual ~HtmlMessagePart(); QString text() const override; void fix() const override; bool isHtml() const override; private: Interface::ObjectTreeSource *mSource; QString mBodyHTML; QByteArray mCharset; friend class DefaultRendererPrivate; }; class MIMETREEPARSER_EXPORT AlternativeMessagePart : public MessagePart { Q_OBJECT public: typedef QSharedPointer Ptr; AlternativeMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, Util::HtmlMode preferredMode); virtual ~AlternativeMessagePart(); QString text() const override; Util::HtmlMode preferredMode() const; bool isHtml() const override; QString plaintextContent() const override; QString htmlContent() const override; QList availableModes(); void fix() const override; private: Util::HtmlMode mPreferredMode; QMap mChildNodes; QMap mChildParts; friend class DefaultRendererPrivate; friend class ObjectTreeParser; friend class MultiPartAlternativeBodyPartFormatter; }; class MIMETREEPARSER_EXPORT CertMessagePart : public MessagePart { Q_OBJECT public: typedef QSharedPointer Ptr; CertMessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, const QGpgME::Protocol *cryptoProto, bool autoImport); virtual ~CertMessagePart(); QString text() const override; private: bool mAutoImport; GpgME::ImportResult mImportResult; const QGpgME::Protocol *mCryptoProto; friend class DefaultRendererPrivate; }; class MIMETREEPARSER_EXPORT EncapsulatedRfc822MessagePart : public MessagePart { Q_OBJECT public: typedef QSharedPointer Ptr; EncapsulatedRfc822MessagePart(MimeTreeParser::ObjectTreeParser *otp, KMime::Content *node, const KMime::Message::Ptr &message); virtual ~EncapsulatedRfc822MessagePart(); QString text() const override; void fix() const override; private: const KMime::Message::Ptr mMessage; friend class DefaultRendererPrivate; }; class MIMETREEPARSER_EXPORT EncryptedMessagePart : public MessagePart { Q_OBJECT Q_PROPERTY(bool decryptMessage READ decryptMessage WRITE setDecryptMessage) Q_PROPERTY(bool isEncrypted READ isEncrypted) Q_PROPERTY(bool passphraseError READ passphraseError) public: typedef QSharedPointer Ptr; EncryptedMessagePart(ObjectTreeParser *otp, const QString &text, const QGpgME::Protocol *cryptoProto, const QString &fromAddress, KMime::Content *node); virtual ~EncryptedMessagePart(); QString text() const override; void setDecryptMessage(bool decrypt); bool decryptMessage() const; void setIsEncrypted(bool encrypted); bool isEncrypted() const; bool isDecryptable() const; bool passphraseError() const; void startDecryption(const QByteArray &text, const QTextCodec *aCodec); void startDecryption(KMime::Content *data = nullptr); QByteArray mDecryptedData; QString plaintextContent() const override; QString htmlContent() const override; private: /** Handles the dectyptioon of a given content * returns true if the decryption was successfull * if used in async mode, check if mMetaData.inProgress is true, it inicates a running decryption process. */ bool okDecryptMIME(KMime::Content &data); protected: bool mPassphraseError; bool mNoSecKey; const QGpgME::Protocol *mCryptoProto; QString mFromAddress; bool mDecryptMessage; QByteArray mVerifiedText; std::vector mDecryptRecipients; friend class DefaultRendererPrivate; }; class MIMETREEPARSER_EXPORT SignedMessagePart : public MessagePart { Q_OBJECT Q_PROPERTY(bool isSigned READ isSigned) public: typedef QSharedPointer Ptr; SignedMessagePart(ObjectTreeParser *otp, const QString &text, const QGpgME::Protocol *cryptoProto, const QString &fromAddress, KMime::Content *node); virtual ~SignedMessagePart(); void setIsSigned(bool isSigned); bool isSigned() const; void startVerification(const QByteArray &text, const QTextCodec *aCodec); void startVerificationDetached(const QByteArray &text, KMime::Content *textNode, const QByteArray &signature); QByteArray mDecryptedData; std::vector mSignatures; QString plaintextContent() const override; QString htmlContent() const override; private: /** Handles the verification of data * If signature is empty it is handled as inline signature otherwise as detached signature mode. * Returns true if the verfication was successfull and the block is signed. * If used in async mode, check if mMetaData.inProgress is true, it inicates a running verification process. */ bool okVerify(const QByteArray &data, const QByteArray &signature, KMime::Content *textNode); void sigStatusToMetaData(); void setVerificationResult(const CryptoBodyPartMemento *m, KMime::Content *textNode); protected: const QGpgME::Protocol *mCryptoProto; QString mFromAddress; QByteArray mVerifiedText; friend EncryptedMessagePart; friend class DefaultRendererPrivate; }; } #endif //__MIMETREEPARSER_MESSAGEPART_H__