File indexing completed on 2024-12-22 05:05:19
0001 // SPDX-FileCopyrightText: 2023 g10 Code GmbH 0002 // SPDX-FileContributor: Carl Schwan <carl.schwan@gnupg.com> 0003 // SPDX-License-Identifier: LGPL-2.0-or-later 0004 0005 #include "fileopener.h" 0006 #include "mimetreeparser_core_debug.h" 0007 0008 #include <KMbox/MBox> 0009 #include <QFile> 0010 #include <QMimeDatabase> 0011 #include <QMimeType> 0012 0013 using namespace MimeTreeParser::Core; 0014 0015 namespace 0016 { 0017 KMime::Message::Ptr openSmimeEncrypted(const QByteArray &content) 0018 { 0019 KMime::Message::Ptr message(new KMime::Message); 0020 0021 auto contentType = message->contentType(); 0022 contentType->setMimeType("application/pkcs7-mime"); 0023 contentType->setParameter(QStringLiteral("smime-type"), QStringLiteral("enveloped-data")); 0024 0025 auto contentDisposition = new KMime::Headers::ContentDisposition; 0026 contentDisposition->setDisposition(KMime::Headers::CDattachment); 0027 contentDisposition->setFilename(QStringLiteral("smime.p7m")); 0028 message->appendHeader(contentDisposition); 0029 0030 auto cte = message->contentTransferEncoding(); 0031 cte->setEncoding(KMime::Headers::CE7Bit); 0032 cte->setDecoded(true); 0033 0034 message->setBody(content); 0035 message->assemble(); 0036 0037 return message; 0038 } 0039 0040 KMime::Message::Ptr openPgpEncrypted(const QByteArray &content) 0041 { 0042 KMime::Message::Ptr message(new KMime::Message); 0043 0044 auto contentType = message->contentType(); 0045 contentType->setMimeType("multipart/encrypted"); 0046 contentType->setBoundary(KMime::multiPartBoundary()); 0047 contentType->setParameter(QStringLiteral("protocol"), QStringLiteral("application/pgp-encrypted")); 0048 0049 auto cte = message->contentTransferEncoding(); 0050 cte->setEncoding(KMime::Headers::CE7Bit); 0051 cte->setDecoded(true); 0052 0053 auto pgpEncrypted = new KMime::Content; 0054 pgpEncrypted->contentType()->setMimeType("application/pgp-encrypted"); 0055 auto contentDisposition = new KMime::Headers::ContentDisposition; 0056 contentDisposition->setDisposition(KMime::Headers::CDattachment); 0057 pgpEncrypted->appendHeader(contentDisposition); 0058 pgpEncrypted->setBody("Version: 1"); 0059 message->appendContent(pgpEncrypted); 0060 0061 auto encryptedContent = new KMime::Content; 0062 encryptedContent->contentType()->setMimeType("application/octet-stream"); 0063 contentDisposition = new KMime::Headers::ContentDisposition; 0064 contentDisposition->setDisposition(KMime::Headers::CDinline); 0065 contentDisposition->setFilename(QStringLiteral("msg.asc")); 0066 encryptedContent->appendHeader(contentDisposition); 0067 encryptedContent->setBody(content); 0068 message->appendContent(encryptedContent); 0069 0070 message->assemble(); 0071 0072 return message; 0073 } 0074 0075 QList<KMime::Message::Ptr> openMbox(const QString &fileName) 0076 { 0077 KMBox::MBox mbox; 0078 const bool ok = mbox.load(fileName); 0079 if (!ok) { 0080 qCWarning(MIMETREEPARSER_CORE_LOG) << "Unable to open" << fileName; 0081 return {}; 0082 } 0083 0084 QList<KMime::Message::Ptr> messages; 0085 const auto entries = mbox.entries(); 0086 for (const auto &entry : entries) { 0087 messages << KMime::Message::Ptr(mbox.readMessage(entry)); 0088 } 0089 return messages; 0090 } 0091 } 0092 0093 QList<KMime::Message::Ptr> FileOpener::openFile(const QString &fileName) 0094 { 0095 QMimeDatabase db; 0096 QMimeType mime = db.mimeTypeForFile(fileName); 0097 0098 QFile file(fileName); 0099 file.open(QIODevice::ReadOnly); 0100 if (!file.isOpen()) { 0101 qCWarning(MIMETREEPARSER_CORE_LOG) << "Could not open file"; 0102 return {}; 0103 } 0104 0105 const auto content = file.readAll(); 0106 0107 if (content.length() == 0) { 0108 qCWarning(MIMETREEPARSER_CORE_LOG) << "File is empty"; 0109 return {}; 0110 } 0111 0112 if (mime.inherits(QStringLiteral("application/pkcs7-mime")) || fileName.endsWith(QStringLiteral("smime.p7m"))) { 0113 return {openSmimeEncrypted(content)}; 0114 } else if (mime.inherits(QStringLiteral("application/pgp-encrypted")) || fileName.endsWith(QStringLiteral(".asc"))) { 0115 return {openPgpEncrypted(content)}; 0116 } else if (content.startsWith("From ")) { 0117 return openMbox(fileName); 0118 } else { 0119 auto msg = new KMime::Message; 0120 msg->setContent(KMime::CRLFtoLF(content)); 0121 msg->parse(); 0122 if (!msg->hasContent()) { 0123 delete msg; 0124 msg = nullptr; 0125 return {}; 0126 } 0127 return {KMime::Message::Ptr(msg)}; 0128 } 0129 0130 return {}; 0131 }