File indexing completed on 2024-06-23 05:19:21
0001 /* 0002 SPDX-FileCopyrightText: 2016 Sandro Knauß <sknauss@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "util.h" 0008 0009 #include "mimetreeparser_debug.h" 0010 0011 #include "nodehelper.h" 0012 0013 #include <KMime/Content> 0014 0015 #include <QMimeDatabase> 0016 0017 using namespace MimeTreeParser; 0018 using namespace MimeTreeParser::Util; 0019 0020 bool MimeTreeParser::Util::isTypeBlacklisted(KMime::Content *node) 0021 { 0022 const auto contentType = node->contentType(); // Create 0023 const QByteArray mediaTypeLower = contentType->mediaType().toLower(); 0024 bool typeBlacklisted = mediaTypeLower == QByteArrayLiteral("multipart"); 0025 if (!typeBlacklisted) { 0026 typeBlacklisted = KMime::isCryptoPart(node); 0027 } 0028 typeBlacklisted = typeBlacklisted || node == node->topLevel(); 0029 const bool firstTextChildOfEncapsulatedMsg = mediaTypeLower == "text" && contentType->subType().toLower() == "plain" && node->parent() 0030 && node->parent()->contentType()->mediaType().toLower() == "message"; 0031 return typeBlacklisted || firstTextChildOfEncapsulatedMsg; 0032 } 0033 0034 QString MimeTreeParser::Util::labelForContent(KMime::Content *node) 0035 { 0036 const QString name = node->contentType()->name(); 0037 QString label = name.isEmpty() ? NodeHelper::fileName(node) : name; 0038 if (label.isEmpty()) { 0039 label = node->contentDescription()->asUnicodeString(); 0040 } 0041 return label; 0042 } 0043 0044 QMimeType MimeTreeParser::Util::mimetype(const QString &name) 0045 { 0046 QMimeDatabase db; 0047 // consider the filename if mimetype cannot be found by content-type 0048 const auto mimeTypes = db.mimeTypesForFileName(name); 0049 for (const auto &mt : mimeTypes) { 0050 if (mt.name() != QLatin1StringView("application/octet-stream")) { 0051 return mt; 0052 } 0053 } 0054 0055 // consider the attachment's contents if neither the Content-Type header 0056 // nor the filename give us a clue 0057 return db.mimeTypeForFile(name); 0058 } 0059 0060 QString MimeTreeParser::Util::iconNameForMimetype(const QString &mimeType, const QString &fallbackFileName1, const QString &fallbackFileName2) 0061 { 0062 QString fileName; 0063 QString tMimeType = mimeType; 0064 0065 // convert non-registered types to registered types 0066 if (mimeType == QLatin1StringView("application/x-vnd.kolab.contact")) { 0067 tMimeType = QStringLiteral("text/x-vcard"); 0068 } else if (mimeType == QLatin1StringView("application/x-vnd.kolab.event")) { 0069 tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.event"); 0070 } else if (mimeType == QLatin1StringView("application/x-vnd.kolab.task")) { 0071 tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.todo"); 0072 } else if (mimeType == QLatin1StringView("application/x-vnd.kolab.journal")) { 0073 tMimeType = QStringLiteral("application/x-vnd.akonadi.calendar.journal"); 0074 } else if (mimeType == QLatin1StringView("application/x-vnd.kolab.note")) { 0075 tMimeType = QStringLiteral("application/x-vnd.akonadi.note"); 0076 } else if (mimeType == QLatin1StringView("image/jpg")) { 0077 tMimeType = QStringLiteral("image/jpeg"); 0078 } else if (mimeType == QLatin1StringView("application/x-pkcs7-signature")) { 0079 tMimeType = QStringLiteral("application/pkcs7-signature"); 0080 } else if (mimeType == QLatin1StringView("message/global")) { 0081 tMimeType = QStringLiteral("message/rfc822"); 0082 } else if (mimeType == QLatin1StringView("text/x-moz-deleted")) { 0083 // Avoid debug warning about unknown mimetype 0084 // Bug: 468801 0085 // We need to show unknown icon 0086 tMimeType.clear(); 0087 fileName = QStringLiteral("unknown"); 0088 } 0089 QMimeDatabase mimeDb; 0090 if (!tMimeType.isEmpty()) { 0091 auto mime = mimeDb.mimeTypeForName(tMimeType); 0092 if (mime.isValid()) { 0093 fileName = mime.iconName(); 0094 } else { 0095 fileName = QStringLiteral("unknown"); 0096 if (!tMimeType.isEmpty()) { 0097 qCWarning(MIMETREEPARSER_LOG) << "unknown mimetype" << tMimeType; 0098 } 0099 } 0100 } 0101 // WorkAround for #199083 0102 if (fileName == QLatin1StringView("text-vcard")) { 0103 fileName = QStringLiteral("text-x-vcard"); 0104 } 0105 0106 if (fileName.isEmpty()) { 0107 fileName = fallbackFileName1; 0108 if (fileName.isEmpty()) { 0109 fileName = fallbackFileName2; 0110 } 0111 if (!fileName.isEmpty()) { 0112 fileName = mimeDb.mimeTypeForFile(QLatin1StringView("/tmp/") + fileName).iconName(); 0113 } 0114 } 0115 0116 return fileName; 0117 } 0118 0119 QString MimeTreeParser::Util::iconNameForContent(KMime::Content *node) 0120 { 0121 if (!node) { 0122 return {}; 0123 } 0124 0125 auto ct = node->contentType(); // Create 0126 QByteArray mimeType = ct->mimeType(); 0127 if (mimeType.isNull() || mimeType == "application/octet-stream") { 0128 const QString fileName = node->contentDisposition()->filename(); 0129 if (!fileName.isEmpty()) { 0130 const QString mime = MimeTreeParser::Util::mimetype(fileName).name(); 0131 mimeType = mime.toLatin1(); 0132 } 0133 } 0134 mimeType = mimeType.toLower(); 0135 return MimeTreeParser::Util::iconNameForMimetype(QLatin1StringView(mimeType), node->contentDisposition()->filename(), ct->name()); 0136 } 0137 0138 QString MimeTreeParser::Util::htmlModeToString(HtmlMode mode) 0139 { 0140 switch (mode) { 0141 case Normal: ///< A normal plaintext message, non-multipart 0142 return QStringLiteral("Normal PlainText Message, non-multipart"); 0143 case Html: ///< A HTML message, non-multipart 0144 return QStringLiteral("A HTML message, non-multipart"); 0145 case MultipartPlain: ///< A multipart/alternative message, the plain text part is currently displayed 0146 return QStringLiteral("A multipart/alternative message, the plain text part is currently displayed"); 0147 case MultipartHtml: ///< A multipart/alternative message, the HTML part is currently displayed 0148 return QStringLiteral("A multipart/alternative message, the HTML part is currently displayed"); 0149 case MultipartIcal: ///< A multipart/alternative message, the ICal part is currently displayed 0150 return QStringLiteral("A multipart/alternative message, the ICal part is currently displayed"); 0151 } 0152 return {}; 0153 }