|
Rex Dieter |
d7d5b6 |
diff --git a/plugins/cliunarchiverplugin/kerfuffle_cliunarchiver.desktop b/plugins/cliunarchiverplugin/kerfuffle_cliunarchiver.desktop
|
|
Rex Dieter |
d7d5b6 |
new file mode 100644
|
|
Rex Dieter |
d7d5b6 |
index 0000000..2b5bd9e
|
|
Rex Dieter |
d7d5b6 |
--- /dev/null
|
|
Rex Dieter |
d7d5b6 |
+++ b/plugins/cliunarchiverplugin/kerfuffle_cliunarchiver.desktop
|
|
Rex Dieter |
d7d5b6 |
@@ -0,0 +1,15 @@
|
|
Rex Dieter |
d7d5b6 |
+[Desktop Entry]
|
|
Rex Dieter |
d7d5b6 |
+Type=Service
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-ServiceTypes=Kerfuffle/Plugin
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-Library=kerfuffle_cliunarchiver
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-PluginInfo-Author=Luke Shumaker
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-PluginInfo-Email=lukeshu@sbcglobal.net
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-PluginInfo-Name= kerfuffle_cliunarchiver
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-PluginInfo-Version=0.0.1
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-PluginInfo-Website=http://www.kde.org
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-PluginInfo-License=GPLv2+
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-Priority=150
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-Kerfuffle-APIRevision=1
|
|
Rex Dieter |
d7d5b6 |
+X-KDE-Kerfuffle-ReadWrite=false
|
|
Rex Dieter |
d7d5b6 |
+Name=The Unarchiver plugin
|
|
Rex Dieter |
d7d5b6 |
+MimeType=application/x-rar;
|
|
Rex Dieter |
d7d5b6 |
diff --git a/plugins/cliunarchiverplugin/cliplugin.cpp b/plugins/cliunarchiverplugin/cliplugin.cpp
|
|
Rex Dieter |
d7d5b6 |
new file mode 100644
|
|
Rex Dieter |
d7d5b6 |
index 0000000..e0adcf7
|
|
Rex Dieter |
d7d5b6 |
--- /dev/null
|
|
Rex Dieter |
d7d5b6 |
+++ b/plugins/cliunarchiverplugin/cliplugin.cpp
|
|
Rex Dieter |
d7d5b6 |
@@ -0,0 +1,170 @@
|
|
Rex Dieter |
d7d5b6 |
+ /*
|
|
Rex Dieter |
d7d5b6 |
+ * ark -- archiver for the KDE project
|
|
Rex Dieter |
d7d5b6 |
+ *
|
|
Rex Dieter |
d7d5b6 |
+ * Copyright (C) 2011 Luke Shumaker <lukeshu@sbcglobal.net>
|
|
Rex Dieter |
d7d5b6 |
+ *
|
|
Rex Dieter |
d7d5b6 |
+ * This program is free software; you can redistribute it and/or
|
|
Rex Dieter |
d7d5b6 |
+ * modify it under the terms of the GNU General Public License
|
|
Rex Dieter |
d7d5b6 |
+ * as published by the Free Software Foundation; either version 2
|
|
Rex Dieter |
d7d5b6 |
+ * of the License, or (at your option) any later version.
|
|
Rex Dieter |
d7d5b6 |
+ *
|
|
Rex Dieter |
d7d5b6 |
+ * This program is distributed in the hope that it will be useful,
|
|
Rex Dieter |
d7d5b6 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Rex Dieter |
d7d5b6 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Rex Dieter |
d7d5b6 |
+ * GNU General Public License for more details.
|
|
Rex Dieter |
d7d5b6 |
+ *
|
|
Rex Dieter |
d7d5b6 |
+ * You should have received a copy of the GNU General Public License
|
|
Rex Dieter |
d7d5b6 |
+ * along with this program; if not, write to the Free Software
|
|
Rex Dieter |
d7d5b6 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
Rex Dieter |
d7d5b6 |
+ *
|
|
Rex Dieter |
d7d5b6 |
+ */
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+#include "kerfuffle/cliinterface.h"
|
|
Rex Dieter |
d7d5b6 |
+#include "kerfuffle/kerfuffle_export.h"
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+#include <KDebug>
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+#include <QDateTime>
|
|
Rex Dieter |
d7d5b6 |
+#include <QDir>
|
|
Rex Dieter |
d7d5b6 |
+#include <QRegExp>
|
|
Rex Dieter |
d7d5b6 |
+#include <QString>
|
|
Rex Dieter |
d7d5b6 |
+#include <QStringList>
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+using namespace Kerfuffle;
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+class CliPlugin: public CliInterface
|
|
Rex Dieter |
d7d5b6 |
+{
|
|
Rex Dieter |
d7d5b6 |
+public:
|
|
Rex Dieter |
d7d5b6 |
+ explicit CliPlugin(QObject *parent, const QVariantList & args)
|
|
Rex Dieter |
d7d5b6 |
+ : CliInterface(parent, args) {
|
|
Rex Dieter |
d7d5b6 |
+ m_indentLevel = 0;
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ virtual ~CliPlugin() {
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ virtual ParameterList parameterList() const {
|
|
Rex Dieter |
d7d5b6 |
+ static ParameterList p;
|
|
Rex Dieter |
d7d5b6 |
+ if (p.isEmpty()) {
|
|
Rex Dieter |
d7d5b6 |
+ /* Limitations:
|
|
Rex Dieter |
d7d5b6 |
+ * 01 - creates an empty file upon entering wrong password
|
|
Rex Dieter |
d7d5b6 |
+ * 02 - unar detects if output is being redirected and then does not accept any input
|
|
Rex Dieter |
d7d5b6 |
+ */
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ ///////////////[ COMMON ]/////////////
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ p[CaptureProgress] = false;
|
|
Rex Dieter |
d7d5b6 |
+ p[PasswordPromptPattern] = QLatin1String("Password (will not be shown): ");
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ ///////////////[ LIST ]/////////////
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ p[ListProgram] = QLatin1String("lsar");
|
|
Rex Dieter |
d7d5b6 |
+ p[ListArgs] = QStringList() << QLatin1String("-json") << QLatin1String("$Archive");
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ ///////////////[ EXTRACT ]/////////////
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ p[ExtractProgram] = QLatin1String("unar");
|
|
Rex Dieter |
d7d5b6 |
+ p[ExtractArgs] = QStringList() << QLatin1String("$Archive") << QLatin1String("$Files") << QLatin1String("$PasswordSwitch") << QLatin1String("$RootNodeSwitch");
|
|
Rex Dieter |
d7d5b6 |
+ p[NoTrailingSlashes] = true;
|
|
Rex Dieter |
d7d5b6 |
+ p[PasswordSwitch] = QStringList() << QLatin1String("-password") << QLatin1String("$Password");
|
|
Rex Dieter |
d7d5b6 |
+ p[RootNodeSwitch] = QStringList() << QLatin1String("-output-directory") << QLatin1String("$Path");
|
|
Rex Dieter |
d7d5b6 |
+ p[FileExistsExpression] = QLatin1String("^\\\"(.+)\\\" already exists.");
|
|
Rex Dieter |
d7d5b6 |
+ p[FileExistsInput] = QStringList()
|
|
Rex Dieter |
d7d5b6 |
+ << QLatin1String("o") //overwrite
|
|
Rex Dieter |
d7d5b6 |
+ << QLatin1String("s") //skip
|
|
Rex Dieter |
d7d5b6 |
+ << QLatin1String("O") //overwrite all
|
|
Rex Dieter |
d7d5b6 |
+ << QLatin1String("S") //autoskip
|
|
Rex Dieter |
d7d5b6 |
+ << QLatin1String("q") //cancel
|
|
Rex Dieter |
d7d5b6 |
+ ;
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ ///////////////[ DELETE ]/////////////
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ p[DeleteProgram] = QLatin1String("x-fakeprogram");
|
|
Rex Dieter |
d7d5b6 |
+ //p[DeleteArgs] =
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ ///////////////[ ADD ]/////////////
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ p[AddProgram] = QLatin1String("x-fakeprogram");
|
|
Rex Dieter |
d7d5b6 |
+ //p[AddArgs] =
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ ///////////////[ ERRORS ]/////////////
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ p[ExtractionFailedPatterns] = QStringList()
|
|
Rex Dieter |
d7d5b6 |
+ << QLatin1String("Failed! \\((.+)\\)$")
|
|
Rex Dieter |
d7d5b6 |
+ << QLatin1String("Segmentation fault$");
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ p[WrongPasswordPatterns] = QStringList()
|
|
Rex Dieter |
d7d5b6 |
+ << QLatin1String("Failed! \\((.+)\\)$");
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+ return p;
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ QString m_entryFilename, m_internalId;
|
|
Rex Dieter |
d7d5b6 |
+ ArchiveEntry m_currentEntry;
|
|
Rex Dieter |
d7d5b6 |
+ int m_indentLevel;
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ bool readListLine(const QString &line) {
|
|
Rex Dieter |
d7d5b6 |
+ /* lsar will give us JSON output. However, we actually parse based on
|
|
Rex Dieter |
d7d5b6 |
+ * the indentation. Ugly, I know, but
|
|
Rex Dieter |
d7d5b6 |
+ * 1. It's easier
|
|
Rex Dieter |
d7d5b6 |
+ * 2. lsar's JSON is invalid JSON, so actual parsers bork.
|
|
Rex Dieter |
d7d5b6 |
+ */
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ int spaces;
|
|
Rex Dieter |
d7d5b6 |
+ for(spaces=0;(spaces
|
|
Rex Dieter |
d7d5b6 |
+ // Since this is so ugly anyway, I'm not even going to check to
|
|
Rex Dieter |
d7d5b6 |
+ // make sure that spaces is even. I mean, what would I do about it?
|
|
Rex Dieter |
d7d5b6 |
+ int m_newIndentLevel = spaces/2;
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ if (m_newIndentLevel>m_indentLevel) {
|
|
Rex Dieter |
d7d5b6 |
+ if (m_newIndentLevel==3) {
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry.clear();
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry[IsDirectory] = false;
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+ } else if (m_newIndentLevel
|
|
Rex Dieter |
d7d5b6 |
+ if ( (m_newIndentLevel<3) && (m_indentLevel>=3) ) {
|
|
Rex Dieter |
d7d5b6 |
+ EntryMetaDataType index = IsDirectory;
|
|
Rex Dieter |
d7d5b6 |
+ if (m_currentEntry[index].toBool()) {
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry[FileName].toString().append(QLatin1String("/"));
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+ kDebug() << "Added entry:" << m_currentEntry;
|
|
Rex Dieter |
d7d5b6 |
+ entry(m_currentEntry);
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+ m_indentLevel = m_newIndentLevel;
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ QRegExp rx(QLatin1String("^\\s*\"([^\"]*)\": (.*),$"));
|
|
Rex Dieter |
d7d5b6 |
+ if (rx.indexIn(line) >= 0) {
|
|
Rex Dieter |
d7d5b6 |
+ QRegExp rx_unquote(QLatin1String("^\"(.*)\"$"));
|
|
Rex Dieter |
d7d5b6 |
+ QString key = rx.cap(1);
|
|
Rex Dieter |
d7d5b6 |
+ QString value = rx.cap(2);
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ if (false) {
|
|
Rex Dieter |
d7d5b6 |
+ } else if (key==QLatin1String("XADFileName")) {
|
|
Rex Dieter |
d7d5b6 |
+ rx_unquote.indexIn(value);
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry[FileName] = m_currentEntry[InternalID] = rx_unquote.cap(1);
|
|
Rex Dieter |
d7d5b6 |
+ } else if (key==QLatin1String("XADFileSize")) {
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry[Size] = value.toInt();
|
|
Rex Dieter |
d7d5b6 |
+ } else if (key==QLatin1String("XADCompressedSize")) {
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry[CompressedSize] = value.toInt();
|
|
Rex Dieter |
d7d5b6 |
+ } else if (key==QLatin1String("XADLastModificationDate")) {
|
|
Rex Dieter |
d7d5b6 |
+ QDateTime ts(QDate::fromString(value, QLatin1String("\"YYYY-MM-DD hh:mm:ss")));
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry[Timestamp] = ts;
|
|
Rex Dieter |
d7d5b6 |
+ } else if (key==QLatin1String("XADIsDirectory")) {
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry[IsDirectory] = (value==QLatin1String("1"));
|
|
Rex Dieter |
d7d5b6 |
+ } else if (key==QLatin1String("RARCRC32")) {
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry[CRC] = value.toInt();
|
|
Rex Dieter |
d7d5b6 |
+ } else if (key==QLatin1String("RARCompressionMethod")) {
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry[Method] = value.toInt();
|
|
Rex Dieter |
d7d5b6 |
+ } else if (key==QLatin1String("Encrypted")) {
|
|
Rex Dieter |
d7d5b6 |
+ m_currentEntry[IsPasswordProtected] = (value.toInt() != 0);
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+ // TODO: add RAR version. ([Version])
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+ return true;
|
|
Rex Dieter |
d7d5b6 |
+ }
|
|
Rex Dieter |
d7d5b6 |
+};
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+KERFUFFLE_EXPORT_PLUGIN(CliPlugin)
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt
|
|
Rex Dieter |
d7d5b6 |
index 3619412..6368839 100644
|
|
Rex Dieter |
d7d5b6 |
--- a/plugins/CMakeLists.txt
|
|
Rex Dieter |
d7d5b6 |
+++ b/plugins/CMakeLists.txt
|
|
Rex Dieter |
d7d5b6 |
@@ -20,6 +20,7 @@ if (LIBARCHIVE_FOUND)
|
|
Rex Dieter |
d7d5b6 |
endif (LIBARCHIVE_FOUND)
|
|
Rex Dieter |
d7d5b6 |
|
|
Rex Dieter |
d7d5b6 |
add_subdirectory( clirarplugin )
|
|
Rex Dieter |
d7d5b6 |
+add_subdirectory( cliunarchiverplugin )
|
|
Rex Dieter |
d7d5b6 |
add_subdirectory( cli7zplugin )
|
|
Rex Dieter |
d7d5b6 |
add_subdirectory( clizipplugin )
|
|
Rex Dieter |
d7d5b6 |
add_subdirectory( libsinglefileplugin )
|
|
Rex Dieter |
d7d5b6 |
diff --git a/plugins/cliunarchiverplugin/CMakeLists.txt b/plugins/cliunarchiverplugin/CMakeLists.txt
|
|
Rex Dieter |
d7d5b6 |
new file mode 100644
|
|
Rex Dieter |
d7d5b6 |
index 0000000..ccd52e7
|
|
Rex Dieter |
d7d5b6 |
--- /dev/null
|
|
Rex Dieter |
d7d5b6 |
+++ b/plugins/cliunarchiverplugin/CMakeLists.txt
|
|
Rex Dieter |
d7d5b6 |
@@ -0,0 +1,21 @@
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+include_directories(
|
|
Rex Dieter |
d7d5b6 |
+ ${CMAKE_CURRENT_SOURCE_DIR}/../..
|
|
Rex Dieter |
d7d5b6 |
+ ${CMAKE_CURRENT_BINARY_DIR}/../..
|
|
Rex Dieter |
d7d5b6 |
+ )
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+########### next target ###############
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+set(kerfuffle_cliunarchiver_SRCS cliplugin.cpp)
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+kde4_add_plugin(kerfuffle_cliunarchiver ${kerfuffle_cliunarchiver_SRCS})
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+target_link_libraries(kerfuffle_cliunarchiver ${KDE4_KDECORE_LIBS} ${KDE4_KIO_LIBS} kerfuffle )
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+########### install files ###############
|
|
Rex Dieter |
d7d5b6 |
+
|
|
Rex Dieter |
d7d5b6 |
+install(TARGETS kerfuffle_cliunarchiver DESTINATION ${PLUGIN_INSTALL_DIR} )
|
|
Rex Dieter |
d7d5b6 |
+install( FILES kerfuffle_cliunarchiver.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
|
|
Rex Dieter |
d7d5b6 |
+
|