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 */