File indexing completed on 2024-06-23 05:18:31

0001 /*
0002   SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
0003 
0004   Parts based on KMail code by:
0005   Various authors.
0006 
0007   SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "job/attachmentjob.h"
0011 #include "contentjobbase_p.h"
0012 #include "job/singlepartjob.h"
0013 #include "part/globalpart.h"
0014 #include "utils/util.h"
0015 
0016 #include "messagecomposer_debug.h"
0017 
0018 using namespace MessageComposer;
0019 using namespace MessageCore;
0020 
0021 class MessageComposer::AttachmentJobPrivate : public ContentJobBasePrivate
0022 {
0023 public:
0024     AttachmentJobPrivate(AttachmentJob *qq)
0025         : ContentJobBasePrivate(qq)
0026     {
0027     }
0028 
0029     AttachmentPart::Ptr part;
0030 
0031     Q_DECLARE_PUBLIC(AttachmentJob)
0032 };
0033 
0034 AttachmentJob::AttachmentJob(AttachmentPart::Ptr part, QObject *parent)
0035     : ContentJobBase(*new AttachmentJobPrivate(this), parent)
0036 {
0037     Q_D(AttachmentJob);
0038     d->part = part;
0039 }
0040 
0041 AttachmentJob::~AttachmentJob() = default;
0042 
0043 AttachmentPart::Ptr AttachmentJob::attachmentPart() const
0044 {
0045     Q_D(const AttachmentJob);
0046     return d->part;
0047 }
0048 
0049 void AttachmentJob::setAttachmentPart(const AttachmentPart::Ptr &part)
0050 {
0051     Q_D(AttachmentJob);
0052     d->part = part;
0053 }
0054 
0055 void AttachmentJob::doStart()
0056 {
0057     Q_D(AttachmentJob);
0058     Q_ASSERT(d->part);
0059 
0060     if (d->part->mimeType() == "multipart/digest" || d->part->mimeType() == "message/rfc822") {
0061         // this is actually a digest, so we don't want any additional headers
0062         // the attachment is really a complete multipart/digest subtype
0063         // and us adding our own headers would break it. so copy over the content
0064         // and leave it alone
0065         auto part = new KMime::Content;
0066         part->setContent(d->part->data());
0067         part->parse();
0068         d->subjobContents << part;
0069         process();
0070         return;
0071     }
0072 
0073     // Set up a subjob to generate the attachment content.
0074     auto sjob = new SinglepartJob(this);
0075     sjob->setData(d->part->data());
0076 
0077     // Figure out a charset to encode parts of the headers with.
0078     const QString dataToEncode = d->part->name() + d->part->description() + d->part->fileName();
0079     const QByteArray charset = MessageComposer::Util::selectCharset(globalPart()->charsets(true), dataToEncode);
0080 
0081     // Set up the headers.
0082     // rfc822 forwarded messages have 7bit CTE, the message itself will have
0083     //  its own CTE for the content
0084     if (d->part->mimeType() == "message/rfc822") {
0085         sjob->contentTransferEncoding()->setEncoding(KMime::Headers::CE7Bit);
0086     } else {
0087         sjob->contentTransferEncoding()->setEncoding(d->part->encoding());
0088     }
0089 
0090     auto ct = sjob->contentType();
0091     ct->setMimeType(d->part->mimeType()); // setMimeType() clears all other params.
0092     ct->setName(d->part->name(), charset);
0093     if (ct->isText()) {
0094         // If it is a text file, detect its charset.
0095         // sjob->contentType()->setCharset( d->detectCharset( d->part->data() ) );
0096 
0097         // From my few tests, this is *very* unreliable.
0098         // Therefore, if we do not know which charset to use, just use UTF-8.
0099         // (cberzan)
0100         QByteArray textCharset = d->part->charset();
0101         if (textCharset.isEmpty()) {
0102             qCWarning(MESSAGECOMPOSER_LOG) << "No charset specified. Using UTF-8.";
0103             textCharset = "utf-8";
0104         }
0105         ct->setCharset(textCharset);
0106     }
0107 
0108     sjob->contentDescription()->fromUnicodeString(d->part->description(), charset);
0109 
0110     auto contentDisposition = sjob->contentDisposition();
0111     contentDisposition->setFilename(d->part->fileName());
0112     contentDisposition->setRFC2047Charset(charset);
0113     if (d->part->isInline()) {
0114         contentDisposition->setDisposition(KMime::Headers::CDinline);
0115     } else {
0116         contentDisposition->setDisposition(KMime::Headers::CDattachment);
0117     }
0118 
0119     ContentJobBase::doStart();
0120 }
0121 
0122 void AttachmentJob::process()
0123 {
0124     Q_D(AttachmentJob);
0125     // The content has been created by our subjob.
0126     Q_ASSERT(d->subjobContents.count() == 1);
0127     d->resultContent = d->subjobContents.constFirst();
0128     emitResult();
0129 }
0130 
0131 #include "moc_attachmentjob.cpp"