Commit d570b04d authored by Elvis Angelaccio's avatar Elvis Angelaccio

Fix detection of 7z multivolumes archives with missing volumes

This exposed a crash caused by CliInterface::handleLine() called after the
CliInterface instance had already been deleted. This is now fixed by moving the
killProcess() calls to readStdout() instead of handleLine() itself.

Differential Revision: D2303
parent e7af0186
......@@ -978,12 +978,15 @@ void CliInterface::readStdout(bool handleAll)
foreach(const QByteArray& line, lines) {
if (!line.isEmpty() || (m_listEmptyLines && m_operationMode == List)) {
handleLine(QString::fromLocal8Bit(line));
if (!handleLine(QString::fromLocal8Bit(line))) {
killProcess();
return;
}
}
}
}
void CliInterface::handleLine(const QString& line)
bool CliInterface::handleLine(const QString& line)
{
// TODO: This should be implemented by each plugin; the way progress is
// shown by each CLI application is subject to a lot of variation.
......@@ -993,7 +996,7 @@ void CliInterface::handleLine(const QString& line)
if (pos > 1) {
int percentage = line.midRef(pos - 2, 2).toInt();
emit progress(float(percentage) / 100);
return;
return true;
}
}
......@@ -1008,8 +1011,7 @@ void CliInterface::handleLine(const QString& line)
if (query.responseCancelled()) {
emit cancelled();
killProcess();
return;
return false;
}
setPassword(query.password());
......@@ -1017,33 +1019,30 @@ void CliInterface::handleLine(const QString& line)
const QString response(password() + QLatin1Char('\n'));
writeToProcess(response.toLocal8Bit());
return;
return true;
}
if (checkForErrorMessage(line, DiskFullPatterns)) {
qCWarning(ARK) << "Found disk full message:" << line;
emit error(i18nc("@info", "Extraction failed because the disk is full."));
killProcess();
return;
return false;
}
if (checkForErrorMessage(line, WrongPasswordPatterns)) {
qCWarning(ARK) << "Wrong password!";
setPassword(QString());
emit error(i18nc("@info", "Extraction failed: Incorrect password"));
killProcess();
return;
return false;
}
if (checkForErrorMessage(line, ExtractionFailedPatterns)) {
qCWarning(ARK) << "Error in extraction:" << line;
emit error(i18n("Extraction failed because of an unexpected error."));
killProcess();
return;
return false;
}
if (handleFileExistsMessage(line)) {
return;
return true;
}
}
......@@ -1057,8 +1056,7 @@ void CliInterface::handleLine(const QString& line)
if (query.responseCancelled()) {
emit cancelled();
killProcess();
return;
return false;
}
setPassword(query.password());
......@@ -1066,36 +1064,35 @@ void CliInterface::handleLine(const QString& line)
const QString response(password() + QLatin1Char('\n'));
writeToProcess(response.toLocal8Bit());
return;
return true;
}
if (checkForErrorMessage(line, WrongPasswordPatterns)) {
qCWarning(ARK) << "Wrong password!";
setPassword(QString());
emit error(i18n("Incorrect password."));
killProcess();
return;
return false;
}
if (checkForErrorMessage(line, ExtractionFailedPatterns)) {
qCWarning(ARK) << "Error in extraction!!";
emit error(i18n("Extraction failed because of an unexpected error."));
killProcess();
return;
return false;
}
if (checkForErrorMessage(line, CorruptArchivePatterns)) {
qCWarning(ARK) << "Archive corrupt";
setCorrupt(true);
return;
// Special case: corrupt is not a "fatal" error so we return true here.
return true;
}
if (handleFileExistsMessage(line)) {
return;
return true;
}
readListLine(line);
return;
return true;
}
if (m_operationMode == Test) {
......@@ -1104,16 +1101,17 @@ void CliInterface::handleLine(const QString& line)
qCDebug(ARK) << "Found a password prompt";
emit error(i18n("Ark does not currently support testing this archive."));
killProcess();
return;
return false;
}
if (checkForTestSuccessMessage(line)) {
qCDebug(ARK) << "Test successful";
emit testSuccess();
return;
return true;
}
}
return true;
}
bool CliInterface::checkForPasswordPromptMessage(const QString& line)
......
......@@ -348,7 +348,13 @@ public:
protected:
virtual void handleLine(const QString& line);
/**
* Handles the given @p line.
* @return True if the line is ok. False if the line contains/triggers a "fatal" error
* or a canceled user query. If false is returned, the caller is supposed to call killProcess().
*/
virtual bool handleLine(const QString& line);
virtual void cacheParameterList();
/**
......
......@@ -101,7 +101,7 @@ ParameterList CliPlugin::parameterList() const
<< QStringLiteral("S") //autoskip
<< QStringLiteral("Q"); //cancel
p[PasswordPromptPattern] = QStringLiteral("Enter password \\(will not be echoed\\)");
p[ExtractionFailedPatterns] = QStringList() << QStringLiteral("ERROR: E_FAIL");
p[ExtractionFailedPatterns] = QStringList() << QStringLiteral("ERROR: E_FAIL") << QStringLiteral("Open ERROR: Can not open the file as \\[7z\\] archive");
p[CorruptArchivePatterns] = QStringList() << QStringLiteral("Unexpected end of archive")
<< QStringLiteral("Headers Error");
p[DiskFullPatterns] = QStringList() << QStringLiteral("No space left on device");
......
......@@ -141,7 +141,7 @@ void CliPlugin::cacheParameterList()
Q_ASSERT(m_param.contains(ListProgram));
}
void CliPlugin::handleLine(const QString& line)
bool CliPlugin::handleLine(const QString& line)
{
// Collect the json output line by line.
if (m_operationMode == List) {
......@@ -153,8 +153,7 @@ void CliPlugin::handleLine(const QString& line)
if (checkForErrorMessage(line, ExtractionFailedPatterns)) {
qCWarning(ARK) << "Error in extraction:" << line;
emit error(i18n("Extraction failed because of an unexpected error."));
killProcess();
return;
return false;
}
}
......@@ -169,14 +168,17 @@ void CliPlugin::handleLine(const QString& line)
if (query.responseCancelled()) {
emit cancelled();
// Process is gone, so we emit finished() manually.
// Process is gone, so we emit finished() manually and we return true.
emit finished(false);
} else {
setPassword(query.password());
CliPlugin::list();
return true;
}
setPassword(query.password());
CliPlugin::list();
}
}
return true;
}
void CliPlugin::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
......
......@@ -50,7 +50,7 @@ protected slots:
protected:
void cacheParameterList() Q_DECL_OVERRIDE;
void handleLine(const QString& line) Q_DECL_OVERRIDE;
bool handleLine(const QString& line) Q_DECL_OVERRIDE;
private slots:
void processFinished(int exitCode, QProcess::ExitStatus exitStatus) Q_DECL_OVERRIDE;
......
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