File indexing completed on 2025-03-09 04:54:12
0001 /* 0002 SPDX-FileCopyrightText: 2011 Martin Bednár <serafean@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "attachmentfromfolderjob.h" 0008 0009 #include "messagecore_debug.h" 0010 #include <KLocalizedString> 0011 0012 #include <QBuffer> 0013 #include <QDir> 0014 #include <QScopedPointer> 0015 #include <QSharedPointer> 0016 0017 static const mode_t archivePermsAttachment = S_IFREG | 0644; 0018 0019 using namespace MessageCore; 0020 0021 class AttachmentFromFolderJob::AttachmentLoadJobPrivate 0022 { 0023 public: 0024 AttachmentLoadJobPrivate(AttachmentFromFolderJob *qq); 0025 0026 void compressFolder(); 0027 void addEntity(const QFileInfoList &f, const QString &path); 0028 0029 AttachmentFromFolderJob *const q; 0030 KZip::Compression mCompression = KZip::DeflateCompression; 0031 AttachmentPart::Ptr mCompressedFolder; 0032 QScopedPointer<KZip> mZip; 0033 QDateTime mArchiveTime = QDateTime::currentDateTime(); 0034 }; 0035 0036 AttachmentFromFolderJob::AttachmentLoadJobPrivate::AttachmentLoadJobPrivate(AttachmentFromFolderJob *qq) 0037 : q(qq) 0038 , mZip(nullptr) 0039 { 0040 } 0041 0042 void AttachmentFromFolderJob::AttachmentLoadJobPrivate::compressFolder() 0043 { 0044 qCDebug(MESSAGECORE_LOG) << "starting compression"; 0045 QString fileName = q->url().fileName(); 0046 QByteArray array; 0047 QBuffer dev(&array); 0048 mZip.reset(new KZip(&dev)); 0049 if (!mZip->open(QIODevice::WriteOnly)) { 0050 q->setError(KJob::UserDefinedError); 0051 q->setErrorText(i18n("Could not create compressed file.")); 0052 q->emitResult(); 0053 return; 0054 } 0055 mZip->setCompression(mCompression); 0056 const QString filename = q->url().fileName(); 0057 if (!mZip->writeDir(filename, QString(), QString(), 040755, mArchiveTime, mArchiveTime, mArchiveTime)) { 0058 qCWarning(MESSAGECORE_LOG) << " Impossible to write file " << fileName; 0059 } 0060 qCDebug(MESSAGECORE_LOG) << "writing root directory : " << filename; 0061 addEntity(QDir(q->url().path()).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks | QDir::Files, QDir::DirsFirst), 0062 fileName + QLatin1Char('/')); 0063 mZip->close(); 0064 0065 Q_ASSERT(mCompressedFolder == nullptr); 0066 0067 mCompressedFolder = AttachmentPart::Ptr(new AttachmentPart); 0068 const QString newName = fileName + QLatin1StringView(".zip"); 0069 mCompressedFolder->setName(newName); 0070 mCompressedFolder->setFileName(newName); 0071 mCompressedFolder->setMimeType("application/zip"); 0072 mCompressedFolder->setUrl(q->url()); 0073 // mCompressedFolder->setCompressed( true ); 0074 mCompressedFolder->setData(array); 0075 // mCompressedFolder->setCompressible(false); 0076 q->setAttachmentPart(mCompressedFolder); 0077 q->emitResult(); 0078 0079 // TODO:add allowCompression bool to AttachmentPart && modify GUI to disable decompressing. 0080 // Or leave attachment as uncompressed and let it be compressed again? 0081 } 0082 0083 void AttachmentFromFolderJob::AttachmentLoadJobPrivate::addEntity(const QFileInfoList &f, const QString &path) 0084 { 0085 for (const QFileInfo &info : f) { 0086 qCDebug(MESSAGECORE_LOG) << q->maximumAllowedSize() << "Attachment size : " << mZip->device()->size(); 0087 0088 if (q->maximumAllowedSize() != -1 && mZip->device()->size() > q->maximumAllowedSize()) { 0089 q->setError(KJob::UserDefinedError); 0090 q->setErrorText(i18n("The resulting attachment would be larger than the maximum allowed size, aborting.")); 0091 q->emitResult(); 0092 return; 0093 } 0094 0095 const QString infoFileName = info.fileName(); 0096 if (info.isDir()) { 0097 qCDebug(MESSAGECORE_LOG) << "adding directory " << infoFileName << "to zip"; 0098 if (!mZip->writeDir(path + infoFileName, QString(), QString(), 040755, mArchiveTime, mArchiveTime, mArchiveTime)) { 0099 q->setError(KJob::UserDefinedError); 0100 q->setErrorText(i18n("Could not add %1 to the archive", infoFileName)); 0101 q->emitResult(); 0102 return; 0103 } 0104 addEntity(QDir(info.filePath()).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks | QDir::Files, QDir::DirsFirst), 0105 path + infoFileName + QLatin1Char('/')); 0106 } 0107 0108 if (info.isFile()) { 0109 qCDebug(MESSAGECORE_LOG) << "Adding file " << path + infoFileName << "to zip"; 0110 QFile file(info.filePath()); 0111 if (!file.open(QIODevice::ReadOnly)) { 0112 q->setError(KJob::UserDefinedError); 0113 q->setErrorText(i18n("Could not open %1 for reading.", file.fileName())); 0114 q->emitResult(); 0115 return; 0116 } 0117 if (!mZip->writeFile(path + infoFileName, file.readAll(), archivePermsAttachment, QString(), QString(), mArchiveTime, mArchiveTime, mArchiveTime)) { 0118 q->setError(KJob::UserDefinedError); 0119 q->setErrorText(i18n("Could not add %1 to the archive", file.fileName())); 0120 q->emitResult(); 0121 } 0122 file.close(); 0123 } 0124 } 0125 } 0126 0127 AttachmentFromFolderJob::AttachmentFromFolderJob(const QUrl &url, QObject *parent) 0128 : AttachmentFromUrlBaseJob(url, parent) 0129 , d(new AttachmentLoadJobPrivate(this)) 0130 { 0131 } 0132 0133 AttachmentFromFolderJob::~AttachmentFromFolderJob() = default; 0134 0135 void AttachmentFromFolderJob::setCompression(KZip::Compression compression) 0136 { 0137 d->mCompression = compression; 0138 } 0139 0140 KZip::Compression AttachmentFromFolderJob::compression() const 0141 { 0142 return d->mCompression; 0143 } 0144 0145 void AttachmentFromFolderJob::doStart() 0146 { 0147 d->compressFolder(); 0148 } 0149 0150 #include "moc_attachmentfromfolderjob.cpp"