Commit 170115f1 authored by Ragnar Thomsen's avatar Ragnar Thomsen
Browse files

Improve handling of corrupt archives by CliPlugins

A new parameter was added to the Kerfuffle::CliInterfaceParameters enum
(called CorruptArchivePatterns), containing a list of regexps matching
output from CliPlugins when a corrupt archive is listed.

Due to the CliInterface not being able to launch a KMessageBox itself, a
query (LoadCorruptQuery) was added which launches a
KMessageBox::warningYesNo asking the user if he wants to try to load the
corrupt archive. This is useful because some files might still be
recoverable.

If the user answers no, loading of the archive is cancelled.

If the user answers yes the archive is loaded as usual, but to prevent
the user from trying to add/delete files from the corrupt archive (which
is likely to fail), the archive is set to readonly. This necessitated a
new private member in ReadOnlyArchiveInterface (m_isCorrupt) and
getter/setter functions. The setter function is used in
CliInterface::HandleLine, while the getter function is used in
ReadWriteArchiveInterface::isReadOnly().

BUG: 261073
BUG: 352949
FIXED-IN: 15.12.0
REVIEW: 125363
parent f23b9ea9
......@@ -108,6 +108,16 @@ bool ReadOnlyArchiveInterface::doResume()
return false;
}
void ReadOnlyArchiveInterface::setCorrupt(bool isCorrupt)
{
m_isCorrupt = isCorrupt;
}
bool ReadOnlyArchiveInterface::isCorrupt() const
{
return m_isCorrupt;
}
ReadWriteArchiveInterface::ReadWriteArchiveInterface(QObject *parent, const QVariantList & args)
: ReadOnlyArchiveInterface(parent, args)
{
......@@ -135,14 +145,18 @@ bool ReadOnlyArchiveInterface::isHeaderEncryptionEnabled() const
bool ReadWriteArchiveInterface::isReadOnly() const
{
// We set corrupt archives to read-only to avoid add/delete actions, that
// are likely to fail anyway.
if (isCorrupt()) {
return true;
}
QFileInfo fileInfo(filename());
if (fileInfo.exists()) {
return ! fileInfo.isWritable();
return !fileInfo.isWritable();
} else {
return !fileInfo.dir().exists(); // TODO: Should also check if we can create a file in that directory
}
}
} // namespace Kerfuffle
......@@ -117,12 +117,15 @@ protected:
*/
void setWaitForFinishedSignal(bool value);
bool isHeaderEncryptionEnabled() const;
void setCorrupt(bool isCorrupt);
bool isCorrupt() const;
private:
QString m_filename;
QString m_password;
bool m_waitForFinishedSignal;
bool m_isHeaderEncryptionEnabled;
bool m_isCorrupt;
};
class KERFUFFLE_EXPORT ReadWriteArchiveInterface: public ReadOnlyArchiveInterface
......
......@@ -790,6 +790,19 @@ void CliInterface::handleLine(const QString& line)
return;
}
if (checkForErrorMessage(line, CorruptArchivePatterns)) {
qCWarning(KERFUFFLE) << "Archive corrupt";
setCorrupt(true);
Kerfuffle::LoadCorruptQuery query(filename());
emit userQuery(&query);
query.waitForResponse();
if (!query.responseYes()) {
emit cancelled();
failOperation();
return;
}
}
if (handleFileExistsMessage(line)) {
return;
}
......
......@@ -74,6 +74,11 @@ enum CliInterfaceParameters {
* $Archive - the path of the archive
*/
ListArgs,
/**
* QStringList (default empty)
* List of regexp patterns that indicate a corrupt archive.
*/
CorruptArchivePatterns,
///////////////[ EXTRACT ]/////////////
......
......@@ -29,6 +29,7 @@
#include "app/logging.h"
#include <KLocalizedString>
#include <KMessageBox>
#include <KPasswordDialog>
#include <kio/renamedialog.h>
......@@ -200,4 +201,27 @@ bool PasswordNeededQuery::responseCancelled()
{
return !m_data.value(QLatin1String( "response" )).toBool();
}
LoadCorruptQuery::LoadCorruptQuery(const QString& archiveFilename)
{
m_data[QStringLiteral("archiveFilename")] = archiveFilename;
}
void LoadCorruptQuery::execute()
{
qCDebug(KERFUFFLE) << "Executing LoadCorrupt prompt";
QApplication::setOverrideCursor(QCursor(Qt::ArrowCursor));
setResponse(KMessageBox::warningYesNo(Q_NULLPTR,
xi18nc("@info", "Corrupt archive detected. Do you want Ark to attempt "
"loading the archive?<nl/><nl/>Some files may be missing "
"or damaged, and the archive will be opened read-only."),
i18nc("@title:window", "Corrupt archive")));
QApplication::restoreOverrideCursor();
}
bool LoadCorruptQuery::responseYes() {
return (m_data.value(QStringLiteral("response")).toInt() == KMessageBox::Yes);
}
}
......@@ -74,6 +74,10 @@ private:
QMutex m_responseMutex;
};
/* *****************************************************************
* Used to query the user if an existing file should be overwritten.
* *****************************************************************
*/
class KERFUFFLE_EXPORT OverwriteQuery : public Query
{
public:
......@@ -96,6 +100,10 @@ private:
bool m_multiMode;
};
/* **************************************
* Used to query the user for a password.
* **************************************
*/
class KERFUFFLE_EXPORT PasswordNeededQuery : public Query
{
public:
......@@ -106,6 +114,19 @@ public:
QString password();
};
/* *************************************************************
* Used to query the user if a corrupt archive should be loaded.
* *************************************************************
*/
class KERFUFFLE_EXPORT LoadCorruptQuery : public Query
{
public:
explicit LoadCorruptQuery(const QString& archiveFilename);
void execute() Q_DECL_OVERRIDE;
bool responseYes();
};
}
#endif /* ifndef QUERIES_H */
......@@ -94,6 +94,8 @@ ParameterList CliPlugin::parameterList() const
<< QStringLiteral("Q"); //cancel
p[PasswordPromptPattern] = QStringLiteral("Enter password \\(will not be echoed\\) :");
p[CorruptArchivePatterns] = QStringList() << QStringLiteral("Unexpected end of archive")
<< QStringLiteral("Headers Error");
}
return p;
......
......@@ -117,6 +117,8 @@ ParameterList CliPlugin::parameterList() const
p[WrongPasswordPatterns] = QStringList() << QLatin1String("password incorrect") << QLatin1String("wrong password");
p[ExtractionFailedPatterns] = QStringList() << QLatin1String( "CRC failed" )
<< QLatin1String( "Cannot find volume" );
p[CorruptArchivePatterns] = QStringList() << QStringLiteral("Unexpected end of archive")
<< QStringLiteral("the file header is corrupt");
}
return p;
......
......@@ -115,6 +115,7 @@ ParameterList CliPlugin::parameterList() const
p[PasswordPromptPattern] = QStringLiteral(" password: ");
p[WrongPasswordPatterns] = QStringList() << QStringLiteral("incorrect password");
//p[ExtractionFailedPatterns] = QStringList() << "CRC failed";
p[CorruptArchivePatterns] = QStringList() << QStringLiteral("End-of-central-directory signature not found");
}
return p;
}
......
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