File indexing completed on 2024-05-05 05:50:39

0001 /*
0002     SPDX-FileCopyrightText: 2007 Henrique Pinto <henrique.pinto@kdemail.net>
0003     SPDX-FileCopyrightText: 2008 Harald Hvaal <haraldhv@stud.ntnu.no>
0004     SPDX-FileCopyrightText: 2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
0005 
0006     SPDX-License-Identifier: BSD-2-Clause
0007 */
0008 
0009 #ifndef ARCHIVE_H
0010 #define ARCHIVE_H
0011 
0012 #include "kerfuffle_export.h"
0013 #include "metadatabackup.h"
0014 #include "options.h"
0015 
0016 #include <KJob>
0017 
0018 #include <QHash>
0019 #include <QMimeType>
0020 
0021 namespace Kerfuffle
0022 {
0023 class LoadJob;
0024 class BatchExtractJob;
0025 class CreateJob;
0026 class ExtractJob;
0027 class DeleteJob;
0028 class AddJob;
0029 class MoveJob;
0030 class CopyJob;
0031 class CommentJob;
0032 class TestJob;
0033 class OpenJob;
0034 class OpenWithJob;
0035 class Plugin;
0036 class PreviewJob;
0037 class Query;
0038 class ReadOnlyArchiveInterface;
0039 
0040 enum ArchiveError { NoError = 0, NoPlugin, FailedPlugin };
0041 
0042 class KERFUFFLE_EXPORT Archive : public QObject
0043 {
0044     Q_OBJECT
0045 
0046     /**
0047      *  Complete base name, without the "tar" extension (if any).
0048      */
0049     Q_PROPERTY(QString completeBaseName READ completeBaseName CONSTANT)
0050     Q_PROPERTY(QString fileName READ fileName CONSTANT)
0051     Q_PROPERTY(QString comment READ comment CONSTANT)
0052     Q_PROPERTY(QMimeType mimeType READ mimeType CONSTANT)
0053     Q_PROPERTY(bool isEmpty READ isEmpty)
0054     Q_PROPERTY(bool isReadOnly READ isReadOnly CONSTANT)
0055     Q_PROPERTY(bool isSingleFile READ isSingleFile)
0056     Q_PROPERTY(bool isSingleFolder MEMBER m_isSingleFolder READ isSingleFolder)
0057     Q_PROPERTY(bool isMultiVolume READ isMultiVolume WRITE setMultiVolume)
0058     Q_PROPERTY(bool numberOfVolumes READ numberOfVolumes)
0059     Q_PROPERTY(EncryptionType encryptionType MEMBER m_encryptionType READ encryptionType)
0060     Q_PROPERTY(uint numberOfEntries READ numberOfEntries)
0061     Q_PROPERTY(qulonglong unpackedSize MEMBER m_extractedFilesSize READ unpackedSize)
0062     Q_PROPERTY(qulonglong packedSize READ packedSize)
0063     Q_PROPERTY(QString subfolderName MEMBER m_subfolderName READ subfolderName)
0064     Q_PROPERTY(QString password READ password)
0065     Q_PROPERTY(QStringList compressionMethods MEMBER m_compressionMethods)
0066     Q_PROPERTY(QStringList encryptionMethods MEMBER m_encryptionMethods)
0067 
0068 public:
0069     enum EncryptionType { Unencrypted, Encrypted, HeaderEncrypted };
0070     Q_ENUM(EncryptionType)
0071 
0072     class Entry;
0073 
0074     QString completeBaseName() const;
0075     QString fileName() const;
0076     QString comment() const;
0077     QMimeType mimeType();
0078     bool isEmpty() const;
0079     bool isReadOnly() const;
0080     bool isSingleFile() const;
0081     bool isSingleFolder() const;
0082     bool isMultiVolume() const;
0083     void setMultiVolume(bool value);
0084     bool hasComment() const;
0085     int numberOfVolumes() const;
0086     EncryptionType encryptionType() const;
0087     QString password() const;
0088     uint numberOfEntries() const;
0089     qulonglong unpackedSize() const;
0090     qulonglong packedSize() const;
0091     QString subfolderName() const;
0092     QString multiVolumeName() const;
0093     ReadOnlyArchiveInterface *interface();
0094 
0095     /**
0096      * @return Whether the archive has more than one top-level entry.
0097      */
0098     bool hasMultipleTopLevelEntries() const;
0099 
0100     /**
0101      * @return Batch extraction job for @p filename to @p destination.
0102      * @param autoSubfolder Whether the job will extract into a subfolder.
0103      * @param preservePaths Whether the job will preserve paths.
0104      * @param parent The parent for the archive.
0105      */
0106     static BatchExtractJob *
0107     batchExtract(const QString &fileName, const QString &destination, bool autoSubfolder, bool preservePaths, QObject *parent = nullptr);
0108 
0109     /**
0110      * @return Job to create an archive for the given @p entries.
0111      * @param fileName The name of the new archive.
0112      * @param mimeType The mimetype of the new archive.
0113      */
0114     static CreateJob *create(const QString &fileName,
0115                              const QString &mimeType,
0116                              const QVector<Archive::Entry *> &entries,
0117                              const CompressionOptions &options,
0118                              QObject *parent = nullptr);
0119 
0120     /**
0121      * @return An empty archive with name @p fileName, mimetype @p mimeType and @p parent as parent.
0122      */
0123     static Archive *createEmpty(const QString &fileName, const QString &mimeType, QObject *parent = nullptr);
0124 
0125     /**
0126      * @return Job to load the archive @p fileName.
0127      * @param parent The parent of the archive that will be loaded.
0128      */
0129     static LoadJob *load(const QString &fileName, QObject *parent = nullptr);
0130 
0131     /**
0132      * @return Job to load the archive @p fileName with mimetype @p mimeType.
0133      * @param parent The parent of the archive that will be loaded.
0134      */
0135     static LoadJob *load(const QString &fileName, const QString &mimeType, QObject *parent = nullptr);
0136 
0137     /**
0138      * @return Job to load the archive @p fileName by using @p plugin.
0139      * @param parent The parent of the archive that will be loaded.
0140      */
0141     static LoadJob *load(const QString &fileName, Plugin *plugin, QObject *parent = nullptr);
0142 
0143     ~Archive() override;
0144 
0145     ArchiveError error() const;
0146     bool isValid() const;
0147 
0148     DeleteJob *deleteFiles(QVector<Archive::Entry *> &entries);
0149     CommentJob *addComment(const QString &comment);
0150     TestJob *testArchive();
0151 
0152     AddJob *addFiles(const QVector<Archive::Entry *> &files, const Archive::Entry *destination, const CompressionOptions &options = CompressionOptions());
0153 
0154     /**
0155      * Renames or moves entries within the archive.
0156      *
0157      * @param files All the renamed or moved files and their child entries (for renaming a directory too).
0158      * @param destination New entry name (for renaming) or destination folder (for moving).
0159      * If ReadOnlyArchiveInterface::entriesWithoutChildren(files).count() returns 1, then it's renaming,
0160      * so you must specify the resulted entry name, even if it's not going to be changed.
0161      * Otherwise (if count is more than 1) it's moving, so destination must contain only targeted folder path
0162      * or be empty, if moving to the root.
0163      */
0164     MoveJob *moveFiles(const QVector<Archive::Entry *> &files, Archive::Entry *destination, const CompressionOptions &options = CompressionOptions());
0165 
0166     /**
0167      * Copies entries within the archive.
0168      *
0169      * @param files All the renamed or moved files and their child entries (for renaming a directory too).
0170      * @param destination Destination path. It must contain only targeted folder path or be empty,
0171      * if copying to the root.
0172      */
0173     CopyJob *copyFiles(const QVector<Archive::Entry *> &files, Archive::Entry *destination, const CompressionOptions &options = CompressionOptions());
0174 
0175     ExtractJob *extractFiles(const QVector<Archive::Entry *> &files, const QString &destinationDir, ExtractionOptions options = ExtractionOptions());
0176 
0177     PreviewJob *preview(Archive::Entry *entry);
0178     OpenJob *open(Archive::Entry *entry);
0179     OpenWithJob *openWith(Archive::Entry *entry);
0180 
0181     /**
0182      * @param password The password to encrypt the archive with.
0183      * @param encryptHeader Whether to encrypt also the list of files.
0184      */
0185     void encrypt(const QString &password, bool encryptHeader);
0186 
0187 private Q_SLOTS:
0188     void onAddFinished(KJob *);
0189     void onUserQuery(Kerfuffle::Query *);
0190     void onCompressionMethodFound(const QString &method);
0191     void onEncryptionMethodFound(const QString &method);
0192 
0193 private:
0194     Archive(ReadOnlyArchiveInterface *archiveInterface, bool isReadOnly, QObject *parent = nullptr);
0195     Archive(ArchiveError errorCode, QObject *parent = nullptr);
0196 
0197     static Archive *create(const QString &fileName, QObject *parent = nullptr);
0198     static Archive *create(const QString &fileName, const QString &fixedMimeType, QObject *parent = nullptr);
0199 
0200     /**
0201      * Create an archive instance from a given @p plugin.
0202      * @param fileName The name of the archive.
0203      * @return A valid archive if the plugin could be loaded, an invalid one otherwise (with the FailedPlugin error set).
0204      */
0205     static Archive *create(const QString &fileName, Plugin *plugin, QObject *parent = nullptr);
0206     ReadOnlyArchiveInterface *m_iface;
0207     bool m_isReadOnly;
0208     bool m_isSingleFolder;
0209     bool m_isMultiVolume;
0210 
0211     QString m_subfolderName;
0212     qulonglong m_extractedFilesSize;
0213     ArchiveError m_error;
0214     EncryptionType m_encryptionType;
0215     QMimeType m_mimeType;
0216     QStringList m_compressionMethods;
0217     QStringList m_encryptionMethods;
0218 
0219     /**
0220      * @brief The user metadata for this archive.
0221      *
0222      * We keep track of the user metadata for the archive so that we can restore
0223      * it after the archive has been modified.
0224      */
0225     std::optional<MetadataBackup> m_userMetaData;
0226 
0227     /**
0228      * @brief Restore the user metadata for this archive.
0229      */
0230     void restoreUserMetadata();
0231 };
0232 
0233 } // namespace Kerfuffle
0234 
0235 #endif // ARCHIVE_H