diff --git a/autotests/kerfuffle/jobstest.cpp b/autotests/kerfuffle/jobstest.cpp --- a/autotests/kerfuffle/jobstest.cpp +++ b/autotests/kerfuffle/jobstest.cpp @@ -28,6 +28,8 @@ #include "kerfuffle/jobs.h" #include "kerfuffle/archiveentry.h" +#include + #include #include #include @@ -91,7 +93,8 @@ JSONArchiveInterface *JobsTest::createArchiveInterface(const QString& filePath) { - JSONArchiveInterface *iface = new JSONArchiveInterface(this, {filePath}); + JSONArchiveInterface *iface = new JSONArchiveInterface(this, {filePath, + QVariant().fromValue(KPluginMetaData())}); if (!iface->open()) { qDebug() << "Could not open" << filePath; return Q_NULLPTR; diff --git a/autotests/plugins/cli7zplugin/cli7ztest.cpp b/autotests/plugins/cli7zplugin/cli7ztest.cpp --- a/autotests/plugins/cli7zplugin/cli7ztest.cpp +++ b/autotests/plugins/cli7zplugin/cli7ztest.cpp @@ -164,7 +164,8 @@ void Cli7zTest::testList() { qRegisterMetaType("Archive::Entry*"); - CliPlugin *plugin = new CliPlugin(this, {QStringLiteral("dummy.7z")}); + CliPlugin *plugin = new CliPlugin(this, {QStringLiteral("dummy.7z"), + QVariant::fromValue(m_plugin->metaData())}); QSignalSpy signalSpyEntry(plugin, &CliPlugin::entry); QSignalSpy signalSpyCompMethod(plugin, &CliPlugin::compressionMethodFound); @@ -242,17 +243,18 @@ void Cli7zTest::testListArgs() { + if (!m_plugin->isValid()) { + QSKIP("cli7z plugin not available. Skipping test.", SkipSingle); + } + QFETCH(QString, archiveName); - CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName)}); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); QVERIFY(plugin); - const QStringList listArgs = { QStringLiteral("l"), - QStringLiteral("-slt"), - QStringLiteral("$PasswordSwitch"), - QStringLiteral("$Archive") }; - QFETCH(QString, password); - const auto replacedArgs = plugin->substituteListVariables(listArgs, password); + + const auto replacedArgs = plugin->cliProperties()->listArgs(archiveName, password); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); @@ -275,77 +277,79 @@ << QString() << false << 5 << QStringLiteral("LZMA2") << 0UL << QStringList { QStringLiteral("a"), - QStringLiteral("/tmp/foo.7z"), + QStringLiteral("-l"), QStringLiteral("-mx=5"), - QStringLiteral("-m0=LZMA2") + QStringLiteral("-m0=LZMA2"), + QStringLiteral("/tmp/foo.7z") }; QTest::newRow("encrypted") << QStringLiteral("/tmp/foo.7z") << QStringLiteral("1234") << false << 5 << QStringLiteral("LZMA2") << 0UL << QStringList { QStringLiteral("a"), - QStringLiteral("/tmp/foo.7z"), + QStringLiteral("-l"), QStringLiteral("-p1234"), QStringLiteral("-mx=5"), - QStringLiteral("-m0=LZMA2") + QStringLiteral("-m0=LZMA2"), + QStringLiteral("/tmp/foo.7z") }; QTest::newRow("header-encrypted") << QStringLiteral("/tmp/foo.7z") << QStringLiteral("1234") << true << 5 << QStringLiteral("LZMA2") << 0UL << QStringList { QStringLiteral("a"), - QStringLiteral("/tmp/foo.7z"), + QStringLiteral("-l"), QStringLiteral("-p1234"), QStringLiteral("-mhe=on"), QStringLiteral("-mx=5"), - QStringLiteral("-m0=LZMA2") + QStringLiteral("-m0=LZMA2"), + QStringLiteral("/tmp/foo.7z") }; QTest::newRow("multi-volume") << QStringLiteral("/tmp/foo.7z") << QString() << false << 5 << QStringLiteral("LZMA2") << 2500UL << QStringList { QStringLiteral("a"), - QStringLiteral("/tmp/foo.7z"), + QStringLiteral("-l"), QStringLiteral("-mx=5"), QStringLiteral("-m0=LZMA2"), - QStringLiteral("-v2500k") + QStringLiteral("-v2500k"), + QStringLiteral("/tmp/foo.7z") }; QTest::newRow("comp-method-bzip2") << QStringLiteral("/tmp/foo.7z") << QString() << false << 5 << QStringLiteral("BZip2") << 0UL << QStringList { QStringLiteral("a"), - QStringLiteral("/tmp/foo.7z"), + QStringLiteral("-l"), QStringLiteral("-mx=5"), - QStringLiteral("-m0=BZip2") + QStringLiteral("-m0=BZip2"), + QStringLiteral("/tmp/foo.7z") }; } void Cli7zTest::testAddArgs() { + if (!m_plugin->isValid()) { + QSKIP("cli7z plugin not available. Skipping test.", SkipSingle); + } + QFETCH(QString, archiveName); - CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName)}); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); QVERIFY(plugin); - const QStringList addArgs = { QStringLiteral("a"), - QStringLiteral("$Archive"), - QStringLiteral("$PasswordSwitch"), - QStringLiteral("$CompressionLevelSwitch"), - QStringLiteral("$CompressionMethodSwitch"), - QStringLiteral("$MultiVolumeSwitch"), - QStringLiteral("$Files") }; - QFETCH(QString, password); QFETCH(bool, encryptHeader); QFETCH(int, compressionLevel); QFETCH(ulong, volumeSize); QFETCH(QString, compressionMethod); - QStringList replacedArgs = plugin->substituteAddVariables(addArgs, {}, password, encryptHeader, compressionLevel, volumeSize, compressionMethod); + const auto replacedArgs = plugin->cliProperties()->addArgs(archiveName, {}, password, encryptHeader, compressionLevel, compressionMethod, volumeSize); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); @@ -422,24 +426,29 @@ void Cli7zTest::testExtractArgs() { + if (!m_plugin->isValid()) { + QSKIP("cli7z plugin not available. Skipping test.", SkipSingle); + } + QFETCH(QString, archiveName); - CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName)}); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); QVERIFY(plugin); - const QStringList extractArgs = { QStringLiteral("$PreservePathSwitch"), - QStringLiteral("$PasswordSwitch"), - QStringLiteral("$Archive"), - QStringLiteral("$Files") }; - QFETCH(QVector, files); + QStringList filesList; + foreach (const Archive::Entry *e, files) { + filesList << e->fullPath(NoTrailingSlash); + } + QFETCH(bool, preservePaths); QFETCH(QString, password); - QStringList replacedArgs = plugin->substituteExtractVariables(extractArgs, files, preservePaths, password); - QVERIFY(replacedArgs.size() >= extractArgs.size()); + const auto replacedArgs = plugin->cliProperties()->extractArgs(archiveName, filesList, preservePaths, password); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); plugin->deleteLater(); } + diff --git a/autotests/plugins/clirarplugin/clirartest.cpp b/autotests/plugins/clirarplugin/clirartest.cpp --- a/autotests/plugins/clirarplugin/clirartest.cpp +++ b/autotests/plugins/clirarplugin/clirartest.cpp @@ -204,7 +204,8 @@ void CliRarTest::testList() { qRegisterMetaType("Archive::Entry*"); - CliPlugin *rarPlugin = new CliPlugin(this, {QStringLiteral("dummy.rar")}); + CliPlugin *rarPlugin = new CliPlugin(this, {QStringLiteral("dummy.rar"), + QVariant::fromValue(m_plugin->metaData())}); QSignalSpy signalSpyEntry(rarPlugin, &CliPlugin::entry); QSignalSpy signalSpyCompMethod(rarPlugin, &CliPlugin::compressionMethodFound); QSignalSpy signalSpyError(rarPlugin, &CliPlugin::error); @@ -300,17 +301,17 @@ void CliRarTest::testListArgs() { + if (!m_plugin->isValid()) { + QSKIP("clirar plugin not available. Skipping test.", SkipSingle); + } + QFETCH(QString, archiveName); - CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName)}); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); QVERIFY(plugin); - const QStringList listArgs = { QStringLiteral("vt"), - QStringLiteral("-v"), - QStringLiteral("$PasswordSwitch"), - QStringLiteral("$Archive") }; - QFETCH(QString, password); - const auto replacedArgs = plugin->substituteListVariables(listArgs, password); + const auto replacedArgs = plugin->cliProperties()->listArgs(archiveName, password); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); @@ -333,77 +334,74 @@ << QString() << false << 3 << QStringLiteral("RAR4") << 0UL << QStringList { QStringLiteral("a"), - QStringLiteral("/tmp/foo.rar"), QStringLiteral("-m3"), - QStringLiteral("-ma4") + QStringLiteral("-ma4"), + QStringLiteral("/tmp/foo.rar") }; QTest::newRow("encrypted") << QStringLiteral("/tmp/foo.rar") << QStringLiteral("1234") << false << 3 << QString() << 0UL << QStringList { QStringLiteral("a"), - QStringLiteral("/tmp/foo.rar"), QStringLiteral("-p1234"), - QStringLiteral("-m3") + QStringLiteral("-m3"), + QStringLiteral("/tmp/foo.rar") }; QTest::newRow("header-encrypted") << QStringLiteral("/tmp/foo.rar") << QStringLiteral("1234") << true << 3 << QString() << 0UL << QStringList { QStringLiteral("a"), - QStringLiteral("/tmp/foo.rar"), QStringLiteral("-hp1234"), - QStringLiteral("-m3") + QStringLiteral("-m3"), + QStringLiteral("/tmp/foo.rar") }; QTest::newRow("multi-volume") << QStringLiteral("/tmp/foo.rar") << QString() << false << 3 << QString() << 2500UL << QStringList { QStringLiteral("a"), - QStringLiteral("/tmp/foo.rar"), QStringLiteral("-m3"), - QStringLiteral("-v2500k") + QStringLiteral("-v2500k"), + QStringLiteral("/tmp/foo.rar") }; QTest::newRow("comp-method-RAR5") << QStringLiteral("/tmp/foo.rar") << QString() << false << 3 << QStringLiteral("RAR5") << 0UL << QStringList { QStringLiteral("a"), - QStringLiteral("/tmp/foo.rar"), QStringLiteral("-m3"), - QStringLiteral("-ma5") + QStringLiteral("-ma5"), + QStringLiteral("/tmp/foo.rar") }; } void CliRarTest::testAddArgs() { - QFETCH(QString, archiveName); - CliPlugin *rarPlugin = new CliPlugin(this, {QVariant(archiveName)}); - QVERIFY(rarPlugin); + if (!m_plugin->isValid()) { + QSKIP("clirar plugin not available. Skipping test.", SkipSingle); + } - const QStringList addArgs = { QStringLiteral("a"), - QStringLiteral("$Archive"), - QStringLiteral("$PasswordSwitch"), - QStringLiteral("$CompressionLevelSwitch"), - QStringLiteral("$CompressionMethodSwitch"), - QStringLiteral("$MultiVolumeSwitch"), - QStringLiteral("$Files") }; + QFETCH(QString, archiveName); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); + QVERIFY(plugin); QFETCH(QString, password); QFETCH(bool, encryptHeader); QFETCH(int, compressionLevel); QFETCH(QString, compressionMethod); QFETCH(ulong, volumeSize); - QStringList replacedArgs = rarPlugin->substituteAddVariables(addArgs, {}, password, encryptHeader, compressionLevel, volumeSize, compressionMethod); + const auto replacedArgs = plugin->cliProperties()->addArgs(archiveName, {}, password, encryptHeader, compressionLevel, compressionMethod, volumeSize); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); - rarPlugin->deleteLater(); + plugin->deleteLater(); } void CliRarTest::testExtractArgs_data() @@ -422,9 +420,9 @@ } << true << QStringLiteral("1234") << QStringList { + QStringLiteral("x"), QStringLiteral("-kb"), QStringLiteral("-p-"), - QStringLiteral("x"), QStringLiteral("-p1234"), QStringLiteral("/tmp/foo.rar"), QStringLiteral("aDir/textfile2.txt"), @@ -439,9 +437,9 @@ } << true << QString() << QStringList { + QStringLiteral("x"), QStringLiteral("-kb"), QStringLiteral("-p-"), - QStringLiteral("x"), QStringLiteral("/tmp/foo.rar"), QStringLiteral("aDir/textfile2.txt"), QStringLiteral("c.txt"), @@ -455,9 +453,9 @@ } << false << QStringLiteral("1234") << QStringList { + QStringLiteral("e"), QStringLiteral("-kb"), QStringLiteral("-p-"), - QStringLiteral("e"), QStringLiteral("-p1234"), QStringLiteral("/tmp/foo.rar"), QStringLiteral("aDir/textfile2.txt"), @@ -472,37 +470,39 @@ } << false << QString() << QStringList { + QStringLiteral("e"), QStringLiteral("-kb"), QStringLiteral("-p-"), - QStringLiteral("e"), QStringLiteral("/tmp/foo.rar"), QStringLiteral("aDir/textfile2.txt"), QStringLiteral("c.txt"), }; } void CliRarTest::testExtractArgs() { - QFETCH(QString, archiveName); - CliPlugin *rarPlugin = new CliPlugin(this, {QVariant(archiveName)}); - QVERIFY(rarPlugin); + if (!m_plugin->isValid()) { + QSKIP("clirar plugin not available. Skipping test.", SkipSingle); + } - const QStringList extractArgs = { QStringLiteral("-kb"), - QStringLiteral("-p-"), - QStringLiteral("$PreservePathSwitch"), - QStringLiteral("$PasswordSwitch"), - QStringLiteral("$Archive"), - QStringLiteral("$Files") }; + QFETCH(QString, archiveName); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); + QVERIFY(plugin); QFETCH(QVector, files); + QStringList filesList; + foreach (const Archive::Entry *e, files) { + filesList << e->fullPath(NoTrailingSlash); + } + QFETCH(bool, preservePaths); QFETCH(QString, password); - QStringList replacedArgs = rarPlugin->substituteExtractVariables(extractArgs, files, preservePaths, password); - QVERIFY(replacedArgs.size() >= extractArgs.size()); + const auto replacedArgs = plugin->cliProperties()->extractArgs(archiveName, filesList, preservePaths, password); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); - rarPlugin->deleteLater(); + plugin->deleteLater(); } diff --git a/autotests/plugins/cliunarchiverplugin/cliunarchivertest.cpp b/autotests/plugins/cliunarchiverplugin/cliunarchivertest.cpp --- a/autotests/plugins/cliunarchiverplugin/cliunarchivertest.cpp +++ b/autotests/plugins/cliunarchiverplugin/cliunarchivertest.cpp @@ -141,17 +141,18 @@ void CliUnarchiverTest::testList() { qRegisterMetaType("Archive::Entry*"); - CliPlugin *unarPlugin = new CliPlugin(this, {QStringLiteral("dummy.rar")}); - QSignalSpy signalSpy(unarPlugin, &CliPlugin::entry); + CliPlugin *plugin = new CliPlugin(this, {QStringLiteral("dummy.rar"), + QVariant::fromValue(m_plugin->metaData())}); + QSignalSpy signalSpy(plugin, &CliPlugin::entry); QFETCH(QString, jsonFilePath); QFETCH(int, expectedEntriesCount); QFile jsonFile(jsonFilePath); QVERIFY(jsonFile.open(QIODevice::ReadOnly)); QTextStream stream(&jsonFile); - unarPlugin->setJsonOutput(stream.readAll()); + plugin->setJsonOutput(stream.readAll()); QCOMPARE(signalSpy.count(), expectedEntriesCount); @@ -177,7 +178,7 @@ QFETCH(QString, expectedTimestamp); QCOMPARE(entry->property("timestamp").toString(), expectedTimestamp); - unarPlugin->deleteLater(); + plugin->deleteLater(); } void CliUnarchiverTest::testListArgs_data() @@ -199,24 +200,25 @@ << QStringLiteral("1234") << QStringList { QStringLiteral("-json"), - QStringLiteral("/tmp/foo.rar"), QStringLiteral("-password"), - QStringLiteral("1234") + QStringLiteral("1234"), + QStringLiteral("/tmp/foo.rar") }; } void CliUnarchiverTest::testListArgs() { + if (!m_plugin->isValid()) { + QSKIP("cliunarchiver plugin not available. Skipping test.", SkipSingle); + } + QFETCH(QString, archiveName); - CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName)}); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); QVERIFY(plugin); - const QStringList listArgs = { QStringLiteral("-json"), - QStringLiteral("$Archive"), - QStringLiteral("$PasswordSwitch") }; - QFETCH(QString, password); - const auto replacedArgs = plugin->substituteListVariables(listArgs, password); + const auto replacedArgs = plugin->cliProperties()->listArgs(archiveName, password); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); @@ -352,11 +354,11 @@ << QStringLiteral("1234") << QStringList { QStringLiteral("-D"), + QStringLiteral("-password"), + QStringLiteral("1234"), QStringLiteral("/tmp/foo.rar"), QStringLiteral("aDir/b.txt"), - QStringLiteral("c.txt"), - QStringLiteral("-password"), - QStringLiteral("1234") + QStringLiteral("c.txt") }; QTest::newRow("unencrypted, multiple files") @@ -376,20 +378,24 @@ void CliUnarchiverTest::testExtractArgs() { + if (!m_plugin->isValid()) { + QSKIP("cliunarchiver plugin not available. Skipping test.", SkipSingle); + } + QFETCH(QString, archiveName); - CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName)}); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); QVERIFY(plugin); - const QStringList extractArgs = { QStringLiteral("-D"), - QStringLiteral("$Archive"), - QStringLiteral("$Files"), - QStringLiteral("$PasswordSwitch") }; - QFETCH(QVector, files); + QStringList filesList; + foreach (const Archive::Entry *e, files) { + filesList << e->fullPath(NoTrailingSlash); + } + QFETCH(QString, password); - QStringList replacedArgs = plugin->substituteExtractVariables(extractArgs, files, false, password); - QVERIFY(replacedArgs.size() >= extractArgs.size()); + const auto replacedArgs = plugin->cliProperties()->extractArgs(archiveName, filesList, false, password); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); diff --git a/autotests/plugins/clizipplugin/cliziptest.h b/autotests/plugins/clizipplugin/cliziptest.h --- a/autotests/plugins/clizipplugin/cliziptest.h +++ b/autotests/plugins/clizipplugin/cliziptest.h @@ -29,21 +29,26 @@ #include "cliplugin.h" #include "autotests/testhelper/testhelper.h" #include "kerfuffle/jobs.h" +#include "pluginmanager.h" using namespace Kerfuffle; class CliZipTest : public QObject { Q_OBJECT private Q_SLOTS: - + void initTestCase(); void testListArgs_data(); void testListArgs(); void testAddArgs_data(); void testAddArgs(); void testExtractArgs_data(); void testExtractArgs(); + +private: + PluginManager m_pluginManger; + Plugin *m_plugin; }; #endif diff --git a/autotests/plugins/clizipplugin/cliziptest.cpp b/autotests/plugins/clizipplugin/cliziptest.cpp --- a/autotests/plugins/clizipplugin/cliziptest.cpp +++ b/autotests/plugins/clizipplugin/cliziptest.cpp @@ -30,6 +30,17 @@ using namespace Kerfuffle; +void CliZipTest::initTestCase() +{ + m_plugin = new Plugin(this); + foreach (Plugin *plugin, m_pluginManger.availablePlugins()) { + if (plugin->metaData().pluginId() == QStringLiteral("kerfuffle_clizip")) { + m_plugin = plugin; + return; + } + } +} + void CliZipTest::testListArgs_data() { QTest::addColumn("archiveName"); @@ -47,16 +58,16 @@ void CliZipTest::testListArgs() { + if (!m_plugin->isValid()) { + QSKIP("clizip plugin not available. Skipping test.", SkipSingle); + } + QFETCH(QString, archiveName); - CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName)}); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); QVERIFY(plugin); - const QStringList listArgs = { QStringLiteral("-l"), - QStringLiteral("-T"), - QStringLiteral("-z"), - QStringLiteral("$Archive") }; - - const auto replacedArgs = plugin->substituteListVariables(listArgs, QString()); + const auto replacedArgs = plugin->cliProperties()->listArgs(archiveName, QString()); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); @@ -74,53 +85,51 @@ QTest::newRow("unencrypted") << QStringLiteral("/tmp/foo.zip") - << QString() << 3 << QStringLiteral("deflate") + << QString() << 3 << QStringLiteral("Deflate") << QStringList { QStringLiteral("-r"), - QStringLiteral("/tmp/foo.zip"), QStringLiteral("-3"), - QStringLiteral("-Zdeflate") + QStringLiteral("-Zdeflate"), + QStringLiteral("/tmp/foo.zip") }; QTest::newRow("encrypted") << QStringLiteral("/tmp/foo.zip") << QStringLiteral("1234") << 3 << QString() << QStringList { QStringLiteral("-r"), - QStringLiteral("/tmp/foo.zip"), QStringLiteral("-P1234"), - QStringLiteral("-3") + QStringLiteral("-3"), + QStringLiteral("/tmp/foo.zip") }; QTest::newRow("comp-method-bzip2") << QStringLiteral("/tmp/foo.zip") - << QString() << 3 << QStringLiteral("bzip2") + << QString() << 3 << QStringLiteral("BZip2") << QStringList { QStringLiteral("-r"), - QStringLiteral("/tmp/foo.zip"), QStringLiteral("-3"), - QStringLiteral("-Zbzip2") + QStringLiteral("-Zbzip2"), + QStringLiteral("/tmp/foo.zip") }; } void CliZipTest::testAddArgs() { + if (!m_plugin->isValid()) { + QSKIP("clizip plugin not available. Skipping test.", SkipSingle); + } + QFETCH(QString, archiveName); - CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName)}); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); QVERIFY(plugin); - const QStringList addArgs = { QStringLiteral("-r"), - QStringLiteral("$Archive"), - QStringLiteral("$PasswordSwitch"), - QStringLiteral("$CompressionLevelSwitch"), - QStringLiteral("$CompressionMethodSwitch"), - QStringLiteral("$Files") }; - QFETCH(QString, password); QFETCH(int, compressionLevel); QFETCH(QString, compressionMethod); - QStringList replacedArgs = plugin->substituteAddVariables(addArgs, {}, password, false, compressionLevel, 0, compressionMethod); + const auto replacedArgs = plugin->cliProperties()->addArgs(archiveName, {}, password, false, compressionLevel, compressionMethod, 0); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); @@ -195,20 +204,25 @@ void CliZipTest::testExtractArgs() { + if (!m_plugin->isValid()) { + QSKIP("clizip plugin not available. Skipping test.", SkipSingle); + } + QFETCH(QString, archiveName); - CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName)}); + CliPlugin *plugin = new CliPlugin(this, {QVariant(archiveName), + QVariant::fromValue(m_plugin->metaData())}); QVERIFY(plugin); - const QStringList extractArgs = { QStringLiteral("$PreservePathSwitch"), - QStringLiteral("$PasswordSwitch"), - QStringLiteral("$Archive"), - QStringLiteral("$Files") }; - QFETCH(QVector, files); + QStringList filesList; + foreach (const Archive::Entry *e, files) { + filesList << e->fullPath(NoTrailingSlash); + } + QFETCH(bool, preservePaths); QFETCH(QString, password); - QStringList replacedArgs = plugin->substituteExtractVariables(extractArgs, files, preservePaths, password); + const auto replacedArgs = plugin->cliProperties()->extractArgs(archiveName, filesList, preservePaths, password); QFETCH(QStringList, expectedArgs); QCOMPARE(replacedArgs, expectedArgs); diff --git a/kerfuffle/CMakeLists.txt b/kerfuffle/CMakeLists.txt --- a/kerfuffle/CMakeLists.txt +++ b/kerfuffle/CMakeLists.txt @@ -16,6 +16,7 @@ queries.cpp addtoarchive.cpp cliinterface.cpp + cliproperties.cpp mimetypes.cpp plugin.cpp pluginmanager.cpp diff --git a/kerfuffle/archive_kerfuffle.h b/kerfuffle/archive_kerfuffle.h --- a/kerfuffle/archive_kerfuffle.h +++ b/kerfuffle/archive_kerfuffle.h @@ -242,4 +242,6 @@ } // namespace Kerfuffle +Q_DECLARE_METATYPE(KPluginMetaData) + #endif // ARCHIVE_H diff --git a/kerfuffle/archive_kerfuffle.cpp b/kerfuffle/archive_kerfuffle.cpp --- a/kerfuffle/archive_kerfuffle.cpp +++ b/kerfuffle/archive_kerfuffle.cpp @@ -85,7 +85,8 @@ return new Archive(FailedPlugin, parent); } - const QVariantList args = {QVariant(QFileInfo(fileName).absoluteFilePath())}; + const QVariantList args = {QVariant(QFileInfo(fileName).absoluteFilePath()), + QVariant().fromValue(plugin->metaData())}; ReadOnlyArchiveInterface *iface = factory->create(Q_NULLPTR, args); if (!iface) { qCWarning(ARK) << "Could not create plugin instance" << plugin->metaData().pluginId(); diff --git a/kerfuffle/archiveformat.h b/kerfuffle/archiveformat.h --- a/kerfuffle/archiveformat.h +++ b/kerfuffle/archiveformat.h @@ -45,7 +45,7 @@ bool supportsWriteComment, bool supportsTesting, bool suppportsMultiVolume, - QStringList compressionMethods, + QVariantMap compressionMethods, QString defaultCompressionMethod); /** @@ -69,7 +69,7 @@ bool supportsWriteComment() const; bool supportsTesting() const; bool supportsMultiVolume() const; - QStringList compressionMethods() const; + QVariantMap compressionMethods() const; QString defaultCompressionMethod() const; private: @@ -81,7 +81,7 @@ bool m_supportsWriteComment; bool m_supportsTesting; bool m_supportsMultiVolume; - QStringList m_compressionMethods; + QVariantMap m_compressionMethods; QString m_defaultCompressionMethod; }; diff --git a/kerfuffle/archiveformat.cpp b/kerfuffle/archiveformat.cpp --- a/kerfuffle/archiveformat.cpp +++ b/kerfuffle/archiveformat.cpp @@ -24,6 +24,7 @@ */ #include "archiveformat.h" +#include "ark_debug.h" #include @@ -43,7 +44,7 @@ bool supportsWriteComment, bool supportsTesting, bool supportsMultiVolume, - QStringList compressionMethods, + QVariantMap compressionMethods, QString defaultCompressionMethod) : m_mimeType(mimeType), m_encryptionType(encryptionType), @@ -76,11 +77,7 @@ bool supportsTesting = formatProps[QStringLiteral("SupportsTesting")].toBool(); bool supportsMultiVolume = formatProps[QStringLiteral("SupportsMultiVolume")].toBool(); - QStringList compressionMethods; - QJsonArray array = formatProps[QStringLiteral("CompressionMethods")].toArray(); - foreach (const QJsonValue &value, array) { - compressionMethods.append(value.toString()); - } + QVariantMap compressionMethods = formatProps[QStringLiteral("CompressionMethods")].toObject().toVariantMap(); QString defaultCompMethod = formatProps[QStringLiteral("CompressionMethodDefault")].toString(); Archive::EncryptionType encType = Archive::Unencrypted; @@ -136,7 +133,7 @@ return m_supportsMultiVolume; } -QStringList ArchiveFormat::compressionMethods() const +QVariantMap ArchiveFormat::compressionMethods() const { return m_compressionMethods; } diff --git a/kerfuffle/archiveinterface.h b/kerfuffle/archiveinterface.h --- a/kerfuffle/archiveinterface.h +++ b/kerfuffle/archiveinterface.h @@ -47,7 +47,7 @@ { Q_OBJECT public: - explicit ReadOnlyArchiveInterface(QObject *parent, const QVariantList & args); + explicit ReadOnlyArchiveInterface(QObject *parent, const QVariantList &args); virtual ~ReadOnlyArchiveInterface(); /** @@ -157,6 +157,7 @@ virtual QString multiVolumeName() const; void setMultiVolume(bool value); int numberOfEntries() const; + QMimeType mimetype() const; signals: void cancelled(); @@ -182,9 +183,11 @@ QString m_comment; int m_numberOfVolumes; int m_numberOfEntries; + KPluginMetaData m_metaData; private: QString m_filename; + QMimeType m_mimetype; QString m_password; bool m_waitForFinishedSignal; bool m_isHeaderEncryptionEnabled; @@ -203,7 +206,7 @@ List, Extract, Add, Move, Copy, Delete, Comment, Test }; - explicit ReadWriteArchiveInterface(QObject *parent, const QVariantList & args); + explicit ReadWriteArchiveInterface(QObject *parent, const QVariantList &args); virtual ~ReadWriteArchiveInterface(); bool isReadOnly() const Q_DECL_OVERRIDE; diff --git a/kerfuffle/archiveinterface.cpp b/kerfuffle/archiveinterface.cpp --- a/kerfuffle/archiveinterface.cpp +++ b/kerfuffle/archiveinterface.cpp @@ -28,6 +28,7 @@ #include "archiveinterface.h" #include "ark_debug.h" +#include "mimetypes.h" #include @@ -46,9 +47,13 @@ , m_isCorrupt(false) , m_isMultiVolume(false) { + Q_ASSERT(args.size() >= 2); + qCDebug(ARK) << "Created read-only interface for" << args.first().toString(); m_filename = args.first().toString(); + m_mimetype = determineMimeType(m_filename); connect(this, &ReadOnlyArchiveInterface::entry, this, &ReadOnlyArchiveInterface::onEntry); + m_metaData = args.at(1).value(); } ReadOnlyArchiveInterface::~ReadOnlyArchiveInterface() @@ -144,7 +149,7 @@ return filename(); } -ReadWriteArchiveInterface::ReadWriteArchiveInterface(QObject *parent, const QVariantList & args) +ReadWriteArchiveInterface::ReadWriteArchiveInterface(QObject *parent, const QVariantList &args) : ReadOnlyArchiveInterface(parent, args) { qCDebug(ARK) << "Created read-write interface for" << args.first().toString(); @@ -254,6 +259,11 @@ return m_isHeaderEncryptionEnabled; } +QMimeType ReadOnlyArchiveInterface::mimetype() const +{ + return m_mimetype; +} + bool ReadWriteArchiveInterface::isReadOnly() const { // We set corrupt archives to read-only to avoid add/delete actions, that diff --git a/kerfuffle/cliinterface.h b/kerfuffle/cliinterface.h --- a/kerfuffle/cliinterface.h +++ b/kerfuffle/cliinterface.h @@ -31,6 +31,7 @@ #include "archiveinterface.h" #include "archiveentry.h" +#include "cliproperties.h" #include "kerfuffle_export.h" #include "part/archivemodel.h" @@ -47,252 +48,6 @@ namespace Kerfuffle { -enum CliInterfaceParameters { - - ///////////////[ COMMON ]///////////// - - /** - * Bool (default false) - * Will look for the %-sign in the stdout while working, in the form of - * (2%, 14%, 35%, etc etc), and report progress based upon this - */ - CaptureProgress = 0, - - /** - * QString - * Default: empty - * A regexp pattern that matches the program's password prompt. - */ - PasswordPromptPattern, - - ///////////////[ LIST ]///////////// - - /** - * QStringList - * The names to the program that will handle listing of this - * archive (eg "rar"). Will be searched for in PATH - */ - ListProgram, - /** - * QStringList - * The arguments that are passed to the program above for - * listing the archive. Special strings that will be - * substituted: - * $Archive - the path of the archive - */ - ListArgs, - /** - * QStringList (default empty) - * List of regexp patterns that indicate a corrupt archive. - */ - CorruptArchivePatterns, - - ///////////////[ EXTRACT ]///////////// - - /** - * QStringList - * The names to the program that will handle extracting of this - * archive (eg "rar"). Will be searched for in PATH - */ - ExtractProgram, - /** - * QStringList - * The arguments that are passed to the program above for - * extracting the archive. Special strings that will be - * substituted: - * $Archive - the path of the archive - * $Files - the files selected to be extracted, if any - * $PreservePathSwitch - the flag for extracting with full paths - * $PasswordSwitch - the switch setting the password. Note that this - * will not be inserted unless the listing function has emitted an - * entry with the IsPasswordProtected property set to true. - */ - ExtractArgs, - /** - * Bool (default false) - * When passing directories to the extract program, do not - * include trailing slashes - * e.g. if the user selected "foo/" and "foo/bar" in the gui, the - * paths "foo" and "foo/bar" will be sent to the program. - */ - NoTrailingSlashes, - /** - * QStringList - * This should be a qstringlist with either two elements. The first - * string is what PreservePathSwitch in the ExtractArgs will be replaced - * with if PreservePath is True/enabled. The second is for the disabled - * case. An empty string means that the argument will not be used in - * that case. - * Example: for rar, "x" means extract with full paths, and "e" means - * extract without full paths. in this case we will use the stringlist - * ("x", "e"). Or, for another format that might use the switch - * "--extractFull" for preservePaths, and nothing otherwise: we use the - * stringlist ("--extractFull", "") - */ - PreservePathSwitch, - /** - * QStringList (default empty) - * The format of the root node switch. The variable $Password will be - * substituted for the password string. NOTE: supplying passwords - * through a virtual terminal is not supported (yet?), because this - * is not cross platform compatible. As of KDE 4.3 there are no plans to - * change this. - * Example: ("-p$Password) - * or ("--password", "$Password") - */ - PasswordSwitch, - /** - * QString - * The format of the compression level switch. The variable $CompressionLevel - * will be substituted for the level. - * Example: ("-mx=$CompressionLevel) - */ - CompressionLevelSwitch, - /** - * QStringList - * This is a stringlist with regexps, defining how to recognize the last - * line in a "File already exists" prompt when extracting. - */ - FileExistsExpression, - /** - * QStringList - * This is a stringlist with regexps defining how to recognize the line - * containing the filename in a "File already exists" prompt when - * extracting. It should have one captured string, which is the filename - * of the file/folder that already exists. - */ - FileExistsFileName, - /** - * int - * This sets on what output channel the FileExistsExpression regex - * should be applied on, in other words, on what stream the "file - * exists" output will appear in. Values accepted: - * 0 - Standard error, stderr (default) - * 1 - Standard output, stdout - */ - FileExistsMode, - /** - * QStringList - * The various responses that can be supplied as a response to the - * "file exists" prompt. The various items are to be supplied in the - * following order: - * index 0 - Yes (overwrite) - * index 1 - No (skip/do not overwrite) - * index 2 - All (overwrite all) - * index 3 - Do not overwrite any files (autoskip) - * index 4 - Cancel operation - */ - FileExistsInput, - /** - * QStringList - * Regexp patterns capturing disk is full error messages. - */ - DiskFullPatterns, - - ///////////////[ DELETE ]///////////// - - /** - * QStringList - * The names to the program that will handle deleting of elements in this - * archive format (eg "rar"). Will be searched for in PATH - */ - DeleteProgram, - /** - * QStringList - * The arguments that are passed to the program above for - * deleting from the archive. Special strings that will be - * substituted: - * $Archive - the path of the archive - * $Files - the files selected to be deleted - */ - DeleteArgs, - /** - * QStringList - * Default: empty - * A list of regexp patterns that will cause the extraction to exit - * with a general fail message - */ - ExtractionFailedPatterns, - /** - * QStringList - * Default: empty - * A list of regexp patterns that will alert the user that the password - * was wrong. - */ - WrongPasswordPatterns, - - ///////////////[ ADD ]///////////// - - /** - * QStringList - * The names to the program that will handle adding in this - * archive format (eg "rar"). Will be searched for in PATH - */ - AddProgram, - /** - * QStringList - * The arguments that are passed to the program above for - * adding to the archive. Special strings that will be - * substituted: - * $Archive - the path of the archive - * $Files - the files selected to be added - */ - AddArgs, - - ///////////////[ MOVE ]///////////// - - /** - * QStringList - * The names to the program that will handle adding in this - * archive format (eg "rar"). Will be searched for in PATH - */ - MoveProgram, - /** - * QStringList - * The arguments that are passed to the program above for - * moving inside the archive. Special strings that will be - * substituted: - * $Archive - the path of the archive - * $Files - the files selected to be moved - * $Destinations - new path of each file selected to be moved - */ - MoveArgs, - - ///////////////[ ENCRYPT ]///////////// - - /** - * QStringList (default empty) - * The variable $Password will be - * substituted for the password string used to encrypt the header. - * Example (rar plugin): ("-hp$Password") - */ - PasswordHeaderSwitch, - - ///////////////[ COMMENT ]///////////// - - /** - * QStringList - * The arguments that are passed to AddProgram when adding - * a comment. - */ - CommentArgs, - /** - * QString - * The variable $CommentFile will be substituted for the file - * containing the comment. - * Example (rar plugin): -z$CommentFile - */ - CommentSwitch, - TestProgram, - TestArgs, - TestPassedPattern, - MultiVolumeSwitch, - MultiVolumeSuffix, - CompressionMethodSwitch -}; - -typedef QHash ParameterList; - class KERFUFFLE_EXPORT CliInterface : public ReadWriteArchiveInterface { Q_OBJECT @@ -315,7 +70,6 @@ virtual bool testArchive() Q_DECL_OVERRIDE; virtual void resetParsing() = 0; - virtual ParameterList parameterList() const = 0; virtual bool readListLine(const QString &line) = 0; bool doKill() Q_DECL_OVERRIDE; bool doSuspend() Q_DECL_OVERRIDE; @@ -334,49 +88,20 @@ */ bool moveToDestination(const QDir &tempDir, const QDir &destDir, bool preservePaths); - QStringList substituteListVariables(const QStringList &listArgs, const QString &password); - QStringList substituteExtractVariables(const QStringList &extractArgs, const QVector &entries, bool preservePaths, const QString &password); - QStringList substituteAddVariables(const QStringList &addArgs, const QVector &entries, const QString &password, bool encryptHeader, int compLevel, ulong volumeSize, QString compMethod); - QStringList substituteMoveVariables(const QStringList &moveArgs, const QVector &entriesWithoutChildren, const Archive::Entry *destination, const QString &password); - QStringList substituteDeleteVariables(const QStringList &deleteArgs, const QVector &entries, const QString &password); - QStringList substituteCommentVariables(const QStringList &commentArgs, const QString &commentFile); - QStringList substituteTestVariables(const QStringList &testArgs, const QString &password); - /** * @see ArchiveModel::entryPathsFromDestination */ void setNewMovedFiles(const QVector &entries, const Archive::Entry *destination, int entriesWithoutChildren); /** - * @return The preserve path switch, according to the @p preservePaths extraction option. - */ - QString preservePathSwitch(bool preservePaths) const; - - /** - * @return The password header-switch with the given @p password. - */ - virtual QStringList passwordHeaderSwitch(const QString& password) const; - - /** - * @return The password switch with the given @p password. - */ - QStringList passwordSwitch(const QString& password) const; - - /** - * @return The compression level switch with the given @p level. - */ - QString compressionLevelSwitch(int level) const; - - virtual QString compressionMethodSwitch(const QString &method) const; - QString multiVolumeSwitch(ulong volumeSize) const; - - /** * @return The list of selected files to extract. */ QStringList extractFilesList(const QVector &files) const; QString multiVolumeName() const Q_DECL_OVERRIDE; + CliProperties *cliProperties() const; + protected: bool setAddedFiles(); @@ -388,23 +113,6 @@ */ virtual bool handleLine(const QString& line); - bool checkForErrorMessage(const QString& line, int parameterIndex); - - /** - * Checks whether a line of the program's output is a password prompt. - * - * It uses the regular expression in the @c PasswordPromptPattern parameter - * for the check. - * - * @param line A line of the program's output. - * - * @return @c true if the given @p line is a password prompt, @c false - * otherwise. - */ - bool checkForPasswordPromptMessage(const QString& line); - - virtual void cacheParameterList(); - /** * Run @p programName with the given @p arguments. * @@ -414,7 +122,7 @@ * @return @c true if the program was found and the process was started correctly, * @c false otherwise (in which case finished(false) is emitted). */ - bool runProcess(const QStringList& programNames, const QStringList& arguments); + bool runProcess(const QString& programName, const QStringList& arguments); /** * Kill the running process. The finished signal is emitted according to @p emitFinished. @@ -429,6 +137,7 @@ void cleanUp(); + CliProperties *m_cliProps; QString m_oldWorkingDir; QTemporaryDir *m_tempExtractDir; QTemporaryDir *m_tempAddDir; @@ -438,8 +147,6 @@ Archive::Entry *m_passedDestination; CompressionOptions m_passedOptions; - ParameterList m_param; - #ifdef Q_OS_WIN KProcess *m_process; #else @@ -454,17 +161,6 @@ private: bool handleFileExistsMessage(const QString& filename); - bool checkForTestSuccessMessage(const QString& line); - - /** - * Performs any additional escaping and processing on @p fileName - * before passing it to the underlying process. - * - * The default implementation returns @p fileName unchanged. - * - * @param fileName String to escape. - */ - virtual QString escapeFileName(const QString &fileName) const; /** * Returns a list of path pairs which will be supplied to rn command. @@ -489,6 +185,16 @@ */ bool isEmptyDir(const QDir &dir); + /** + * Performs any additional escaping and processing on @p fileName + * before passing it to the underlying process. + * + * The default implementation returns @p fileName unchanged. + * + * @param fileName String to escape. + */ + virtual QString escapeFileName(const QString &fileName) const; + void cleanUpExtracting(); void finishCopying(bool result); diff --git a/kerfuffle/cliinterface.cpp b/kerfuffle/cliinterface.cpp --- a/kerfuffle/cliinterface.cpp +++ b/kerfuffle/cliinterface.cpp @@ -73,16 +73,7 @@ if (QMetaType::type("QProcess::ExitStatus") == 0) { qRegisterMetaType("QProcess::ExitStatus"); } -} - -void CliInterface::cacheParameterList() -{ - m_param = parameterList(); - Q_ASSERT(m_param.contains(ExtractProgram)); - Q_ASSERT(m_param.contains(ListProgram)); - Q_ASSERT(m_param.contains(PreservePathSwitch)); - Q_ASSERT(m_param.contains(FileExistsExpression)); - Q_ASSERT(m_param.contains(FileExistsInput)); + m_cliProps = new CliProperties(this, m_metaData, mimetype()); } CliInterface::~CliInterface() @@ -104,13 +95,10 @@ bool CliInterface::list() { resetParsing(); - cacheParameterList(); m_operationMode = List; m_numberOfEntries = 0; - const auto args = substituteListVariables(m_param.value(ListArgs).toStringList(), password()); - - if (!runProcess(m_param.value(ListProgram).toStringList(), args)) { + if (!runProcess(m_cliProps->property("listProgram").toString(), m_cliProps->listArgs(filename(), password()))) { return false; } @@ -121,26 +109,20 @@ { qCDebug(ARK) << Q_FUNC_INFO << "to" << destinationDirectory; - cacheParameterList(); m_operationMode = Extract; m_extractionOptions = options; m_extractedFiles = files; m_extractDestDir = destinationDirectory; - const QStringList extractArgs = m_param.value(ExtractArgs).toStringList(); - if (extractArgs.contains(QStringLiteral("$PasswordSwitch")) && options.encryptedArchiveHint() && password().isEmpty()) { + + + if (!m_cliProps->property("passwordSwitch").toString().isEmpty() && options.encryptedArchiveHint() && password().isEmpty()) { qCDebug(ARK) << "Password hint enabled, querying user"; if (!passwordQuery()) { return false; } } - // Populate the argument list. - const QStringList args = substituteExtractVariables(extractArgs, - files, - options.preservePaths(), - password()); - QUrl destDir = QUrl(destinationDirectory); QDir::setCurrent(destDir.adjusted(QUrl::RemoveScheme).url()); @@ -162,7 +144,11 @@ QDir::setCurrent(destDir.adjusted(QUrl::RemoveScheme).url()); } - if (!runProcess(m_param.value(ExtractProgram).toStringList(), args)) { + if (!runProcess(m_cliProps->property("extractProgram").toString(), + m_cliProps->extractArgs(filename(), + extractFilesList(files), + options.preservePaths(), + password()))) { return false; } @@ -173,12 +159,8 @@ { Q_UNUSED(numberOfEntriesToAdd) - cacheParameterList(); - m_operationMode = Add; - const QStringList addArgs = m_param.value(AddArgs).toStringList(); - QVector filesToPass = QVector(); // If destination path is specified, we have recreate its structure inside the temp directory // and then place symlinks of targeted files there. @@ -223,40 +205,38 @@ filesToPass = files; } - if (addArgs.contains(QStringLiteral("$PasswordSwitch")) && options.encryptedArchiveHint() && password().isEmpty()) { + if (!m_cliProps->property("passwordSwitch").toString().isEmpty() && options.encryptedArchiveHint() && password().isEmpty()) { qCDebug(ARK) << "Password hint enabled, querying user"; if (!passwordQuery()) { return false; } } - const auto args = substituteAddVariables(m_param.value(AddArgs).toStringList(), - filesToPass, - password(), - isHeaderEncryptionEnabled(), - options.compressionLevel(), - options.volumeSize(), - options.compressionMethod()); - - return runProcess(m_param.value(AddProgram).toStringList(), args); + return runProcess(m_cliProps->property("addProgram").toString(), + m_cliProps->addArgs(filename(), + entryFullPaths(filesToPass, NoTrailingSlash), + password(), + isHeaderEncryptionEnabled(), + options.compressionLevel(), + options.compressionMethod(), + options.volumeSize())); } bool CliInterface::moveFiles(const QVector &files, Archive::Entry *destination, const CompressionOptions &options) { Q_UNUSED(options); - cacheParameterList(); m_operationMode = Move; m_removedFiles = files; QVector withoutChildren = entriesWithoutChildren(files); setNewMovedFiles(files, destination, withoutChildren.count()); - const auto moveArgs = m_param.value(MoveArgs).toStringList(); - - const auto args = substituteMoveVariables(moveArgs, withoutChildren, destination, password()); - - return runProcess(m_param.value(MoveProgram).toStringList(), args); + return runProcess(m_cliProps->property("moveProgram").toString(), + m_cliProps->moveArgs(filename(), + withoutChildren, + destination, + password())); } bool CliInterface::copyFiles(const QVector &files, Archive::Entry *destination, const CompressionOptions &options) @@ -278,45 +258,29 @@ bool CliInterface::deleteFiles(const QVector &files) { - cacheParameterList(); m_operationMode = Delete; m_removedFiles = files; - const auto deleteArgs = m_param.value(DeleteArgs).toStringList(); - - const auto args = substituteDeleteVariables(deleteArgs, - files, - password()); - - return runProcess(m_param.value(DeleteProgram).toStringList(), args); + return runProcess(m_cliProps->property("deleteProgram").toString(), + m_cliProps->deleteArgs(filename(), files, password())); } bool CliInterface::testArchive() { resetParsing(); - cacheParameterList(); m_operationMode = Test; - const auto args = substituteTestVariables(m_param.value(TestArgs).toStringList(), password()); - - return runProcess(m_param.value(TestProgram).toStringList(), args); + return runProcess(m_cliProps->property("testProgram").toString(), m_cliProps->testArgs(filename(), password())); } -bool CliInterface::runProcess(const QStringList& programNames, const QStringList& arguments) +bool CliInterface::runProcess(const QString& programName, const QStringList& arguments) { Q_ASSERT(!m_process); - QString programPath; - for (int i = 0; i < programNames.count(); i++) { - programPath = QStandardPaths::findExecutable(programNames.at(i)); - if (!programPath.isEmpty()) - break; - } + QString programPath = QStandardPaths::findExecutable(programName); if (programPath.isEmpty()) { - const QString names = programNames.join(QStringLiteral(", ")); - emit error(xi18ncp("@info", "Failed to locate program %2 on disk.", - "Failed to locate programs %2 on disk.", programNames.count(), names)); + emit error(xi18nc("@info", "Failed to locate program %2 on disk.", programName)); emit finished(false); return false; } @@ -685,248 +649,6 @@ return true; } -QStringList CliInterface::substituteListVariables(const QStringList &listArgs, const QString &password) -{ - // Required if we call this function from unit tests. - cacheParameterList(); - - QStringList args; - foreach (const QString& arg, listArgs) { - if (arg == QLatin1String("$Archive")) { - args << filename(); - continue; - } - - if (arg == QLatin1String("$PasswordSwitch")) { - args << passwordSwitch(password); - continue; - } - - // Simple argument (e.g. -slt in 7z), nothing to substitute, just add it to the list. - args << arg; - } - - // Remove empty strings, if any. - args.removeAll(QString()); - - return args; -} - -QStringList CliInterface::substituteExtractVariables(const QStringList &extractArgs, const QVector &entries, bool preservePaths, const QString &password) -{ - // Required if we call this function from unit tests. - cacheParameterList(); - - QStringList args; - foreach (const QString& arg, extractArgs) { - qCDebug(ARK) << "Processing argument" << arg; - - if (arg == QLatin1String("$Archive")) { - args << filename(); - continue; - } - - if (arg == QLatin1String("$PreservePathSwitch")) { - args << preservePathSwitch(preservePaths); - continue; - } - - if (arg == QLatin1String("$PasswordSwitch")) { - args << passwordSwitch(password); - continue; - } - - if (arg == QLatin1String("$Files")) { - args << extractFilesList(entries); - continue; - } - - // Simple argument (e.g. -kb in unrar), nothing to substitute, just add it to the list. - args << arg; - } - - // Remove empty strings, if any. - args.removeAll(QString()); - - return args; -} - -QStringList CliInterface::substituteAddVariables(const QStringList &addArgs, const QVector &entries, const QString &password, bool encryptHeader, int compLevel, ulong volumeSize, QString compMethod) -{ - // Required if we call this function from unit tests. - cacheParameterList(); - - QStringList args; - foreach (const QString& arg, addArgs) { - qCDebug(ARK) << "Processing argument " << arg; - - if (arg == QLatin1String("$Archive")) { - args << filename(); - continue; - } - - if (arg == QLatin1String("$PasswordSwitch")) { - args << (encryptHeader ? passwordHeaderSwitch(password) : passwordSwitch(password)); - continue; - } - - if (arg == QLatin1String("$CompressionLevelSwitch")) { - args << compressionLevelSwitch(compLevel); - continue; - } - - if (arg == QLatin1String("$CompressionMethodSwitch")) { - args << compressionMethodSwitch(compMethod); - continue; - } - - if (arg == QLatin1String("$MultiVolumeSwitch")) { - args << multiVolumeSwitch(volumeSize); - continue; - } - - if (arg == QLatin1String("$Files")) { - args << entryFullPaths(entries, NoTrailingSlash); - continue; - } - - // Simple argument (e.g. a in 7z), nothing to substitute, just add it to the list. - args << arg; - } - - // Remove empty strings, if any. - args.removeAll(QString()); - - return args; -} - -QStringList CliInterface::substituteMoveVariables(const QStringList &moveArgs, const QVector &entriesWithoutChildren, const Archive::Entry *destination, const QString &password) -{ - // Required if we call this function from unit tests. - cacheParameterList(); - - QStringList args; - foreach (const QString& arg, moveArgs) { - qCDebug(ARK) << "Processing argument " << arg; - - if (arg == QLatin1String("$Archive")) { - args << filename(); - continue; - } - - if (arg == QLatin1String("$PasswordSwitch")) { - args << passwordSwitch(password); - continue; - } - - if (arg == QLatin1String("$PathPairs")) { - args << entryPathDestinationPairs(entriesWithoutChildren, destination); - continue; - } - - // Simple argument (e.g. a in 7z), nothing to substitute, just add it to the list. - args << arg; - } - - // Remove empty strings, if any. - args.removeAll(QString()); - - return args; -} - -QStringList CliInterface::substituteDeleteVariables(const QStringList &deleteArgs, const QVector &entries, const QString &password) -{ - cacheParameterList(); - - QStringList args; - foreach (const QString& arg, deleteArgs) { - qCDebug(ARK) << "Processing argument" << arg; - - if (arg == QLatin1String("$Archive")) { - args << filename(); - continue; - } - - if (arg == QLatin1String("$PasswordSwitch")) { - args << passwordSwitch(password); - continue; - } - - if (arg == QLatin1String("$Files")) { - foreach (const Archive::Entry *e, entries) { - args << escapeFileName(e->fullPath(NoTrailingSlash)); - } - continue; - } - - // Simple argument (e.g. d in rar), nothing to substitute, just add it to the list. - args << arg; - } - - // Remove empty strings, if any. - args.removeAll(QString()); - - return args; -} - -QStringList CliInterface::substituteCommentVariables(const QStringList &commentArgs, const QString &commentFile) -{ - // Required if we call this function from unit tests. - cacheParameterList(); - - QStringList args; - foreach (const QString& arg, commentArgs) { - qCDebug(ARK) << "Processing argument " << arg; - - if (arg == QLatin1String("$Archive")) { - args << filename(); - continue; - } - - if (arg == QLatin1String("$CommentSwitch")) { - QString commentSwitch = m_param.value(CommentSwitch).toString(); - commentSwitch.replace(QStringLiteral("$CommentFile"), commentFile); - args << commentSwitch; - continue; - } - - args << arg; - } - - // Remove empty strings, if any. - args.removeAll(QString()); - - return args; -} - -QStringList CliInterface::substituteTestVariables(const QStringList &testArgs, const QString &password) -{ - // Required if we call this function from unit tests. - cacheParameterList(); - - QStringList args; - foreach (const QString& arg, testArgs) { - qCDebug(ARK) << "Processing argument " << arg; - - if (arg == QLatin1String("$Archive")) { - args << filename(); - continue; - } - - if (arg == QLatin1String("$PasswordSwitch")) { - args << passwordSwitch(password); - continue; - } - - args << arg; - } - - // Remove empty strings, if any. - args.removeAll(QString()); - - return args; -} - void CliInterface::setNewMovedFiles(const QVector &entries, const Archive::Entry *destination, int entriesWithoutChildren) { m_newMovedFiles.clear(); @@ -971,104 +693,6 @@ } } -QString CliInterface::preservePathSwitch(bool preservePaths) const -{ - Q_ASSERT(m_param.contains(PreservePathSwitch)); - const QStringList theSwitch = m_param.value(PreservePathSwitch).toStringList(); - Q_ASSERT(theSwitch.size() == 2); - - return (preservePaths ? theSwitch.at(0) : theSwitch.at(1)); -} - -QStringList CliInterface::passwordHeaderSwitch(const QString& password) const -{ - if (password.isEmpty()) { - return QStringList(); - } - - Q_ASSERT(m_param.contains(PasswordHeaderSwitch)); - - QStringList passwordHeaderSwitch = m_param.value(PasswordHeaderSwitch).toStringList(); - Q_ASSERT(!passwordHeaderSwitch.isEmpty() && passwordHeaderSwitch.size() <= 2); - - if (passwordHeaderSwitch.size() == 1) { - passwordHeaderSwitch[0].replace(QLatin1String("$Password"), password); - } else { - passwordHeaderSwitch[1] = password; - } - - return passwordHeaderSwitch; -} - -QStringList CliInterface::passwordSwitch(const QString& password) const -{ - if (password.isEmpty()) { - return QStringList(); - } - - Q_ASSERT(m_param.contains(PasswordSwitch)); - - QStringList passwordSwitch = m_param.value(PasswordSwitch).toStringList(); - Q_ASSERT(!passwordSwitch.isEmpty() && passwordSwitch.size() <= 2); - - if (passwordSwitch.size() == 1) { - passwordSwitch[0].replace(QLatin1String("$Password"), password); - } else { - passwordSwitch[1] = password; - } - - return passwordSwitch; -} - -QString CliInterface::compressionLevelSwitch(int level) const -{ - if (level < 0 || level > 9) { - return QString(); - } - - Q_ASSERT(m_param.contains(CompressionLevelSwitch)); - - QString compLevelSwitch = m_param.value(CompressionLevelSwitch).toString(); - Q_ASSERT(!compLevelSwitch.isEmpty()); - - compLevelSwitch.replace(QLatin1String("$CompressionLevel"), QString::number(level)); - - return compLevelSwitch; -} - -QString CliInterface::compressionMethodSwitch(const QString &method) const -{ - if (method.isEmpty()) { - return QString(); - } - - Q_ASSERT(m_param.contains(CompressionMethodSwitch)); - QString compMethodSwitch = m_param.value(CompressionMethodSwitch).toString(); - Q_ASSERT(!compMethodSwitch.isEmpty()); - - compMethodSwitch.replace(QLatin1String("$CompressionMethod"), method); - - return compMethodSwitch; -} - -QString CliInterface::multiVolumeSwitch(ulong volumeSize) const -{ - // The maximum value we allow in the QDoubleSpinBox is 1000MB. Converted to - // KB this is 1024000. - if (volumeSize <= 0 || volumeSize > 1024000) { - return QString(); - } - - Q_ASSERT(m_param.contains(MultiVolumeSwitch)); - - QString multiVolumeSwitch = m_param.value(MultiVolumeSwitch).toString(); - Q_ASSERT(!multiVolumeSwitch.isEmpty()); - - multiVolumeSwitch.replace(QLatin1String("$VolumeSize"), QString::number(volumeSize)); - - return multiVolumeSwitch; -} - QStringList CliInterface::extractFilesList(const QVector &entries) const { QStringList filesList; @@ -1163,14 +787,14 @@ // TODO: The same check methods are called in handleLine(), this // is suboptimal. - bool wrongPasswordMessage = checkForErrorMessage(QLatin1String( lines.last() ), WrongPasswordPatterns); + bool wrongPasswordMessage = m_cliProps->isWrongPasswordMsg(QLatin1String(lines.last())); bool foundErrorMessage = (wrongPasswordMessage || - checkForErrorMessage(QLatin1String(lines.last()), DiskFullPatterns) || - checkForErrorMessage(QLatin1String(lines.last()), ExtractionFailedPatterns) || - checkForPasswordPromptMessage(QLatin1String(lines.last())) || - checkForErrorMessage(QLatin1String(lines.last()), FileExistsExpression)); + m_cliProps->isDiskFullMsg(QLatin1String(lines.last())) || + m_cliProps->isExtractionFailedMsg(QLatin1String(lines.last())) || + m_cliProps->isfileExistsMsg(QLatin1String(lines.last()))) || + m_cliProps->isPasswordPrompt(QLatin1String(lines.last())); if (foundErrorMessage) { handleAll = true; @@ -1226,7 +850,7 @@ { // TODO: This should be implemented by each plugin; the way progress is // shown by each CLI application is subject to a lot of variation. - if ((m_operationMode == Extract || m_operationMode == Add) && m_param.contains(CaptureProgress) && m_param.value(CaptureProgress).toBool()) { + if ((m_operationMode == Extract || m_operationMode == Add) && m_cliProps->property("captureProgress").toBool()) { //read the percentage int pos = line.indexOf(QLatin1Char( '%' )); if (pos > 1) { @@ -1238,7 +862,7 @@ if (m_operationMode == Extract) { - if (checkForPasswordPromptMessage(line)) { + if (m_cliProps->isPasswordPrompt(line)) { qCDebug(ARK) << "Found a password prompt"; Kerfuffle::PasswordNeededQuery query(filename()); @@ -1258,20 +882,20 @@ return true; } - if (checkForErrorMessage(line, DiskFullPatterns)) { + if (m_cliProps->isDiskFullMsg(line)) { qCWarning(ARK) << "Found disk full message:" << line; emit error(i18nc("@info", "Extraction failed because the disk is full.")); return false; } - if (checkForErrorMessage(line, WrongPasswordPatterns)) { + if (m_cliProps->isWrongPasswordMsg(line)) { qCWarning(ARK) << "Wrong password!"; setPassword(QString()); emit error(i18nc("@info", "Extraction failed: Incorrect password")); return false; } - if (checkForErrorMessage(line, ExtractionFailedPatterns)) { + if (m_cliProps->isExtractionFailedMsg(line)) { qCWarning(ARK) << "Error in extraction:" << line; emit error(i18n("Extraction failed because of an unexpected error.")); return false; @@ -1283,7 +907,7 @@ } if (m_operationMode == List) { - if (checkForPasswordPromptMessage(line)) { + if (m_cliProps->isPasswordPrompt(line)) { qCDebug(ARK) << "Found a password prompt"; Kerfuffle::PasswordNeededQuery query(filename()); @@ -1303,20 +927,20 @@ return true; } - if (checkForErrorMessage(line, WrongPasswordPatterns)) { + if (m_cliProps->isWrongPasswordMsg(line)) { qCWarning(ARK) << "Wrong password!"; setPassword(QString()); emit error(i18n("Incorrect password.")); return false; } - if (checkForErrorMessage(line, ExtractionFailedPatterns)) { + if (m_cliProps->isExtractionFailedMsg(line)) { qCWarning(ARK) << "Error in extraction!!"; emit error(i18n("Extraction failed because of an unexpected error.")); return false; } - if (checkForErrorMessage(line, CorruptArchivePatterns)) { + if (m_cliProps->isCorruptArchiveMsg(line)) { qCWarning(ARK) << "Archive corrupt"; setCorrupt(true); // Special case: corrupt is not a "fatal" error so we return true here. @@ -1332,14 +956,14 @@ if (m_operationMode == Test) { - if (checkForPasswordPromptMessage(line)) { + if (m_cliProps->isPasswordPrompt(line)) { qCDebug(ARK) << "Found a password prompt"; emit error(i18n("Ark does not currently support testing this archive.")); return false; } - if (checkForTestSuccessMessage(line)) { + if (m_cliProps->isTestPassedMsg(line)) { qCDebug(ARK) << "Test successful"; emit testSuccess(); return true; @@ -1349,28 +973,10 @@ return true; } -bool CliInterface::checkForPasswordPromptMessage(const QString& line) -{ - const QString passwordPromptPattern(m_param.value(PasswordPromptPattern).toString()); - - if (passwordPromptPattern.isEmpty()) - return false; - - if (m_passwordPromptPattern.pattern().isEmpty()) { - m_passwordPromptPattern.setPattern(m_param.value(PasswordPromptPattern).toString()); - } - - if (m_passwordPromptPattern.match(line).hasMatch()) { - return true; - } - - return false; -} - bool CliInterface::handleFileExistsMessage(const QString& line) { // Check for a filename and store it. - foreach (const QString &pattern, m_param.value(FileExistsFileName).toStringList()) { + foreach (const QString &pattern, m_cliProps->property("fileExistsFileName").toStringList()) { const QRegularExpression rxFileNamePattern(pattern); const QRegularExpressionMatch rxMatch = rxFileNamePattern.match(line); @@ -1380,7 +986,7 @@ } } - if (!checkForErrorMessage(line, FileExistsExpression)) { + if (!m_cliProps->isfileExistsMsg(line)) { return false; } @@ -1393,7 +999,7 @@ qCDebug(ARK) << "Finished response"; QString responseToProcess; - const QStringList choices = m_param.value(FileExistsInput).toStringList(); + const QStringList choices = m_cliProps->property("fileExistsInput").toStringList(); if (query.responseOverwrite()) { responseToProcess = choices.at(0); @@ -1419,41 +1025,6 @@ return true; } -bool CliInterface::checkForErrorMessage(const QString& line, int parameterIndex) -{ - QList patterns; - - if (m_patternCache.contains(parameterIndex)) { - patterns = m_patternCache.value(parameterIndex); - } else { - if (!m_param.contains(parameterIndex)) { - return false; - } - - foreach(const QString& rawPattern, m_param.value(parameterIndex).toStringList()) { - patterns << QRegularExpression(rawPattern); - } - m_patternCache[parameterIndex] = patterns; - } - - foreach(const QRegularExpression& pattern, patterns) { - if (pattern.match(line).hasMatch()) { - return true; - } - } - return false; -} - -bool CliInterface::checkForTestSuccessMessage(const QString& line) -{ - const QRegularExpression rx(m_param.value(TestPassedPattern).toString()); - const QRegularExpressionMatch rxMatch = rx.match(line); - if (rxMatch.hasMatch()) { - return true; - } - return false; -} - bool CliInterface::doKill() { if (m_process) { @@ -1508,8 +1079,6 @@ bool CliInterface::addComment(const QString &comment) { - cacheParameterList(); - m_operationMode = Comment; m_commentTempFile = new QTemporaryFile; @@ -1523,10 +1092,8 @@ stream << comment << endl; m_commentTempFile->close(); - const auto args = substituteCommentVariables(m_param.value(CommentArgs).toStringList(), - m_commentTempFile->fileName()); - - if (!runProcess(m_param.value(AddProgram).toStringList(), args)) { + if (!runProcess(m_cliProps->property("addProgram").toString(), + m_cliProps->commentArgs(filename(), m_commentTempFile->fileName()))) { return false; } m_comment = comment; @@ -1538,7 +1105,7 @@ QString oldSuffix = QMimeDatabase().suffixForFileName(filename()); QString name; - foreach (const QString &multiSuffix, m_param.value(MultiVolumeSuffix).toStringList()) { + foreach (const QString &multiSuffix, m_cliProps->property("multiVolumeSuffix").toStringList()) { QString newSuffix = multiSuffix; newSuffix.replace(QStringLiteral("$Suffix"), oldSuffix); name = filename().remove(oldSuffix).append(newSuffix); @@ -1549,4 +1116,9 @@ return name; } +CliProperties *CliInterface::cliProperties() const +{ + return m_cliProps; +} + } diff --git a/kerfuffle/cliproperties.h b/kerfuffle/cliproperties.h new file mode 100644 --- /dev/null +++ b/kerfuffle/cliproperties.h @@ -0,0 +1,152 @@ +/* + * ark -- archiver for the KDE project + * + * Copyright (C) 2016 Ragnar Thomsen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef CLIPROPERTIES_H +#define CLIPROPERTIES_H + +#include "archiveinterface.h" +#include "kerfuffle_export.h" + +#include + +namespace Kerfuffle +{ + +class KERFUFFLE_EXPORT CliProperties: public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString addProgram MEMBER m_addProgram) + Q_PROPERTY(QString deleteProgram MEMBER m_deleteProgram) + Q_PROPERTY(QString extractProgram MEMBER m_extractProgram) + Q_PROPERTY(QString listProgram MEMBER m_listProgram) + Q_PROPERTY(QString moveProgram MEMBER m_moveProgram) + Q_PROPERTY(QString testProgram MEMBER m_testProgram) + + Q_PROPERTY(QStringList addSwitch MEMBER m_addSwitch) + Q_PROPERTY(QStringList commentSwitch MEMBER m_commentSwitch) + Q_PROPERTY(QString deleteSwitch MEMBER m_deleteSwitch) + Q_PROPERTY(QStringList extractSwitch MEMBER m_extractSwitch) + Q_PROPERTY(QStringList extractSwitchNoPreserve MEMBER m_extractSwitchNoPreserve) + Q_PROPERTY(QStringList listSwitch MEMBER m_listSwitch) + Q_PROPERTY(QString moveSwitch MEMBER m_moveSwitch) + Q_PROPERTY(QStringList testSwitch MEMBER m_testSwitch) + + Q_PROPERTY(QStringList passwordSwitch MEMBER m_passwordSwitch) + Q_PROPERTY(QStringList passwordSwitchHeaderEnc MEMBER m_passwordSwitchHeaderEnc) + Q_PROPERTY(QString compressionLevelSwitch MEMBER m_compressionLevelSwitch) + Q_PROPERTY(QHash compressionMethodSwitch MEMBER m_compressionMethodSwitch) + 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 extractionFailedPatterns MEMBER m_extractionFailedPatterns) + Q_PROPERTY(QStringList corruptArchivePatterns MEMBER m_corruptArchivePatterns) + Q_PROPERTY(QStringList diskFullPatterns MEMBER m_diskFullPatterns) + + Q_PROPERTY(QStringList fileExistsInput MEMBER m_fileExistsInput) + Q_PROPERTY(QStringList multiVolumeSuffix MEMBER m_multiVolumeSuffix) + + Q_PROPERTY(bool captureProgress MEMBER m_captureProgress) + +public: + explicit CliProperties(QObject *parent, const KPluginMetaData &metaData, const QMimeType &archiveType); + + QStringList addArgs(const QString &archive, + const QStringList &files, + const QString &password, + bool headerEncryption, + int compressionLevel, + const QString &compressionMethod, + uint volumeSize); + QStringList commentArgs(const QString &archive, const QString &commentfile); + QStringList deleteArgs(const QString &archive, const QVector &files, const QString &password); + QStringList extractArgs(const QString &archive, const QStringList &files, bool preservePaths, const QString &password); + QStringList listArgs(const QString &archive, const QString &password); + 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 isExtractionFailedMsg(const QString &line); + bool isCorruptArchiveMsg(const QString &line); + bool isDiskFullMsg(const QString &line); + +private: + QStringList substituteCommentSwitch(const QString &commentfile) const; + QStringList substitutePasswordSwitch(const QString &password, bool headerEnc = false) const; + QString substituteCompressionLevelSwitch(int level) const; + QString substituteCompressionMethodSwitch(const QString &method) const; + QString substituteMultiVolumeSwitch(uint volumeSize) const; + + QString m_addProgram; + QString m_deleteProgram; + QString m_extractProgram; + QString m_listProgram; + QString m_moveProgram; + QString m_testProgram; + + QStringList m_addSwitch; + QStringList m_commentSwitch; + QString m_deleteSwitch; + QStringList m_extractSwitch; + QStringList m_extractSwitchNoPreserve; + QStringList m_listSwitch; + QString m_moveSwitch; + QStringList m_testSwitch; + + QStringList m_passwordSwitch; + QStringList m_passwordSwitchHeaderEnc; + QString m_compressionLevelSwitch; + QHash m_compressionMethodSwitch; + QString m_multiVolumeSwitch; + + QStringList m_passwordPromptPatterns; + QStringList m_wrongPasswordPatterns; + QStringList m_testPassedPatterns; + QStringList m_fileExistsPatterns; + QStringList m_fileExistsFileName; + QStringList m_extractionFailedPatterns; + QStringList m_corruptArchivePatterns; + QStringList m_diskFullPatterns; + + QStringList m_fileExistsInput; + QStringList m_multiVolumeSuffix; + + bool m_captureProgress; + + QMimeType m_mimeType; + KPluginMetaData m_metaData; +}; +} + +#endif /* CLIPROPERTIES_H */ diff --git a/kerfuffle/cliproperties.cpp b/kerfuffle/cliproperties.cpp new file mode 100644 --- /dev/null +++ b/kerfuffle/cliproperties.cpp @@ -0,0 +1,342 @@ +/* + * ark -- archiver for the KDE project + * + * Copyright (C) 2016 Ragnar Thomsen + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ( INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "cliproperties.h" +#include "ark_debug.h" +#include "archiveformat.h" +#include "pluginmanager.h" + +namespace Kerfuffle +{ + +CliProperties::CliProperties(QObject *parent, const KPluginMetaData &metaData, const QMimeType &archiveType) + : QObject(parent) + , m_mimeType(archiveType) + , m_metaData(metaData) +{ +} + +QStringList CliProperties::addArgs(const QString &archive, const QStringList &files, const QString &password, bool headerEncryption, int compressionLevel, const QString &compressionMethod, uint volumeSize) +{ + QStringList args; + foreach (const QString &s, m_addSwitch) { + args << s; + } + if (!password.isEmpty()) { + args << substitutePasswordSwitch(password, headerEncryption); + } + if (compressionLevel > -1) { + args << substituteCompressionLevelSwitch(compressionLevel); + } + if (!compressionMethod.isEmpty()) { + args << substituteCompressionMethodSwitch(compressionMethod); + } + if (volumeSize > 0) { + args << substituteMultiVolumeSwitch(volumeSize); + } + args << archive; + args << files; + + args.removeAll(QString()); + return args; +} + +QStringList CliProperties::commentArgs(const QString &archive, const QString &commentfile) +{ + QStringList args; + foreach (const QString &s, substituteCommentSwitch(commentfile)) { + args << s; + } + args << archive; + + args.removeAll(QString()); + return args; +} + +QStringList CliProperties::deleteArgs(const QString &archive, const QVector &files, const QString &password) +{ + QStringList args; + args << m_deleteSwitch; + if (!password.isEmpty()) { + args << substitutePasswordSwitch(password); + } + args << archive; + foreach (const Archive::Entry *e, files) { + args << e->fullPath(NoTrailingSlash); + } + + args.removeAll(QString()); + return args; +} + +QStringList CliProperties::extractArgs(const QString &archive, const QStringList &files, bool preservePaths, const QString &password) +{ + QStringList args; + + if (preservePaths && !m_extractSwitch.isEmpty()) { + args << m_extractSwitch; + } else if (!preservePaths && !m_extractSwitchNoPreserve.isEmpty()) { + args << m_extractSwitchNoPreserve; + } + + if (!password.isEmpty()) { + args << substitutePasswordSwitch(password); + } + args << archive; + args << files; + + args.removeAll(QString()); + return args; +} + +QStringList CliProperties::listArgs(const QString &archive, const QString &password) +{ + QStringList args; + foreach (const QString &s, m_listSwitch) { + args << s; + } + if (!password.isEmpty()) { + args << substitutePasswordSwitch(password); + } + args << archive; + + args.removeAll(QString()); + return args; +} + +QStringList CliProperties::moveArgs(const QString &archive, const QVector &entries, Archive::Entry *destination, const QString &password) +{ + QStringList args; + args << m_moveSwitch; + if (!password.isEmpty()) { + args << substitutePasswordSwitch(password); + } + args << archive; + if (entries.count() > 1) { + foreach (const Archive::Entry *file, entries) { + args << file->fullPath(NoTrailingSlash) << destination->fullPath() + file->name(); + } + } else { + args << entries.at(0)->fullPath(NoTrailingSlash) << destination->fullPath(NoTrailingSlash); + } + + args.removeAll(QString()); + return args; +} + +QStringList CliProperties::testArgs(const QString &archive, const QString &password) +{ + QStringList args; + foreach (const QString &s, m_testSwitch) { + args << s; + } + if (!password.isEmpty()) { + args << substitutePasswordSwitch(password); + } + args << archive; + + args.removeAll(QString()); + return args; +} + +QStringList CliProperties::substituteCommentSwitch(const QString &commentfile) const +{ + Q_ASSERT(!commentfile.isEmpty()); + + Q_ASSERT(ArchiveFormat::fromMetadata(m_mimeType, m_metaData).supportsWriteComment()); + + QStringList commentSwitches = m_commentSwitch; + Q_ASSERT(!commentSwitches.isEmpty()); + + QMutableListIterator i(commentSwitches); + while (i.hasNext()) { + i.next(); + i.value().replace(QLatin1String("$CommentFile"), commentfile); + } + + return commentSwitches; +} + +QStringList CliProperties::substitutePasswordSwitch(const QString &password, bool headerEnc) const +{ + if (password.isEmpty()) { + return QStringList(); + } + + Archive::EncryptionType encryptionType = ArchiveFormat::fromMetadata(m_mimeType, m_metaData).encryptionType(); + Q_ASSERT(encryptionType != Archive::EncryptionType::Unencrypted); + + QStringList passwordSwitch; + if (headerEnc) { + passwordSwitch = m_passwordSwitchHeaderEnc; + } else { + passwordSwitch = m_passwordSwitch; + } + Q_ASSERT(!passwordSwitch.isEmpty()); + + QMutableListIterator i(passwordSwitch); + while (i.hasNext()) { + i.next(); + i.value().replace(QLatin1String("$Password"), password); + } + + return passwordSwitch; +} + +QString CliProperties::substituteCompressionLevelSwitch(int level) const +{ + if (level < 0 || level > 9) { + return QString(); + } + + Q_ASSERT(ArchiveFormat::fromMetadata(m_mimeType, m_metaData).maxCompressionLevel() != -1); + + QString compLevelSwitch = m_compressionLevelSwitch; + Q_ASSERT(!compLevelSwitch.isEmpty()); + + compLevelSwitch.replace(QLatin1String("$CompressionLevel"), QString::number(level)); + + return compLevelSwitch; +} + +QString CliProperties::substituteCompressionMethodSwitch(const QString &method) const +{ + if (method.isEmpty()) { + return QString(); + } + + Q_ASSERT(!ArchiveFormat::fromMetadata(m_mimeType, m_metaData).compressionMethods().isEmpty()); + + QString compMethodSwitch = m_compressionMethodSwitch[m_mimeType.name()].toString(); + Q_ASSERT(!compMethodSwitch.isEmpty()); + + QString cliMethod = ArchiveFormat::fromMetadata(m_mimeType, m_metaData).compressionMethods().value(method).toString(); + + compMethodSwitch.replace(QLatin1String("$CompressionMethod"), cliMethod); + + return compMethodSwitch; +} + +QString CliProperties::substituteMultiVolumeSwitch(uint volumeSize) const +{ + // The maximum value we allow in the QDoubleSpinBox is 1000MB. Converted to + // KB this is 1024000. + if (volumeSize <= 0 || volumeSize > 1024000) { + return QString(); + } + + Q_ASSERT(ArchiveFormat::fromMetadata(m_mimeType, m_metaData).supportsMultiVolume()); + + QString multiVolumeSwitch = m_multiVolumeSwitch; + Q_ASSERT(!multiVolumeSwitch.isEmpty()); + + multiVolumeSwitch.replace(QLatin1String("$VolumeSize"), QString::number(volumeSize)); + + 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) { + if (QRegularExpression(rx).match(line).hasMatch()) { + return true; + } + } + 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::isExtractionFailedMsg(const QString &line) +{ + foreach(const QString &rx, m_extractionFailedPatterns) { + 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/kerfuffle/compressionoptionswidget.cpp b/kerfuffle/compressionoptionswidget.cpp --- a/kerfuffle/compressionoptionswidget.cpp +++ b/kerfuffle/compressionoptionswidget.cpp @@ -173,7 +173,7 @@ compMethodComboBox->setEnabled(true); compMethodComboBox->setToolTip(QString()); compMethodComboBox->clear(); - compMethodComboBox->insertItems(0, archiveFormat.compressionMethods()); + compMethodComboBox->insertItems(0, archiveFormat.compressionMethods().keys()); if (!m_opts.compressionMethod().isEmpty() && compMethodComboBox->findText(m_opts.compressionMethod()) > -1) { compMethodComboBox->setCurrentText(m_opts.compressionMethod()); diff --git a/plugins/cli7zplugin/cliplugin.h b/plugins/cli7zplugin/cliplugin.h --- a/plugins/cli7zplugin/cliplugin.h +++ b/plugins/cli7zplugin/cliplugin.h @@ -37,15 +37,8 @@ virtual ~CliPlugin(); virtual void resetParsing() Q_DECL_OVERRIDE; - virtual Kerfuffle::ParameterList parameterList() const Q_DECL_OVERRIDE; virtual bool readListLine(const QString &line) Q_DECL_OVERRIDE; - /** - * @return The password header-switch with the given @p password. - */ - virtual QStringList passwordHeaderSwitch(const QString& password) const Q_DECL_OVERRIDE; - virtual QString compressionMethodSwitch(const QString &method) const Q_DECL_OVERRIDE; - private: enum ArchiveType { ArchiveType7z = 0, @@ -65,6 +58,8 @@ ParseStateEntryInformation } m_parseState; + void setupCliProperties(); + int m_linesComment; Kerfuffle::Archive::Entry *m_currentArchiveEntry; bool m_isFirstInformationEntry; diff --git a/plugins/cli7zplugin/cliplugin.cpp b/plugins/cli7zplugin/cliplugin.cpp --- a/plugins/cli7zplugin/cliplugin.cpp +++ b/plugins/cli7zplugin/cliplugin.cpp @@ -44,6 +44,8 @@ , m_isFirstInformationEntry(true) { qCDebug(ARK) << "Loaded cli_7z plugin"; + + setupCliProperties(); } CliPlugin::~CliPlugin() @@ -57,72 +59,60 @@ m_numberOfVolumes = 0; } -ParameterList CliPlugin::parameterList() const +void CliPlugin::setupCliProperties() { - static ParameterList p; - - if (p.isEmpty()) { - //p[CaptureProgress] = true; - p[ListProgram] = p[ExtractProgram] = p[DeleteProgram] = p[MoveProgram] = p[AddProgram] = p[TestProgram] = QStringList() << QStringLiteral("7z"); - p[ListArgs] = QStringList() << QStringLiteral("l") - << QStringLiteral("-slt") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$Archive"); - p[ExtractArgs] = QStringList() << QStringLiteral("$PreservePathSwitch") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$Archive") - << QStringLiteral("$Files"); - p[PreservePathSwitch] = QStringList() << QStringLiteral("x") - << QStringLiteral("e"); - p[PasswordSwitch] = QStringList() << QStringLiteral("-p$Password"); - p[PasswordHeaderSwitch] = QStringList { QStringLiteral("-p$Password"), QStringLiteral("-mhe=on") }; - p[WrongPasswordPatterns] = QStringList() << QStringLiteral("Wrong password"); - p[CompressionLevelSwitch] = QStringLiteral("-mx=$CompressionLevel"); - p[AddArgs] = QStringList() << QStringLiteral("a") - << QStringLiteral("-l") - << QStringLiteral("$Archive") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$CompressionLevelSwitch") - << QStringLiteral("$CompressionMethodSwitch") - << QStringLiteral("$MultiVolumeSwitch") - << QStringLiteral("$Files"); - p[MoveArgs] = QStringList() << QStringLiteral("rn") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$Archive") - << QStringLiteral("$PathPairs"); - p[DeleteArgs] = QStringList() << QStringLiteral("d") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$Archive") - << QStringLiteral("$Files"); - p[TestArgs] = QStringList() << QStringLiteral("t") - << QStringLiteral("$Archive") - << QStringLiteral("$PasswordSwitch"); - p[TestPassedPattern] = QStringLiteral("^Everything is Ok$"); - - p[FileExistsExpression] = 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\\? $"); - p[FileExistsFileName] = QStringList() << QStringLiteral("^file \\./(.*)$") - << QStringLiteral("^ Path: \\./(.*)$"); - p[FileExistsInput] = QStringList() << QStringLiteral("Y") //overwrite - << QStringLiteral("N") //skip - << QStringLiteral("A") //overwrite all - << QStringLiteral("S") //autoskip - << QStringLiteral("Q"); //cancel - p[PasswordPromptPattern] = QStringLiteral("Enter password \\(will not be echoed\\)"); - 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"); - p[MultiVolumeSwitch] = QStringLiteral("-v$VolumeSizek"); - p[MultiVolumeSuffix] = QStringList() << QStringLiteral("$Suffix.001"); - QMap compMethodMap; - compMethodMap[QStringLiteral("zip")] = QStringLiteral("-mm=$CompressionMethod"); - compMethodMap[QStringLiteral("7z")] = QStringLiteral("-m0=$CompressionMethod"); - p[CompressionMethodSwitch] = compMethodMap; - } - - return p; + qCDebug(ARK) << "Setting up parameters..."; + + m_cliProps->setProperty("captureProgress", false); + + m_cliProps->setProperty("addProgram", QStringLiteral("7z")); + m_cliProps->setProperty("addSwitch", QStringList{QStringLiteral("a"), + QStringLiteral("-l")}); + + m_cliProps->setProperty("deleteProgram", QStringLiteral("7z")); + m_cliProps->setProperty("deleteSwitch", QStringLiteral("d")); + + m_cliProps->setProperty("extractProgram", QStringLiteral("7z")); + m_cliProps->setProperty("extractSwitch", QStringList{QStringLiteral("x")}); + m_cliProps->setProperty("extractSwitchNoPreserve", QStringList{QStringLiteral("e")}); + + m_cliProps->setProperty("listProgram", QStringLiteral("7z")); + m_cliProps->setProperty("listSwitch", QStringList{QStringLiteral("l"), + QStringLiteral("-slt")}); + + m_cliProps->setProperty("moveProgram", QStringLiteral("7z")); + m_cliProps->setProperty("moveSwitch", QStringLiteral("rn")); + + m_cliProps->setProperty("testProgram", QStringLiteral("7z")); + m_cliProps->setProperty("testSwitch", QStringLiteral("t")); + + m_cliProps->setProperty("passwordSwitch", QStringList{QStringLiteral("-p$Password")}); + m_cliProps->setProperty("passwordSwitchHeaderEnc", QStringList{QStringLiteral("-p$Password"), + QStringLiteral("-mhe=on")}); + m_cliProps->setProperty("compressionLevelSwitch", QStringLiteral("-mx=$CompressionLevel")); + m_cliProps->setProperty("compressionMethodSwitch", QHash{{QStringLiteral("application/x-7z-compressed"), QStringLiteral("-m0=$CompressionMethod")}, + {QStringLiteral("application/zip"), QStringLiteral("-mm=$CompressionMethod")}}); + 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("fileExistsInput", QStringList{QStringLiteral("Y"), //Overwrite + QStringLiteral("N"), //Skip + QStringLiteral("A"), //Overwrite all + QStringLiteral("S"), //Autoskip + QStringLiteral("Q")}); //Cancel + m_cliProps->setProperty("extractionFailedPatterns", QStringList{QStringLiteral("ERROR: E_FAIL"), + QStringLiteral("Open ERROR: Can not open the file as \\[7z\\] archive")}); + 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")}); } bool CliPlugin::readListLine(const QString& line) @@ -295,40 +285,4 @@ return true; } -QStringList CliPlugin::passwordHeaderSwitch(const QString& password) const -{ - if (password.isEmpty()) { - return QStringList(); - } - - Q_ASSERT(m_param.contains(PasswordHeaderSwitch)); - - QStringList passwordHeaderSwitch = m_param.value(PasswordHeaderSwitch).toStringList(); - Q_ASSERT(!passwordHeaderSwitch.isEmpty() && passwordHeaderSwitch.size() == 2); - - passwordHeaderSwitch[0].replace(QLatin1String("$Password"), password); - - return passwordHeaderSwitch; -} - -QString CliPlugin::compressionMethodSwitch(const QString &method) const -{ - if (method.isEmpty()) { - return QString(); - } - - Q_ASSERT(!filename().isEmpty()); - Q_ASSERT(m_param.contains(CompressionMethodSwitch)); - - QMap switches = m_param.value(CompressionMethodSwitch).toMap(); - Q_ASSERT(!switches.isEmpty()); - - QString compMethodSwitch; - - compMethodSwitch = switches[QFileInfo(filename()).suffix().toLower()].toString(); - compMethodSwitch.replace(QLatin1String("$CompressionMethod"), method); - - return compMethodSwitch; -} - #include "cliplugin.moc" diff --git a/plugins/cli7zplugin/kerfuffle_cli7z.json.cmake b/plugins/cli7zplugin/kerfuffle_cli7z.json.cmake --- a/plugins/cli7zplugin/kerfuffle_cli7z.json.cmake +++ b/plugins/cli7zplugin/kerfuffle_cli7z.json.cmake @@ -12,7 +12,7 @@ "Name[es]": "Complemento de archivo 7zip", "Name[et]": "7zip arhiivi plugin", "Name[fi]": "7zip-pakkaustuki", - "Name[fr]": "Module externe d'archive « 7zip »", + "Name[fr]": "Module externe d'archive « 7zip »", "Name[gl]": "Complemento de arquivo de 7zip", "Name[he]": "תוסף ארכיוני 7zip", "Name[it]": "Estensione per archivi 7zip", @@ -51,14 +51,14 @@ "CompressionLevelMax": 9, "CompressionLevelMin": 0, "CompressionMethodDefault": "LZMA2", - "CompressionMethods": [ - "BZip2", - "Copy", - "Deflate", - "LZMA", - "LZMA2", - "PPMd" - ], + "CompressionMethods": { + "BZip2" : "BZip2", + "Copy" : "Copy", + "Deflate" : "Deflate", + "LZMA" : "LZMA", + "LZMA2" : "LZMA2", + "PPMd" : "PPMd" + }, "HeaderEncryption": true, "SupportsMultiVolume": true, "SupportsTesting": true @@ -68,16 +68,16 @@ "CompressionLevelMax": 9, "CompressionLevelMin": 0, "CompressionMethodDefault": "Deflate", - "CompressionMethods": [ - "BZip2", - "Copy", - "Deflate", - "Deflate64", - "LZMA", - "PPMd" - ], + "CompressionMethods": { + "BZip2" : "BZip2", + "Copy" : "Copy", + "Deflate" : "Deflate", + "Deflate64" : "Deflate64", + "LZMA" : "LZMA", + "PPMd": "PPMd" + }, "Encryption": true, "SupportsMultiVolume": true, "SupportsTesting": true } -} \ No newline at end of file +} diff --git a/plugins/clirarplugin/cliplugin.h b/plugins/clirarplugin/cliplugin.h --- a/plugins/clirarplugin/cliplugin.h +++ b/plugins/clirarplugin/cliplugin.h @@ -36,11 +36,8 @@ virtual ~CliPlugin(); virtual void resetParsing() Q_DECL_OVERRIDE; - virtual Kerfuffle::ParameterList parameterList() const Q_DECL_OVERRIDE; virtual bool readListLine(const QString &line) Q_DECL_OVERRIDE; - virtual QString compressionMethodSwitch(const QString &method) const Q_DECL_OVERRIDE; - private: enum ParseState { @@ -52,6 +49,8 @@ ParseStateLinkTarget } m_parseState; + void setupCliProperties(); + bool handleUnrar5Line(const QString &line); void handleUnrar5Entry(); bool handleUnrar4Line(const QString &line); diff --git a/plugins/clirarplugin/cliplugin.cpp b/plugins/clirarplugin/cliplugin.cpp --- a/plugins/clirarplugin/cliplugin.cpp +++ b/plugins/clirarplugin/cliplugin.cpp @@ -48,6 +48,8 @@ // Empty lines are needed for parsing output of unrar. setListEmptyLines(true); + + setupCliProperties(); } CliPlugin::~CliPlugin() @@ -63,78 +65,70 @@ m_numberOfVolumes = 0; } -ParameterList CliPlugin::parameterList() const +void CliPlugin::setupCliProperties() { - static ParameterList p; - - if (p.isEmpty()) { - p[CaptureProgress] = true; - p[ListProgram] = p[ExtractProgram] = p[TestProgram] = QStringList() << QStringLiteral("unrar"); - p[DeleteProgram] = p[MoveProgram] = p[AddProgram] = QStringList() << QStringLiteral("rar"); - - p[ListArgs] = QStringList() << QStringLiteral("vt") - << QStringLiteral("-v") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$Archive"); - p[ExtractArgs] = QStringList() << QStringLiteral("-kb") - << QStringLiteral("-p-") - << QStringLiteral("$PreservePathSwitch") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$Archive") - << QStringLiteral("$Files"); - p[PreservePathSwitch] = QStringList() << QStringLiteral("x") - << QStringLiteral("e"); - p[PasswordSwitch] = QStringList() << QStringLiteral("-p$Password"); - p[PasswordHeaderSwitch] = QStringList() << QStringLiteral("-hp$Password"); - p[CompressionLevelSwitch] = QStringLiteral("-m$CompressionLevel"); - p[MultiVolumeSwitch] = QStringLiteral("-v$VolumeSizek"); - p[DeleteArgs] = QStringList() << QStringLiteral("d") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$Archive") - << QStringLiteral("$Files"); - p[FileExistsExpression] = QStringList() - << QStringLiteral("^\\[Y\\]es, \\[N\\]o, \\[A\\]ll, n\\[E\\]ver, \\[R\\]ename, \\[Q\\]uit $"); - p[FileExistsFileName] = QStringList() << QStringLiteral("^(.+) already exists. Overwrite it") // unrar 3 & 4 - << QStringLiteral("^Would you like to replace the existing file (.+)$"); // unrar 5 - p[FileExistsInput] = QStringList() << QStringLiteral("Y") //overwrite - << QStringLiteral("N") //skip - << QStringLiteral("A") //overwrite all - << QStringLiteral("E") //autoskip - << QStringLiteral("Q"); //cancel - p[AddArgs] = QStringList() << QStringLiteral("a") - << QStringLiteral("$Archive") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$CompressionLevelSwitch") - << QStringLiteral("$CompressionMethodSwitch") - << QStringLiteral("$MultiVolumeSwitch") - << QStringLiteral("$Files"); - p[MoveArgs] = QStringList() << QStringLiteral("rn") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$Archive") - << QStringLiteral("$PathPairs"); - p[PasswordPromptPattern] = QLatin1String("Enter password \\(will not be echoed\\) for"); - p[WrongPasswordPatterns] = QStringList() << QStringLiteral("password incorrect") << QStringLiteral("wrong password"); - p[ExtractionFailedPatterns] = QStringList() << QStringLiteral("CRC failed") - << QStringLiteral("Cannot find volume"); - p[CorruptArchivePatterns] = QStringList() << QStringLiteral("Unexpected end of archive") - << QStringLiteral("the file header is corrupt"); - p[DiskFullPatterns] = QStringList() << QStringLiteral("No space left on device"); - p[CommentArgs] = QStringList() << QStringLiteral("c") - << QStringLiteral("$CommentSwitch") - << QStringLiteral("$Archive"); - p[CommentSwitch] = QStringLiteral("-z$CommentFile"); - p[TestArgs] = QStringList() << QStringLiteral("t") - << QStringLiteral("$Archive") - << QStringLiteral("$PasswordSwitch"); - p[TestPassedPattern] = QStringLiteral("^All OK$"); - // rar will sometimes create multi-volume archives where first volume is - // called name.part1.rar and other times name.part01.rar. - p[MultiVolumeSuffix] = QStringList() << QStringLiteral("part01.$Suffix") - << QStringLiteral("part1.$Suffix"); - p[CompressionMethodSwitch] = QStringLiteral("-ma$CompressionMethod"); - } - - return p; + qCDebug(ARK) << "Setting up parameters..."; + + m_cliProps->setProperty("captureProgress", true); + + m_cliProps->setProperty("addProgram", QStringLiteral("rar")); + m_cliProps->setProperty("addSwitch", QStringList({QStringLiteral("a")})); + + m_cliProps->setProperty("deleteProgram", QStringLiteral("rar")); + m_cliProps->setProperty("deleteSwitch", QStringLiteral("d")); + + m_cliProps->setProperty("extractProgram", QStringLiteral("unrar")); + m_cliProps->setProperty("extractSwitch", QStringList{QStringLiteral("x"), + QStringLiteral("-kb"), + QStringLiteral("-p-")}); + m_cliProps->setProperty("extractSwitchNoPreserve", QStringList{QStringLiteral("e"), + QStringLiteral("-kb"), + QStringLiteral("-p-")}); + + m_cliProps->setProperty("listProgram", QStringLiteral("unrar")); + m_cliProps->setProperty("listSwitch", QStringList{QStringLiteral("vt"), + QStringLiteral("-v")}); + + m_cliProps->setProperty("moveProgram", QStringLiteral("rar")); + m_cliProps->setProperty("moveSwitch", QStringLiteral("rn")); + + m_cliProps->setProperty("testProgram", QStringLiteral("unrar")); + m_cliProps->setProperty("testSwitch", QStringLiteral("t")); + + m_cliProps->setProperty("commentSwitch", QStringList{QStringLiteral("c"), + QStringLiteral("-z$CommentFile")}); + + m_cliProps->setProperty("passwordSwitch", QStringList{QStringLiteral("-p$Password")}); + m_cliProps->setProperty("passwordSwitchHeaderEnc", QStringList{QStringLiteral("-hp$Password")}); + + m_cliProps->setProperty("compressionLevelSwitch", QStringLiteral("-m$CompressionLevel")); + m_cliProps->setProperty("compressionMethodSwitch", QHash{{QStringLiteral("application/vnd.rar"), QStringLiteral("-ma$CompressionMethod")}, + {QStringLiteral("application/x-rar"), QStringLiteral("-ma$CompressionMethod")}}); + 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("fileExistsInput", QStringList{QStringLiteral("Y"), //Overwrite + QStringLiteral("N"), //Skip + QStringLiteral("A"), //Overwrite all + QStringLiteral("E"), //Autoskip + QStringLiteral("Q")}); //Cancel + m_cliProps->setProperty("extractionFailedPatterns", QStringList{QStringLiteral("CRC failed"), + QStringLiteral("Cannot find volume")}); + 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. + m_cliProps->setProperty("multiVolumeSuffix", QStringList{QStringLiteral("part01.$Suffix"), + QStringLiteral("part1.$Suffix")}); } bool CliPlugin::readListLine(const QString &line) @@ -549,22 +543,4 @@ m_parseState = nextState; } -QString CliPlugin::compressionMethodSwitch(const QString &method) const -{ - if (method.isEmpty()) { - return QString(); - } - - Q_ASSERT(m_param.contains(CompressionMethodSwitch)); - QString compMethodSwitch = m_param.value(CompressionMethodSwitch).toString(); - Q_ASSERT(!compMethodSwitch.isEmpty()); - compMethodSwitch.replace(QLatin1String("$CompressionMethod"), method); - - // This is needed for because the user-visible strings are different from the - // ones needed by the switch (e.g. RAR4 vs 4). - compMethodSwitch.remove(QLatin1String("RAR")); - - return compMethodSwitch; -} - #include "cliplugin.moc" diff --git a/plugins/clirarplugin/kerfuffle_clirar.json.cmake b/plugins/clirarplugin/kerfuffle_clirar.json.cmake --- a/plugins/clirarplugin/kerfuffle_clirar.json.cmake +++ b/plugins/clirarplugin/kerfuffle_clirar.json.cmake @@ -12,7 +12,7 @@ "Name[es]": "Complemento de archivo RAR", "Name[et]": "RAR-arhiivi plugin", "Name[fi]": "RAR-pakkaustuki", - "Name[fr]": "Module externe d'archive « RAR »", + "Name[fr]": "Module externe d'archive « RAR »", "Name[gl]": "Complemento de arquivo RAR", "Name[he]": "תוסף ארכיוני RAR", "Name[it]": "Estensione per archivi RAR", @@ -52,10 +52,10 @@ "CompressionLevelMax": 5, "CompressionLevelMin": 0, "CompressionMethodDefault": "RAR4", - "CompressionMethods": [ - "RAR4", - "RAR5" - ], + "CompressionMethods": { + "RAR4" : "4", + "RAR5" : "5" + }, "HeaderEncryption": true, "SupportsMultiVolume": true, "SupportsTesting": true, @@ -66,13 +66,13 @@ "CompressionLevelMax": 5, "CompressionLevelMin": 0, "CompressionMethodDefault": "RAR4", - "CompressionMethods": [ - "RAR4", - "RAR5" - ], + "CompressionMethods": { + "RAR4" : "4", + "RAR5" : "5" + }, "HeaderEncryption": true, "SupportsMultiVolume": true, "SupportsTesting": true, "SupportsWriteComment": true } -} \ No newline at end of file +} diff --git a/plugins/cliunarchiverplugin/cliplugin.h b/plugins/cliunarchiverplugin/cliplugin.h --- a/plugins/cliunarchiverplugin/cliplugin.h +++ b/plugins/cliunarchiverplugin/cliplugin.h @@ -37,7 +37,6 @@ virtual bool list() Q_DECL_OVERRIDE; virtual bool extractFiles(const QVector &files, const QString &destinationDirectory, const Kerfuffle::ExtractionOptions &options) Q_DECL_OVERRIDE; virtual void resetParsing() Q_DECL_OVERRIDE; - virtual Kerfuffle::ParameterList parameterList() const Q_DECL_OVERRIDE; virtual bool readListLine(const QString &line) Q_DECL_OVERRIDE; /** @@ -50,14 +49,13 @@ protected: - void cacheParameterList() Q_DECL_OVERRIDE; bool handleLine(const QString& line) Q_DECL_OVERRIDE; private slots: void processFinished(int exitCode, QProcess::ExitStatus exitStatus) Q_DECL_OVERRIDE; private: - + void setupCliProperties(); void readJsonOutput(); QString m_jsonOutput; diff --git a/plugins/cliunarchiverplugin/cliplugin.cpp b/plugins/cliunarchiverplugin/cliplugin.cpp --- a/plugins/cliunarchiverplugin/cliplugin.cpp +++ b/plugins/cliunarchiverplugin/cliplugin.cpp @@ -38,6 +38,7 @@ : CliInterface(parent, args) { qCDebug(ARK) << "Loaded cli_unarchiver plugin"; + setupCliProperties(); } CliPlugin::~CliPlugin() @@ -47,11 +48,9 @@ bool CliPlugin::list() { resetParsing(); - cacheParameterList(); m_operationMode = List; - const auto args = substituteListVariables(m_param.value(ListArgs).toStringList(), password()); - return runProcess(m_param.value(ListProgram).toStringList(), args); + return runProcess(m_cliProps->property("listProgram").toString(), m_cliProps->listArgs(filename(), password())); } bool CliPlugin::extractFiles(const QVector &files, const QString &destinationDirectory, const ExtractionOptions &options) @@ -77,36 +76,24 @@ m_numberOfVolumes = 0; } -ParameterList CliPlugin::parameterList() const +void CliPlugin::setupCliProperties() { - static ParameterList p; - if (p.isEmpty()) { + m_cliProps->setProperty("captureProgress", false); - ///////////////[ COMMON ]///////////// + m_cliProps->setProperty("extractProgram", QStringLiteral("unar")); + m_cliProps->setProperty("extractSwitch", QStringList{QStringLiteral("-D")}); + m_cliProps->setProperty("extractSwitchNoPreserve", QStringList{QStringLiteral("-D")}); - p[CaptureProgress] = false; - // Displayed when running lsar -json with header-encrypted archives. - p[PasswordPromptPattern] = QStringLiteral("This archive requires a password to unpack. Use the -p option to provide one."); + m_cliProps->setProperty("listProgram", QStringLiteral("lsar")); + m_cliProps->setProperty("listSwitch", QStringList{QStringLiteral("-json")}); - ///////////////[ LIST ]///////////// + m_cliProps->setProperty("passwordSwitch", QStringList{QStringLiteral("-password"), + QStringLiteral("$Password")}); - p[ListProgram] = QStringLiteral("lsar"); - p[ListArgs] = QStringList() << QStringLiteral("-json") << QStringLiteral("$Archive") << QStringLiteral("$PasswordSwitch"); + m_cliProps->setProperty("passwordPromptPatterns", QStringList{QStringLiteral("This archive requires a password to unpack. Use the -p option to provide one.")}); - ///////////////[ EXTRACT ]///////////// - - p[ExtractProgram] = QStringLiteral("unar"); - p[ExtractArgs] = QStringList() << QStringLiteral("-D") << QStringLiteral("$Archive") << QStringLiteral("$Files") << QStringLiteral("$PasswordSwitch"); - p[NoTrailingSlashes] = true; - p[PasswordSwitch] = QStringList() << QStringLiteral("-password") << QStringLiteral("$Password"); - - ///////////////[ ERRORS ]///////////// - - p[ExtractionFailedPatterns] = QStringList() - << QStringLiteral("Failed! \\((.+)\\)$") - << QStringLiteral("Segmentation fault$"); - } - return p; + m_cliProps->setProperty("extractionFailedPatterns", QStringList{QStringLiteral("Failed! \\((.+)\\)$"), + QStringLiteral("Segmentation fault$")}); } bool CliPlugin::readListLine(const QString &line) @@ -133,13 +120,6 @@ readJsonOutput(); } -void CliPlugin::cacheParameterList() -{ - m_param = parameterList(); - Q_ASSERT(m_param.contains(ExtractProgram)); - Q_ASSERT(m_param.contains(ListProgram)); -} - bool CliPlugin::handleLine(const QString& line) { // Collect the json output line by line. @@ -149,16 +129,16 @@ // TODO: is this check really needed? if (m_operationMode == Copy) { - if (checkForErrorMessage(line, ExtractionFailedPatterns)) { + if (m_cliProps->isExtractionFailedMsg(line)) { qCWarning(ARK) << "Error in extraction:" << line; emit error(i18n("Extraction failed because of an unexpected error.")); return false; } } if (m_operationMode == List) { // This can only be an header-encrypted archive. - if (checkForPasswordPromptMessage(line)) { + if (m_cliProps->isPasswordPrompt(line)) { qCDebug(ARK) << "Detected header-encrypted RAR archive"; Kerfuffle::PasswordNeededQuery query(filename()); diff --git a/plugins/cliunarchiverplugin/kerfuffle_cliunarchiver.json.cmake b/plugins/cliunarchiverplugin/kerfuffle_cliunarchiver.json.cmake --- a/plugins/cliunarchiverplugin/kerfuffle_cliunarchiver.json.cmake +++ b/plugins/cliunarchiverplugin/kerfuffle_cliunarchiver.json.cmake @@ -41,5 +41,11 @@ "unar" ], "X-KDE-Kerfuffle-ReadWrite": false, - "X-KDE-Priority": 100 -} \ No newline at end of file + "X-KDE-Priority": 100, + "application/vnd.rar": { + "HeaderEncryption": true + }, + "application/x-rar": { + "HeaderEncryption": true + } +} diff --git a/plugins/clizipplugin/cliplugin.h b/plugins/clizipplugin/cliplugin.h --- a/plugins/clizipplugin/cliplugin.h +++ b/plugins/clizipplugin/cliplugin.h @@ -38,18 +38,16 @@ virtual void resetParsing() Q_DECL_OVERRIDE; virtual QString escapeFileName(const QString &fileName) const Q_DECL_OVERRIDE; - virtual Kerfuffle::ParameterList parameterList() const Q_DECL_OVERRIDE; virtual bool readListLine(const QString &line) Q_DECL_OVERRIDE; virtual bool moveFiles(const QVector &files, Archive::Entry *destination, const CompressionOptions& options) Q_DECL_OVERRIDE; virtual int moveRequiredSignals() const Q_DECL_OVERRIDE; - virtual QString compressionMethodSwitch(const QString &method) const Q_DECL_OVERRIDE; - private slots: void continueMoving(bool result); private: + void setupCliProperties(); bool setMovingAddedFiles(); void finishMoving(bool result); QString convertCompressionMethod(const QString &method); diff --git a/plugins/clizipplugin/cliplugin.cpp b/plugins/clizipplugin/cliplugin.cpp --- a/plugins/clizipplugin/cliplugin.cpp +++ b/plugins/clizipplugin/cliplugin.cpp @@ -42,6 +42,7 @@ , m_linesComment(0) { qCDebug(ARK) << "Loaded cli_zip plugin"; + setupCliProperties(); } CliPlugin::~CliPlugin() @@ -78,60 +79,49 @@ return quoted; } -ParameterList CliPlugin::parameterList() const +void CliPlugin::setupCliProperties() { - static ParameterList p; - - if (p.isEmpty()) { - p[CaptureProgress] = false; - p[ListProgram] = QStringList() << QStringLiteral("zipinfo"); - p[ExtractProgram] = p[TestProgram] = QStringList() << QStringLiteral("unzip"); - p[DeleteProgram] = p[AddProgram] = QStringList() << QStringLiteral("zip"); - - p[ListArgs] = QStringList() << QStringLiteral("-l") - << QStringLiteral("-T") - << QStringLiteral("-z") - << QStringLiteral("$Archive"); - p[ExtractArgs] = QStringList() << QStringLiteral("$PreservePathSwitch") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$Archive") - << QStringLiteral("$Files"); - p[PreservePathSwitch] = QStringList() << QStringLiteral("") - << QStringLiteral("-j"); - p[PasswordSwitch] = QStringList() << QStringLiteral("-P$Password"); - p[CompressionLevelSwitch] = QStringLiteral("-$CompressionLevel"); - p[DeleteArgs] = QStringList() << QStringLiteral("-d") - << QStringLiteral("$Archive") - << QStringLiteral("$Files"); - - p[FileExistsExpression] = QStringList() - << QStringLiteral("^replace (.+)\\? \\[y\\]es, \\[n\\]o, \\[A\\]ll, \\[N\\]one, \\[r\\]ename: $"); - p[FileExistsFileName] = QStringList() << p[FileExistsExpression].toString(); - p[FileExistsInput] = QStringList() << QStringLiteral("y") //overwrite - << QStringLiteral("n") //skip - << QStringLiteral("A") //overwrite all - << QStringLiteral("N"); //autoskip - - p[AddArgs] = QStringList() << QStringLiteral("-r") - << QStringLiteral("$Archive") - << QStringLiteral("$PasswordSwitch") - << QStringLiteral("$CompressionLevelSwitch") - << QStringLiteral("$CompressionMethodSwitch") - << QStringLiteral("$Files"); - - p[PasswordPromptPattern] = QStringLiteral(" password: "); - p[WrongPasswordPatterns] = QStringList() << QStringLiteral("incorrect password"); - p[ExtractionFailedPatterns] = QStringList() << QStringLiteral("unsupported compression method"); - p[CorruptArchivePatterns] = QStringList() << QStringLiteral("End-of-central-directory signature not found"); - p[DiskFullPatterns] = QStringList() << QStringLiteral("write error \\(disk full\\?\\)") - << QStringLiteral("No space left on device"); - p[TestArgs] = QStringList() << QStringLiteral("-t") - << QStringLiteral("$Archive") - << QStringLiteral("$PasswordSwitch"); - p[TestPassedPattern] = QStringLiteral("^No errors detected in compressed data of "); - p[CompressionMethodSwitch] = QStringLiteral("-Z$CompressionMethod"); - } - return p; + qCDebug(ARK) << "Setting up parameters..."; + + m_cliProps->setProperty("captureProgress", false); + + m_cliProps->setProperty("addProgram", QStringLiteral("zip")); + m_cliProps->setProperty("addSwitch", QStringList({QStringLiteral("-r")})); + + m_cliProps->setProperty("deleteProgram", QStringLiteral("zip")); + m_cliProps->setProperty("deleteSwitch", QStringLiteral("-d")); + + m_cliProps->setProperty("extractProgram", QStringLiteral("unzip")); + m_cliProps->setProperty("extractSwitchNoPreserve", QStringList{QStringLiteral("-j")}); + + m_cliProps->setProperty("listProgram", QStringLiteral("zipinfo")); + m_cliProps->setProperty("listSwitch", QStringList{QStringLiteral("-l"), + QStringLiteral("-T"), + QStringLiteral("-z")}); + + m_cliProps->setProperty("testProgram", QStringLiteral("unzip")); + m_cliProps->setProperty("testSwitch", QStringLiteral("-t")); + + m_cliProps->setProperty("passwordSwitch", QStringList{QStringLiteral("-P$Password")}); + + m_cliProps->setProperty("compressionLevelSwitch", QStringLiteral("-$CompressionLevel")); + m_cliProps->setProperty("compressionMethodSwitch", QHash{{QStringLiteral("application/zip"), QStringLiteral("-Z$CompressionMethod")}, + {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("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")}); + m_cliProps->setProperty("diskFullPatterns", QStringList{QStringLiteral("write error \\(disk full\\?\\)"), + QStringLiteral("No space left on device")}); } bool CliPlugin::readListLine(const QString &line) @@ -297,22 +287,6 @@ cleanUp(); } -QString CliPlugin::compressionMethodSwitch(const QString &method) const -{ - if (method.isEmpty()) { - return QString(); - } - - Q_ASSERT(m_param.contains(CompressionMethodSwitch)); - QString compMethodSwitch = m_param.value(CompressionMethodSwitch).toString(); - Q_ASSERT(!compMethodSwitch.isEmpty()); - - // We use capitalization of methods in UI, but CLI requires lowercase. - compMethodSwitch.replace(QLatin1String("$CompressionMethod"), method.toLower()); - - return compMethodSwitch; -} - QString CliPlugin::convertCompressionMethod(const QString &method) { if (method == QLatin1String("stor")) { diff --git a/plugins/clizipplugin/kerfuffle_clizip.json.cmake b/plugins/clizipplugin/kerfuffle_clizip.json.cmake --- a/plugins/clizipplugin/kerfuffle_clizip.json.cmake +++ b/plugins/clizipplugin/kerfuffle_clizip.json.cmake @@ -12,7 +12,7 @@ "Name[es]": "Complemento de archivo ZIP", "Name[et]": "ZIP-arhiivi plugin", "Name[fi]": "ZIP-pakkaustuki", - "Name[fr]": "Module externe d'archive « zip »", + "Name[fr]": "Module externe d'archive « zip »", "Name[gl]": "Complemento de arquivo ZIP", "Name[he]": "תוסף ארכיוני ZIP", "Name[it]": "Estensione per archivi ZIP", @@ -58,13 +58,13 @@ "CompressionLevelDefault": 6, "CompressionLevelMax": 9, "CompressionLevelMin": 0, - "CompressionMethodDefault": "deflate", - "CompressionMethods": [ - "BZip2", - "Deflate", - "Store" - ], + "CompressionMethodDefault": "Deflate", + "CompressionMethods": { + "BZip2" : "bzip2", + "Deflate" : "deflate", + "Store" : "store" + }, "Encryption": true, "SupportsTesting": true } -} \ No newline at end of file +}