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

0001 /*
0002   SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
0003 
0004   Based on KMail code by various authors.
0005 
0006   SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "attachmentcompressjob.h"
0010 
0011 #include <KLocalizedString>
0012 #include <KZip>
0013 
0014 #include <QBuffer>
0015 #include <QDateTime>
0016 #include <QSharedPointer>
0017 #include <QTimer>
0018 
0019 using namespace MessageCore;
0020 static const mode_t archivePerms = S_IFREG | 0644;
0021 
0022 class MessageCore::AttachmentCompressJob::AttachmentCompressJobPrivate
0023 {
0024 public:
0025     AttachmentCompressJobPrivate(AttachmentCompressJob *qq);
0026 
0027     void doStart(); // slot
0028 
0029     AttachmentCompressJob *const q;
0030     AttachmentPart::Ptr mOriginalPart;
0031     AttachmentPart::Ptr mCompressedPart;
0032     bool mCompressedPartLarger = false;
0033 };
0034 
0035 AttachmentCompressJob::AttachmentCompressJobPrivate::AttachmentCompressJobPrivate(AttachmentCompressJob *qq)
0036     : q(qq)
0037 {
0038 }
0039 
0040 void AttachmentCompressJob::AttachmentCompressJobPrivate::doStart()
0041 {
0042     Q_ASSERT(mOriginalPart);
0043     const QByteArray decoded = mOriginalPart->data();
0044 
0045     QByteArray array;
0046     QBuffer dev(&array);
0047     KZip zip(&dev);
0048     if (!zip.open(QIODevice::WriteOnly)) {
0049         q->setError(KJob::UserDefinedError);
0050         q->setErrorText(i18n("Could not initiate attachment compression."));
0051         q->emitResult();
0052         return;
0053     }
0054 
0055     // Compress.
0056     zip.setCompression(KZip::DeflateCompression);
0057     QDateTime zipTime = QDateTime::currentDateTime();
0058     if (!zip.writeFile(mOriginalPart->name(), decoded, archivePerms, QString(/*user*/), QString(/*group*/), zipTime, zipTime, zipTime)) {
0059         q->setError(KJob::UserDefinedError);
0060         q->setErrorText(i18n("Could not compress the attachment."));
0061         q->emitResult();
0062         return;
0063     }
0064     zip.close();
0065     mCompressedPartLarger = (array.size() >= decoded.size());
0066 
0067     // Create new part.
0068     Q_ASSERT(mCompressedPart == nullptr);
0069     mCompressedPart = AttachmentPart::Ptr(new AttachmentPart);
0070     mCompressedPart->setName(mOriginalPart->name() + QLatin1StringView(".zip")); // TODO not sure name should be .zipped too
0071     mCompressedPart->setFileName(mOriginalPart->fileName() + QLatin1StringView(".zip"));
0072     mCompressedPart->setDescription(mOriginalPart->description());
0073     mCompressedPart->setInline(mOriginalPart->isInline());
0074     mCompressedPart->setMimeType("application/zip");
0075     mCompressedPart->setCompressed(true);
0076     mCompressedPart->setEncrypted(mOriginalPart->isEncrypted());
0077     mCompressedPart->setSigned(mOriginalPart->isSigned());
0078     mCompressedPart->setData(array);
0079     q->emitResult(); // Success.
0080 
0081     // TODO consider adding a copy constructor to AttachmentPart.
0082 }
0083 
0084 AttachmentCompressJob::AttachmentCompressJob(const AttachmentPart::Ptr &part, QObject *parent)
0085     : KJob(parent)
0086     , d(new AttachmentCompressJobPrivate(this))
0087 {
0088     d->mOriginalPart = part;
0089 }
0090 
0091 AttachmentCompressJob::~AttachmentCompressJob() = default;
0092 
0093 void AttachmentCompressJob::start()
0094 {
0095     QTimer::singleShot(0, this, [this]() {
0096         d->doStart();
0097     });
0098 }
0099 
0100 const AttachmentPart::Ptr AttachmentCompressJob::originalPart() const
0101 {
0102     return d->mOriginalPart;
0103 }
0104 
0105 void AttachmentCompressJob::setOriginalPart(const AttachmentPart::Ptr &part)
0106 {
0107     d->mOriginalPart = part;
0108 }
0109 
0110 AttachmentPart::Ptr AttachmentCompressJob::compressedPart() const
0111 {
0112     return d->mCompressedPart;
0113 }
0114 
0115 bool AttachmentCompressJob::isCompressedPartLarger() const
0116 {
0117     return d->mCompressedPartLarger;
0118 }
0119 
0120 #include "moc_attachmentcompressjob.cpp"