File indexing completed on 2025-03-09 04:54:33

0001 /*
0002    SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "plainheaderstyle.h"
0008 #include "header/headerstyle_util.h"
0009 #include "messageviewer/messageviewersettings.h"
0010 
0011 #include "header/headerstrategy.h"
0012 
0013 #include <MessageCore/StringUtil>
0014 
0015 #include <KLocalizedString>
0016 #include <KMime/KMimeMessage>
0017 #include <QApplication>
0018 
0019 using namespace MessageCore;
0020 
0021 using namespace MessageViewer;
0022 
0023 class MessageViewer::PlainHeaderStylePrivate
0024 {
0025 public:
0026     PlainHeaderStylePrivate() = default;
0027 
0028     [[nodiscard]] QString formatAllMessageHeaders(KMime::Message *message) const;
0029     MessageViewer::HeaderStyleUtil mHeaderStyleUtil;
0030 };
0031 
0032 QString PlainHeaderStylePrivate::formatAllMessageHeaders(KMime::Message *message) const
0033 {
0034     QByteArray head = message->head();
0035     QByteArrayView headView(head);
0036     auto header = KMime::HeaderParsing::parseNextHeader(headView);
0037     QString result;
0038     while (header) {
0039         result += mHeaderStyleUtil.strToHtml(QLatin1StringView(header->type()) + QLatin1StringView(": ") + header->asUnicodeString());
0040         result += QLatin1StringView("<br />\n");
0041         header = KMime::HeaderParsing::parseNextHeader(headView);
0042     }
0043 
0044     return result;
0045 }
0046 
0047 PlainHeaderStyle::PlainHeaderStyle()
0048     : HeaderStyle()
0049     , d(new MessageViewer::PlainHeaderStylePrivate)
0050 {
0051 }
0052 
0053 PlainHeaderStyle::~PlainHeaderStyle() = default;
0054 
0055 //
0056 // PlainHeaderStyle:
0057 //   show every header field on a line by itself,
0058 //   show subject larger
0059 //
0060 QString PlainHeaderStyle::format(KMime::Message *message) const
0061 {
0062     if (!message) {
0063         return {};
0064     }
0065     const HeaderStrategy *strategy = headerStrategy();
0066     // The direction of the header is determined according to the direction
0067     // of the application layout.
0068 
0069     const QString dir = QApplication::isRightToLeft() ? QStringLiteral("rtl") : QStringLiteral("ltr");
0070 
0071     // However, the direction of the message subject within the header is
0072     // determined according to the contents of the subject itself. Since
0073     // the "Re:" and "Fwd:" prefixes would always cause the subject to be
0074     // considered left-to-right, they are ignored when determining its
0075     // direction.
0076 
0077     const QString subjectDir = d->mHeaderStyleUtil.subjectDirectionString(message);
0078     QString headerStr;
0079 
0080     if (strategy->headersToDisplay().isEmpty() && strategy->defaultPolicy() == HeaderStrategy::Display) {
0081         // crude way to emulate "all" headers - Note: no strings have
0082         // i18n(), so direction should always be ltr.
0083         headerStr = QStringLiteral("<div class=\"header\" dir=\"ltr\">");
0084         headerStr += d->formatAllMessageHeaders(message);
0085         return headerStr + QLatin1StringView("</div>");
0086     }
0087 
0088     headerStr = QStringLiteral("<div class=\"header\" dir=\"%1\">").arg(dir);
0089 
0090     // case HdrLong:
0091     if (strategy->showHeader(QStringLiteral("subject"))) {
0092         KTextToHTML::Options flags = KTextToHTML::PreserveSpaces;
0093         if (showEmoticons()) {
0094             flags |= KTextToHTML::ReplaceSmileys;
0095         }
0096 
0097         headerStr += QStringLiteral("<div dir=\"%1\"><b style=\"font-size:130%\">").arg(subjectDir) + d->mHeaderStyleUtil.subjectString(message, flags)
0098             + QLatin1StringView("</b></div>\n");
0099     }
0100 
0101     if (strategy->showHeader(QStringLiteral("date"))) {
0102         const auto dateFormat = isPrinting() ? MessageViewer::HeaderStyleUtil::ShortDate : MessageViewer::HeaderStyleUtil::CustomDate;
0103         headerStr.append(i18n("Date: ") + HeaderStyleUtil::strToHtml(HeaderStyleUtil::dateString(message, dateFormat)) + QLatin1StringView("<br/>\n"));
0104     }
0105 
0106     if (strategy->showHeader(QStringLiteral("from"))) {
0107         headerStr.append(i18n("From: ") + StringUtil::emailAddrAsAnchor(message->from(), StringUtil::DisplayFullAddress, QString(), StringUtil::ShowLink));
0108         if (!vCardName().isEmpty()) {
0109             headerStr.append(QLatin1StringView("&nbsp;&nbsp;<a href=\"") + vCardName() + QLatin1StringView("\">") + i18n("[vCard]")
0110                              + QLatin1StringView("</a>"));
0111         }
0112 
0113         if (strategy->showHeader(QStringLiteral("organization")) && message->organization(false)) {
0114             headerStr.append(QLatin1StringView("&nbsp;&nbsp;(") + d->mHeaderStyleUtil.strToHtml(message->organization()->asUnicodeString()) + QLatin1Char(')'));
0115         }
0116         headerStr.append(QLatin1StringView("<br/>\n"));
0117     }
0118 
0119     if (strategy->showHeader(QStringLiteral("to"))) {
0120         headerStr.append(i18nc("To-field of the mailheader.", "To: ") + StringUtil::emailAddrAsAnchor(message->to(), StringUtil::DisplayFullAddress)
0121                          + QLatin1StringView("<br/>\n"));
0122     }
0123 
0124     if (strategy->showHeader(QStringLiteral("cc")) && message->cc(false)) {
0125         const QString str = StringUtil::emailAddrAsAnchor(message->cc(), StringUtil::DisplayFullAddress);
0126         if (!str.isEmpty()) {
0127             headerStr.append(i18n("CC: ") + str + QLatin1StringView("<br/>\n"));
0128         }
0129     }
0130 
0131     if (strategy->showHeader(QStringLiteral("bcc")) && message->bcc(false)) {
0132         const QString str = StringUtil::emailAddrAsAnchor(message->bcc(), StringUtil::DisplayFullAddress);
0133         if (!str.isEmpty()) {
0134             headerStr.append(i18n("BCC: ") + str + QLatin1StringView("<br/>\n"));
0135         }
0136     }
0137 
0138     if (strategy->showHeader(QStringLiteral("reply-to")) && message->replyTo(false)) {
0139         headerStr.append(i18n("Reply to: ") + StringUtil::emailAddrAsAnchor(message->replyTo(), StringUtil::DisplayFullAddress) + QLatin1StringView("<br/>\n"));
0140     }
0141 
0142     headerStr += QLatin1StringView("</div>\n");
0143 
0144     return headerStr;
0145 }
0146 
0147 const char *MessageViewer::PlainHeaderStyle::name() const
0148 {
0149     return "plain";
0150 }