File indexing completed on 2025-03-09 04:54:12

0001 /*
0002   SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
0003 
0004   SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "attachmentpart.h"
0008 
0009 #include <KMime/Content>
0010 #include <KMime/Util>
0011 
0012 #include <QUrl>
0013 
0014 using namespace MessageCore;
0015 
0016 size_t qHash(const MessageCore::AttachmentPart::Ptr &ptr, size_t seed)
0017 {
0018     return ::qHash(ptr.data(), seed);
0019 }
0020 
0021 // TODO move to kmime_util?
0022 static qint64 sizeWithEncoding(const QByteArray &data, KMime::Headers::contentEncoding encoding) // local
0023 {
0024     auto content = new KMime::Content;
0025     content->setBody(data);
0026     content->contentTransferEncoding()->setEncoding(encoding);
0027 
0028     const int size = content->size();
0029     delete content;
0030 
0031     return size;
0032 }
0033 
0034 static KMime::Headers::contentEncoding bestEncodingForTypeAndData(const QByteArray &mimeType, const QByteArray &data)
0035 {
0036     // Choose the best encoding for text/* and message/* attachments, but
0037     // always use base64 for anything else to prevent CRLF/LF conversions
0038     // etc. from corrupting the binary data
0039     if (mimeType.isEmpty() || mimeType.startsWith("text/") || mimeType.startsWith("message/")) {
0040         auto possibleEncodings = KMime::encodingsForData(data);
0041         possibleEncodings.removeAll(KMime::Headers::CE8Bit);
0042         if (!possibleEncodings.isEmpty()) {
0043             return possibleEncodings.first();
0044         } else {
0045             return KMime::Headers::CEquPr; // TODO: maybe some other default?
0046         }
0047     } else {
0048         return KMime::Headers::CEbase64;
0049     }
0050 }
0051 
0052 class MessageCore::AttachmentPart::AttachmentPartPrivate
0053 {
0054 public:
0055     AttachmentPartPrivate() = default;
0056 
0057     QUrl mUrl;
0058     QString mName;
0059     QString mFileName;
0060     QString mDescription;
0061     QByteArray mCharset;
0062     QByteArray mMimeType;
0063     QByteArray mData;
0064     KMime::Headers::contentEncoding mEncoding = KMime::Headers::CE7Bit;
0065     qint64 mSize = -1;
0066     bool mIsInline = false;
0067     bool mAutoEncoding = true;
0068     bool mCompressed = false;
0069     bool mToEncrypt = false;
0070     bool mToSign = false;
0071 };
0072 
0073 AttachmentPart::AttachmentPart()
0074     : d(new AttachmentPartPrivate)
0075 {
0076 }
0077 
0078 AttachmentPart::~AttachmentPart()
0079 {
0080     delete d;
0081 }
0082 
0083 QString AttachmentPart::name() const
0084 {
0085     return d->mName;
0086 }
0087 
0088 void AttachmentPart::setName(const QString &name)
0089 {
0090     d->mName = name;
0091 }
0092 
0093 QString AttachmentPart::fileName() const
0094 {
0095     return d->mFileName;
0096 }
0097 
0098 void AttachmentPart::setFileName(const QString &name)
0099 {
0100     d->mFileName = name;
0101 }
0102 
0103 QString AttachmentPart::description() const
0104 {
0105     return d->mDescription;
0106 }
0107 
0108 void AttachmentPart::setDescription(const QString &description)
0109 {
0110     d->mDescription = description;
0111 }
0112 
0113 bool AttachmentPart::isInline() const
0114 {
0115     return d->mIsInline;
0116 }
0117 
0118 void AttachmentPart::setInline(bool inl)
0119 {
0120     d->mIsInline = inl;
0121 }
0122 
0123 bool AttachmentPart::isAutoEncoding() const
0124 {
0125     return d->mAutoEncoding;
0126 }
0127 
0128 void AttachmentPart::setAutoEncoding(bool enabled)
0129 {
0130     d->mAutoEncoding = enabled;
0131 
0132     if (enabled) {
0133         d->mEncoding = bestEncodingForTypeAndData(d->mMimeType, d->mData);
0134     }
0135 
0136     d->mSize = sizeWithEncoding(d->mData, d->mEncoding);
0137 }
0138 
0139 KMime::Headers::contentEncoding AttachmentPart::encoding() const
0140 {
0141     return d->mEncoding;
0142 }
0143 
0144 void AttachmentPart::setEncoding(KMime::Headers::contentEncoding encoding)
0145 {
0146     d->mAutoEncoding = false;
0147     d->mEncoding = encoding;
0148     d->mSize = sizeWithEncoding(d->mData, d->mEncoding);
0149 }
0150 
0151 QByteArray AttachmentPart::charset() const
0152 {
0153     return d->mCharset;
0154 }
0155 
0156 void AttachmentPart::setCharset(const QByteArray &charset)
0157 {
0158     d->mCharset = charset;
0159 }
0160 
0161 QByteArray AttachmentPart::mimeType() const
0162 {
0163     return d->mMimeType;
0164 }
0165 
0166 void AttachmentPart::setMimeType(const QByteArray &mimeType)
0167 {
0168     d->mMimeType = mimeType;
0169 }
0170 
0171 bool AttachmentPart::isCompressed() const
0172 {
0173     return d->mCompressed;
0174 }
0175 
0176 void AttachmentPart::setCompressed(bool compressed)
0177 {
0178     d->mCompressed = compressed;
0179 }
0180 
0181 bool AttachmentPart::isEncrypted() const
0182 {
0183     return d->mToEncrypt;
0184 }
0185 
0186 void AttachmentPart::setEncrypted(bool encrypted)
0187 {
0188     d->mToEncrypt = encrypted;
0189 }
0190 
0191 bool AttachmentPart::isSigned() const
0192 {
0193     return d->mToSign;
0194 }
0195 
0196 void AttachmentPart::setSigned(bool sign)
0197 {
0198     d->mToSign = sign;
0199 }
0200 
0201 QByteArray AttachmentPart::data() const
0202 {
0203     return d->mData;
0204 }
0205 
0206 void AttachmentPart::setData(const QByteArray &data)
0207 {
0208     d->mData = data;
0209 
0210     if (d->mAutoEncoding) {
0211         d->mEncoding = bestEncodingForTypeAndData(d->mMimeType, d->mData);
0212     }
0213 
0214     d->mSize = sizeWithEncoding(d->mData, d->mEncoding);
0215 }
0216 
0217 qint64 AttachmentPart::size() const
0218 {
0219     return d->mSize;
0220 }
0221 
0222 bool AttachmentPart::isMessageOrMessageCollection() const
0223 {
0224     return (mimeType() == QByteArrayLiteral("message/rfc822")) || (mimeType() == QByteArrayLiteral("multipart/digest"));
0225 }
0226 
0227 void AttachmentPart::setUrl(const QUrl &url)
0228 {
0229     d->mUrl = url;
0230 }
0231 
0232 QUrl AttachmentPart::url() const
0233 {
0234     return d->mUrl;
0235 }