File indexing completed on 2024-05-05 05:50:41
0001 /* 0002 SPDX-FileCopyrightText: 2007 Henrique Pinto <henrique.pinto@kdemail.net> 0003 SPDX-FileCopyrightText: 2008-2009 Harald Hvaal <haraldhv@stud.ntnu.no> 0004 SPDX-FileCopyrightText: 2009-2012 Raphael Kubo da Costa <rakuco@FreeBSD.org> 0005 SPDX-FileCopyrightText: 2016 Vladyslav Batyrenko <mvlabat@gmail.com> 0006 0007 SPDX-License-Identifier: BSD-2-Clause 0008 */ 0009 0010 #ifndef JOBS_H 0011 #define JOBS_H 0012 0013 #include "archive_kerfuffle.h" 0014 #include "archiveentry.h" 0015 #include "archiveinterface.h" 0016 #include "kerfuffle_export.h" 0017 #include "queries.h" 0018 0019 #include <KJob> 0020 0021 #include <QElapsedTimer> 0022 #include <QPointer> 0023 #include <QTemporaryDir> 0024 0025 namespace Kerfuffle 0026 { 0027 class KERFUFFLE_EXPORT Job : public KJob 0028 { 0029 Q_OBJECT 0030 0031 public: 0032 /** 0033 * @return The archive processed by this job. 0034 * @warning This method should not be called before start(). 0035 */ 0036 Archive *archive() const; 0037 QString errorString() const override; 0038 void start() override; 0039 0040 protected: 0041 Job(Archive *archive, ReadOnlyArchiveInterface *interface); 0042 Job(Archive *archive); 0043 Job(ReadOnlyArchiveInterface *interface); 0044 ~Job() override; 0045 bool doKill() override; 0046 0047 ReadOnlyArchiveInterface *archiveInterface(); 0048 0049 void connectToArchiveInterfaceSignals(); 0050 0051 public Q_SLOTS: 0052 virtual void doWork() = 0; 0053 0054 protected Q_SLOTS: 0055 virtual void onCancelled(); 0056 virtual void onError(const QString &message, const QString &details, int errorCode); 0057 virtual void onInfo(const QString &info); 0058 virtual void onEntry(Archive::Entry *entry); 0059 virtual void onProgress(double progress); 0060 virtual void onEntryRemoved(const QString &path); 0061 virtual void onFinished(bool result); 0062 virtual void onUserQuery(Kerfuffle::Query *query); 0063 0064 Q_SIGNALS: 0065 void entryRemoved(const QString &entry); 0066 void newEntry(Archive::Entry *); 0067 void userQuery(Kerfuffle::Query *); 0068 0069 private: 0070 Archive *m_archive; 0071 ReadOnlyArchiveInterface *m_archiveInterface; 0072 QElapsedTimer jobTimer; 0073 0074 class Private; 0075 Private *const d; 0076 }; 0077 0078 /** 0079 * Load an existing archive. 0080 * Example usage: 0081 * 0082 * \code 0083 * 0084 * auto job = Archive::load(filename); 0085 * connect(job, &KJob::result, [](KJob *job) { 0086 * if (!job->error) { 0087 * auto archive = qobject_cast<Archive::LoadJob*>(job)->archive(); 0088 * // do something with archive. 0089 * } 0090 * }); 0091 * job->start(); 0092 * 0093 * \endcode 0094 */ 0095 class KERFUFFLE_EXPORT LoadJob : public Job 0096 { 0097 Q_OBJECT 0098 0099 public: 0100 explicit LoadJob(Archive *archive); 0101 explicit LoadJob(ReadOnlyArchiveInterface *interface); 0102 0103 qlonglong extractedFilesSize() const; 0104 bool isPasswordProtected() const; 0105 bool isSingleFolderArchive() const; 0106 QString subfolderName() const; 0107 0108 public Q_SLOTS: 0109 void doWork() override; 0110 0111 protected Q_SLOTS: 0112 void onFinished(bool result) override; 0113 0114 private: 0115 explicit LoadJob(Archive *archive, ReadOnlyArchiveInterface *interface); 0116 0117 bool m_isSingleFolderArchive; 0118 bool m_isPasswordProtected; 0119 QString m_subfolderName; 0120 QString m_basePath; 0121 qlonglong m_extractedFilesSize; 0122 qlonglong m_dirCount; 0123 qlonglong m_filesCount; 0124 0125 private Q_SLOTS: 0126 void onNewEntry(const Archive::Entry *); 0127 }; 0128 0129 /** 0130 * Perform a batch extraction of an existing archive. 0131 * Internally it runs a LoadJob before the actual extraction, 0132 * to figure out properties such as the subfolder name. 0133 */ 0134 class KERFUFFLE_EXPORT BatchExtractJob : public Job 0135 { 0136 Q_OBJECT 0137 0138 public: 0139 explicit BatchExtractJob(LoadJob *loadJob, const QString &destination, bool autoSubfolder, bool preservePaths); 0140 0141 public Q_SLOTS: 0142 void doWork() override; 0143 0144 protected: 0145 bool doKill() override; 0146 0147 private Q_SLOTS: 0148 void slotLoadingProgress(double progress); 0149 void slotExtractProgress(double progress); 0150 void slotLoadingFinished(KJob *job); 0151 0152 private: 0153 /** 0154 * Tracks whether the job is loading or extracting the archive. 0155 */ 0156 enum Step { Loading, Extracting }; 0157 0158 void setupDestination(); 0159 0160 Step m_step = Loading; 0161 ExtractJob *m_extractJob = nullptr; 0162 LoadJob *m_loadJob; 0163 QString m_destination; 0164 bool m_autoSubfolder; 0165 bool m_preservePaths; 0166 unsigned long m_lastPercentage = 0; 0167 }; 0168 0169 /** 0170 * Create a new archive given a bunch of entries. 0171 */ 0172 class KERFUFFLE_EXPORT CreateJob : public Job 0173 { 0174 Q_OBJECT 0175 0176 public: 0177 explicit CreateJob(Archive *archive, const QVector<Archive::Entry *> &entries, const CompressionOptions &options); 0178 0179 ~CreateJob(); 0180 /** 0181 * @param password The password to encrypt the archive with. 0182 * @param encryptHeader Whether to encrypt also the list of files. 0183 */ 0184 void enableEncryption(const QString &password, bool encryptHeader); 0185 0186 /** 0187 * Set whether the new archive should be multivolume. 0188 */ 0189 void setMultiVolume(bool isMultiVolume); 0190 0191 public Q_SLOTS: 0192 void doWork() override; 0193 0194 protected: 0195 bool doKill() override; 0196 0197 private: 0198 QPointer<AddJob> m_addJob; 0199 QVector<Archive::Entry *> m_entries; 0200 CompressionOptions m_options; 0201 }; 0202 0203 class KERFUFFLE_EXPORT ExtractJob : public Job 0204 { 0205 Q_OBJECT 0206 0207 public: 0208 ExtractJob(const QVector<Archive::Entry *> &entries, const QString &destinationDir, ExtractionOptions options, ReadOnlyArchiveInterface *interface); 0209 0210 QString destinationDirectory() const; 0211 ExtractionOptions extractionOptions() const; 0212 0213 public Q_SLOTS: 0214 void doWork() override; 0215 0216 private: 0217 QVector<Archive::Entry *> m_entries; 0218 QString m_destinationDir; 0219 ExtractionOptions m_options; 0220 }; 0221 0222 /** 0223 * Abstract base class for jobs that extract a single file to a temporary dir. 0224 * It's not possible to pass extraction options and paths will be always preserved. 0225 * The only option that the job needs to know is whether the file is password protected. 0226 */ 0227 class KERFUFFLE_EXPORT TempExtractJob : public Job 0228 { 0229 Q_OBJECT 0230 0231 public: 0232 TempExtractJob(Archive::Entry *entry, bool passwordProtectedHint, ReadOnlyArchiveInterface *interface); 0233 0234 Archive::Entry *entry() const; 0235 0236 /** 0237 * @return The absolute path of the extracted file. 0238 * The path is validated in order to prevent directory traversal attacks. 0239 */ 0240 QString validatedFilePath() const; 0241 0242 ExtractionOptions extractionOptions() const; 0243 0244 /** 0245 * @return The temporary dir used for the extraction. 0246 * It is safe to delete this pointer in order to remove the directory. 0247 */ 0248 QTemporaryDir *tempDir() const; 0249 0250 public Q_SLOTS: 0251 void doWork() override; 0252 0253 private: 0254 QString extractionDir() const; 0255 0256 Archive::Entry *m_entry; 0257 QTemporaryDir *m_tmpExtractDir; 0258 bool m_passwordProtectedHint; 0259 }; 0260 0261 /** 0262 * This TempExtractJob can be used to preview a file. 0263 * The temporary extraction directory will be deleted upon job's completion. 0264 */ 0265 class KERFUFFLE_EXPORT PreviewJob : public TempExtractJob 0266 { 0267 Q_OBJECT 0268 0269 public: 0270 PreviewJob(Archive::Entry *entry, bool passwordProtectedHint, ReadOnlyArchiveInterface *interface); 0271 }; 0272 0273 /** 0274 * This TempExtractJob can be used to open a file in its dedicated application. 0275 * For this reason, the temporary extraction directory will NOT be deleted upon job's completion. 0276 */ 0277 class KERFUFFLE_EXPORT OpenJob : public TempExtractJob 0278 { 0279 Q_OBJECT 0280 0281 public: 0282 OpenJob(Archive::Entry *entry, bool passwordProtectedHint, ReadOnlyArchiveInterface *interface); 0283 }; 0284 0285 class KERFUFFLE_EXPORT OpenWithJob : public OpenJob 0286 { 0287 Q_OBJECT 0288 0289 public: 0290 OpenWithJob(Archive::Entry *entry, bool passwordProtectedHint, ReadOnlyArchiveInterface *interface); 0291 }; 0292 0293 class KERFUFFLE_EXPORT AddJob : public Job 0294 { 0295 Q_OBJECT 0296 0297 public: 0298 AddJob(const QVector<Archive::Entry *> &files, const Archive::Entry *destination, const CompressionOptions &options, ReadWriteArchiveInterface *interface); 0299 0300 public Q_SLOTS: 0301 void doWork() override; 0302 0303 protected Q_SLOTS: 0304 void onFinished(bool result) override; 0305 0306 private: 0307 QString m_oldWorkingDir; 0308 const QVector<Archive::Entry *> m_entries; 0309 const Archive::Entry *m_destination; 0310 CompressionOptions m_options; 0311 }; 0312 0313 /** 0314 * This MoveJob can be used to rename or move entries within the archive. 0315 * @see Archive::moveFiles for more details. 0316 */ 0317 class KERFUFFLE_EXPORT MoveJob : public Job 0318 { 0319 Q_OBJECT 0320 0321 public: 0322 MoveJob(const QVector<Archive::Entry *> &files, Archive::Entry *destination, const CompressionOptions &options, ReadWriteArchiveInterface *interface); 0323 0324 public Q_SLOTS: 0325 void doWork() override; 0326 0327 protected Q_SLOTS: 0328 void onFinished(bool result) override; 0329 0330 private: 0331 int m_finishedSignalsCount; 0332 const QVector<Archive::Entry *> m_entries; 0333 Archive::Entry *m_destination; 0334 CompressionOptions m_options; 0335 }; 0336 0337 /** 0338 * This CopyJob can be used to copy entries within the archive. 0339 * @see Archive::copyFiles for more details. 0340 */ 0341 class KERFUFFLE_EXPORT CopyJob : public Job 0342 { 0343 Q_OBJECT 0344 0345 public: 0346 CopyJob(const QVector<Archive::Entry *> &entries, Archive::Entry *destination, const CompressionOptions &options, ReadWriteArchiveInterface *interface); 0347 0348 public Q_SLOTS: 0349 void doWork() override; 0350 0351 protected Q_SLOTS: 0352 void onFinished(bool result) override; 0353 0354 private: 0355 int m_finishedSignalsCount; 0356 const QVector<Archive::Entry *> m_entries; 0357 Archive::Entry *m_destination; 0358 CompressionOptions m_options; 0359 }; 0360 0361 class KERFUFFLE_EXPORT DeleteJob : public Job 0362 { 0363 Q_OBJECT 0364 0365 public: 0366 DeleteJob(const QVector<Archive::Entry *> &files, ReadWriteArchiveInterface *interface); 0367 0368 public Q_SLOTS: 0369 void doWork() override; 0370 0371 private: 0372 QVector<Archive::Entry *> m_entries; 0373 }; 0374 0375 class KERFUFFLE_EXPORT CommentJob : public Job 0376 { 0377 Q_OBJECT 0378 0379 public: 0380 CommentJob(const QString &comment, ReadWriteArchiveInterface *interface); 0381 0382 public Q_SLOTS: 0383 void doWork() override; 0384 0385 private: 0386 QString m_comment; 0387 }; 0388 0389 class KERFUFFLE_EXPORT TestJob : public Job 0390 { 0391 Q_OBJECT 0392 0393 public: 0394 explicit TestJob(ReadOnlyArchiveInterface *interface); 0395 bool testSucceeded(); 0396 0397 public Q_SLOTS: 0398 void doWork() override; 0399 0400 private Q_SLOTS: 0401 virtual void onTestSuccess(); 0402 0403 private: 0404 bool m_testSuccess; 0405 }; 0406 0407 } // namespace Kerfuffle 0408 0409 #endif // JOBS_H