Commit 3b8f60b6 authored by Elvis Angelaccio's avatar Elvis Angelaccio

cliunarchiver: fix opening header-encrypted archives

cliunarchiver plugin was never ported to the new "non-blocking" way (see 074d5277).
This patch implements that and fixes a crash when opening header-encrypted
archives.

Differential Revision: D2287
parent 382305a7
......@@ -61,8 +61,8 @@ namespace Kerfuffle
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)
{
......
......@@ -373,14 +373,6 @@ protected:
*/
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 @@ private:
*/
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 @@ private:
QRegularExpression m_passwordPromptPattern;
QHash<int, QList<QRegularExpression> > 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 @@ private:
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);
};
......
......@@ -22,13 +22,15 @@
#include "cliplugin.h"
#include "ark_debug.h"
#include "kerfuffle/kerfuffle_export.h"
#include "kerfuffle_export.h"
#include "queries.h"
#include <QJsonArray>
#include <QJsonParseError>
#include <KLocalizedString>
#include <KPluginFactory>
#include <KPtyProcess>
using namespace Kerfuffle;
......@@ -51,31 +53,7 @@ bool CliPlugin::list()
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<QVariant> &files, const QString &destinationDirectory, const ExtractionOptions &options)
......@@ -170,7 +148,75 @@ void CliPlugin::handleLine(const QString& line)
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()
......
......@@ -52,6 +52,9 @@ protected:
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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment