diff --git a/kerfuffle/archiveinterface.h b/kerfuffle/archiveinterface.h index 28dc6fe9..d0da1550 100644 --- a/kerfuffle/archiveinterface.h +++ b/kerfuffle/archiveinterface.h @@ -1,266 +1,266 @@ /* * Copyright (c) 2007 Henrique Pinto * Copyright (c) 2008-2009 Harald Hvaal * Copyright (c) 2009-2012 Raphael Kubo da Costa * Copyright (c) 2016 Vladyslav Batyrenko * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef ARCHIVEINTERFACE_H #define ARCHIVEINTERFACE_H #include "archive_kerfuffle.h" #include "kerfuffle_export.h" #include "archiveentry.h" #include #include #include #include namespace Kerfuffle { class Query; class KERFUFFLE_EXPORT ReadOnlyArchiveInterface: public QObject { Q_OBJECT public: explicit ReadOnlyArchiveInterface(QObject *parent, const QVariantList &args); ~ReadOnlyArchiveInterface() override; /** * Returns the filename of the archive currently being handled. */ QString filename() const; /** * Returns the comment of the archive. */ QString comment() const; /** * @return The password of the archive, if any. */ QString password() const; bool isMultiVolume() const; int numberOfVolumes() const; /** * Returns whether the file can only be read. * * @return @c true The file cannot be written. * @return @c false The file can be read and written. */ virtual bool isReadOnly() const; virtual bool open(); /** * List archive contents. * This runs the process of reading archive contents. * When subclassing, you can block as long as you need (unless you called setWaitForFinishedSignal(true)). * @returns whether the listing succeeded. * @note If returning false, make sure to emit the error() signal beforewards to notify * the user of the error condition. */ virtual bool list() = 0; virtual bool testArchive() = 0; void setPassword(const QString &password); void setHeaderEncryptionEnabled(bool enabled); /** * Extracts the given @p files to the given @p destinationDirectory. * If @p files is empty, the whole archive will be extracted. * When subclassing, you can block as long as you need (unless you called setWaitForFinishedSignal(true)). * @returns whether the extraction succeeded. * @note If returning false, make sure to emit the error() signal beforewards to notify * the user of the error condition. */ virtual bool extractFiles(const QVector &files, const QString &destinationDirectory, const ExtractionOptions &options) = 0; /** * @return Whether the plugins do NOT run the functions in their own thread. * @see setWaitForFinishedSignal() */ bool waitForFinishedSignal(); /** * Returns count of required finish signals for a job to be finished. * * These two methods are used by move and copy jobs, which in some plugins implementations have to call * several processes sequentially. For instance, moving entries in zip archive is only possible if * extracting the entries, deleting them, recreating destination folder structure and adding them back again. */ virtual int moveRequiredSignals() const; virtual int copyRequiredSignals() const; /** * Returns the list of filenames retrieved from the list of entries. */ static QStringList entryFullPaths(const QVector &entries, PathFormat format = WithTrailingSlash); /** * Returns the list of the entries, excluding their children. * * This method relies on entries paths so doesn't require parents to be set. */ static QVector entriesWithoutChildren(const QVector &entries); /** * Returns the string list of entry paths, which will be a result of adding/moving/copying entries. * * @param entries The entries which will be added/moved/copied. * @param destination Destination path within the archive to which entries have to be added. For renaming an entry * the path has to contain a new filename too. * @param entriesWithoutChildren Entries count, excluding their children. For AddJob or CopyJob 0 MUST be passed. * * @return For entries * some/dir/ * some/dir/entry * some/dir/some/entry * some/another/entry * and destination * some/destination * will return * some/destination/dir/ * some/destination/dir/entry * some/destination/dir/some/enty * some/destination/entry */ static QStringList entryPathsFromDestination(QStringList entries, const Archive::Entry *destination, int entriesWithoutChildren); /** * @return true if the interface has killed the job or if it will stop it as soon as possible. * Otherwise returns false if the interface is not able to kill the operation. */ virtual bool doKill(); bool isHeaderEncryptionEnabled() const; virtual QString multiVolumeName() const; void setMultiVolume(bool value); uint numberOfEntries() const; QMimeType mimetype() const; /** * @return Whether the interface supports progress reporting for BatchExtractJobs. */ virtual bool hasBatchExtractionProgress() const; Q_SIGNALS: /** * Emitted when the user cancels the operation. Examples: * - the user cancels the password dialog * - the user cancels the overwrite dialog */ void cancelled(); void error(const QString &message, const QString &details = QString()); void entry(Archive::Entry *archiveEntry); void progress(double progress); void info(const QString &info); void finished(bool result); void testSuccess(); void compressionMethodFound(const QString &method); void encryptionMethodFound(const QString &method); /** * Emitted when @p query needs to be executed on the GUI thread. */ - void userQuery(Query *query); + void userQuery(Kerfuffle::Query *query); protected: /** * Setting this option to true will NOT run the functions in their own thread. * Instead it will be necessary to call finished(bool) when the operation is actually finished. */ void setWaitForFinishedSignal(bool value); void setCorrupt(bool isCorrupt); bool isCorrupt() const; QString m_comment; int m_numberOfVolumes; uint m_numberOfEntries; KPluginMetaData m_metaData; private: QString m_filename; QMimeType m_mimetype; QString m_password; bool m_waitForFinishedSignal; bool m_isHeaderEncryptionEnabled; bool m_isCorrupt; bool m_isMultiVolume; private Q_SLOTS: void onEntry(Archive::Entry *archiveEntry); }; class KERFUFFLE_EXPORT ReadWriteArchiveInterface: public ReadOnlyArchiveInterface { Q_OBJECT public: enum OperationMode { NoOperation, List, Extract, Add, Move, Copy, Delete, Comment, Test }; explicit ReadWriteArchiveInterface(QObject *parent, const QVariantList &args); ~ReadWriteArchiveInterface() override; bool isReadOnly() const override; /** * Adds the given @p files under the given @p destination. * If @p destination is null, the files will be added under the root of the archive. * @param options The compression options that must be respected. * @param numberOfEntriesToAdd The total number of entries the will be added. * @return Whether the operation succeeded. * @note If returning false, make sure to emit the error() signal beforewards to notify * the user of the error condition. */ virtual bool addFiles(const QVector &files, const Archive::Entry *destination, const CompressionOptions& options, uint numberOfEntriesToAdd = 0) = 0; virtual bool moveFiles(const QVector &files, Archive::Entry *destination, const CompressionOptions& options) = 0; virtual bool copyFiles(const QVector &files, Archive::Entry *destination, const CompressionOptions& options) = 0; virtual bool deleteFiles(const QVector &files) = 0; virtual bool addComment(const QString &comment) = 0; Q_SIGNALS: void entryRemoved(const QString &path); private Q_SLOTS: void onEntryRemoved(const QString &path); }; } // namespace Kerfuffle #endif // ARCHIVEINTERFACE_H diff --git a/kerfuffle/jobs.h b/kerfuffle/jobs.h index 4e9c98e7..b671af3c 100644 --- a/kerfuffle/jobs.h +++ b/kerfuffle/jobs.h @@ -1,429 +1,429 @@ /* * Copyright (c) 2007 Henrique Pinto * Copyright (c) 2008-2009 Harald Hvaal * Copyright (c) 2009-2012 Raphael Kubo da Costa * Copyright (c) 2016 Vladyslav Batyrenko * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef JOBS_H #define JOBS_H #include "kerfuffle_export.h" #include "archiveinterface.h" #include "archive_kerfuffle.h" #include "archiveentry.h" #include "queries.h" #include #include #include namespace Kerfuffle { class KERFUFFLE_EXPORT Job : public KJob { Q_OBJECT public: /** * @return The archive processed by this job. * @warning This method should not be called before start(). */ Archive *archive() const; QString errorString() const override; void start() override; protected: Job(Archive *archive, ReadOnlyArchiveInterface *interface); Job(Archive *archive); Job(ReadOnlyArchiveInterface *interface); ~Job() override; bool doKill() override; ReadOnlyArchiveInterface *archiveInterface(); void connectToArchiveInterfaceSignals(); public Q_SLOTS: virtual void doWork() = 0; protected Q_SLOTS: virtual void onCancelled(); virtual void onError(const QString &message, const QString &details); virtual void onInfo(const QString &info); virtual void onEntry(Archive::Entry *entry); virtual void onProgress(double progress); virtual void onEntryRemoved(const QString &path); virtual void onFinished(bool result); - virtual void onUserQuery(Query *query); + virtual void onUserQuery(Kerfuffle::Query *query); Q_SIGNALS: void entryRemoved(const QString & entry); void newEntry(Archive::Entry*); void userQuery(Kerfuffle::Query*); private: Archive *m_archive; ReadOnlyArchiveInterface *m_archiveInterface; QElapsedTimer jobTimer; class Private; Private * const d; }; /** * Load an existing archive. * Example usage: * * \code * * auto job = Archive::load(filename); * connect(job, &KJob::result, [](KJob *job) { * if (!job->error) { * auto archive = qobject_cast(job)->archive(); * // do something with archive. * } * }); * job->start(); * * \endcode */ class KERFUFFLE_EXPORT LoadJob : public Job { Q_OBJECT public: explicit LoadJob(Archive *archive); explicit LoadJob(ReadOnlyArchiveInterface *interface); qlonglong extractedFilesSize() const; bool isPasswordProtected() const; bool isSingleFolderArchive() const; QString subfolderName() const; public Q_SLOTS: void doWork() override; protected Q_SLOTS: void onFinished(bool result) override; private: explicit LoadJob(Archive *archive, ReadOnlyArchiveInterface *interface); bool m_isSingleFolderArchive; bool m_isPasswordProtected; QString m_subfolderName; QString m_basePath; qlonglong m_extractedFilesSize; qlonglong m_dirCount; qlonglong m_filesCount; private Q_SLOTS: void onNewEntry(const Archive::Entry*); }; /** * Perform a batch extraction of an existing archive. * Internally it runs a LoadJob before the actual extraction, * to figure out properties such as the subfolder name. */ class KERFUFFLE_EXPORT BatchExtractJob : public Job { Q_OBJECT public: explicit BatchExtractJob(LoadJob *loadJob, const QString &destination, bool autoSubfolder, bool preservePaths); public Q_SLOTS: void doWork() override; protected: bool doKill() override; private Q_SLOTS: void slotLoadingProgress(double progress); void slotExtractProgress(double progress); void slotLoadingFinished(KJob *job); private: /** * Tracks whether the job is loading or extracting the archive. */ enum Step {Loading, Extracting}; void setupDestination(); Step m_step = Loading; ExtractJob *m_extractJob = nullptr; LoadJob *m_loadJob; QString m_destination; bool m_autoSubfolder; bool m_preservePaths; unsigned long m_lastPercentage = 0; }; /** * Create a new archive given a bunch of entries. */ class KERFUFFLE_EXPORT CreateJob : public Job { Q_OBJECT public: explicit CreateJob(Archive *archive, const QVector &entries, const CompressionOptions& options); /** * @param password The password to encrypt the archive with. * @param encryptHeader Whether to encrypt also the list of files. */ void enableEncryption(const QString &password, bool encryptHeader); /** * Set whether the new archive should be multivolume. */ void setMultiVolume(bool isMultiVolume); public Q_SLOTS: void doWork() override; protected: bool doKill() override; private: AddJob *m_addJob = nullptr; QVector m_entries; CompressionOptions m_options; }; class KERFUFFLE_EXPORT ExtractJob : public Job { Q_OBJECT public: ExtractJob(const QVector &entries, const QString& destinationDir, const ExtractionOptions& options, ReadOnlyArchiveInterface *interface); QString destinationDirectory() const; ExtractionOptions extractionOptions() const; public Q_SLOTS: void doWork() override; private: QVector m_entries; QString m_destinationDir; ExtractionOptions m_options; }; /** * Abstract base class for jobs that extract a single file to a temporary dir. * It's not possible to pass extraction options and paths will be always preserved. * The only option that the job needs to know is whether the file is password protected. */ class KERFUFFLE_EXPORT TempExtractJob : public Job { Q_OBJECT public: TempExtractJob(Archive::Entry *entry, bool passwordProtectedHint, ReadOnlyArchiveInterface *interface); /** * @return The absolute path of the extracted file. * The path is validated in order to prevent directory traversal attacks. */ QString validatedFilePath() const; ExtractionOptions extractionOptions() const; /** * @return The temporary dir used for the extraction. * It is safe to delete this pointer in order to remove the directory. */ QTemporaryDir *tempDir() const; public Q_SLOTS: void doWork() override; private: QString extractionDir() const; Archive::Entry *m_entry; QTemporaryDir *m_tmpExtractDir; bool m_passwordProtectedHint; }; /** * This TempExtractJob can be used to preview a file. * The temporary extraction directory will be deleted upon job's completion. */ class KERFUFFLE_EXPORT PreviewJob : public TempExtractJob { Q_OBJECT public: PreviewJob(Archive::Entry *entry, bool passwordProtectedHint, ReadOnlyArchiveInterface *interface); }; /** * This TempExtractJob can be used to open a file in its dedicated application. * For this reason, the temporary extraction directory will NOT be deleted upon job's completion. */ class KERFUFFLE_EXPORT OpenJob : public TempExtractJob { Q_OBJECT public: OpenJob(Archive::Entry *entry, bool passwordProtectedHint, ReadOnlyArchiveInterface *interface); }; class KERFUFFLE_EXPORT OpenWithJob : public OpenJob { Q_OBJECT public: OpenWithJob(Archive::Entry *entry, bool passwordProtectedHint, ReadOnlyArchiveInterface *interface); }; class KERFUFFLE_EXPORT AddJob : public Job { Q_OBJECT public: AddJob(const QVector &files, const Archive::Entry *destination, const CompressionOptions& options, ReadWriteArchiveInterface *interface); public Q_SLOTS: void doWork() override; protected Q_SLOTS: void onFinished(bool result) override; private: QString m_oldWorkingDir; const QVector m_entries; const Archive::Entry *m_destination; CompressionOptions m_options; }; /** * This MoveJob can be used to rename or move entries within the archive. * @see Archive::moveFiles for more details. */ class KERFUFFLE_EXPORT MoveJob : public Job { Q_OBJECT public: MoveJob(const QVector &files, Archive::Entry *destination, const CompressionOptions& options, ReadWriteArchiveInterface *interface); public Q_SLOTS: void doWork() override; protected Q_SLOTS: void onFinished(bool result) override; private: int m_finishedSignalsCount; const QVector m_entries; Archive::Entry *m_destination; CompressionOptions m_options; }; /** * This CopyJob can be used to copy entries within the archive. * @see Archive::copyFiles for more details. */ class KERFUFFLE_EXPORT CopyJob : public Job { Q_OBJECT public: CopyJob(const QVector &entries, Archive::Entry *destination, const CompressionOptions& options, ReadWriteArchiveInterface *interface); public Q_SLOTS: void doWork() override; protected Q_SLOTS: void onFinished(bool result) override; private: int m_finishedSignalsCount; const QVector m_entries; Archive::Entry *m_destination; CompressionOptions m_options; }; class KERFUFFLE_EXPORT DeleteJob : public Job { Q_OBJECT public: DeleteJob(const QVector &files, ReadWriteArchiveInterface *interface); public Q_SLOTS: void doWork() override; private: QVector m_entries; }; class KERFUFFLE_EXPORT CommentJob : public Job { Q_OBJECT public: CommentJob(const QString& comment, ReadWriteArchiveInterface *interface); public Q_SLOTS: void doWork() override; private: QString m_comment; }; class KERFUFFLE_EXPORT TestJob : public Job { Q_OBJECT public: explicit TestJob(ReadOnlyArchiveInterface *interface); bool testSucceeded(); public Q_SLOTS: void doWork() override; private Q_SLOTS: virtual void onTestSuccess(); private: bool m_testSuccess; }; } // namespace Kerfuffle #endif // JOBS_H