diff --git a/plugins/cliunarchiverplugin/cliplugin.cpp b/plugins/cliunarchiverplugin/cliplugin.cpp index e542c5ef..4a8ab874 100644 --- a/plugins/cliunarchiverplugin/cliplugin.cpp +++ b/plugins/cliunarchiverplugin/cliplugin.cpp @@ -1,213 +1,213 @@ /* * ark -- archiver for the KDE project * * Copyright (C) 2011 Luke Shumaker * Copyright (C) 2016 Elvis Angelaccio * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "cliplugin.h" #include #include #include #include using namespace Kerfuffle; K_PLUGIN_FACTORY_WITH_JSON(CliPluginFactory, "kerfuffle_cliunarchiver.json", registerPlugin();) CliPlugin::CliPlugin(QObject *parent, const QVariantList &args) : CliInterface(parent, args) { qCDebug(ARK) << "Loaded cli_unarchiver plugin"; } CliPlugin::~CliPlugin() { } bool CliPlugin::list() { resetParsing(); cacheParameterList(); m_operationMode = List; const auto args = substituteListVariables(m_param.value(ListArgs).toStringList(), password()); if (!runProcess(m_param.value(ListProgram).toStringList(), args)) { return false; } if (!password().isEmpty()) { // lsar -json exits with error code 1 if the archive is header-encrypted and the password is wrong. if (m_exitCode == 1) { qCWarning(ARK) << "Wrong password, list() aborted"; emit error(i18n("Wrong password.")); emit finished(false); killProcess(); setPassword(QString()); return false; } // lsar -json exits with error code 2 if the archive is header-encrypted and no password is given as argument. // At this point we have already asked a password to the user, so we can just list() again. if (m_exitCode == 2) { return CliPlugin::list(); } } return true; } bool CliPlugin::copyFiles(const QList &files, const QString &destinationDirectory, const ExtractionOptions &options) { ExtractionOptions newOptions = options; // unar has the following limitations: // 1. creates an empty file upon entering a wrong password. // 2. detects that the stdout has been redirected and blocks the stdin. // This prevents Ark from executing unar's overwrite queries. // To prevent both, we always extract to a temporary directory // and then we move the files to the intended destination. qCDebug(ARK) << "Enabling extraction to temporary directory."; newOptions[QStringLiteral("AlwaysUseTmpDir")] = true; return CliInterface::copyFiles(files, destinationDirectory, newOptions); } void CliPlugin::resetParsing() { m_jsonOutput.clear(); } ParameterList CliPlugin::parameterList() const { static ParameterList p; if (p.isEmpty()) { ///////////////[ COMMON ]///////////// 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."); ///////////////[ LIST ]///////////// p[ListProgram] = QStringLiteral("lsar"); p[ListArgs] = QStringList() << QStringLiteral("-json") << QStringLiteral("$Archive") << QStringLiteral("$PasswordSwitch"); ///////////////[ 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; } bool CliPlugin::readListLine(const QString &line) { Q_UNUSED(line) return true; } void CliPlugin::setJsonOutput(const QString &jsonOutput) { m_jsonOutput = jsonOutput; readJsonOutput(); } void CliPlugin::readStdout(bool handleAll) { if (!handleAll) { CliInterface::readStdout(false); return; } // We are ready to read the json output. readJsonOutput(); } void CliPlugin::cacheParameterList() { m_param = parameterList(); Q_ASSERT(m_param.contains(ExtractProgram)); Q_ASSERT(m_param.contains(ListProgram)); } void CliPlugin::handleLine(const QString& line) { // Collect the json output line by line. if (m_operationMode == List) { m_jsonOutput += line + QLatin1Char('\n'); } CliInterface::handleLine(line); } void CliPlugin::readJsonOutput() { QJsonParseError error; QJsonDocument jsonDoc = QJsonDocument::fromJson(m_jsonOutput.toUtf8(), &error); if (error.error != QJsonParseError::NoError) { qCDebug(ARK) << "Could not parse json output:" << error.errorString(); return; } const QJsonObject json = jsonDoc.object(); const QJsonArray entries = json.value(QStringLiteral("lsarContents")).toArray(); foreach (const QJsonValue& value, entries) { - const QJsonObject currentEntry = value.toObject(); + const QJsonObject currentEntryJson = value.toObject(); - m_currentEntry->clearMetaData(); + Archive::Entry *currentEntry = new Archive::Entry(this); - QString filename = currentEntry.value(QStringLiteral("XADFileName")).toString(); + QString filename = currentEntryJson.value(QStringLiteral("XADFileName")).toString(); - m_currentEntry->setProperty("isDirectory", !currentEntry.value(QStringLiteral("XADIsDirectory")).isUndefined()); - if (m_currentEntry->isDir()) { + currentEntry->setProperty("isDirectory", !currentEntryJson.value(QStringLiteral("XADIsDirectory")).isUndefined()); + if (currentEntry->isDir()) { filename += QLatin1Char('/'); } - m_currentEntry->setProperty("fullPath", filename); + currentEntry->setProperty("fullPath", filename); // FIXME: archives created from OSX (i.e. with the __MACOSX folder) list each entry twice, the 2nd time with size 0 - m_currentEntry->setProperty("size", currentEntry.value(QStringLiteral("XADFileSize"))); - m_currentEntry->setProperty("compressedSize", currentEntry.value(QStringLiteral("XADCompressedSize"))); - m_currentEntry->setProperty("timestamp", currentEntry.value(QStringLiteral("XADLastModificationDate")).toVariant()); - m_currentEntry->setProperty("size", currentEntry.value(QStringLiteral("XADFileSize"))); - m_currentEntry->setProperty("isPasswordProtected", (currentEntry.value(QStringLiteral("XADIsEncrypted")).toInt() == 1)); + currentEntry->setProperty("size", currentEntryJson.value(QStringLiteral("XADFileSize"))); + currentEntry->setProperty("compressedSize", currentEntryJson.value(QStringLiteral("XADCompressedSize"))); + currentEntry->setProperty("timestamp", currentEntryJson.value(QStringLiteral("XADLastModificationDate")).toVariant()); + currentEntry->setProperty("size", currentEntryJson.value(QStringLiteral("XADFileSize"))); + currentEntry->setProperty("isPasswordProtected", (currentEntryJson.value(QStringLiteral("XADIsEncrypted")).toInt() == 1)); // TODO: missing fields - emit entry(m_currentEntry); + emit entry(currentEntry); } } #include "cliplugin.moc" diff --git a/plugins/cliunarchiverplugin/cliplugin.h b/plugins/cliunarchiverplugin/cliplugin.h index 2a9c49ce..03587710 100644 --- a/plugins/cliunarchiverplugin/cliplugin.h +++ b/plugins/cliunarchiverplugin/cliplugin.h @@ -1,64 +1,63 @@ /* * ark -- archiver for the KDE project * * Copyright (C) 2011 Luke Shumaker * Copyright (C) 2016 Elvis Angelaccio * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #ifndef CLIPLUGIN_H #define CLIPLUGIN_H #include "kerfuffle/archiveentry.h" #include "kerfuffle/cliinterface.h" class CliPlugin : public Kerfuffle::CliInterface { Q_OBJECT public: explicit CliPlugin(QObject *parent, const QVariantList &args); virtual ~CliPlugin(); virtual bool list() Q_DECL_OVERRIDE; virtual bool copyFiles(const QList &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; /** * Fill the lsar's json output all in once (useful for unit testing). */ void setJsonOutput(const QString &jsonOutput); protected slots: void readStdout(bool handleAll = false) Q_DECL_OVERRIDE; protected: void cacheParameterList() Q_DECL_OVERRIDE; void handleLine(const QString& line) Q_DECL_OVERRIDE; private: void readJsonOutput(); - Kerfuffle::Archive::Entry *m_currentEntry; QString m_jsonOutput; }; #endif // CLIPLUGIN_H