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 }