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

0001 /*
0002     SPDX-FileCopyrightText: 2009 Harald Hvaal <haraldhv@stud.ntnu.no>
0003     SPDX-FileCopyrightText: 2009-2011 Raphael Kubo da Costa <rakuco@FreeBSD.org>
0004     SPDX-FileCopyrightText: 2016 Vladyslav Batyrenko <mvlabat@gmail.com>
0005 
0006     SPDX-License-Identifier: BSD-2-Clause
0007 */
0008 #ifndef CLIINTERFACE_H
0009 #define CLIINTERFACE_H
0010 
0011 #include "archiveentry.h"
0012 #include "archiveinterface.h"
0013 #include "cliproperties.h"
0014 #include "kerfuffle_export.h"
0015 
0016 #include <QProcess>
0017 #include <QRegularExpression>
0018 
0019 class KProcess;
0020 class KPtyProcess;
0021 
0022 class QDir;
0023 class QTemporaryDir;
0024 class QTemporaryFile;
0025 
0026 namespace Kerfuffle
0027 {
0028 class KERFUFFLE_EXPORT CliInterface : public ReadWriteArchiveInterface
0029 {
0030     Q_OBJECT
0031 
0032 public:
0033     explicit CliInterface(QObject *parent, const QVariantList &args);
0034     ~CliInterface() override;
0035 
0036     int copyRequiredSignals() const override;
0037 
0038     bool list() override;
0039     bool extractFiles(const QVector<Archive::Entry *> &files, const QString &destinationDirectory, const ExtractionOptions &options) override;
0040     bool addFiles(const QVector<Archive::Entry *> &files,
0041                   const Archive::Entry *destination,
0042                   const CompressionOptions &options,
0043                   uint numberOfEntriesToAdd = 0) override;
0044     bool moveFiles(const QVector<Archive::Entry *> &files, Archive::Entry *destination, const CompressionOptions &options) override;
0045     bool copyFiles(const QVector<Archive::Entry *> &files, Archive::Entry *destination, const CompressionOptions &options) override;
0046     bool deleteFiles(const QVector<Archive::Entry *> &files) override;
0047     bool addComment(const QString &comment) override;
0048     bool testArchive() override;
0049 
0050     virtual void resetParsing() = 0;
0051     virtual bool readListLine(const QString &line) = 0;
0052     virtual bool readExtractLine(const QString &line) = 0;
0053     virtual bool readDeleteLine(const QString &line);
0054     virtual bool isPasswordPrompt(const QString &line);
0055     virtual bool isWrongPasswordMsg(const QString &line);
0056     virtual bool isCorruptArchiveMsg(const QString &line);
0057     virtual bool isDiskFullMsg(const QString &line);
0058     virtual bool isFileExistsMsg(const QString &line);
0059     virtual bool isFileExistsFileName(const QString &line);
0060     virtual bool isNewMovedFileNamesMsg(const QString &line);
0061     bool doKill() override;
0062 
0063     /**
0064      * Sets if the listing should include empty lines.
0065      *
0066      * The default value is false.
0067      */
0068     void setListEmptyLines(bool emptyLines);
0069 
0070     /**
0071      * Move all files from @p tmpDir to @p destDir, preserving paths if @p preservePaths is true.
0072      * @return Whether the operation has been successful.
0073      */
0074     bool moveToDestination(const QDir &tempDir, const QDir &destDir, bool preservePaths);
0075 
0076     /**
0077      * @see ArchiveModel::entryPathsFromDestination
0078      */
0079     void setNewMovedFiles(const QVector<Archive::Entry *> &entries, const Archive::Entry *destination, int entriesWithoutChildren);
0080 
0081     /**
0082      * @return The list of selected files to extract.
0083      */
0084     QStringList extractFilesList(const QVector<Archive::Entry *> &files) const;
0085 
0086     QString multiVolumeName() const override;
0087 
0088     CliProperties *cliProperties() const;
0089 
0090 protected:
0091     bool setAddedFiles();
0092 
0093     /**
0094      * Handles the given @p line.
0095      * @return True if the line is ok. False if the line contains/triggers a "fatal" error
0096      * or a canceled user query. If false is returned, the caller is supposed to call killProcess().
0097      */
0098     virtual bool handleLine(const QString &line);
0099 
0100     /**
0101      * Run @p programName with the given @p arguments.
0102      *
0103      * @param programName The program that will be run (not the whole path).
0104      * @param arguments A list of arguments that will be passed to the program.
0105      *
0106      * @return @c true if the program was found and the process was started correctly,
0107      *         @c false otherwise (in which case finished(false) is emitted).
0108      */
0109     bool runProcess(const QString &programName, const QStringList &arguments);
0110 
0111     /**
0112      * Kill the running process. The finished signal is emitted according to @p emitFinished.
0113      */
0114     void killProcess(bool emitFinished = true);
0115 
0116     /**
0117      * Ask the password *before* running any process.
0118      * @return True if the user supplies a password, false otherwise (in which case finished() is emitted).
0119      */
0120     bool passwordQuery();
0121 
0122     void cleanUp();
0123 
0124     CliProperties *m_cliProps = nullptr;
0125     QString m_oldWorkingDirExtraction; // Used ONLY by extraction jobs.
0126     QString m_oldWorkingDir; // Used by copy and move jobs.
0127     QScopedPointer<QTemporaryDir> m_tempWorkingDir;
0128     QScopedPointer<QTemporaryDir> m_tempAddDir;
0129     OperationMode m_subOperation = NoOperation;
0130     QVector<Archive::Entry *> m_passedFiles;
0131     QVector<Archive::Entry *> m_tempAddedFiles;
0132     Archive::Entry *m_passedDestination = nullptr;
0133     CompressionOptions m_passedOptions;
0134 
0135 #ifdef Q_OS_WIN
0136     KProcess *m_process = nullptr;
0137 #else
0138     KPtyProcess *m_process = nullptr;
0139 #endif
0140 
0141     bool m_abortingOperation = false;
0142 
0143 protected Q_SLOTS:
0144     virtual void readStdout(bool handleAll = false);
0145 
0146 private:
0147     bool handleFileExistsMessage(const QString &filename);
0148 
0149     /**
0150      * Returns a list of path pairs which will be supplied to rn command.
0151      * <src_file_1> <dest_file_1> [ <src_file_2> <dest_file_2> ... ]
0152      * Also constructs a list of new entries resulted in moving.
0153      *
0154      * @param entriesWithoutChildren List of archive entries
0155      * @param destination Must be a directory entry if QList contains more that one entry
0156      */
0157     QStringList entryPathDestinationPairs(const QVector<Archive::Entry *> &entriesWithoutChildren, const Archive::Entry *destination);
0158 
0159     /**
0160      * Wrapper around KProcess::write() or KPtyDevice::write(), depending on
0161      * the platform.
0162      */
0163     void writeToProcess(const QByteArray &data);
0164 
0165     /**
0166      * Moves the dropped @files from the temp dir to the @p finalDest.
0167      * @return @c true if the files have been moved, @c false otherwise.
0168      */
0169     bool moveDroppedFilesToDest(const QVector<Archive::Entry *> &files, const QString &finalDest);
0170 
0171     /**
0172      * @return Whether @p dir is an empty directory.
0173      */
0174     bool isEmptyDir(const QDir &dir);
0175 
0176     /**
0177      * Performs any additional escaping and processing on @p fileName
0178      * before passing it to the underlying process.
0179      *
0180      * The default implementation returns @p fileName unchanged.
0181      *
0182      * @param fileName String to escape.
0183      */
0184     virtual QString escapeFileName(const QString &fileName) const;
0185 
0186     void cleanUpExtracting();
0187     void restoreWorkingDirExtraction();
0188 
0189     void finishCopying(bool result);
0190 
0191     QByteArray m_stdOutData;
0192     QRegularExpression m_passwordPromptPattern;
0193     QHash<int, QList<QRegularExpression>> m_patternCache;
0194 
0195     QVector<Archive::Entry *> m_removedFiles;
0196     QVector<Archive::Entry *> m_newMovedFiles;
0197     int m_exitCode = 0;
0198     bool m_listEmptyLines = false;
0199     QString m_storedFileName;
0200 
0201     ExtractionOptions m_extractionOptions;
0202     QString m_extractDestDir;
0203     QScopedPointer<QTemporaryDir> m_extractTempDir;
0204     QScopedPointer<QTemporaryFile> m_commentTempFile;
0205     QVector<Archive::Entry *> m_extractedFiles;
0206     qulonglong m_archiveSizeOnDisk = 0;
0207     qulonglong m_listedSize = 0;
0208 
0209     QMetaObject::Connection m_readyStdOutConnection;
0210 
0211 protected Q_SLOTS:
0212     virtual void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
0213 
0214 private Q_SLOTS:
0215     void extractProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
0216     void continueCopying(bool result);
0217     void onEntry(Archive::Entry *archiveEntry);
0218 };
0219 }
0220 
0221 #endif /* CLIINTERFACE_H */