Index: ark/plugins/CMakeLists.txt
===================================================================
--- ark/plugins/CMakeLists.txt	(revision 1237729)
+++ ark/plugins/CMakeLists.txt	(working copy)
@@ -14,6 +14,7 @@
 endif (LIBARCHIVE_FOUND)
 
 add_subdirectory( clirarplugin )
+add_subdirectory( cliunarchiverplugin )
 add_subdirectory( cli7zplugin )
 add_subdirectory( clizipplugin )
 add_subdirectory( libsinglefileplugin )
Index: ark/plugins/cliunarchiverplugin/CMakeLists.txt
===================================================================
--- ark/plugins/cliunarchiverplugin/CMakeLists.txt	(revision 0)
+++ ark/plugins/cliunarchiverplugin/CMakeLists.txt	(revision 0)
@@ -0,0 +1,21 @@
+
+include_directories(
+                     ${CMAKE_CURRENT_SOURCE_DIR}/../..
+                     ${CMAKE_CURRENT_BINARY_DIR}/../..
+                   )
+
+########### next target ###############
+
+set(kerfuffle_cliunarchiver_SRCS cliplugin.cpp)
+
+kde4_add_plugin(kerfuffle_cliunarchiver ${kerfuffle_cliunarchiver_SRCS})
+
+target_link_libraries(kerfuffle_cliunarchiver  ${KDE4_KDECORE_LIBS} ${KDE4_KIO_LIBS} kerfuffle )
+
+
+
+########### install files ###############
+
+install(TARGETS kerfuffle_cliunarchiver  DESTINATION ${PLUGIN_INSTALL_DIR} )
+install( FILES kerfuffle_cliunarchiver.desktop  DESTINATION  ${SERVICES_INSTALL_DIR} )
+
Index: ark/plugins/cliunarchiverplugin/cliplugin.cpp
===================================================================
--- ark/plugins/cliunarchiverplugin/cliplugin.cpp	(revision 0)
+++ ark/plugins/cliunarchiverplugin/cliplugin.cpp	(revision 0)
@@ -0,0 +1,172 @@
+/*
+ * ark -- archiver for the KDE project
+ *
+ * Copyright (C) 2011 Luke Shumaker <lukeshu@sbcglobal.net>
+ *
+ * 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 "kerfuffle/cliinterface.h"
+#include "kerfuffle/kerfuffle_export.h"
+
+#include <KDebug>
+
+#include <QDateTime>
+#include <QDir>
+#include <QRegExp>
+#include <QString>
+#include <QStringList>
+
+using namespace Kerfuffle;
+
+class CliPlugin: public CliInterface
+{
+public:
+    explicit CliPlugin(QObject *parent, const QVariantList & args)
+        : CliInterface(parent, args) {
+        m_indentLevel = 0;
+    }
+
+    virtual ~CliPlugin() {
+    }
+
+    virtual ParameterList parameterList() const {
+        static ParameterList p;
+        if (p.isEmpty()) {
+            /* As I'm writing this, I'm noticing that unar is quite limited.
+             * The following limitations are used to tag unused bits of code:
+             *  01 - cannot extract just one file from the archive
+             *  02 - overwrites existing files without prompt
+             *  03 - cannot edit archives
+             *  04 - if a wrong password is given, it fails (usually segfaults)
+             *       without telling what went wrong
+             */
+
+            ///////////////[ COMMON ]/////////////
+
+            p[CaptureProgress] = false;
+            //p[PasswordPromptPattern] = 
+
+            ///////////////[ LIST ]/////////////
+            
+            p[ListProgram] = "lsar";
+            p[ListArgs] = QStringList() << "-json" << "$Archive";
+
+            ///////////////[ EXTRACT ]/////////////
+
+            p[ExtractProgram] = "unar";
+            p[ExtractArgs] = QStringList() << "$PasswordSwitch" << "$Archive";
+            //p[NoTrailingSlashes]  = // limitation: 01
+            //p[PreservePathSwitch] = // limitation: 01
+            //p[NoTrailingSlashes]  = // limitation: 01
+            //p[RootNodeSwitch]     = // limitation: 01
+            p[PasswordSwitch] = QStringList() << "-p $Password";
+            p[FileExistsExpression] = "some regexp that nothing will ever _ever_ match"; // limitation: 02
+            //p[FileExistsMode]       = // limitation: 02
+            //p[FileExistsInput]      = // limitation: 02
+
+            ///////////////[ DELETE ]/////////////
+            
+            p[DeleteProgram] = "x-fakeprogram"; // limitation: 03
+            //p[DeleteArgs]    = // limitation: 03
+
+            ///////////////[ ADD ]/////////////
+
+            p[AddProgram] = "x-fakeprogram"; // limitation: 03
+            //p[AddArgs]    = // limitation: 03
+
+            ///////////////[ ERRORS ]/////////////
+
+            p[ExtractionFailedPatterns] = QStringList()
+                << "Failed! \\((.+)\\)$"
+                << "Segmentation fault$"; // Why is this so common!?
+
+            p[WrongPasswordPatterns] = QStringList()
+                //<< "Failed!" // limitation: 04
+                <<  "\\.\\.\\. This archive requires a password to unpack\\. Use the -p option to provide one\\.$";
+        }
+        return p;
+    }
+
+    QString m_entryFilename, m_internalId;
+    ArchiveEntry m_currentEntry;
+    int m_indentLevel;
+
+    bool readListLine(const QString &line) {
+        /* lsar will give us JSON output.  However, we actually parse based on
+         * the indentation.  Ugly, I know, but
+         *  1. It's easier
+         *  2. lsar's JSON is invalid JSON, so actual parsers bork.
+         */
+
+        int spaces;
+        for(spaces=0;(spaces<line.size())&&(line[spaces]==QChar(' '));spaces++){}
+        // Since this is so ugly anyway, I'm not even going to check to
+        // make sure that spaces is even.  I mean, what would I do about it?
+        int m_newIndentLevel = spaces/2;
+
+        if (m_newIndentLevel>m_indentLevel) {
+            if (m_newIndentLevel==3) {
+                m_currentEntry.clear();
+                m_currentEntry[IsDirectory] = false;
+            }
+        } else if (m_newIndentLevel<m_indentLevel) {
+            if ( (m_newIndentLevel<3) && (m_indentLevel>=3) ) {
+                EntryMetaDataType index = IsDirectory;
+                if (m_currentEntry[index].toBool()) {
+                    m_currentEntry[FileName].toString().append(QString("/"));
+                }
+                kDebug() << "Added entry:" << m_currentEntry;
+                entry(m_currentEntry);
+            }
+        }
+        m_indentLevel = m_newIndentLevel;
+
+        QRegExp rx("^\\s*\"([^\"]*)\": (.*),$");
+        if (rx.indexIn(line) >= 0) {
+            QRegExp rx_unquote("^\"(.*)\"$");
+            QString key = rx.cap(1);
+            QString value = rx.cap(2);
+
+            if (false) {
+            } else if (key=="XADFileName") {
+                rx_unquote.indexIn(value);
+                m_currentEntry[FileName] = m_currentEntry[InternalID] = rx_unquote.cap(1);
+            } else if (key=="XADFileSize") {
+                m_currentEntry[Size] = value.toInt();
+            } else if (key=="XADCompressedSize") {
+                m_currentEntry[CompressedSize] = value.toInt();
+            } else if (key=="XADLastModificationDate") {
+                QDateTime ts(QDate::fromString(value, "\"YYYY-MM-DD hh:mm:ss"));
+                m_currentEntry[Timestamp] = ts;
+            } else if (key=="XADIsDirectory") {
+                m_currentEntry[IsDirectory] = (value=="1");
+            } else if (key=="RARCRC32") {
+                m_currentEntry[CRC] = value.toInt();
+            } else if (key=="RARCompressionMethod") {
+                m_currentEntry[Method] = value.toInt();
+            } else if (key=="Encrypted") {
+                m_currentEntry[IsPasswordProtected] = (value.toInt() != 0);
+            }
+            // TODO: add RAR version. ([Version])
+        }
+
+        return true;
+    }
+};
+
+KERFUFFLE_EXPORT_PLUGIN(CliPlugin)
+
Index: ark/plugins/cliunarchiverplugin/kerfuffle_cliunarchiver.desktop
===================================================================
--- ark/plugins/cliunarchiverplugin/kerfuffle_cliunarchiver.desktop	(revision 0)
+++ ark/plugins/cliunarchiverplugin/kerfuffle_cliunarchiver.desktop	(revision 0)
@@ -0,0 +1,15 @@
+[Desktop Entry]
+Type=Service
+X-KDE-ServiceTypes=Kerfuffle/Plugin
+X-KDE-Library=kerfuffle_cliunarchiver
+X-KDE-PluginInfo-Author=Luke Shumaker
+X-KDE-PluginInfo-Email=lukeshu@sbcglobal.net
+X-KDE-PluginInfo-Name= kerfuffle_cliunarchiver
+X-KDE-PluginInfo-Version=0.0.1
+X-KDE-PluginInfo-Website=http://www.kde.org
+X-KDE-PluginInfo-License=GPLv2+
+X-KDE-Priority=150
+X-KDE-Kerfuffle-APIRevision=1
+X-KDE-Kerfuffle-ReadWrite=true
+Name=The Unarchiver plugin
+MimeType=application/x-rar;
