diff --git a/kerfuffle/cliinterface.h b/kerfuffle/cliinterface.h --- a/kerfuffle/cliinterface.h +++ b/kerfuffle/cliinterface.h @@ -373,14 +373,6 @@ */ bool passwordQuery(); - ParameterList m_param; - int m_exitCode; - -protected slots: - virtual void readStdout(bool handleAll = false); - -private: - /** * Checks whether a line of the program's output is a password prompt. * @@ -394,9 +386,26 @@ */ bool checkForPasswordPromptMessage(const QString& line); + bool checkForErrorMessage(const QString& line, int parameterIndex); + + + ParameterList m_param; + +#ifdef Q_OS_WIN + KProcess *m_process; +#else + KPtyProcess *m_process; +#endif + + bool m_abortingOperation; + + +protected slots: + virtual void readStdout(bool handleAll = false); + +private: bool handleFileExistsMessage(const QString& filename); - bool checkForErrorMessage(const QString& line, int parameterIndex); bool checkForTestSuccessMessage(const QString& line); /** @@ -428,15 +437,9 @@ QRegularExpression m_passwordPromptPattern; QHash > m_patternCache; -#ifdef Q_OS_WIN - KProcess *m_process; -#else - KPtyProcess *m_process; -#endif - QVariantList m_removedFiles; + int m_exitCode; bool m_listEmptyLines; - bool m_abortingOperation; QString m_storedFileName; CompressionOptions m_compressionOptions; @@ -447,7 +450,7 @@ QVariantList m_copiedFiles; private slots: - void processFinished(int exitCode, QProcess::ExitStatus exitStatus); + virtual void processFinished(int exitCode, QProcess::ExitStatus exitStatus); void copyProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); }; diff --git a/kerfuffle/cliinterface.cpp b/kerfuffle/cliinterface.cpp --- a/kerfuffle/cliinterface.cpp +++ b/kerfuffle/cliinterface.cpp @@ -61,8 +61,8 @@ CliInterface::CliInterface(QObject *parent, const QVariantList & args) : ReadWriteArchiveInterface(parent, args), m_process(0), - m_listEmptyLines(false), m_abortingOperation(false), + m_listEmptyLines(false), m_extractTempDir(Q_NULLPTR), m_commentTempFile(Q_NULLPTR) { diff --git a/plugins/cliunarchiverplugin/cliplugin.h b/plugins/cliunarchiverplugin/cliplugin.h --- a/plugins/cliunarchiverplugin/cliplugin.h +++ b/plugins/cliunarchiverplugin/cliplugin.h @@ -52,6 +52,9 @@ void cacheParameterList() Q_DECL_OVERRIDE; void handleLine(const QString& line) Q_DECL_OVERRIDE; +private slots: + void processFinished(int exitCode, QProcess::ExitStatus exitStatus) Q_DECL_OVERRIDE; + private: void readJsonOutput(); diff --git a/plugins/cliunarchiverplugin/cliplugin.cpp b/plugins/cliunarchiverplugin/cliplugin.cpp --- a/plugins/cliunarchiverplugin/cliplugin.cpp +++ b/plugins/cliunarchiverplugin/cliplugin.cpp @@ -22,13 +22,15 @@ #include "cliplugin.h" #include "ark_debug.h" -#include "kerfuffle/kerfuffle_export.h" +#include "kerfuffle_export.h" +#include "queries.h" #include #include #include #include +#include using namespace Kerfuffle; @@ -51,31 +53,7 @@ m_operationMode = List; const auto args = substituteListVariables(m_param.value(ListArgs).toStringList(), password()); - - if (!runProcess(m_param.value(ListProgram).toStringList(), args)) { - return false; - } - - if (!password().isEmpty()) { - - // lsar -json exits with error code 1 if the archive is header-encrypted and the password is wrong. - if (m_exitCode == 1) { - qCWarning(ARK) << "Wrong password, list() aborted"; - emit error(i18n("Wrong password.")); - emit finished(false); - killProcess(); - setPassword(QString()); - return false; - } - - // lsar -json exits with error code 2 if the archive is header-encrypted and no password is given as argument. - // At this point we have already asked a password to the user, so we can just list() again. - if (m_exitCode == 2) { - return CliPlugin::list(); - } - } - - return true; + return runProcess(m_param.value(ListProgram).toStringList(), args); } bool CliPlugin::copyFiles(const QList &files, const QString &destinationDirectory, const ExtractionOptions &options) @@ -170,7 +148,75 @@ m_jsonOutput += line + QLatin1Char('\n'); } - CliInterface::handleLine(line); + // TODO: is this check really needed? + if (m_operationMode == Copy) { + if (checkForErrorMessage(line, ExtractionFailedPatterns)) { + qCWarning(ARK) << "Error in extraction:" << line; + emit error(i18n("Extraction failed because of an unexpected error.")); + killProcess(); + return; + } + } + + if (m_operationMode == List) { + // This can only be an header-encrypted archive. + if (checkForPasswordPromptMessage(line)) { + qCDebug(ARK) << "Detected header-encrypted RAR archive"; + + Kerfuffle::PasswordNeededQuery query(filename()); + emit userQuery(&query); + query.waitForResponse(); + + if (query.responseCancelled()) { + emit cancelled(); + // Process is gone, so we emit finished() manually. + emit finished(false); + } else { + setPassword(query.password()); + CliPlugin::list(); + } + } + } +} + +void CliPlugin::processFinished(int exitCode, QProcess::ExitStatus exitStatus) +{ + qCDebug(ARK) << "Process finished, exitcode:" << exitCode << "exitstatus:" << exitStatus; + + if (m_process) { + //handle all the remaining data in the process + readStdout(true); + + delete m_process; + m_process = Q_NULLPTR; + } + + // #193908 - #222392 + // Don't emit finished() if the job was killed quietly. + if (m_abortingOperation) { + return; + } + + if (!password().isEmpty()) { + + // lsar -json exits with error code 1 if the archive is header-encrypted and the password is wrong. + if (exitCode == 1) { + qCWarning(ARK) << "Wrong password, list() aborted"; + emit error(i18n("Wrong password.")); + emit finished(false); + setPassword(QString()); + return; + } + } + + // lsar -json exits with error code 2 if the archive is header-encrypted and no password is given as argument. + // At this point we are asking a password to the user and we are going to list() again after we get one. + // This means that we cannot emit finished here. + if (exitCode == 2) { + return; + } + + emit finished(true); } void CliPlugin::readJsonOutput()