diff --git a/kerfuffle/cliinterface.h b/kerfuffle/cliinterface.h --- a/kerfuffle/cliinterface.h +++ b/kerfuffle/cliinterface.h @@ -70,6 +70,12 @@ virtual bool readListLine(const QString &line) = 0; virtual bool readExtractLine(const QString &line) = 0; virtual bool readDeleteLine(const QString &line); + virtual bool isPasswordPrompt(const QString &line); + virtual bool isWrongPasswordMsg(const QString &line); + virtual bool isCorruptArchiveMsg(const QString &line); + virtual bool isDiskFullMsg(const QString &line); + virtual bool isFileExistsMsg(const QString &line); + virtual bool isFileExistsFileName(const QString &line); bool doKill() override; /** diff --git a/kerfuffle/cliinterface.cpp b/kerfuffle/cliinterface.cpp --- a/kerfuffle/cliinterface.cpp +++ b/kerfuffle/cliinterface.cpp @@ -778,13 +778,13 @@ // TODO: The same check methods are called in handleLine(), this // is suboptimal. - bool wrongPasswordMessage = m_cliProps->isWrongPasswordMsg(QLatin1String(lines.last())); + bool wrongPasswordMessage = isWrongPasswordMsg(QLatin1String(lines.last())); bool foundErrorMessage = (wrongPasswordMessage || - m_cliProps->isDiskFullMsg(QLatin1String(lines.last())) || - m_cliProps->isfileExistsMsg(QLatin1String(lines.last()))) || - m_cliProps->isPasswordPrompt(QLatin1String(lines.last())); + isDiskFullMsg(QLatin1String(lines.last())) || + isFileExistsMsg(QLatin1String(lines.last()))) || + isPasswordPrompt(QLatin1String(lines.last())); if (foundErrorMessage) { handleAll = true; @@ -852,7 +852,7 @@ if (m_operationMode == Extract) { - if (m_cliProps->isPasswordPrompt(line)) { + if (isPasswordPrompt(line)) { qCDebug(ARK) << "Found a password prompt"; Kerfuffle::PasswordNeededQuery query(filename()); @@ -871,13 +871,13 @@ return true; } - if (m_cliProps->isDiskFullMsg(line)) { + if (isDiskFullMsg(line)) { qCWarning(ARK) << "Found disk full message:" << line; emit error(i18nc("@info", "Extraction failed because the disk is full.")); return false; } - if (m_cliProps->isWrongPasswordMsg(line)) { + if (isWrongPasswordMsg(line)) { qCWarning(ARK) << "Wrong password!"; setPassword(QString()); emit error(i18nc("@info", "Extraction failed: Incorrect password")); @@ -892,7 +892,7 @@ } if (m_operationMode == List) { - if (m_cliProps->isPasswordPrompt(line)) { + if (isPasswordPrompt(line)) { qCDebug(ARK) << "Found a password prompt"; Kerfuffle::PasswordNeededQuery query(filename()); @@ -911,24 +911,20 @@ return true; } - if (m_cliProps->isWrongPasswordMsg(line)) { + if (isWrongPasswordMsg(line)) { qCWarning(ARK) << "Wrong password!"; setPassword(QString()); emit error(i18n("Incorrect password.")); return false; } - if (m_cliProps->isCorruptArchiveMsg(line)) { + if (isCorruptArchiveMsg(line)) { qCWarning(ARK) << "Archive corrupt"; setCorrupt(true); // Special case: corrupt is not a "fatal" error so we return true here. return true; } - if (handleFileExistsMessage(line)) { - return true; - } - return readListLine(line); } @@ -938,7 +934,7 @@ if (m_operationMode == Test) { - if (m_cliProps->isPasswordPrompt(line)) { + if (isPasswordPrompt(line)) { qCDebug(ARK) << "Found a password prompt"; emit error(i18n("Ark does not currently support testing this archive.")); @@ -964,17 +960,19 @@ bool CliInterface::handleFileExistsMessage(const QString& line) { // Check for a filename and store it. - foreach (const QString &pattern, m_cliProps->property("fileExistsFileName").toStringList()) { - const QRegularExpression rxFileNamePattern(pattern); - const QRegularExpressionMatch rxMatch = rxFileNamePattern.match(line); - - if (rxMatch.hasMatch()) { - m_storedFileName = rxMatch.captured(1); - qCWarning(ARK) << "Detected existing file:" << m_storedFileName; + if (isFileExistsFileName(line)) { + foreach (const QString &pattern, m_cliProps->property("fileExistsFileNameRegExp").toStringList()) { + const QRegularExpression rxFileNamePattern(pattern); + const QRegularExpressionMatch rxMatch = rxFileNamePattern.match(line); + + if (rxMatch.hasMatch()) { + m_storedFileName = rxMatch.captured(1); + qCWarning(ARK) << "Detected existing file:" << m_storedFileName; + } } } - if (!m_cliProps->isfileExistsMsg(line)) { + if (!isFileExistsMsg(line)) { return false; } @@ -1109,4 +1107,40 @@ } } +bool CliInterface::isPasswordPrompt(const QString &line) +{ + Q_UNUSED(line); + return false; +} + +bool CliInterface::isWrongPasswordMsg(const QString &line) +{ + Q_UNUSED(line); + return false; +} + +bool CliInterface::isCorruptArchiveMsg(const QString &line) +{ + Q_UNUSED(line); + return false; +} + +bool CliInterface::isDiskFullMsg(const QString &line) +{ + Q_UNUSED(line); + return false; +} + +bool CliInterface::isFileExistsMsg(const QString &line) +{ + Q_UNUSED(line); + return false; +} + +bool CliInterface::isFileExistsFileName(const QString &line) +{ + Q_UNUSED(line); + return false; +} + } diff --git a/kerfuffle/cliproperties.h b/kerfuffle/cliproperties.h --- a/kerfuffle/cliproperties.h +++ b/kerfuffle/cliproperties.h @@ -62,13 +62,8 @@ Q_PROPERTY(QHash encryptionMethodSwitch MEMBER m_encryptionMethodSwitch) Q_PROPERTY(QString multiVolumeSwitch MEMBER m_multiVolumeSwitch) - Q_PROPERTY(QStringList passwordPromptPatterns MEMBER m_passwordPromptPatterns) - Q_PROPERTY(QStringList wrongPasswordPatterns MEMBER m_wrongPasswordPatterns) Q_PROPERTY(QStringList testPassedPatterns MEMBER m_testPassedPatterns) - Q_PROPERTY(QStringList fileExistsPatterns MEMBER m_fileExistsPatterns) - Q_PROPERTY(QStringList fileExistsFileName MEMBER m_fileExistsFileName) - Q_PROPERTY(QStringList corruptArchivePatterns MEMBER m_corruptArchivePatterns) - Q_PROPERTY(QStringList diskFullPatterns MEMBER m_diskFullPatterns) + Q_PROPERTY(QStringList fileExistsFileNameRegExp MEMBER m_fileExistsFileNameRegExp) Q_PROPERTY(QStringList fileExistsInput MEMBER m_fileExistsInput) Q_PROPERTY(QStringList multiVolumeSuffix MEMBER m_multiVolumeSuffix) @@ -93,13 +88,7 @@ QStringList moveArgs(const QString &archive, const QVector &entries, Archive::Entry *destination, const QString &password); QStringList testArgs(const QString &archive, const QString &password); - bool isPasswordPrompt(const QString &line); - bool isWrongPasswordMsg(const QString &line); bool isTestPassedMsg(const QString &line); - bool isfileExistsMsg(const QString &line); - bool isFileExistsFileName(const QString &line); - bool isCorruptArchiveMsg(const QString &line); - bool isDiskFullMsg(const QString &line); private: QStringList substituteCommentSwitch(const QString &commentfile) const; @@ -132,13 +121,8 @@ QHash m_encryptionMethodSwitch; QString m_multiVolumeSwitch; - QStringList m_passwordPromptPatterns; - QStringList m_wrongPasswordPatterns; QStringList m_testPassedPatterns; - QStringList m_fileExistsPatterns; - QStringList m_fileExistsFileName; - QStringList m_corruptArchivePatterns; - QStringList m_diskFullPatterns; + QStringList m_fileExistsFileNameRegExp; QStringList m_fileExistsInput; QStringList m_multiVolumeSuffix; diff --git a/kerfuffle/cliproperties.cpp b/kerfuffle/cliproperties.cpp --- a/kerfuffle/cliproperties.cpp +++ b/kerfuffle/cliproperties.cpp @@ -290,26 +290,6 @@ return multiVolumeSwitch; } -bool CliProperties::isPasswordPrompt(const QString &line) -{ - foreach(const QString &rx, m_passwordPromptPatterns) { - if (QRegularExpression(rx).match(line).hasMatch()) { - return true; - } - } - return false; -} - -bool CliProperties::isWrongPasswordMsg(const QString &line) -{ - foreach(const QString &rx, m_wrongPasswordPatterns) { - if (QRegularExpression(rx).match(line).hasMatch()) { - return true; - } - } - return false; -} - bool CliProperties::isTestPassedMsg(const QString &line) { foreach(const QString &rx, m_testPassedPatterns) { @@ -320,44 +300,4 @@ return false; } -bool CliProperties::isfileExistsMsg(const QString &line) -{ - foreach(const QString &rx, m_fileExistsPatterns) { - if (QRegularExpression(rx).match(line).hasMatch()) { - return true; - } - } - return false; -} - -bool CliProperties::isFileExistsFileName(const QString &line) -{ - foreach(const QString &rx, m_fileExistsFileName) { - if (QRegularExpression(rx).match(line).hasMatch()) { - return true; - } - } - return false; -} - -bool CliProperties::isCorruptArchiveMsg(const QString &line) -{ - foreach(const QString &rx, m_corruptArchivePatterns) { - if (QRegularExpression(rx).match(line).hasMatch()) { - return true; - } - } - return false; -} - -bool CliProperties::isDiskFullMsg(const QString &line) -{ - foreach(const QString &rx, m_diskFullPatterns) { - if (QRegularExpression(rx).match(line).hasMatch()) { - return true; - } - } - return false; -} - } diff --git a/plugins/cli7zplugin/cliplugin.h b/plugins/cli7zplugin/cliplugin.h --- a/plugins/cli7zplugin/cliplugin.h +++ b/plugins/cli7zplugin/cliplugin.h @@ -39,6 +39,12 @@ bool readListLine(const QString &line) override; bool readExtractLine(const QString &line) override; bool readDeleteLine(const QString &line) override; + bool isPasswordPrompt(const QString &line) override; + bool isWrongPasswordMsg(const QString &line) override; + bool isCorruptArchiveMsg(const QString &line) override; + bool isDiskFullMsg(const QString &line) override; + bool isFileExistsMsg(const QString &line) override; + bool isFileExistsFileName(const QString &line) override; private: enum ArchiveType { diff --git a/plugins/cli7zplugin/cliplugin.cpp b/plugins/cli7zplugin/cliplugin.cpp --- a/plugins/cli7zplugin/cliplugin.cpp +++ b/plugins/cli7zplugin/cliplugin.cpp @@ -95,22 +95,14 @@ m_cliProps->setProperty("encryptionMethodSwitch", QHash{{QStringLiteral("application/x-7z-compressed"), QString()}, {QStringLiteral("application/zip"), QStringLiteral("-mem=$EncryptionMethod")}}); m_cliProps->setProperty("multiVolumeSwitch", QStringLiteral("-v$VolumeSizek")); - - m_cliProps->setProperty("passwordPromptPatterns", QStringList{QStringLiteral("Enter password \\(will not be echoed\\)")}); - m_cliProps->setProperty("wrongPasswordPatterns", QStringList{QStringLiteral("Wrong password")}); m_cliProps->setProperty("testPassedPatterns", QStringList{QStringLiteral("^Everything is Ok$")}); - m_cliProps->setProperty("fileExistsPatterns", QStringList{QStringLiteral("^\\(Y\\)es / \\(N\\)o / \\(A\\)lways / \\(S\\)kip all / A\\(u\\)to rename all / \\(Q\\)uit\\? $"), - QStringLiteral("^\\? \\(Y\\)es / \\(N\\)o / \\(A\\)lways / \\(S\\)kip all / A\\(u\\)to rename all / \\(Q\\)uit\\? $")}); - m_cliProps->setProperty("fileExistsFileName", QStringList{QStringLiteral("^file \\./(.*)$"), - QStringLiteral("^ Path: \\./(.*)$")}); + m_cliProps->setProperty("fileExistsFileNameRegExp", QStringList{QStringLiteral("^file \\./(.*)$"), + QStringLiteral("^ Path: \\./(.*)$")}); m_cliProps->setProperty("fileExistsInput", QStringList{QStringLiteral("Y"), //Overwrite QStringLiteral("N"), //Skip QStringLiteral("A"), //Overwrite all QStringLiteral("S"), //Autoskip QStringLiteral("Q")}); //Cancel - m_cliProps->setProperty("corruptArchivePatterns", QStringList{QStringLiteral("Unexpected end of archive"), - QStringLiteral("Headers Error")}); - m_cliProps->setProperty("diskFullPatterns", QStringList{QStringLiteral("No space left on device")}); m_cliProps->setProperty("multiVolumeSuffix", QStringList{QStringLiteral("$Suffix.001")}); } @@ -355,4 +347,37 @@ } } +bool CliPlugin::isPasswordPrompt(const QString &line) +{ + return line.startsWith(QLatin1String("Enter password (will not be echoed):")); +} + +bool CliPlugin::isWrongPasswordMsg(const QString &line) +{ + return line.contains(QLatin1String("Wrong password")); +} + +bool CliPlugin::isCorruptArchiveMsg(const QString &line) +{ + return (line == QLatin1String("Unexpected end of archive") || + line == QLatin1String("Headers Error")); +} + +bool CliPlugin::isDiskFullMsg(const QString &line) +{ + return line.contains(QLatin1String("No space left on device")); +} + +bool CliPlugin::isFileExistsMsg(const QString &line) +{ + return (line == QLatin1String("(Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? ") || + line == QLatin1String("? (Y)es / (N)o / (A)lways / (S)kip all / A(u)to rename all / (Q)uit? ")); +} + +bool CliPlugin::isFileExistsFileName(const QString &line) +{ + return (line.startsWith(QLatin1String("file ./")) || + line.startsWith(QLatin1String(" Path: ./"))); +} + #include "cliplugin.moc" diff --git a/plugins/clirarplugin/cliplugin.h b/plugins/clirarplugin/cliplugin.h --- a/plugins/clirarplugin/cliplugin.h +++ b/plugins/clirarplugin/cliplugin.h @@ -39,6 +39,12 @@ bool readListLine(const QString &line) override; bool readExtractLine(const QString &line) override; bool hasBatchExtractionProgress() const override; + bool isPasswordPrompt(const QString &line) override; + bool isWrongPasswordMsg(const QString &line) override; + bool isCorruptArchiveMsg(const QString &line) override; + bool isDiskFullMsg(const QString &line) override; + bool isFileExistsMsg(const QString &line) override; + bool isFileExistsFileName(const QString &line) override; private: diff --git a/plugins/clirarplugin/cliplugin.cpp b/plugins/clirarplugin/cliplugin.cpp --- a/plugins/clirarplugin/cliplugin.cpp +++ b/plugins/clirarplugin/cliplugin.cpp @@ -108,21 +108,14 @@ m_cliProps->setProperty("multiVolumeSwitch", QStringLiteral("-v$VolumeSizek")); - m_cliProps->setProperty("passwordPromptPatterns", QStringList{QStringLiteral("Enter password \\(will not be echoed\\) for")}); - m_cliProps->setProperty("wrongPasswordPatterns", QStringList{QStringLiteral("password incorrect"), - QStringLiteral("wrong password")}); m_cliProps->setProperty("testPassedPatterns", QStringList{QStringLiteral("^All OK$")}); - m_cliProps->setProperty("fileExistsPatterns", QStringList{QStringLiteral("^\\[Y\\]es, \\[N\\]o, \\[A\\]ll, n\\[E\\]ver, \\[R\\]ename, \\[Q\\]uit $")}); - m_cliProps->setProperty("fileExistsFileName", QStringList{QStringLiteral("^(.+) already exists. Overwrite it"), // unrar 3 & 4 - QStringLiteral("^Would you like to replace the existing file (.+)$")}); // unrar 5 + m_cliProps->setProperty("fileExistsFileNameRegExp", QStringList{QStringLiteral("^(.+) already exists. Overwrite it"), // unrar 3 & 4 + QStringLiteral("^Would you like to replace the existing file (.+)$")}); // unrar 5 m_cliProps->setProperty("fileExistsInput", QStringList{QStringLiteral("Y"), //Overwrite QStringLiteral("N"), //Skip QStringLiteral("A"), //Overwrite all QStringLiteral("E"), //Autoskip QStringLiteral("Q")}); //Cancel - m_cliProps->setProperty("corruptArchivePatterns", QStringList{QStringLiteral("Unexpected end of archive"), - QStringLiteral("the file header is corrupt")}); - m_cliProps->setProperty("diskFullPatterns", QStringList{QStringLiteral("No space left on device")}); // rar will sometimes create multi-volume archives where first volume is // called name.part1.rar and other times name.part01.rar. @@ -575,4 +568,37 @@ m_parseState = nextState; } +bool CliPlugin::isPasswordPrompt(const QString &line) +{ + return line.startsWith(QLatin1String("Enter password \\(will not be echoed\\) for")); +} + +bool CliPlugin::isWrongPasswordMsg(const QString &line) +{ + return (line.contains(QLatin1String("password incorrect")) || line.contains(QLatin1String("wrong password"))); +} + +bool CliPlugin::isCorruptArchiveMsg(const QString &line) +{ + return (line == QLatin1String("Unexpected end of archive") || + line.contains(QLatin1String("the file header is corrupt")) || + line.endsWith(QLatin1String("checksum error"))); +} + +bool CliPlugin::isDiskFullMsg(const QString &line) +{ + return line.contains(QLatin1String("No space left on device")); +} + +bool CliPlugin::isFileExistsMsg(const QString &line) +{ + return (line == QLatin1String("[Y]es, [N]o, [A]ll, n[E]ver, [R]ename, [Q]uit ")); +} + +bool CliPlugin::isFileExistsFileName(const QString &line) +{ + return (line.startsWith(QLatin1String("Would you like to replace the existing file ")) || // unrar 5 + line.contains(QLatin1String(" already exists. Overwrite it"))); // unrar 3 & 4 +} + #include "cliplugin.moc" diff --git a/plugins/cliunarchiverplugin/cliplugin.h b/plugins/cliunarchiverplugin/cliplugin.h --- a/plugins/cliunarchiverplugin/cliplugin.h +++ b/plugins/cliunarchiverplugin/cliplugin.h @@ -38,6 +38,7 @@ void resetParsing() override; bool readListLine(const QString &line) override; bool readExtractLine(const QString &line) override; + bool isPasswordPrompt(const QString &line) override; /** * Fill the lsar's json output all in once (useful for unit testing). diff --git a/plugins/cliunarchiverplugin/cliplugin.cpp b/plugins/cliunarchiverplugin/cliplugin.cpp --- a/plugins/cliunarchiverplugin/cliplugin.cpp +++ b/plugins/cliunarchiverplugin/cliplugin.cpp @@ -90,8 +90,6 @@ m_cliProps->setProperty("passwordSwitch", QStringList{QStringLiteral("-password"), QStringLiteral("$Password")}); - - m_cliProps->setProperty("passwordPromptPatterns", QStringList{QStringLiteral("This archive requires a password to unpack. Use the -p option to provide one.")}); } bool CliPlugin::readListLine(const QString &line) @@ -152,7 +150,7 @@ if (m_operationMode == List) { // This can only be an header-encrypted archive. - if (m_cliProps->isPasswordPrompt(line)) { + if (isPasswordPrompt(line)) { qCDebug(ARK) << "Detected header-encrypted RAR archive"; Kerfuffle::PasswordNeededQuery query(filename()); @@ -273,4 +271,9 @@ } } +bool CliPlugin::isPasswordPrompt(const QString &line) +{ + return (line == QLatin1String("This archive requires a password to unpack. Use the -p option to provide one.")); +} + #include "cliplugin.moc" diff --git a/plugins/clizipplugin/cliplugin.h b/plugins/clizipplugin/cliplugin.h --- a/plugins/clizipplugin/cliplugin.h +++ b/plugins/clizipplugin/cliplugin.h @@ -38,6 +38,12 @@ QString escapeFileName(const QString &fileName) const override; bool readListLine(const QString &line) override; bool readExtractLine(const QString &line) override; + bool isPasswordPrompt(const QString &line) override; + bool isWrongPasswordMsg(const QString &line) override; + bool isCorruptArchiveMsg(const QString &line) override; + bool isDiskFullMsg(const QString &line) override; + bool isFileExistsMsg(const QString &line) override; + bool isFileExistsFileName(const QString &line) override; bool moveFiles(const QVector &files, Archive::Entry *destination, const CompressionOptions& options) override; int moveRequiredSignals() const override; diff --git a/plugins/clizipplugin/cliplugin.cpp b/plugins/clizipplugin/cliplugin.cpp --- a/plugins/clizipplugin/cliplugin.cpp +++ b/plugins/clizipplugin/cliplugin.cpp @@ -109,20 +109,13 @@ {QStringLiteral("application/x-java-archive"), QStringLiteral("-Z$CompressionMethod")}}); m_cliProps->setProperty("multiVolumeSwitch", QStringLiteral("-v$VolumeSizek")); - m_cliProps->setProperty("passwordPromptPatterns", QStringList{QStringLiteral(" password: ")}); - m_cliProps->setProperty("wrongPasswordPatterns", QStringList{QStringLiteral("incorrect password")}); m_cliProps->setProperty("testPassedPatterns", QStringList{QStringLiteral("^No errors detected in compressed data of ")}); - m_cliProps->setProperty("fileExistsPatterns", QStringList{QStringLiteral("^replace (.+)\\? \\[y\\]es, \\[n\\]o, \\[A\\]ll, \\[N\\]one, \\[r\\]ename: $")}); - m_cliProps->setProperty("fileExistsFileName", QStringList{QStringLiteral("^replace (.+)\\? \\[y\\]es, \\[n\\]o, \\[A\\]ll, \\[N\\]one, \\[r\\]ename: $")}); + m_cliProps->setProperty("fileExistsFileNameRegExp", QStringList{QStringLiteral("^replace (.+)\\? \\[y\\]es, \\[n\\]o, \\[A\\]ll, \\[N\\]one, \\[r\\]ename: $")}); m_cliProps->setProperty("fileExistsInput", QStringList{QStringLiteral("y"), //Overwrite QStringLiteral("n"), //Skip QStringLiteral("A"), //Overwrite all QStringLiteral("N")}); //Autoskip m_cliProps->setProperty("extractionFailedPatterns", QStringList{QStringLiteral("unsupported compression method")}); - m_cliProps->setProperty("corruptArchivePatterns", QStringList{QStringLiteral("End-of-central-directory signature not found"), - QStringLiteral("didn't find end-of-central-dir signature at end of central dir")}); - m_cliProps->setProperty("diskFullPatterns", QStringList{QStringLiteral("write error \\(disk full\\?\\)"), - QStringLiteral("No space left on device")}); } bool CliPlugin::readListLine(const QString &line) @@ -335,4 +328,38 @@ return method; } +bool CliPlugin::isPasswordPrompt(const QString &line) +{ + return line.endsWith(QLatin1String(" password: ")); +} + +bool CliPlugin::isWrongPasswordMsg(const QString &line) +{ + return line.endsWith(QLatin1String("incorrect password")); +} + +bool CliPlugin::isCorruptArchiveMsg(const QString &line) +{ + return (line.contains(QLatin1String("End-of-central-directory signature not found")) || + line.contains(QLatin1String("didn't find end-of-central-dir signature at end of central dir"))); +} + +bool CliPlugin::isDiskFullMsg(const QString &line) +{ + return (line.contains(QLatin1String("No space left on device")) || + line.contains(QLatin1String("write error (disk full?)"))); +} + +bool CliPlugin::isFileExistsMsg(const QString &line) +{ + return (line.startsWith(QLatin1String("replace ")) && + line.endsWith(QLatin1String("? [y]es, [n]o, [A]ll, [N]one, [r]ename: "))); +} + +bool CliPlugin::isFileExistsFileName(const QString &line) +{ + return (line.startsWith(QLatin1String("replace ")) && + line.endsWith(QLatin1String("? [y]es, [n]o, [A]ll, [N]one, [r]ename: "))); +} + #include "cliplugin.moc"