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"